public List <AtmosphericConditions> GetAtmosphericCurve(double dT, double endUT = -1) { if (!Body.atmosphere) { return(null); } var atmoR = Body.Radius + Body.atmosphereDepth; var startUT = StartPos.magnitude < atmoR? StartUT : TrajectoryCalculator.NearestRadiusUT(Orbit, atmoR, StartUT); if (endUT < 0) { endUT = BrakeEndUT; } if (startUT > endUT) { return(null); } var samples = (int)Math.Ceiling((endUT - startUT) / dT) + 1; var curve = new List <AtmosphericConditions>(samples); dT = (endUT - startUT) / samples; for (int i = 1; i <= samples; i++) { var cond = new AtmosphericConditions(Orbit, startUT + dT * i); cond.Duration = dT; curve.Add(cond); } return(curve); }
void update_from_orbit(Orbit orb, double UT) { //calculate the position of a landing site if (orb.ApA <= TargetAltitude) { AtTargetUT = orb.StartUT + (orb.ApAhead()? orb.timeToAp : 1); } else if (orb.PeA < TargetAltitude) { AtTargetUT = TrajectoryCalculator.NearestRadiusUT(orb, Body.Radius + TargetAltitude, UT); } else { AtTargetUT = orb.StartUT + orb.timeToPe; } TransferTime = AtTargetUT - StartUT; AtTargetPos = orb.getRelativePositionAtUT(AtTargetUT); AtTargetVel = orb.getOrbitalVelocityAtUT(AtTargetUT); var at_target_rot = TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToTarget); approach = new Coordinates((at_target_rot * (AtTargetPos - AtTargetVel * 10)).xzy + Body.position, Body); SurfacePoint = new WayPoint((at_target_rot * AtTargetPos).xzy + Body.position, Body); SurfacePoint.Pos.SetAlt2Surface(Body); SurfacePoint.Name = "Landing Site"; }
void update_from_orbit(Orbit orb, double UT) { //calculate the position of a landing site if (orb.ApA <= TargetAltitude) { AtTargetUT = orb.StartUT + (orb.ApAhead()? orb.timeToAp : 1); } else { AtTargetUT = TrajectoryCalculator.NearestRadiusUT(orb, Body.Radius + TargetAltitude, UT); } TransferTime = AtTargetUT - StartUT; AtTargetPos = orb.getRelativePositionAtUT(AtTargetUT); AtTargetVel = orb.getOrbitalVelocityAtUT(AtTargetUT); SurfacePoint = new WayPoint((TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToSurface) * AtTargetPos).xzy + Body.position, Body); SurfacePoint.Name = "Landing Site"; }
public double Altitude2UT(double altitude) { if (!HavePoints || altitude > Points[0].Altitude) { return(TrajectoryCalculator.NearestRadiusUT(Orbit, altitude + Orbit.referenceBody.Radius, StartUT)); } for (int i = 1, count = Points.Count; i < count; i++) { var p1 = Points[i]; if (p1.Altitude > altitude) { continue; } var p0 = Points[i - 1]; return(p0.UT + p0.Duration * (altitude - p0.Altitude) / (p1.Altitude - p0.Altitude)); } return(EndUT); }
void update_from_orbit() { AtTargetUT = Body.atmosphere && Orbit.altitude > Body.atmosphereDepth ? TrajectoryCalculator.NearestRadiusUT(Orbit, Body.Radius + Body.atmosphereDepth, StartUT) + 1 : StartUT; var end_alt = Math.Max(Orbit.PeA + 10, TargetAltitude); Path = new LandingPath(VSL, Orbit, end_alt, AtTargetUT, Math.Min(LandingTrajectoryAutopilot.C.AtmoTrajectoryResolution, Utils.ClampL((VSL.Altitude.Absolute - TargetAltitude) / Math.Abs(VSL.VerticalSpeed.Absolute) / 20, 0.1)), VSL.Physics.M - ManeuverFuel); update_overheat_info(Path, VSL.TCA.part.temperature); AtTargetVel = Path.LastPoint.vel; AtTargetPos = Path.LastPoint.pos; AtTargetUT = Path.LastPoint.UT; TransferTime = AtTargetUT - StartUT; update_landing_site(Path); }
public Point PointAtAltitude(double altitude) { if (!HavePoints || altitude > Points[0].Altitude) { return(newP(TrajectoryCalculator.NearestRadiusUT(Orbit, altitude + Orbit.referenceBody.Radius, StartUT))); } for (int i = 1, count = Points.Count; i < count; i++) { var p1 = Points[i]; if (p1.Altitude > altitude) { continue; } var p0 = Points[i - 1]; var p = p0; var t = (p0.Altitude - altitude) / (p0.Altitude - p1.Altitude); p.UT += p0.Duration * t; p.Duration = p1.UT - p.UT; p.pos = Vector3d.Lerp(p0.pos, p1.pos, t); p.Update(); return(p); } return(LastPoint); }
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); } }