public ReentrySimulation(Orbit _initialOrbit, double _UT, double _dragMassExcludingUsedParachutes, List <SimulatedParachute> _parachuteList, double _mass, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt) { // Store all the input values as they were given input_initialOrbit = _initialOrbit; input_UT = _UT; input_dragMassExcludingUsedParachutes = _dragMassExcludingUsedParachutes; input_parachuteList = _parachuteList; input_mass = _mass; input_descentSpeedPolicy = _descentSpeedPolicy; input_decelEndAltitudeASL = _decelEndAltitudeASL; input_maxThrustAccel = _maxThrustAccel; input_parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; input_probableLandingSiteASL = _probableLandingSiteASL; input_multiplierHasError = _multiplierHasError; input_dt = _dt; max_dt = _dt; dt = max_dt; // Get a copy of the original orbit, to be more thread safe initialOrbit = new Orbit(); initialOrbit.UpdateFromOrbitAtUT(_initialOrbit, _UT, _initialOrbit.referenceBody); CelestialBody body = _initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; seaLevelAtmospheres = body.atmosphereMultiplier; scaleHeight = 1000 * body.atmosphereScaleHeight; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.dragMassExcludingUsedParachutes = _dragMassExcludingUsedParachutes; this.parachutes = _parachuteList; this.parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; this.multiplierHasError = _multiplierHasError; this.mass = _mass; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = _descentSpeedPolicy; decelRadius = bodyRadius + _decelEndAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = _maxThrustAccel; this.probableLandingSiteASL = _probableLandingSiteASL; this.probableLandingSiteRadius = _probableLandingSiteASL + bodyRadius; referenceFrame = ReferenceFrame.CreateAtCurrentTime(_initialOrbit.referenceBody); orbitReenters = OrbitReenters(_initialOrbit); if (orbitReenters) { startUT = _UT; } maxDragGees = 0; deltaVExpended = 0; trajectory = new List <AbsoluteVector>(); }
public ReentrySimulation(Orbit initialOrbit, double UT, double dragCoefficient, IDescentSpeedPolicy descentSpeedPolicy, double endAltitudeASL, double maxThrustAccel) { CelestialBody body = initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; seaLevelAtmospheres = body.atmosphereMultiplier; scaleHeight = 1000 * body.atmosphereScaleHeight; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.dragCoefficient = dragCoefficient; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = descentSpeedPolicy; landedRadius = bodyRadius + endAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = maxThrustAccel; referenceFrame = ReferenceFrame.CreateAtCurrentTime(initialOrbit.referenceBody); orbitReenters = OrbitReenters(initialOrbit); if (orbitReenters) { startUT = UT; t = startUT; AdvanceToFreefallEnd(initialOrbit); } maxDragGees = 0; deltaVExpended = 0; trajectory = new List <AbsoluteVector>(); }
public ReentrySimulation(Orbit _initialOrbit, double _UT, SimulatedVessel _vessel, SimCurves _simcurves, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt, double _min_dt) { // Store all the input values as they were given input_initialOrbit = _initialOrbit; input_UT = _UT; vessel = _vessel; input_descentSpeedPolicy = _descentSpeedPolicy; input_decelEndAltitudeASL = _decelEndAltitudeASL; input_maxThrustAccel = _maxThrustAccel; input_parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; input_probableLandingSiteASL = _probableLandingSiteASL; input_multiplierHasError = _multiplierHasError; input_dt = _dt; // the vessel attitude relative to the surface vel. Fixed for now attitude = Quaternion.Euler(180,0,0); min_dt = _min_dt; max_dt = _dt; dt = max_dt; // Get a copy of the original orbit, to be more thread safe initialOrbit = new Orbit(); initialOrbit.UpdateFromOrbitAtUT(_initialOrbit, _UT, _initialOrbit.referenceBody); CelestialBody body = _initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; this.multiplierHasError = _multiplierHasError; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = _descentSpeedPolicy; decelRadius = bodyRadius + _decelEndAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = _maxThrustAccel; this.probableLandingSiteASL = _probableLandingSiteASL; this.probableLandingSiteRadius = _probableLandingSiteASL + bodyRadius; referenceFrame = ReferenceFrame.CreateAtCurrentTime(_initialOrbit.referenceBody); orbitReenters = OrbitReenters(_initialOrbit); if (orbitReenters) startUT = _UT; maxDragGees = 0; deltaVExpended = 0; trajectory = new List<AbsoluteVector>(); simCurves = _simcurves; once = true; }
public override void Drive(FlightCtrlState s) { if (landStep == LandStep.OFF) { return; } descentSpeedPolicy = PickDescentSpeedPolicy(); predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation predictor.endAltitudeASL = DecelerationEndAltitude(); prediction = predictor.GetResult(); //grab a reference to the current result, in case a new one comes in while we're doing stuff if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN && landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT) { return; } switch (landStep) { case LandStep.UNTARGETED_DEORBIT: DriveUntargetedDeorbit(s); break; case LandStep.PLANE_CHANGE: DrivePlaneChange(s); break; case LandStep.LOW_DEORBIT_BURN: DriveLowDeorbitBurn(s); break; case LandStep.DEORBIT_BURN: DriveDeorbitBurn(s); break; case LandStep.COURSE_CORRECTIONS: DriveCourseCorrections(s); break; case LandStep.KILLING_HORIZONTAL_VELOCITY: DriveKillHorizontalVelocity(s); break; case LandStep.FINAL_DESCENT: DriveUntargetedLanding(s); break; default: break; } }
public override void Drive(FlightCtrlState s) { if (!active) { return; } // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it. // However if it is any other sort or result it is not much use to us, so do not bother! { ReentrySimulation.Result result = predictor.Result; if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.prediction = result; } } } { ReentrySimulation.Result result = predictor.GetErrorResult(); if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.errorPrediction = result; } } } descentSpeedPolicy = PickDescentSpeedPolicy(); predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation predictor.decelEndAltitudeASL = DecelerationEndAltitude(); predictor.parachuteSemiDeployMultiplier = this.parachutePlan.Multiplier; // Consider lowering the langing gear { double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (deployGears && !deployedGears && (minalt < 1000)) { DeployLandingGears(); } } base.Drive(s); }
public override void Drive(FlightCtrlState s) { if (!active) { return; } descentSpeedPolicy = PickDescentSpeedPolicy(); predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation predictor.decelEndAltitudeASL = DecelerationEndAltitude(); predictor.parachuteSemiDeployMultiplier = this.parachutePlan.Multiplier; // Consider lowering the langing gear { double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (deployGears && !deployedGears && (minalt < 1000)) { DeployLandingGears(); } } base.Drive(s); }
public void Init(Orbit _initialOrbit, double _UT, SimulatedVessel _vessel, SimCurves _simcurves, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt, double _min_dt, double _maxOrbits, bool _noSKiptoFreefall) { // Store all the input values as they were given input_initialOrbit = _initialOrbit; input_UT = _UT; vessel = _vessel; input_descentSpeedPolicy = _descentSpeedPolicy; input_decelEndAltitudeASL = _decelEndAltitudeASL; input_maxThrustAccel = _maxThrustAccel; input_parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; input_probableLandingSiteASL = _probableLandingSiteASL; input_multiplierHasError = _multiplierHasError; input_dt = _dt; // the vessel attitude relative to the surface vel. Fixed for now attitude = Quaternion.Euler(180,0,0); min_dt = _min_dt; max_dt = _dt; dt = max_dt; steps = 0; maxOrbits = _maxOrbits; noSKiptoFreefall = _noSKiptoFreefall; // Get a copy of the original orbit, to be more thread safe //initialOrbit = new Orbit(); initialOrbit.UpdateFromOrbitAtUT(_initialOrbit, _UT, _initialOrbit.referenceBody); CelestialBody body = _initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; this.multiplierHasError = _multiplierHasError; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = _descentSpeedPolicy; decelRadius = bodyRadius + _decelEndAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = _maxThrustAccel; this.probableLandingSiteASL = _probableLandingSiteASL; this.probableLandingSiteRadius = _probableLandingSiteASL + bodyRadius; referenceFrame.UpdateAtCurrentTime(_initialOrbit.referenceBody); orbitReenters = OrbitReenters(_initialOrbit); startX = initialOrbit.SwappedRelativePositionAtUT(startUT); // This calls some Unity function so it should be done outside the thread if (orbitReenters) { startUT = _UT; t = startUT; AdvanceToFreefallEnd(initialOrbit); } maxDragGees = 0; deltaVExpended = 0; trajectory = ListPool<AbsoluteVector>.Instance.Borrow(); simCurves = _simcurves; once = true; }
public static ReentrySimulation Borrow(Orbit _initialOrbit, double _UT, SimulatedVessel _vessel, SimCurves _simcurves, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt, double _min_dt, double _maxOrbits, bool _noSKiptoFreefall) { ReentrySimulation sim = pool.Borrow(); sim.Init(_initialOrbit, _UT, _vessel, _simcurves, _descentSpeedPolicy, _decelEndAltitudeASL, _maxThrustAccel, _parachuteSemiDeployMultiplier, _probableLandingSiteASL, _multiplierHasError, _dt, _min_dt, _maxOrbits, _noSKiptoFreefall); return sim; }
public override AutopilotStep Drive(FlightCtrlState s) { if (vessel.LandedOrSplashed) { core.landing.StopLanding(); return(null); } // TODO perhaps we should pop the parachutes at this point, or at least consider it depending on the altitude. double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (vesselState.limitedMaxThrustAccel < vesselState.gravityForce.magnitude) { // if we have TWR < 1, just try as hard as we can to decelerate: // (we need this special case because otherwise the calculations spit out NaN's) core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; core.thrust.trans_spd_act = 0; } else if (minalt > 200) { if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.surfaceVelocity, vesselState.up) < 80)) { // if we have positive vertical velocity, point up and don't thrust: core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.forward, -vesselState.surfaceVelocity) > 45)) { // if we're not facing approximately retrograde, turn to point retrograde and don't thrust: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else { //if we're above 200m, point retrograde and control surface velocity: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; //core.thrust.trans_spd_act = (float)Math.Sqrt((vesselState.maxThrustAccel - vesselState.gravityForce.magnitude) * 2 * minalt) * 0.90F; Vector3d estimatedLandingPosition = vesselState.CoM + vesselState.surfaceVelocity.sqrMagnitude / (2 * vesselState.limitedMaxThrustAccel) * vesselState.surfaceVelocity.normalized; double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(estimatedLandingPosition); aggressivePolicy = new GravityTurnDescentSpeedPolicy(terrainRadius, mainBody.GeeASL * 9.81, vesselState.limitedMaxThrustAccel); // this constant policy creation is wastefull... core.thrust.trans_spd_act = (float)(aggressivePolicy.MaxAllowedSpeed(vesselState.CoM - mainBody.position, vesselState.surfaceVelocity)); } } else { // last 200 meters: core.thrust.trans_spd_act = -Mathf.Lerp(0, (float)Math.Sqrt((vesselState.limitedMaxThrustAccel - vesselState.localg) * 2 * 200) * 0.90F, (float)minalt / 200); // take into account desired landing speed: core.thrust.trans_spd_act = (float)Math.Min(-core.landing.touchdownSpeed, core.thrust.trans_spd_act); // core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; // core.thrust.trans_kill_h = true; // if (Math.Abs(Vector3d.Angle(-vessel.surfaceVelocity, vesselState.up)) < 10) if (vesselState.speedSurfaceHorizontal < 5) { // if we're falling more or less straight down, control vertical speed and // kill horizontal velocity core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; } else { // if we're falling at a significant angle from vertical, our vertical speed might be // quite small but we might still need to decelerate. Control the total speed instead // by thrusting directly retrograde core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; core.thrust.trans_spd_act *= -1; } } status = "Final descent: " + vesselState.altitudeBottom.ToString("F0") + "m above terrain"; // ComputeCourseCorrection doesn't work close to the ground /* if (core.landing.landAtTarget) * { * core.rcs.enabled = true; * Vector3d deltaV = core.landing.ComputeCourseCorrection(false); * core.rcs.SetWorldVelocityError(deltaV); * * status += "\nDV: " + deltaV.magnitude.ToString("F3") + " m/s"; * } */ return(this); }
public override void Drive(FlightCtrlState s) { if (landStep == LandStep.OFF) return; // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it. However if it is any other sort or result it is not much use to us, so do not bother! { ReentrySimulation.Result result = predictor.GetResult(); if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.prediction = result; } } } { ReentrySimulation.Result result = predictor.GetErrorResult(); if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.errorPrediction = result; } } } descentSpeedPolicy = PickDescentSpeedPolicy(); predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation predictor.decelEndAltitudeASL = DecelerationEndAltitude(); predictor.parachuteSemiDeployMultiplier = this.parachutePlan.Multiplier; // Consider lowering the langing gear { double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (deployGears && !deployedGears && (minalt < 1000)) DeployLandingGears(); } if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN && landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT) return; switch (landStep) { case LandStep.UNTARGETED_DEORBIT: DriveUntargetedDeorbit(s); break; case LandStep.PLANE_CHANGE: DrivePlaneChange(s); break; case LandStep.LOW_DEORBIT_BURN: DriveLowDeorbitBurn(s); break; case LandStep.DEORBIT_BURN: DriveDeorbitBurn(s); break; case LandStep.COURSE_CORRECTIONS: DriveCourseCorrections(s); break; case LandStep.KILLING_HORIZONTAL_VELOCITY: DriveKillHorizontalVelocity(s); break; case LandStep.FINAL_DESCENT: DriveUntargetedLanding(s); break; default: break; } }
public override void Drive(FlightCtrlState s) { if (landStep == LandStep.OFF) return; descentSpeedPolicy = PickDescentSpeedPolicy(); predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation predictor.endAltitudeASL = DecelerationEndAltitude(); prediction = predictor.GetResult(); //grab a reference to the current result, in case a new one comes in while we're doing stuff if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN && landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT) return; switch (landStep) { case LandStep.UNTARGETED_DEORBIT: DriveUntargetedDeorbit(s); break; case LandStep.PLANE_CHANGE: DrivePlaneChange(s); break; case LandStep.LOW_DEORBIT_BURN: DriveLowDeorbitBurn(s); break; case LandStep.DEORBIT_BURN: DriveDeorbitBurn(s); break; case LandStep.COURSE_CORRECTIONS: DriveCourseCorrections(s); break; case LandStep.KILLING_HORIZONTAL_VELOCITY: DriveKillHorizontalVelocity(s); break; case LandStep.FINAL_DESCENT: DriveUntargetedLanding(s); break; default: break; } }
Vector3d x; //coordinate system used is centered on main body #endregion Fields #region Constructors public ReentrySimulation(Orbit _initialOrbit, double _UT, double _dragMassExcludingUsedParachutes, List<SimulatedParachute> _parachuteList, double _mass, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt) { // Store all the input values as they were given input_initialOrbit = _initialOrbit; input_UT = _UT; input_dragMassExcludingUsedParachutes = _dragMassExcludingUsedParachutes; input_parachuteList = _parachuteList; input_mass = _mass; input_descentSpeedPolicy = _descentSpeedPolicy; input_decelEndAltitudeASL = _decelEndAltitudeASL; input_maxThrustAccel = _maxThrustAccel; input_parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; input_probableLandingSiteASL = _probableLandingSiteASL; input_multiplierHasError = _multiplierHasError; input_dt = _dt; max_dt = _dt; dt = max_dt; CelestialBody body = _initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; seaLevelAtmospheres = body.atmosphereMultiplier; scaleHeight = 1000 * body.atmosphereScaleHeight; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.dragMassExcludingUsedParachutes = _dragMassExcludingUsedParachutes; this.parachutes = _parachuteList; this.parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; this.multiplierHasError = _multiplierHasError; this.mass = _mass; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = _descentSpeedPolicy; decelRadius = bodyRadius + _decelEndAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = _maxThrustAccel; this.probableLandingSiteASL = _probableLandingSiteASL; this.probableLandingSiteRadius = _probableLandingSiteASL + bodyRadius; referenceFrame = ReferenceFrame.CreateAtCurrentTime(_initialOrbit.referenceBody); orbitReenters = OrbitReenters(_initialOrbit); if (orbitReenters) { startUT = _UT; t = startUT; AdvanceToFreefallEnd(_initialOrbit); } maxDragGees = 0; deltaVExpended = 0; trajectory = new List<AbsoluteVector>(); }
public override AutopilotStep Drive(FlightCtrlState s) { if (vessel.LandedOrSplashed) { core.landing.StopLanding(); return null; } // TODO perhaps we should pop the parachutes at this point, or at least consider it depending on the altitude. double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (vesselState.limitedMaxThrustAccel < vesselState.gravityForce.magnitude) { // if we have TWR < 1, just try as hard as we can to decelerate: // (we need this special case because otherwise the calculations spit out NaN's) core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; core.thrust.trans_spd_act = 0; } else if (minalt > 200) { if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.surfaceVelocity, vesselState.up) < 80)) { // if we have positive vertical velocity, point up and don't thrust: core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.forward, -vesselState.surfaceVelocity) > 45)) { // if we're not facing approximately retrograde, turn to point retrograde and don't thrust: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else { //if we're above 200m, point retrograde and control surface velocity: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; //core.thrust.trans_spd_act = (float)Math.Sqrt((vesselState.maxThrustAccel - vesselState.gravityForce.magnitude) * 2 * minalt) * 0.90F; Vector3d estimatedLandingPosition = vesselState.CoM + vesselState.surfaceVelocity.sqrMagnitude / (2 * vesselState.limitedMaxThrustAccel) * vesselState.surfaceVelocity.normalized; double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(estimatedLandingPosition); aggressivePolicy = new GravityTurnDescentSpeedPolicy(terrainRadius, mainBody.GeeASL * 9.81, vesselState.limitedMaxThrustAccel); // this constant policy creation is wastefull... core.thrust.trans_spd_act = (float)(aggressivePolicy.MaxAllowedSpeed(vesselState.CoM - mainBody.position, vesselState.surfaceVelocity)); } } else { // last 200 meters: core.thrust.trans_spd_act = -Mathf.Lerp(0, (float)Math.Sqrt((vesselState.limitedMaxThrustAccel - vesselState.localg) * 2 * 200) * 0.90F, (float)minalt / 200); // take into account desired landing speed: core.thrust.trans_spd_act = (float)Math.Min(-core.landing.touchdownSpeed, core.thrust.trans_spd_act); // core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; // core.thrust.trans_kill_h = true; // if (Math.Abs(Vector3d.Angle(-vessel.surfaceVelocity, vesselState.up)) < 10) if (vesselState.speedSurfaceHorizontal < 5) { // if we're falling more or less straight down, control vertical speed and // kill horizontal velocity core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; } else { // if we're falling at a significant angle from vertical, our vertical speed might be // quite small but we might still need to decelerate. Control the total speed instead // by thrusting directly retrograde core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; core.thrust.trans_spd_act *= -1; } } status = "Final descent: " + vesselState.altitudeBottom.ToString("F0") + "m above terrain"; // ComputeCourseCorrection doesn't work close to the ground /* if (core.landing.landAtTarget) { core.rcs.enabled = true; Vector3d deltaV = core.landing.ComputeCourseCorrection(false); core.rcs.SetWorldVelocityError(deltaV); status += "\nDV: " + deltaV.magnitude.ToString("F3") + " m/s"; } */ return this; }
public override AutopilotStep Drive(FlightCtrlState s) { if (vessel.LandedOrSplashed) { core.landing.StopLanding(); vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); vessel.Autopilot.Enable(VesselAutopilot.AutopilotMode.RadialIn); return(null); } if (useChute) { waitForChute = vesselState.parachutes.Any(p => p.Anim.isPlaying); } double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (vesselState.limitedMaxThrustAccel < vesselState.gravityForce.magnitude) { // if we have TWR < 1, just try as hard as we can to decelerate: // (we need this special case because otherwise the calculations spit out NaN's) core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; core.thrust.trans_spd_act = 0; } else if (minalt > 25D * gee) { if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.surfaceVelocity, vesselState.up) < 80)) { // if we have positive vertical velocity, point up and don't thrust: core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.forward, -vesselState.surfaceVelocity) > 45)) { // if we're not facing approximately retrograde, turn to point retrograde and don't thrust: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else if (useChute) { // rely on parachutes to get down to 200m // always point up towards target, so any lift providing surface will get us closer Vector3d diff = core.target.GetPositionTargetPosition() - core.landing.LandingSite; core.attitude.attitudeTo(Quaternion.LookRotation(-vesselState.surfaceVelocity, diff), AttitudeReference.INERTIAL, null); // for fine tuning we need to reduce deploy angles or we just spin around target finalDifferenceTarget.value = diff.magnitude; if (finalDifferenceTarget < 100) { foreach (var mcs in vessel.FindPartModulesImplementing <ModuleControlSurface>()) { if (mcs.deploy) { Vector2 scaledLimit = Vector2.Max((float)finalDifferenceTarget / 100f * mcs.deployAngleLimits, new Vector2(-2, 2)); mcs.deployAngle = Mathf.Clamp(mcs.deployAngle, scaledLimit.x, scaledLimit.y); } } } //Debug.Log(String.Format("Diff to target: {0:F2} ", (Vector3) diff)); //assume we fall straight due to parachutes double maxSpeed = 0.9 * Math.Sqrt(2d * vesselState.altitudeTrue * (vesselState.limitedMaxThrustAccel - gee)); if (!waitForChute && (vesselState.TerminalVelocity() > maxSpeed)) { Debug.Log(String.Format("Emergency break in final descent alt:{0} accel:{1} maxSpeed:{2} terminal v:{3}", vesselState.altitudeTrue, vesselState.limitedMaxThrustAccel, maxSpeed, vesselState.TerminalVelocity())); core.thrust.trans_spd_act = (float)maxSpeed; core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; } else { core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } } else { //if we're above 200m, point retrograde and control surface velocity: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; //core.thrust.trans_spd_act = (float)Math.Sqrt((vesselState.maxThrustAccel - vesselState.gravityForce.magnitude) * 2 * minalt) * 0.90F; Vector3d estimatedLandingPosition = vesselState.CoM + vesselState.surfaceVelocity.sqrMagnitude / (2 * vesselState.limitedMaxThrustAccel) * vesselState.surfaceVelocity.normalized; double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(estimatedLandingPosition); aggressivePolicy = new GravityTurnDescentSpeedPolicy(terrainRadius, gee, vesselState.limitedMaxThrustAccel); // this constant policy creation is wastefull... core.thrust.trans_spd_act = (float)(aggressivePolicy.MaxAllowedSpeed(vesselState.CoM - mainBody.position, vesselState.surfaceVelocity)); } } else { // last 250m on Kerbin, lower on lighter, higher on heavier bodies // + 15% safety margin on break distance + distance for last three second with touchdown speed double safety_alt = Math.Max(0.85D * (minalt - core.landing.touchdownSpeed * 2D /*s*/), 0); if (mainBody.atmosphere) { // calculate effective terminal velocity for powered landing // it is smaller as reduced speed from slow down decreases drag // equations are derived from F = k * v^2 + m* ( a -g ), meaning accelerating from ground with help of drag // equation assumes that k is constant, which fails at bigger altitude, but within final touchdown it is safe assumption double a_eff = vesselState.limitedMaxThrustAccel - gee; double v_terminal = vesselState.TerminalVelocity() * Math.Sqrt(a_eff / gee); //double x_0 = - 0.5D * v_terminal / a_eff * Math.Log( 1+ core.landing.touchdownSpeed * core.landing.touchdownSpeed/ (v_terminal * v_terminal)); // v(t) = v_terminal * tan( a_eff * t / v_terminal) + arctan( touchdownSpeed / v_terminal) ) // x(t) = x_o - v_terminal^2 / a_eff * ln(cos(a_eff / v_terminal * t + arctan(touchdownSpeed / v_terminal) )) // note: equations are only for small t where assumption about drag holds -> parameter in cos stays in [0,pi/2] // v(x) = v_terminal * tan( arccos( e ^(-a_eff/v_terminal^2 * ( x -x_0)))) // for survivable touchdownspeeds x_0 is few cm, so we neglect it core.thrust.trans_spd_act = (float)(-v_terminal * Math.Tan(Math.Acos(Math.Exp(-a_eff / (v_terminal * v_terminal) * safety_alt)))); Debug.Log(String.Format("FinalDescent: Limit speed for safety alt={0:F0} to v_target={1:F1}, v={2:F1}, targetThrottle={3:P0}, tmode={4}", safety_alt, core.thrust.trans_spd_act, vesselState.speedVertical, core.thrust.targetThrottle, core.thrust.tmode)); } else { // last 200 meters ramp down speed with limit of falling full throttle break core.thrust.trans_spd_act = -Mathf.Sqrt((float)((vesselState.limitedMaxThrustAccel - vesselState.localg) * safety_alt * 2D + core.landing.touchdownSpeed * core.landing.touchdownSpeed)); } // take into account desired landing speed: core.thrust.trans_spd_act = (float)Math.Min(-core.landing.touchdownSpeed, core.thrust.trans_spd_act); //avoid hopping due to throttle PID oversteering on very last moment, so we do direct control if (-vesselState.speedVertical < 3D * core.landing.touchdownSpeed && core.thrust.targetThrottle > 0.2 && safety_alt < 5) { core.attitude.attitudeTo(Quaternion.LookRotation(vesselState.up, vessel.transform.forward), AttitudeReference.INERTIAL, null); if (-vesselState.speedVertical > core.landing.touchdownSpeed + 1D) { // break with maximum thrust or 50 m/s if we have more available, so speed between 2 physical updates should change at most 1 m/s core.thrust.trans_spd_act = 100f * Mathf.Clamp01((float)((gee + 50) / vesselState.limitedMaxThrustAccel)); } else { //constant speed descent, we just fight gravity core.thrust.trans_spd_act = 95f * Mathf.Clamp01((float)(gee / vesselState.limitedMaxThrustAccel)); } core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; Debug.Log(String.Format("FinalDescent: Touchdown soon ! safety alt={0:F1}, v_vertical={2:F1}, v_horizontal={3:F1} => thrust={1:F0} % ", safety_alt, core.thrust.trans_spd_act, vesselState.speedVertical.value, vesselState.speedSurfaceHorizontal.value)); } else if (vesselState.speedSurfaceHorizontal < 5) { // if we're falling more or less straight down, control vertical speed and // kill horizontal velocity core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; } else { // if we're falling at a significant angle from vertical, our vertical speed might be // quite small but we might still need to decelerate. Control the total speed instead // by thrusting directly retrograde core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; core.thrust.trans_spd_act *= -1; } } status = "Final descent: " + vesselState.altitudeBottom.ToString("F0") + "m above terrain"; // ComputeCourseCorrection doesn't work close to the ground /* if (core.landing.landAtTarget) * { * core.rcs.enabled = true; * Vector3d deltaV = core.landing.ComputeCourseCorrection(false); * core.rcs.SetWorldVelocityError(deltaV); * * status += "\nDV: " + deltaV.magnitude.ToString("F3") + " m/s"; * } */ return(this); }
Vector3d x; //coordinate system used is centered on main body #endregion Fields #region Constructors public ReentrySimulation(Orbit initialOrbit, double UT, double dragCoefficient, List<SimulatedParachute> parachuteList, double mass, IDescentSpeedPolicy descentSpeedPolicy, double endAltitudeASL, double maxThrustAccel) { CelestialBody body = initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; seaLevelAtmospheres = body.atmosphereMultiplier; scaleHeight = 1000 * body.atmosphereScaleHeight; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.dragCoefficient = dragCoefficient; this.parachutes = parachuteList; this.mass = mass; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = descentSpeedPolicy; landedRadius = bodyRadius + endAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = maxThrustAccel; referenceFrame = ReferenceFrame.CreateAtCurrentTime(initialOrbit.referenceBody); orbitReenters = OrbitReenters(initialOrbit); if (orbitReenters) { startUT = UT; t = startUT; AdvanceToFreefallEnd(initialOrbit); } maxDragGees = 0; deltaVExpended = 0; trajectory = new List<AbsoluteVector>(); }
public override AutopilotStep Drive(FlightCtrlState s) { if (vessel.LandedOrSplashed) { core.landing.StopLanding(); return(null); } // TODO perhaps we should pop the parachutes at this point, or at least consider it depending on the altitude. double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (vesselState.limitedMaxThrustAccel < vesselState.gravityForce.magnitude) { // if we have TWR < 1, just try as hard as we can to decelerate: // (we need this special case because otherwise the calculations spit out NaN's) core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_kill_h = true; core.thrust.trans_spd_act = 0; } else if (minalt > 200) { if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.surfaceVelocity, vesselState.up) < 80)) { // if we have positive vertical velocity, point up and don't thrust: core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else if ((vesselState.surfaceVelocity.magnitude > 5) && (Vector3d.Angle(vesselState.forward, -vesselState.surfaceVelocity) > 45)) { // if we're not facing approximately retrograde, turn to point retrograde and don't thrust: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.DIRECT; core.thrust.trans_spd_act = 0; } else { //if we're above 200m, point retrograde and control surface velocity: core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; //core.thrust.trans_spd_act = (float)Math.Sqrt((vesselState.maxThrustAccel - vesselState.gravityForce.magnitude) * 2 * minalt) * 0.90F; Vector3d estimatedLandingPosition = vesselState.CoM + vesselState.surfaceVelocity.sqrMagnitude / (2 * vesselState.limitedMaxThrustAccel) * vesselState.surfaceVelocity.normalized; double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(estimatedLandingPosition); aggressivePolicy = new GravityTurnDescentSpeedPolicy(terrainRadius, mainBody.GeeASL * 9.81, vesselState.limitedMaxThrustAccel); // this constant policy creation is wastefull... core.thrust.trans_spd_act = (float)(aggressivePolicy.MaxAllowedSpeed(vesselState.CoM - mainBody.position, vesselState.surfaceVelocity)); thrustAt200Meters = (float)vesselState.limitedMaxThrustAccel; // this gets updated until we are below 200 meters } } else { float previous_trans_spd_act = Math.Abs(core.thrust.trans_spd_act); // avoid issues going from KEEP_SURFACE mode to KEEP_VERTICAL mode // Last 200 meters, at this point the rocket has a TWR that will rise rapidly, so be sure to use the same policy based on an older // TWR. Otherwise we would suddenly get a large jump in desired speed leading to a landing that is too fast. core.thrust.trans_spd_act = Mathf.Lerp(0, (float)Math.Sqrt((thrustAt200Meters - vesselState.localg) * 2 * 200) * 0.90F, (float)minalt / 200); // Sometimes during the descent we end up going up a bit due to overthrusting during breaking, avoid thrusting up even more and destabilizing the rocket core.thrust.trans_spd_act = (float)Math.Min(previous_trans_spd_act, core.thrust.trans_spd_act); // take into account desired landing speed: core.thrust.trans_spd_act = (float)Math.Max(core.landing.touchdownSpeed, core.thrust.trans_spd_act); // Prevent that we switch back from Vertical mode to KeepSurface mode // When that happens the rocket will start tilting and end up falling over if (vesselState.speedSurfaceHorizontal < 5) { forceVerticalMode = true; } if (forceVerticalMode) { // if we're falling more or less straight down, control vertical speed and // kill horizontal velocity core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_VERTICAL; core.thrust.trans_spd_act *= -1; core.thrust.trans_kill_h = false; // rockets are long, and will fall over if you attempt to do any manouvers to kill that last bit of horizontal speed if (core.landing.rcsAdjustment) // If allowed, use RCS to stablize the rocket { core.rcs.enabled = true; } // Turn on SAS because we are likely to have a bit of horizontal speed left that needs to stabilize // Use SmartASS, because Mechjeb doesn't expect SAS to be used (i.e. it is automatically turned off again) core.EngageSmartASSControl(MechJebModuleSmartASS.Mode.SURFACE, MechJebModuleSmartASS.Target.VERTICAL_PLUS, true); } else { // if we're falling at a significant angle from vertical, our vertical speed might be // quite small but we might still need to decelerate. Control the total speed instead // by thrusting directly retrograde core.attitude.attitudeTo(Vector3d.back, AttitudeReference.SURFACE_VELOCITY, null); core.thrust.tmode = MechJebModuleThrustController.TMode.KEEP_SURFACE; } } status = "Final descent: " + vesselState.altitudeBottom.ToString("F0") + "m above terrain"; // ComputeCourseCorrection doesn't work close to the ground /* if (core.landing.landAtTarget) * { * core.rcs.enabled = true; * Vector3d deltaV = core.landing.ComputeCourseCorrection(false); * core.rcs.SetWorldVelocityError(deltaV); * * status += "\nDV: " + deltaV.magnitude.ToString("F3") + " m/s"; * } */ return(this); }
public override void Drive(FlightCtrlState s) { if (!active) return; // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it. // However if it is any other sort or result it is not much use to us, so do not bother! { ReentrySimulation.Result result = predictor.Result; if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.prediction = result; } } } { ReentrySimulation.Result result = predictor.GetErrorResult(); if (null != result) { if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT) { this.errorPrediction = result; } } } descentSpeedPolicy = PickDescentSpeedPolicy(); PatchPredictorPolicy(); // Consider lowering the langing gear { double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue)); if (deployGears && !deployedGears && (minalt < 1000)) DeployLandingGears(); } base.Drive(s); }
public ReentrySimulation(Orbit _initialOrbit, double _UT, SimulatedVessel _vessel, SimCurves _simcurves, IDescentSpeedPolicy _descentSpeedPolicy, double _decelEndAltitudeASL, double _maxThrustAccel, double _parachuteSemiDeployMultiplier, double _probableLandingSiteASL, bool _multiplierHasError, double _dt, double _min_dt) { // Store all the input values as they were given input_initialOrbit = _initialOrbit; input_UT = _UT; vessel = _vessel; input_descentSpeedPolicy = _descentSpeedPolicy; input_decelEndAltitudeASL = _decelEndAltitudeASL; input_maxThrustAccel = _maxThrustAccel; input_parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; input_probableLandingSiteASL = _probableLandingSiteASL; input_multiplierHasError = _multiplierHasError; input_dt = _dt; // the vessel attitude relative to the surface vel. Fixed for now attitude = Quaternion.Euler(180, 0, 0); min_dt = _min_dt; max_dt = _dt; dt = max_dt; // Get a copy of the original orbit, to be more thread safe initialOrbit = new Orbit(); initialOrbit.UpdateFromOrbitAtUT(_initialOrbit, _UT, _initialOrbit.referenceBody); CelestialBody body = _initialOrbit.referenceBody; bodyHasAtmosphere = body.atmosphere; bodyRadius = body.Radius; gravParameter = body.gravParameter; this.parachuteSemiDeployMultiplier = _parachuteSemiDeployMultiplier; this.multiplierHasError = _multiplierHasError; bodyAngularVelocity = body.angularVelocity; this.descentSpeedPolicy = _descentSpeedPolicy; decelRadius = bodyRadius + _decelEndAltitudeASL; aerobrakedRadius = bodyRadius + body.RealMaxAtmosphereAltitude(); mainBody = body; this.maxThrustAccel = _maxThrustAccel; this.probableLandingSiteASL = _probableLandingSiteASL; this.probableLandingSiteRadius = _probableLandingSiteASL + bodyRadius; referenceFrame = ReferenceFrame.CreateAtCurrentTime(_initialOrbit.referenceBody); orbitReenters = OrbitReenters(_initialOrbit); if (orbitReenters) { startUT = _UT; } maxDragGees = 0; deltaVExpended = 0; trajectory = new List <AbsoluteVector>(); simCurves = _simcurves; once = true; }