public static float BrakeDistancePrecise(float V0, VesselWrapper VSL, out float ttb) { ttb = 0f; var dist = 0f; var mass = VSL.Physics.M; var throttle = ThrottleControl.NextThrottle(V0, 1, mass, VSL.Engines.MaxThrustM, VSL.Engines.DecelerationTime10); float next_mass; float ttb_cur; while (V0 > 0.1) { throttle = ThrottleControl.NextThrottle(V0, throttle, mass, VSL.Engines.MaxThrustM, VSL.Engines.DecelerationTime10); ttb_cur = EnginesProps.TTB(V0 / 2, VSL.Engines.MaxThrustM, mass, VSL.Engines.MaxMassFlow, throttle, out next_mass); dist += BrakeDistance(V0, ttb_cur, VSL.Engines.MaxThrustM, mass, VSL.Engines.MaxMassFlow, throttle); ttb += ttb_cur; mass = next_mass; V0 /= 2; } throttle = ThrottleControl.NextThrottle(V0, throttle, mass, VSL.Engines.MaxThrustM, VSL.Engines.DecelerationTime10); ttb_cur = EnginesProps.TTB(V0, VSL.Engines.MaxThrustM, mass, VSL.Engines.MaxMassFlow, throttle, out next_mass); dist += BrakeDistance(V0, ttb_cur, VSL.Engines.MaxThrustM, mass, VSL.Engines.MaxMassFlow, throttle); ttb += ttb_cur; return(dist); }
public LandingPath(VesselWrapper vsl, Orbit orb, double target_altitude, double startUT, double dt, double start_mass, double fuel = 0, double brake_vel = 0) { VSL = vsl; Orbit = orb; TargetAltitude = target_altitude; StartUT = startUT; UT0 = VSL.Physics.UT; EndMass = start_mass; FuelUsed = 0; FuelLeft = fuel; BrakeDeltaV = brake_vel; if (Orbit.referenceBody.atmosphere || brake_vel > 0 && fuel > 0) { EndUT = startUT + orb.timeToPe; HavePoints = brake_vel > 0 && fuel > 0; var p = newP(StartUT); var m = start_mass; var s = Math.Max(VSL.Geometry.MinArea, VSL.Geometry.AreaWithBrakes); var ascending = p.Ascending; var orig_dt = dt; p.Duration = dt; while ((ascending || p.Altitude > TargetAltitude) && p.UT < EndUT) { var dAlt = p.Altitude - TargetAltitude; var linear_time = dAlt / p.SrfSpeed; if (!ascending && dt > 0.01 && linear_time / 2 < dt) { p.Duration = dt = linear_time / 2; } var drag_accel = p.SpecificDrag * s / m; var prev_alt = p.Altitude; Atmosphere |= drag_accel > 0; HavePoints |= Atmosphere; if (HavePoints) { if (Points.Count == 0) { FirstPointUT = p.UT; if (Atmosphere) { AtmoStartUT = p.UT; } } Points.Add(p); // VSL.Log("drag dV {}, m {}, fm {}, brake_vel {}, p {}", // drag_dv, m, fuel, brake_vel, p);//debug var r = p.pos.magnitude; if (p.HorSrfSpeed > 1 && brake_vel > 0 && fuel > 0) { //adjust dt to capture most of the thrust float mflow; var thrust = VSL.Engines.ThrustAtAlt((float)p.SrfSpeed, (float)p.Altitude, out mflow); var dV_cm = thrust / m * dt; if (dt > 0.01 && dV_cm > p.SrfSpeed / 10) { dt = p.SrfSpeed / 10 * m / thrust * 0.9; } //compute thrust direction var vV = Utils.ClampL(Vector3d.Dot(p.vel, p.pos / r), 1e-5); var b_dir = LandingTrajectoryAutopilot.CorrectedBrakeVelocity(VSL, p.vel, p.pos, p.DynamicPressure / 1000 / LandingTrajectoryAutopilot.C.MinDPressure, (p.Altitude - TargetAltitude) / vV).normalized; //compute change in velocity and mass var Ve = thrust / mflow; var dm = mflow * dt; if (dm > fuel) { dm = fuel; } var bV = (double)VSL.Engines.DeltaV(Ve, (float)dm); if (bV > brake_vel) { bV = brake_vel; dm = EnginesProps.FuelNeeded((float)bV, Ve, (float)m); } p.vel -= b_dir * bV; brake_vel -= bV; // VSL.Log("vV {}, vB {}, thrust {}, mflow {}, Ve {}, dm {}\nb_dir {}\nvel {}\npos {}", // vV, bV, thrust, mflow, Ve, dm, b_dir, p.vel, p.pos);//debug //spend fuel fuel -= dm; m -= dm; } //adjust dt if its too small else if (!ascending && dt < orig_dt && linear_time / 50 > dt) { dt = Math.Min(linear_time / 50, orig_dt); } if (Atmosphere) { p.vel -= p.srf_vel / p.SrfSpeed * Math.Min(drag_accel * dt, p.SrfSpeed); } p.vel -= p.pos * p.Body.gMagnitudeAtCenter / r / r / r * dt; p.pos += p.vel * dt; p.UT += dt; p.Update(); if (Atmosphere && AtmoStopUT < 0 && p.SrfSpeed < 10) { AtmoStopUT = p.UT; } } else { p.Update(p.UT + dt); } ascending &= p.Altitude > prev_alt; } if (HavePoints) { Points.Add(p); if (Atmosphere && AtmoStopUT < 0) { AtmoStopUT = p.UT; } } EndUT = p.UT; LastPoint = p; EndMass = m; FuelUsed = start_mass - m; FuelLeft = Math.Max(fuel, 0); if (brake_vel > 0) { BrakeDeltaV -= brake_vel; } } else { EndUT = TrajectoryCalculator.NearestRadiusUT(Orbit, Orbit.referenceBody.Radius + TargetAltitude, StartUT); LastPoint = newP(EndUT); } }