/// <summary> /// Old school style override of PatchedConics.CheckEncounter, set up in Start and reset at destroy. /// We prevent any encounter with our starting body, and otherwise hand off to the default implementation. /// </summary> /// <param name="p">The patch currently being analyzed</param> /// <param name="nextPatch">The next patch to be analyzed</param> /// <param name="startEpoch">The time when the vessel reaches p</param> /// <param name="sec">The driver of the orbit to check for an encounter; this is the only parameter that we actually use here rather than passing along to the default implementation</param> /// <param name="targetBody">The user's currently selected target</param> /// <param name="pars">Stuff that controls how the solver works</param> /// <param name="logErrors">true to print things to the log, false otherwise</param> /// <returns> /// true if encounter found, false otherwise (or if one would have been found for our starting body) /// </returns> private bool MyCheckEncounter( Orbit p, Orbit nextPatch, double startEpoch, OrbitDriver sec, CelestialBody targetBody, PatchedConics.SolverParameters pars, bool logErrors = true) { // Suppress encounters with our starting body, because it makes the solver put NaN orbits in the flight plan return(sec?.celestialBody == editingNode?.origin ? false : originalCheckEncounter(p, nextPatch, startEpoch, sec, targetBody, pars, logErrors)); }
private Orbit createOrbitFromState(VesselState state) { var orbit = new Orbit(); orbit.UpdateFromStateVectors(Util.SwapYZ(state.position), Util.SwapYZ(state.velocity), state.referenceBody, state.time); var pars = new PatchedConics.SolverParameters(); pars.FollowManeuvers = false; PatchedConics.CalculatePatch(orbit, new Orbit(), state.time, pars, null); return(orbit); }
private static Orbit CreateOrbitFromState(VesselState state) { Orbit orbit = new Orbit(); orbit.UpdateFromStateVectors(state.Position.SwapYZ(), state.Velocity.SwapYZ(), state.ReferenceBody, state.Time); PatchedConics.SolverParameters pars = new PatchedConics.SolverParameters { FollowManeuvers = false }; PatchedConics.CalculatePatch(orbit, new Orbit(), state.Time, pars, null); return(orbit); }
// calculate the next patch, which makes patchEndTransition be valid // public static Orbit CalculateNextOrbit(this Orbit o, double UT = Double.NegativeInfinity) { PatchedConics.SolverParameters solverParameters = new PatchedConics.SolverParameters(); // hack up a dynamic default value to the current time if (UT == Double.NegativeInfinity) { UT = Planetarium.GetUniversalTime(); } o.StartUT = UT; o.EndUT = o.eccentricity >= 1.0 ? o.period : UT + o.period; Orbit nextOrbit = new Orbit(); PatchedConics.CalculatePatch(o, nextOrbit, UT, solverParameters, null); return(nextOrbit); }
static void DistanceToTarget(double[] x, double[] fi, object obj) { OptimizerData data = (OptimizerData)obj; double t = x[3]; Vector3d DV = new Vector3d(x[0], x[1], x[2]); Orbit orbit = new Orbit(); orbit.UpdateFromStateVectors(data.initial_orbit.getRelativePositionAtUT(t), data.initial_orbit.getOrbitalVelocityAtUT(t) + DV.xzy, data.initial_orbit.referenceBody, t); orbit.StartUT = t; var pars = new PatchedConics.SolverParameters(); Vector3d pos; while (true) { Orbit next_orbit = new Orbit(); PatchedConics.CalculatePatch(orbit, next_orbit, orbit.StartUT, pars, null); if (orbit.EndUT > x[4]) { pos = orbit.getTruePositionAtUT(x[4]); Vector3d err = pos - data.target_orbit.getTruePositionAtUT(x[4]); /* this needs to be components of err and cannot simply be err.magnitude */ fi[0] = err.x; fi[1] = err.y; fi[2] = err.z; /* similarly here, and the 10,000x fudge factor was experimentally determined */ fi[3] = DV.x * 10000.0; fi[4] = DV.y * 10000.0; fi[5] = DV.z * 10000.0; return; } // As of 0.25 CalculatePatch fails if the orbit does not change SoI if (next_orbit.referenceBody == null) { next_orbit.UpdateFromOrbitAtUT(orbit, orbit.StartUT + orbit.period, orbit.referenceBody); } orbit = next_orbit; } }
static void DistanceToTarget(double[] x, double[] fi, object obj) { OptimizerData data = (OptimizerData)obj; double t = data.original_UT + x[3]; Vector3d DV = new Vector3d(x[0], x[1], x[2]); Orbit orbit = new Orbit(); orbit.UpdateFromStateVectors(data.initial_orbit.getRelativePositionAtUT(t), data.initial_orbit.getOrbitalVelocityAtUT(t) + DV.xzy, data.initial_orbit.referenceBody, t); orbit.StartUT = t; var pars = new PatchedConics.SolverParameters(); Vector3d pos; while (true) { Orbit next_orbit = new Orbit(); PatchedConics.CalculatePatch(orbit, next_orbit, orbit.StartUT, pars, null); if (orbit.EndUT > data.UT_arrival) { pos = orbit.getTruePositionAtUT(data.UT_arrival); Vector3d err = pos - data.pos_arrival; fi[0] = err.x; fi[1] = err.y; fi[2] = err.z; return; } // As of 0.25 CalculatePatch fails if the orbit does not change SoI if (next_orbit.referenceBody == null) { next_orbit.UpdateFromOrbitAtUT(orbit, orbit.StartUT + orbit.period, orbit.referenceBody); } orbit = next_orbit; } }
public static bool _CalculatePatch(Orbit p, Orbit nextPatch, double startEpoch, PatchedConics.SolverParameters pars, CelestialBody targetBody) { p.activePatch = true; p.nextPatch = nextPatch; p.patchEndTransition = Orbit.PatchTransitionType.FINAL; p.closestEncounterLevel = Orbit.EncounterSolutionLevel.NONE; p.numClosePoints = 0; log_patches(p, "Patch 0"); int count = Planetarium.Orbits.Count; for (int i = 0; i < count; i++) { OrbitDriver orbitDriver = Planetarium.Orbits[i]; if (orbitDriver.orbit == p) { continue; } if (orbitDriver.celestialBody) { if (targetBody == null) { goto IL_B6; } if (orbitDriver.celestialBody == targetBody) { goto IL_B6; } IL_C5: if (orbitDriver.referenceBody == p.referenceBody) { var enc = PatchedConics.CheckEncounter(p, nextPatch, startEpoch, orbitDriver, targetBody, pars); Utils.Log("Encounter with {}: {}", orbitDriver.celestialBody.bodyName, enc); log_patches(p, "Patch"); goto IL_FA; } goto IL_FA; IL_B6: p.closestTgtApprUT = 0.0; goto IL_C5; } IL_FA :; } log_patches(p, "Patch 1"); if (p.patchEndTransition == Orbit.PatchTransitionType.FINAL) { if (!pars.debug_disableEscapeCheck) { if (p.ApR <= p.referenceBody.sphereOfInfluence) { if (p.eccentricity < 1.0) { p.UTsoi = -1.0; p.StartUT = startEpoch; p.EndUT = startEpoch + p.period; p.patchEndTransition = Orbit.PatchTransitionType.FINAL; goto IL_2C0; } } if (double.IsInfinity(p.referenceBody.sphereOfInfluence)) { p.FEVp = Math.Acos(-(1.0 / p.eccentricity)); p.SEVp = -p.FEVp; p.StartUT = startEpoch; p.EndUT = double.PositiveInfinity; p.UTsoi = double.PositiveInfinity; p.patchEndTransition = Orbit.PatchTransitionType.FINAL; } else { p.FEVp = p.TrueAnomalyAtRadius(p.referenceBody.sphereOfInfluence); p.SEVp = -p.FEVp; p.timeToTransition1 = p.GetDTforTrueAnomaly(p.FEVp, 0.0); p.timeToTransition2 = p.GetDTforTrueAnomaly(p.SEVp, 0.0); p.UTsoi = startEpoch + p.timeToTransition1; nextPatch.UpdateFromOrbitAtUT(p, p.UTsoi, p.referenceBody.referenceBody); p.StartUT = startEpoch; p.EndUT = p.UTsoi; p.patchEndTransition = Orbit.PatchTransitionType.ESCAPE; } } } IL_2C0: nextPatch.StartUT = p.EndUT; double arg_2FD_1; if (nextPatch.eccentricity < 1.0) { arg_2FD_1 = nextPatch.StartUT + nextPatch.period; } else { arg_2FD_1 = nextPatch.period; } nextPatch.EndUT = arg_2FD_1; nextPatch.patchStartTransition = p.patchEndTransition; nextPatch.previousPatch = p; log_patches(p, "Patch 2"); return(p.patchEndTransition != Orbit.PatchTransitionType.FINAL); }
public static bool CheckEncounterButDontBitchAboutIt(Orbit p, Orbit nextPatch, double startEpoch, OrbitDriver sec, CelestialBody targetBody, PatchedConics.SolverParameters pars, bool logErrors) { Orbit orbit = sec.orbit; double num = 1.1; if (GameSettings.ALWAYS_SHOW_TARGET_APPROACH_MARKERS && sec.celestialBody == targetBody) { num = Math.Sqrt(orbit.semiMajorAxis / sec.celestialBody.sphereOfInfluence); } if (!Orbit.PeApIntersects(p, orbit, sec.celestialBody.sphereOfInfluence * num)) { return(false); } if (p.closestEncounterLevel < Orbit.EncounterSolutionLevel.ORBIT_INTERSECT) { p.closestEncounterLevel = Orbit.EncounterSolutionLevel.ORBIT_INTERSECT; p.closestEncounterBody = sec.celestialBody; } double clEctr = p.ClEctr1; double clEctr2 = p.ClEctr2; double fEVp = p.FEVp; double fEVs = p.FEVs; double sEVp = p.SEVp; double sEVs = p.SEVs; int num2 = FindClosestPointsRevertedCauseNewOneSucks(p, orbit, ref clEctr, ref clEctr2, ref fEVp, ref fEVs, ref sEVp, ref sEVs, 0.0001, pars.maxGeometrySolverIterations, ref pars.GeoSolverIterations); if (num2 < 1) { return(false); } double dTforTrueAnomaly = p.GetDTforTrueAnomaly(fEVp, 0.0); double dTforTrueAnomaly2 = p.GetDTforTrueAnomaly(sEVp, 0.0); double num3 = dTforTrueAnomaly + startEpoch; double num4 = dTforTrueAnomaly2 + startEpoch; // avoid bad numbers if (double.IsInfinity(num3) && !double.IsInfinity(num4)) { num3 = num4; } if (double.IsInfinity(num4) && !double.IsInfinity(num3)) { num4 = num3; } if (double.IsInfinity(num3) && double.IsInfinity(num4)) { UnityEngine.Debug.Log("CheckEncounter: both intercept UTs are infinite"); return(false); } if ((num3 < p.StartUT || num3 > p.EndUT) && (num4 < p.StartUT || num4 > p.EndUT)) { return(false); } if (num4 < num3 || num3 < p.StartUT || num3 > p.EndUT) { UtilMath.SwapValues(ref fEVp, ref sEVp); UtilMath.SwapValues(ref fEVs, ref sEVs); UtilMath.SwapValues(ref clEctr, ref clEctr2); UtilMath.SwapValues(ref dTforTrueAnomaly, ref dTforTrueAnomaly2); UtilMath.SwapValues(ref num3, ref num4); } if (num4 < p.StartUT || num4 > p.EndUT || double.IsInfinity(num4)) { num2 = 1; } p.numClosePoints = num2; p.FEVp = fEVp; p.FEVs = fEVs; p.SEVp = sEVp; p.SEVs = sEVs; p.ClEctr1 = clEctr; p.ClEctr2 = clEctr2; if (Math.Min(p.ClEctr1, p.ClEctr2) > sec.celestialBody.sphereOfInfluence) { if (GameSettings.ALWAYS_SHOW_TARGET_APPROACH_MARKERS && sec.celestialBody == targetBody) { p.UTappr = startEpoch; p.ClAppr = PatchedConics.GetClosestApproach(p, orbit, startEpoch, p.nearestTT * 0.5, pars); p.closestTgtApprUT = p.UTappr; } return(false); } if (p.closestEncounterLevel < Orbit.EncounterSolutionLevel.SOI_INTERSECT_1) { p.closestEncounterLevel = Orbit.EncounterSolutionLevel.SOI_INTERSECT_1; p.closestEncounterBody = sec.celestialBody; } p.timeToTransition1 = dTforTrueAnomaly; p.secondaryPosAtTransition1 = orbit.getPositionAtUTSigma(num3); UnityEngine.Debug.DrawLine(ScaledSpace.LocalToScaledSpace(p.referenceBody.position), ScaledSpace.LocalToScaledSpace(p.secondaryPosAtTransition1), Color.yellow); p.timeToTransition2 = dTforTrueAnomaly2; p.secondaryPosAtTransition2 = orbit.getPositionAtUTSigma(num4); UnityEngine.Debug.DrawLine(ScaledSpace.LocalToScaledSpace(p.referenceBody.position), ScaledSpace.LocalToScaledSpace(p.secondaryPosAtTransition2), Color.red); p.nearestTT = p.timeToTransition1; p.nextTT = p.timeToTransition2; if (double.IsNaN(p.nearestTT)) { UnityEngine.Debug.Log(string.Concat(new object[] { "nearestTT is NaN! t1: ", p.timeToTransition1, ", t2: ", p.timeToTransition2, ", FEVp: ", p.FEVp, ", SEVp: ", p.SEVp })); } p.UTappr = startEpoch; p.ClAppr = PatchedConics.GetClosestApproach(p, orbit, startEpoch, p.nearestTT * 0.5, pars); if (PatchedConics.EncountersBody(p, orbit, nextPatch, sec, startEpoch, pars)) { return(true); } if (num2 > 1) { p.closestEncounterLevel = Orbit.EncounterSolutionLevel.SOI_INTERSECT_2; p.closestEncounterBody = sec.celestialBody; UnityEngine.Debug.DrawLine(ScaledSpace.LocalToScaledSpace(p.getPositionAtUTSigma(p.UTappr)), ScaledSpace.LocalToScaledSpace(orbit.getPositionAtUTSigma(p.UTappr)), XKCDColors.Orange * 0.5f); p.UTappr = startEpoch + p.nearestTT; p.ClAppr = PatchedConics.GetClosestApproach(p, orbit, startEpoch, (p.nextTT - p.nearestTT) * 0.5, pars); if (PatchedConics.EncountersBody(p, orbit, nextPatch, sec, startEpoch, pars)) { return(true); } UnityEngine.Debug.DrawLine(ScaledSpace.LocalToScaledSpace(p.getPositionAtUTSigma(p.UTappr)), ScaledSpace.LocalToScaledSpace(orbit.getPositionAtUTSigma(p.UTappr)), XKCDColors.Orange); } if (sec.celestialBody == targetBody) { p.closestTgtApprUT = p.UTappr; } return(false); }
public static bool CalculatePatch(Orbit p, Orbit nextPatch, double startEpoch, PatchedConics.SolverParameters pars, CelestialBody targetBody);
static void DistanceToTarget(double[] x, double[] fi, object obj) { OptimizerData data = (OptimizerData)obj; double t = data.original_UT + x[3]; Vector3d DV = new Vector3d(x[0], x[1], x[2]); Orbit orbit = new Orbit(); orbit.UpdateFromStateVectors(data.initial_orbit.getRelativePositionAtUT(t), data.initial_orbit.getOrbitalVelocityAtUT(t) + DV.xzy, data.initial_orbit.referenceBody, t); orbit.StartUT = t; var pars = new PatchedConics.SolverParameters(); Vector3d pos; while(true) { Orbit next_orbit = new Orbit(); PatchedConics.CalculatePatch(orbit, next_orbit, orbit.StartUT, pars, null); if (orbit.EndUT > data.UT_arrival) { pos = orbit.getTruePositionAtUT(data.UT_arrival); Vector3d err = pos - data.pos_arrival; fi[0] = err.x; fi[1] = err.y; fi[2] = err.z; return; } // As of 0.25 CalculatePatch fails if the orbit does not change SoI if (next_orbit.referenceBody == null) { next_orbit.UpdateFromOrbitAtUT(orbit, orbit.StartUT + orbit.period, orbit.referenceBody); } orbit = next_orbit; } }
private Orbit createOrbitFromState(VesselState state) { var orbit = new Orbit(); orbit.UpdateFromStateVectors(Util.SwapYZ(state.position), Util.SwapYZ(state.velocity), state.referenceBody, state.time); var pars = new PatchedConics.SolverParameters(); pars.FollowManeuvers = false; PatchedConics.CalculatePatch(orbit, new Orbit(), state.time, pars, null); return orbit; }