public static double SuicideBurnCountdown(Orbit orbit, VesselState vesselState, Vessel vessel) { if (vesselState.mainBody == null) { return(0); } if (orbit.PeA > 0) { return(Double.PositiveInfinity); } double angleFromHorizontal = 90 - Vector3d.Angle(-vessel.srf_velocity, vesselState.up); angleFromHorizontal = MuUtils.Clamp(angleFromHorizontal, 0, 90); double sine = Math.Sin(angleFromHorizontal * Math.PI / 180); double g = vesselState.localg; double T = vesselState.limitedMaxThrustAccel; double effectiveDecel = 0.5 * (-2 * g * sine + Math.Sqrt((2 * g * sine) * (2 * g * sine) + 4 * (T * T - g * g))); double decelTime = vesselState.speedSurface / effectiveDecel; Vector3d estimatedLandingSite = vesselState.CoM + 0.5 * decelTime * vessel.srf_velocity; double terrainRadius = vesselState.mainBody.Radius + vesselState.mainBody.TerrainAltitude(estimatedLandingSite); double impactTime = 0; try { impactTime = orbit.NextTimeOfRadius(vesselState.time, terrainRadius); } catch (ArgumentException) { return(0); } return(impactTime - decelTime / 2 - vesselState.time); }
//Time during a's next orbit at which object a comes nearest to object b. //If a is hyperbolic, the examined interval is the next 100 units of mean anomaly. //This is quite a large segment of the hyperbolic arc. However, for extremely high //hyperbolic eccentricity it may not find the actual closest approach. public static double NextClosestApproachTime(this Orbit a, Orbit b, double UT) { double closestApproachTime = UT; double closestApproachDistance = Double.MaxValue; double minTime = UT; double interval = a.period; if (a.eccentricity > 1) { interval = 100 / a.MeanMotion(); //this should be an interval of time that covers a large chunk of the hyperbolic arc } double maxTime = UT + interval; const int numDivisions = 20; for (int iter = 0; iter < 8; iter++) { double dt = (maxTime - minTime) / numDivisions; for (int i = 0; i < numDivisions; i++) { double t = minTime + i * dt; double distance = a.Separation(b, t); if (distance < closestApproachDistance) { closestApproachDistance = distance; closestApproachTime = t; } } minTime = MuUtils.Clamp(closestApproachTime - dt, UT, UT + interval); maxTime = MuUtils.Clamp(closestApproachTime + dt, UT, UT + interval); } return(closestApproachTime); }