protected override void fine_tune_approach() { CorrectionTimer.Reset(); ComputeTrajectory(new DeorbitTrajectoryCorrector(this, LandingTrajectoryAutopilot.C.Dtol / 2)); stage = Stage.Correct; trajectory = null; }
void deorbit() { CorrectionTimer.Reset(); clear_nodes(); add_trajectory_node(); CFG.AP1.On(Autopilot1.Maneuver); stage = Stage.Deorbit; }
void deorbit() { SaveGame("before_landing"); CorrectionTimer.Reset(); clear_nodes(); add_trajectory_node_rel(); CFG.AP1.On(Autopilot1.Maneuver); stage = Stage.Deorbit; }
protected override void fine_tune_approach() { trajectory = null; Dtol = LTRJ.Dtol/2; CorrectionTimer.Reset(); var NodeDeltaV = Vector3d.zero; setup_calculation((o, b) => horizontal_correction(o, b, ref NodeDeltaV, Math.Max(CorrectionOffset, VSL.Torque.NoEngines.TurnTime))); stage = Stage.Correct; }
void deorbit() { SaveGame("before_landing"); CorrectionTimer.Reset(); clear_nodes(); add_trajectory_node_rel(); MAN.MinDeltaV = Utils.ClampL(ThrottleControl.C.MinDeltaV, (float)trajectory.ManeuverDeltaV.magnitude * 0.01f); CFG.AP1.On(Autopilot1.Maneuver); stage = Stage.Deorbit; }
protected bool correct_trajectory() { warp_to_coundown(); if (!CorrectionTimer.TimePassed) { return(false); } CorrectionTimer.Reset(); trajectory.UpdateOrbit(VesselOrbit, true); if (trajectory.DistanceToTarget >= LTRJ.Dtol) { fine_tune_approach(); return(false); } return(!Body.atmosphere); }
protected bool correct_trajectory() { if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH) { VSL.Controls.WarpToTime = VSL.Physics.UT + (VSL.Info.Countdown > 0? Utils.ClampH(VSL.Info.Countdown, 60) : 60); } else { VSL.Controls.StopWarp(); } if (!CorrectionTimer.TimePassed) { return(false); } CorrectionTimer.Reset(); trajectory.UpdateOrbit(VesselOrbit, true); if (trajectory.DistanceToTarget >= LTRJ.Dtol) { fine_tune_approach(); return(false); } return(!Body.atmosphere); }
// double startAlpha; //debug // double startUT = -1; //debug // void log_flight() //debug // { // var target = ToOrbit != null? ToOrbit.Target : VesselOrbit.getRelativePositionAtUT(VSL.Physics.UT+VesselOrbit.timeToAp); // var alpha = Utils.ProjectionAngle(VesselOrbit.pos, target, target-VesselOrbit.pos) * Mathf.Deg2Rad; // var arc = (startAlpha-alpha)*VesselOrbit.radius; // CSV(VSL.Physics.UT-startUT, VSL.VerticalSpeed.Absolute, Vector3d.Exclude(VesselOrbit.pos, VesselOrbit.vel).magnitude, // arc, VesselOrbit.radius-Body.Radius, // VSL.Engines.Thrust.magnitude, // VSL.Physics.M, 90-Vector3d.Angle(VesselOrbit.vel.xzy, VSL.Physics.Up));//debug // } protected override void Update() { if (!IsActive) { CFG.AP2.OffIfOn(Autopilot2.Rendezvous); return; } switch (stage) { case Stage.Start: if (VSL.InOrbit && VesselOrbit.ApR > MinPeR && VesselOrbit.radius > MinPeR) { start_orbit(); } else { to_orbit(); } break; case Stage.Launch: if (ToOrbit.LaunchUT > VSL.Physics.UT) { Status("Waiting for launch window..."); correct_launch(false); //FIXME: sometimes AtmoSim returns inconsistent TTA which results in jumps of the Countdown. VSL.Info.Countdown = ToOrbit.LaunchUT - VSL.Physics.UT; VSL.Controls.WarpToTime = ToOrbit.LaunchUT; break; } // if(startUT < 0) //debug // { // startAlpha = Utils.ProjectionAngle(VesselOrbit.pos, ToOrbit.Target, ToOrbit.Target-VesselOrbit.pos) * Mathf.Deg2Rad; // startUT = VSL.Physics.UT; // } // log_flight();//debug if (ToOrbit.Liftoff()) { break; } stage = Stage.ToOrbit; MinDist.Reset(); break; case Stage.ToOrbit: // log_flight();//debug if (ToOrbit.GravityTurn(ManeuverOffset, GLB.ORB.GTurnCurve, GLB.ORB.Dist2VelF, REN.Dtol)) { if (ToOrbit.dApA < REN.Dtol) { update_trajectory(); MinDist.Update(CurrentDistance); if (MinDist) { start_orbit(); } } } else { start_orbit(); } break; case Stage.StartOrbit: // log_flight();//debug Status("Achiving starting orbit..."); if (CFG.AP1[Autopilot1.Maneuver]) { break; } update_trajectory(); CurrentDistance = -1; if (trajectory.RelDistanceToTarget < REN.CorrectionStart || trajectory.TimeToTarget / VesselOrbit.period > REN.MaxTTR) { stage = Stage.Rendezvou; } else { compute_rendezvou_trajectory(); } break; case Stage.ComputeRendezvou: // log_flight();//debug if (TimeWarp.CurrentRateIndex == 0 && TimeWarp.CurrentRate > 1) { Status("Waiting for Time Warp to end..."); break; } if (!trajectory_computed()) { break; } #if DEBUG if (trajectory.KillerOrbit || trajectory.Orbit.eccentricity > 0.6) { PauseMenu.Display(); } #endif if (!trajectory.KillerOrbit && trajectory.RelDistanceToTarget < REN.CorrectionStart && (CurrentDistance < 0 || trajectory.DistanceToTarget < CurrentDistance)) { CorrectionTimer.Reset(); if (trajectory.ManeuverDeltaV.magnitude > 1) { VSL.Controls.StopWarp(); if (TimeWarp.CurrentRate > 1 || trajectory.TimeToStart < trajectory.ManeuverDuration / 2) { update_trajectory(); fine_tune_approach(); } else { CurrentDistance = trajectory.DistanceToTarget; add_trajectory_node(); CFG.AP1.On(Autopilot1.Maneuver); stage = Stage.Rendezvou; } break; } update_trajectory(); if (CurrentDistance > REN.Dtol && trajectory.TimeToTarget > trajectory.BrakeDuration + ManeuverOffset + TimeWarp.CurrentRate) { stage = Stage.Coast; break; } } if (CurrentDistance > 0 && CurrentDistance / VesselOrbit.semiMajorAxis < REN.CorrectionStart) { VSL.Controls.StopWarp(); match_orbits(); break; } Status("red", "Failed to compute rendezvou trajectory.\nPlease, try again."); CFG.AP2.Off(); #if DEBUG PauseMenu.Display(); #endif break; case Stage.Rendezvou: // log_flight();//debug Status("Correcting trajectory..."); if (CFG.AP1[Autopilot1.Maneuver]) { break; } update_trajectory(); if (CurrentDistance < REN.ApproachThreshold) { match_orbits(); } else { stage = Stage.Coast; } break; case Stage.Coast: Status("Coasting..."); if (!CorrectionTimer.TimePassed) { if (VSL.Controls.CanWarp) { VSL.Controls.WarpToTime = trajectory.AtTargetUT - trajectory.BrakeDuration + ManeuverOffset; } break; } CorrectionTimer.Reset(); update_trajectory(); fine_tune_approach(); break; case Stage.MatchOrbits: // log_flight();//debug Status("Matching orbits at nearest approach..."); if (CFG.AP1[Autopilot1.Maneuver]) { break; } update_trajectory(); update_direct_distance(); if (TargetLoaded) { approach_or_brake(); } else { var relD = DirectDistance / VesselOrbit.semiMajorAxis; if (relD > REN.CorrectionStart) { start_orbit(); } else if (relD > REN.CorrectionStart / 4) { fine_tune_approach(); } else { approach_or_brake(); } } break; case Stage.Approach: Status("Approaching..."); THR.DeltaV = 0; var dP = TargetOrbit.pos - VesselOrbit.pos; var dPm = dP.magnitude; if (dPm - VSL.Geometry.MinDistance < REN.Dtol) { brake(); break; } var throttle = VSL.Controls.OffsetAlignmentFactor(); if (throttle.Equals(0)) { break; } var dV = Vector3d.Dot(VesselOrbit.vel - TargetOrbit.vel, dP / dPm); var nV = Utils.Clamp(dPm * REN.ApproachVelF, 1, REN.MaxApproachV); if (dV + GLB.THR.MinDeltaV < nV) { VSL.Engines.ActivateEngines(); THR.DeltaV = (float)(nV - dV) * throttle * throttle; } else { brake(); } break; case Stage.Brake: Status("Braking near target..."); if (CFG.AP1[Autopilot1.MatchVelNear]) { break; } if (CFG.AP1[Autopilot1.MatchVel]) { if ((TargetOrbit.vel - VesselOrbit.vel).magnitude > GLB.THR.MinDeltaV) { break; } CFG.AP1.Off(); THR.Throttle = 0; } if ((VSL.Physics.wCoM - TargetVessel.CurrentCoM).magnitude - VSL.Geometry.R - TargetVessel.Radius() > REN.Dtol) { approach(); break; } CFG.AP2.Off(); CFG.AT.OnIfNot(Attitude.KillRotation); ClearStatus(); break; } }
// double startAlpha; //debug // double startUT = -1; //debug // void log_flight() //debug // { // var target = ToOrbit != null? ToOrbit.Target : VesselOrbit.getRelativePositionAtUT(VSL.Physics.UT+VesselOrbit.timeToAp); // var alpha = Utils.ProjectionAngle(VesselOrbit.pos, target, target-VesselOrbit.pos) * Mathf.Deg2Rad; // var arc = (startAlpha-alpha)*VesselOrbit.radius; // CSV(VSL.Physics.UT-startUT, VSL.VerticalSpeed.Absolute, Vector3d.Exclude(VesselOrbit.pos, VesselOrbit.vel).magnitude, // arc, VesselOrbit.radius-Body.Radius, // VSL.Engines.Thrust.magnitude, // VSL.Physics.M, 90-Vector3d.Angle(VesselOrbit.vel.xzy, VSL.Physics.Up));//debug // } protected override void Update() { if (!IsActive) { CFG.AP2.OffIfOn(Autopilot2.Rendezvous); return; } switch (stage) { case Stage.Start: if (VSL.InOrbit && VesselOrbit.ApR > MinPeR && VesselOrbit.radius > MinPeR) { update_trajectory(); if (CurrentDistance > REN.CorrectionStart) { start_orbit(); } else { fine_tune_approach(); } } else { to_orbit(); } break; case Stage.Launch: if (ToOrbit.LaunchUT > VSL.Physics.UT) { Status("Waiting for launch window..."); correct_launch(false); //FIXME: sometimes AtmoSim returns inconsistent TTA which results in jumps of the Countdown. VSL.Info.Countdown = ToOrbit.LaunchUT - VSL.Physics.UT; VSL.Controls.WarpToTime = ToOrbit.LaunchUT; break; } // if(startUT < 0) //debug // { // startAlpha = Utils.ProjectionAngle(VesselOrbit.pos, ToOrbit.Target, ToOrbit.Target-VesselOrbit.pos) * Mathf.Deg2Rad; // startUT = VSL.Physics.UT; // } // log_flight();//debug if (ToOrbit.Liftoff()) { break; } stage = Stage.ToOrbit; MinDist.Reset(); break; case Stage.ToOrbit: // log_flight();//debug if (ToOrbit.GravityTurn(TRJ.ManeuverOffset, GLB.ORB.GTurnCurve, GLB.ORB.Dist2VelF, REN.Dtol)) { if (ToOrbit.dApA < REN.Dtol) { update_trajectory(); MinDist.Update(CurrentDistance); if (MinDist) { start_orbit(); } } } else { start_orbit(); } break; case Stage.StartOrbit: // log_flight();//debug if (CFG.AP1[Autopilot1.Maneuver]) { break; } update_trajectory(); CurrentDistance = -1; if (trajectory.DistanceToTarget < REN.CorrectionStart || (trajectory.TransferTime + trajectory.TimeToStart) / VesselOrbit.period > REN.MaxTTR) { stage = Stage.Rendezvou; } else { compute_rendezvou_trajectory(); } break; case Stage.ComputeRendezvou: // log_flight();//debug if (!trajectory_computed()) { break; } if (trajectory.ManeuverDeltaV.magnitude > GLB.THR.MinDeltaV * 5 && trajectory.DistanceToTarget < REN.CorrectionStart && (CurrentDistance < 0 || trajectory.DistanceToTarget < CurrentDistance)) { CorrectionTimer.Start(); CurrentDistance = trajectory.DistanceToTarget; add_trajectory_node(); CFG.AP1.On(Autopilot1.Maneuver); stage = Stage.Rendezvou; } else if (trajectory.DistanceToTarget < REN.CorrectionStart) { match_orbits(); } else { Status("red", "Failed to compute rendezvou trajectory.\nPlease, try again."); CFG.AP2.Off(); return; } break; case Stage.Rendezvou: // log_flight();//debug if (CFG.AP1[Autopilot1.Maneuver]) { break; } if (!CorrectionTimer.TimePassed && CurrentDistance >= 0) { break; } CorrectionTimer.Reset(); update_trajectory(); if (CurrentDistance < REN.ApproachThreshold) { match_orbits(); } else { fine_tune_approach(); } break; case Stage.MatchOrbits: // log_flight();//debug Status("Matching orbits at nearest approach..."); if (CFG.AP1[Autopilot1.Maneuver]) { break; } update_trajectory(); var dist = Utils.ClampL((TargetOrbit.pos - VesselOrbit.pos).magnitude - VSL.Geometry.R - TargetVessel.Radius(), 0); if (dist > REN.CorrectionStart) { start_orbit(); } else if (dist > REN.CorrectionStart / 4) { fine_tune_approach(); } else if (dist > REN.Dtol) { approach(); } else { brake(); } break; case Stage.Approach: Status("Approaching..."); var dP = TargetOrbit.pos - VesselOrbit.pos; var dPm = dP.magnitude; if (dPm - VSL.Geometry.R - TargetVessel.Radius() < REN.Dtol) { brake(); break; } if (VSL.Controls.AttitudeError > 1) { break; } var dV = Vector3d.Dot(VesselOrbit.vel - TargetOrbit.vel, dP / dPm); var nV = Utils.Clamp(dPm * REN.ApproachVelF, 1, REN.MaxApproachV); if (dV + GLB.THR.MinDeltaV < nV) { VSL.Engines.ActivateEngines(); THR.DeltaV = (float)(nV - dV); } else { brake(); } break; case Stage.Brake: Status("Braking near target..."); if (CFG.AP1[Autopilot1.MatchVelNear]) { break; } if (CFG.AP1[Autopilot1.MatchVel]) { if ((TargetOrbit.vel - VesselOrbit.vel).magnitude > GLB.THR.MinDeltaV) { break; } CFG.AP1.Off(); THR.Throttle = 0; } if ((VSL.Physics.wCoM - TargetVessel.CurrentCoM).magnitude - VSL.Geometry.R - TargetVessel.Radius() > REN.Dtol) { approach(); break; } CFG.AP2.Off(); CFG.AT.OnIfNot(Attitude.KillRotation); ClearStatus(); break; } }