protected override bool check_target() { if (!base.check_target()) { return(false); } if (VesselOrbit.PeR > Body.Radius) { Status("yellow", "Cannot perform <b>Ballistic Jump</b> from orbit.\n" + "Use <b>Land at Target</b> instead."); return(false); } //compute initial orbit estimation using LambertSolver var solver = new LambertSolver(VesselOrbit, CFG.Target.RelOrbPos(Body), VSL.Physics.UT); var dV = solver.dV4TransferME(); if (Vector3d.Dot(VesselOrbit.vel + dV, VesselOrbit.pos) < 0) { dV = -2 * VesselOrbit.vel - dV; } var trj = new LandingTrajectory(VSL, dV, VSL.Physics.UT, CFG.Target, TargetAltitude, false); if (trj.TransferTime < TRJ.ManeuverOffset) { Status("yellow", "The target is too close for the jump.\n" + "Use <b>Go To</b> instead."); return(false); } return(true); }
protected override bool check_target() { if (!base.check_target()) { return(false); } if (VesselOrbit.PeR > Body.Radius) { Status("yellow", "Cannot perform <b>Ballistic Jump</b> from orbit.\n" + "Use <b>Land at Target</b> instead."); return(false); } //compute initial orbit estimation using LambertSolver var dV = compute_intial_jump_velocity() - VesselOrbit.vel; var trj = new LandingTrajectory(VSL, dV, VSL.Physics.UT, CFG.Target, TargetAltitude, false); if (trj.TransferTime < ManeuverOffset) { #if DEBUG Log("Too close jump trajectory: {}", trj); #endif Status("yellow", "The target is too close for the jump.\n" + "Use <b>Go To</b> instead."); return(false); } return(true); }
protected LandingTrajectory fixed_Ecc_orbit(LandingTrajectory old, LandingTrajectory best, ref Vector3d NodeDeltaV, double ecc) { double StartUT; double targetAlt; if (old != null) { targetAlt = old.TargetAltitude; StartUT = AngleDelta2StartUT(old, Math.Abs(VesselOrbit.inclination) <= 45 ? old.DeltaLon : old.DeltaLat, TRJ.ManeuverOffset, VesselOrbit.period, VesselOrbit.period); NodeDeltaV += PlaneCorrection(old); if (old.BrakeEndDeltaAlt < LTRJ.FlyOverAlt) //correct fly-over altitude { NodeDeltaV += new Vector3d((LTRJ.FlyOverAlt - old.BrakeEndDeltaAlt) / 100, 0, 0); } } else { StartUT = VSL.Physics.UT + TRJ.ManeuverOffset; targetAlt = TargetAltitude; } return(new LandingTrajectory(VSL, dV4Ecc(VesselOrbit, ecc, StartUT, Body.Radius * 0.9) + Node2OrbitDeltaV(NodeDeltaV, StartUT), StartUT, CFG.Target, targetAlt)); }
IEnumerable <LandingTrajectory> optimize_DeltaFi() { var dFi = ScanDeltaFi? 10.0 * Math.Sign(Best.DeltaFi) : Best.DeltaFi; var fi = 0.0; var bestFi = fi; var cur = Best; var scanned = !ScanDeltaFi; while (Math.Abs(dFi) > 1e-3) { cur = new LandingTrajectory(m.VSL, (QuaternionD.AngleAxis(fi + angle, m.VesselOrbit.getRelativePositionAtUT(startUT)) * dir) * velocity - m.VesselOrbit.getOrbitalVelocityAtUT(startUT), startUT, m.CFG.Target, cur.TargetAltitude); if (cur.DistanceToTarget < Best.DistanceToTarget) { Best = cur; bestFi = fi; } else if (scanned || Math.Abs(fi + angle) > 120) { dFi /= -2.1; fi = bestFi; scanned = true; } fi += dFi; // Utils.Log("D {}, fi {} ({}), dfi {}, DeltaFi {}, trajectory {}", // cur.DistanceToTarget, fi, fi+angle, dFi, cur.DeltaFi, cur);//debug yield return(cur); } angle += bestFi; }
IEnumerable <LandingTrajectory> optimize_DeltaV() { var dV = dR2dV(Best.DeltaR); // Utils.Log("dR {}, Angle2Tgt {}, G {}", Best.DeltaR, m.CFG.Target.AngleTo(m.VSL), m.Body.GeeASL);//debug var bestV = velocity; var dVEnd = Math.Abs(dV) / 100; LandingTrajectory cur = Best, prev; while (Math.Abs(dV) > dVEnd) { prev = cur; cur = new LandingTrajectory(m.VSL, (QuaternionD.AngleAxis(angle, m.VesselOrbit.getRelativePositionAtUT(startUT)) * dir) * velocity - m.VesselOrbit.getOrbitalVelocityAtUT(startUT), startUT, m.CFG.Target, cur.TargetAltitude); if (cur.DistanceToTarget < Best.DistanceToTarget) { Best = cur; bestV = velocity; } if (cur.DistanceToTarget > prev.DistanceToTarget) { dV /= -2.1; velocity = bestV; } velocity += dV; // Utils.Log("D {}, dR {}, dV {}, V {}", cur.DistanceToTarget, cur.DeltaR, dV, velocity);//debug yield return(cur); } velocity = bestV; }
public override IEnumerator <LandingTrajectory> GetEnumerator() { Best = newT(m.VSL.Physics.UT + m.CorrectionOffset + TimeWarp.CurrentRate + 1, 0, Vector3d.zero); LandingTrajectory cur = null; while (continue_calculation(cur, Best)) { cur = Best; var ddV = Utils.ClampSignedL(dR2dV(Best.DeltaR), 1); foreach (var t in optimize_prograde(ddV)) { yield return(t); } var dI = Utils.Clamp((float)Best.DeltaFi / 2, -1, 1); if (Best.ManeuverDuration <= 0) { continue; } var dV = m.hV(Best.StartUT).normalized *prograde_dV; foreach (var t in optimize_inclination(dI, dV)) { yield return(t); } } }
public IEnumerator <LandingTrajectory> GetEnumerator() { // m.Log("Calculating initial orbit eccentricity...");//debug var tPos = m.CFG.Target.OrbPos(m.Body); var UT = m.VSL.Physics.UT + TrajectoryCalculator.AngleDelta(m.VesselOrbit, tPos, m.VSL.Physics.UT) / 360 * m.VesselOrbit.period; if (UT < m.VSL.Physics.UT) { UT += m.VesselOrbit.period; } var vPos = m.VesselOrbit.getRelativePositionAtUT(UT); var vVel = m.VesselOrbit.getOrbitalVelocityAtUT(UT); var incl = Math.Abs(90 - Utils.Angle2(tPos, m.VesselOrbit.GetOrbitNormal())); var ini_dV = TrajectoryCalculator.dV4Pe(m.VesselOrbit, (m.Body.Radius + m.TargetAltitude * 0.9), UT); ini_dV = QuaternionD.AngleAxis(incl, vPos) * (ini_dV + vVel); var dir = -ini_dV.normalized; var maxV = ini_dV.magnitude; ini_dV -= vVel; Best = new LandingTrajectory(m.VSL, ini_dV, UT, m.CFG.Target, m.TargetAltitude); yield return(Best); //if there's not enough fuel, just go with the smallest maneuver possible if (Best.FullManeuver) { //search for the best trajectory using current comparer var start = Best; var bestV = 0.0; var dV = maxV / 10; var V = dV; while (Math.Abs(dV) > TrajectoryCalculator.C.dVtol) { var cur = new LandingTrajectory(m.VSL, start.ManeuverDeltaV + dir * V, start.StartUT, m.CFG.Target, start.TargetAltitude); // m.Log("V {}, dV {}, is better {}\ncur {}\nbest {}", // V, dV, comparer.isBetter(cur, Best), cur, Best);//debug if (comparer.isBetter(cur, Best)) { Best = cur; bestV = V; } V += dV; if (V < 0 || V > maxV || cur != Best) { dV /= -2.1; V = bestV; } yield return(cur); } } m.initialEcc = Best.Orbit.eccentricity; // m.Log("initialEcc: {}", m.initialEcc);//debug }
protected LandingTrajectory fixed_inclination_orbit(LandingTrajectory old, LandingTrajectory best, ref Vector3d dir, ref double V, float start_offset) { var StartUT = VSL.Physics.UT + start_offset; if (old != null) { V += old.DeltaR * (1 - CFG.Target.AngleTo(VSL) / Math.PI * 0.9) * Body.GeeASL; dir = Quaternion.AngleAxis((float)old.DeltaFi, VSL.Physics.Up.xzy) * dir; } return(new LandingTrajectory(VSL, dir * V - VesselOrbit.getOrbitalVelocityAtUT(StartUT), StartUT, CFG.Target, old == null? TargetAltitude : old.TargetAltitude)); }
protected LandingTrajectory horizontal_correction(LandingTrajectory old, LandingTrajectory best, ref Vector3d NodeDeltaV, double start_offset) { var StartUT = VSL.Physics.UT+start_offset; if(old != null) { if(Math.Abs(old.DeltaR) > Math.Abs(old.DeltaFi)) NodeDeltaV += new Vector3d(0, 0, ProgradeCorrection(old)); else NodeDeltaV += PlaneCorrection(old); } return new LandingTrajectory(VSL, Node2OrbitDeltaV(NodeDeltaV, StartUT), StartUT, CFG.Target, old == null? TargetAltitude : old.TargetAltitude); }
protected LandingTrajectory orbit_correction(LandingTrajectory old, LandingTrajectory best, ref double angle, ref double V, float start_offset) { var StartUT = VSL.Physics.UT + start_offset; if (old != null) { V += old.DeltaR * (1 - CFG.Target.AngleTo(VSL) / Math.PI * 0.9) * Body.GeeASL; angle += old.DeltaFi; } var vel = VesselOrbit.getOrbitalVelocityAtUT(StartUT); return(new LandingTrajectory(VSL, QuaternionD.AngleAxis(angle, VSL.Physics.Up.xzy) * vel.normalized * V - vel, StartUT, CFG.Target, old == null? TargetAltitude : old.TargetAltitude)); }
protected LandingTrajectory fixed_Ecc_orbit(LandingTrajectory old, LandingTrajectory best, ref Vector3d NodeDeltaV, double ecc) { double StartUT; double targetAlt; if(old != null) { targetAlt = old.TargetAltitude; var deltaAngle = Math.Abs(90-VesselOrbit.inclination) > 45 ? old.DeltaLon : old.DeltaLat; var inv_target_lat = 90-Math.Abs(Coordinates.NormalizeLatitude(old.Target.Pos.Lat)); var target_at_pole = inv_target_lat < 5; deltaAngle *= inv_target_lat/90; //if target is at a pole, just use its longitude as start UT if(target_at_pole) StartUT = VSL.Physics.UT+ Math.Max(Utils.ClampAngle(Utils.AngleDelta(old.Target.Pos.Lon, VSL.vessel.longitude))/360*VesselOrbit.period, ManeuverOffset); //otherwise correct start UT according to lat-lon delta between target and landing site else StartUT = AngleDelta2StartUT(old, deltaAngle, ManeuverOffset, VesselOrbit.period, VesselOrbit.period); //if start UT is good enough, correct orbital plane and landing site if(target_at_pole || Math.Abs(deltaAngle) < 1) { NodeDeltaV += PlaneCorrection(old); //correct fly-over altitude if needed if(old.BrakeEndDeltaAlt < LTRJ.FlyOverAlt) NodeDeltaV += new Vector3d((LTRJ.FlyOverAlt-old.BrakeEndDeltaAlt)*Body.GeeASL/100, 0, 0); //if close enough, start tuning deltaR if(Math.Abs(old.DeltaFi) < 1) NodeDeltaV += Orbit2NodeDeltaV(old.StartVel.normalized * ProgradeCorrection(old), old.StartUT); } // Log("target_at_pole {}, inv_target_lat {}/{}/{}, deltaAngle {}, deltaFi {}, vsl-target-deltaLon {}, StartT {}", // target_at_pole, inv_target_lat, Coordinates.NormalizeLatitude(old.Target.Pos.Lat), old.Target.Pos.Lat, // deltaAngle, old.DeltaFi, // Utils.ClampAngle(Utils.AngleDelta(old.Target.Pos.Lon, VSL.vessel.longitude)), // StartUT-VSL.Physics.UT);//debug } else { StartUT = VSL.Physics.UT+ManeuverOffset; targetAlt = TargetAltitude; } return new LandingTrajectory(VSL, dV4Ecc(VesselOrbit, ecc, StartUT, Body.Radius+targetAlt-10)+ Node2OrbitDeltaV(NodeDeltaV, StartUT), StartUT, CFG.Target, targetAlt); }
protected LandingTrajectory horizontal_correction(LandingTrajectory old, LandingTrajectory best, ref Vector3d NodeDeltaV, double start_offset) { var StartUT = VSL.Physics.UT + start_offset; if (old != null) { if (Math.Abs(old.DeltaR) > Math.Abs(old.DeltaFi)) { NodeDeltaV += new Vector3d(0, 0, old.DeltaR * Utils.ClampH(old.Orbit.period / 16 / old.TimeToSurface, 1)); } else { NodeDeltaV += PlaneCorrection(old); } } return(new LandingTrajectory(VSL, Node2OrbitDeltaV(NodeDeltaV, StartUT), StartUT, CFG.Target, old == null? TargetAltitude : old.TargetAltitude)); }
public override IEnumerator <LandingTrajectory> GetEnumerator() { Best = new LandingTrajectory(m.VSL, dir * velocity - m.VesselOrbit.getOrbitalVelocityAtUT(startUT), startUT, m.CFG.Target, m.TargetAltitude); LandingTrajectory prev = null; while (continue_calculation(prev, Best)) { prev = Best; foreach (var t in optimize_DeltaV()) { yield return(t); } foreach (var t in optimize_DeltaFi()) { yield return(t); } Utils.Log("Best so far: {}", Best.DistanceToTarget); } }
public override IEnumerator <LandingTrajectory> GetEnumerator() { var startUT = m.VSL.Physics.UT + m.ManeuverOffset; Best = newT(startUT, inclination, deorbit(startUT)); foreach (var t in scan_startUT()) { yield return(t); } LandingTrajectory prev = null; while (continue_calculation(prev, Best)) { prev = Best; startUT = Best.StartUT; var dR = Math.Abs(Best.DeltaR); var dT = (float)Math.Max(Math.Abs(Best.DeltaR) / 360 * m.VesselOrbit.period, 1); foreach (var t in optimize_startUT(dT)) { yield return(t); } var dI = (float)Utils.Clamp(Utils.ClampSignedL(Best.DeltaFi, 0.1), -10, 10); foreach (var t in optimize_inclination(dI, deorbit(Best.StartUT))) { yield return(t); } var dR1 = Math.Abs(Best.DeltaR); if (!Best.FullBrake || dR1 < 1 || Math.Abs(dR - dR1) < 1) { var ddV = -Utils.ClampSignedL(dR2dV(Best.DeltaR), 1); foreach (var t in optimize_ecc(ddV)) { yield return(t); } } // if(Math.Abs(dR-Math.Abs(Best.DeltaR)) < 1) // Ecc = Math.Max(Ecc-dEcc, 0); } }
IEnumerator<YieldInstruction> compute_initial_eccentricity() { // Log("Calculating initial orbit eccentricity...");//debug var tPos = CFG.Target.RelOrbPos(Body); var UT = VSL.Physics.UT + AngleDelta(VesselOrbit, tPos, VSL.Physics.UT)/360*VesselOrbit.period; var vPos = VesselOrbit.getRelativePositionAtUT(UT); var vVel = VesselOrbit.getOrbitalVelocityAtUT(UT); var dir = Vector3d.Exclude(vPos, vVel); var ini_dV = dV4Pe(VesselOrbit, (Body.Radius+TargetAltitude)*0.999, UT); var trj = new LandingTrajectory(VSL, ini_dV, UT, CFG.Target, TargetAltitude); var atmo_curve = trj.GetAtmosphericCurve(5); var maxV = vVel.magnitude; var minV = 0.0; var dV = 0.0; dir = -dir.normalized; var in_plane = Math.Abs(90-Vector3.Angle(tPos, VesselOrbit.GetOrbitNormal())) < 5; // Log("in plane {}, ini dV {}\nini trj:\n{}", in_plane, ini_dV, trj);//debug yield return null; while(maxV-minV > 1) { dV = (maxV+minV)/2; trj = new LandingTrajectory(VSL, ini_dV+dir*dV, UT, CFG.Target, trj.TargetAltitude); atmo_curve = trj.GetAtmosphericCurve(5); // Log("dV: {} : {} : {} m/s\ntrj:\n{}", minV, dV, maxV, trj);//debug if(!trj.NotEnoughFuel && (in_plane || trj.DeltaR < 0) && (atmo_curve != null && (will_overheat(atmo_curve) || atmo_curve[atmo_curve.Count-1].DynamicPressure > DEO.MaxDynPressure) || !Body.atmosphere && trj.LandingAngle < DEO.MinLandingAngle)) minV = dV; else maxV = dV; yield return null; } currentEcc = trj.Orbit.eccentricity; dEcc = currentEcc/DEO.EccSteps; // Log("currentEcc: {}, dEcc {}", currentEcc, dEcc);//debug }
public void DeorbitCallback(Multiplexer.Command cmd) { switch (cmd) { case Multiplexer.Command.Resume: // Utils.Log("Resuming: stage {}, landing_stage {}, landing {}", stage, landing_stage, landing);//debug if (!check_patched_conics()) { return; } NeedRadarWhenMooving(); if (stage == Stage.None && !landing) { goto case Multiplexer.Command.On; } else if (VSL.HasManeuverNode) { CFG.AP1.OnIfNot(Autopilot1.Maneuver); } break; case Multiplexer.Command.On: reset(); if (!check_patched_conics()) { return; } if (!setup()) { CFG.AP2.Off(); return; } if (VesselOrbit.PeR < Body.Radius) { Status("red", "Already deorbiting. Trying to correct course and land."); fine_tune_approach(); } else { // Log("Calculating initial orbit eccentricity...");//debug var tPos = CFG.Target.RelOrbPos(Body); var UT = VSL.Physics.UT + AngleDelta(VesselOrbit, tPos, VSL.Physics.UT) / 360 * VesselOrbit.period; var vPos = VesselOrbit.getRelativePositionAtUT(UT); var dir = Vector3d.Exclude(vPos, tPos - vPos); var ini_orb = CircularOrbit(dir, UT); var ini_dV = ini_orb.getOrbitalVelocityAtUT(UT) - VesselOrbit.getOrbitalVelocityAtUT(UT) + dV4Pe(ini_orb, Body.Radius * 0.9, UT); var trj = new LandingTrajectory(VSL, ini_dV, UT, CFG.Target, TargetAltitude); var dV = 10.0; dir = -dir.normalized; while (trj.Orbit.eccentricity < DEO.StartEcc) { // Log("\ndV: {}m/s\nini trj:\n{}", dV, trj);//debug if (trj.DeltaR > 0) { break; } trj = new LandingTrajectory(VSL, ini_dV + dir * dV, UT, CFG.Target, trj.TargetAltitude); dV += 10; } if (trj.Orbit.eccentricity > DEO.StartEcc) { currentEcc = DEO.StartEcc; if (Body.atmosphere) { currentEcc = Utils.ClampH(currentEcc * (2.1 - Utils.ClampH(VSL.Torque.MaxPossible.AngularDragResistance / Body.atmDensityASL * DEO.AngularDragF, 1)), DEO.MaxEcc); } } else { currentEcc = Utils.ClampL(trj.Orbit.eccentricity - DEO.dEcc, DEO.dEcc); } // Log("currentEcc: {}, dEcc {}", currentEcc, DEO.dEcc);//debug if (Globals.Instance.AutosaveBeforeLanding) { Utils.SaveGame(VSL.vessel.vesselName.Replace(" ", "_") + "-before_landing"); } compute_landing_trajectory(); } goto case Multiplexer.Command.Resume; case Multiplexer.Command.Off: UnregisterFrom <Radar>(); reset(); break; } }
double ProgradeCorrection(LandingTrajectory old) { return(old.DeltaR * Utils.ClampH(old.Orbit.period / old.TimeToTarget * Body.GeeASL, 1)); }