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);
        }
示例#2
0
        void update()
        {
            if (TransferTime < 0)
            {
                TrajectoryCalculator.ClosestApproach(Orbit, TargetOrbit, StartUT, VSL.Geometry.MinDistance, out AtTargetUT);
                TransferTime = AtTargetUT - StartUT;
            }
            else
            {
                AtTargetUT = StartUT + TransferTime;
            }
            AtTargetPos      = Orbit.getRelativePositionAtUT(AtTargetUT);
            AtTargetVel      = Orbit.getOrbitalVelocityAtUT(AtTargetUT);
            TargetPos        = TargetOrbit.getRelativePositionAtUT(AtTargetUT);
            DistanceToTarget = Utils.ClampL((AtTargetPos - TargetPos).magnitude - VSL.Geometry.MinDistance, 0);
            DeltaTA          = Utils.ProjectionAngle(AtTargetPos, TargetPos,
                                                     Vector3d.Cross(Orbit.GetOrbitNormal(), AtTargetPos)) *
                               Math.Sign(TargetOrbit.period - OrigOrbit.period);
            DeltaFi = TrajectoryCalculator.RelativeInclination(Orbit, TargetPos);
            DeltaR  = Vector3d.Dot(TargetPos - AtTargetPos, AtTargetPos.normalized);
            var t_orbit = Target.GetOrbit();
            var t_vel   = t_orbit != null?t_orbit.getOrbitalVelocityAtUT(AtTargetUT) : Vector3d.zero;

            BrakeDeltaV   = t_vel - Orbit.getOrbitalVelocityAtUT(AtTargetUT);
            BrakeDuration = VSL.Engines.TTB((float)BrakeDeltaV.magnitude);
            KillerOrbit   = Orbit.PeR < MinPeR && Orbit.timeToPe < TransferTime;
//            Utils.Log("{}", this);//debug
        }
        void update()
        {
            if (TransferTime < 0)
            {
                TrajectoryCalculator.ClosestApproach(Orbit, TargetOrbit, StartUT, VSL.Geometry.MinDistance, out AtTargetUT);
                TransferTime = AtTargetUT - StartUT;
            }
            else
            {
                AtTargetUT = StartUT + TransferTime;
            }
            var obt     = TrajectoryCalculator.NextOrbit(Orbit, AtTargetUT);
            var t_orbit = TrajectoryCalculator.NextOrbit(TargetOrbit, AtTargetUT);

            AtTargetPos      = obt.getRelativePositionAtUT(AtTargetUT);
            AtTargetVel      = obt.getOrbitalVelocityAtUT(AtTargetUT);
            TargetPos        = TrajectoryCalculator.RelativePosAtUT(obt.referenceBody, t_orbit, AtTargetUT);
            AtTargetRelPos   = AtTargetPos - TargetPos;
            DistanceToTarget = AtTargetRelPos.magnitude - VSL.Geometry.MinDistance;
            DirectHit        = DistanceToTarget < 1;
            DistanceToTarget = Utils.ClampL(DistanceToTarget, 0);
            BrakeDeltaV      = t_orbit.GetFrameVelAtUT(AtTargetUT) - obt.GetFrameVelAtUT(AtTargetUT);
            var brake_dV = (float)BrakeDeltaV.magnitude;

            BrakeDuration = VSL.Engines.TTB_Precise(brake_dV);
            BrakeFuel     = VSL.Engines.FuelNeeded(brake_dV);
            FullBrake     = GetTotalFuel() < VSL.Engines.AvailableFuelMass;
            //check if this trajectory is too close to any of celestial bodies it passes by
            KillerOrbit = TransferTime < BrakeDuration + ManeuverDuration;
            update_killer(OrigOrbit, StartUT);
            update_killer(Orbit, AtTargetUT);
//            Utils.Log("{}", this);//debug
        }
        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";
        }
		public bool GravityTurn(double ApA_offset, double gturn_curve, double dist2vel, double Dtol)
		{
			UpdateTargetPosition();
			VSL.Engines.ActivateNextStageOnFlameout();
			dApA = TargetR-VesselOrbit.ApR;
			var vel  = Vector3d.zero;
			var cApV = VesselOrbit.getRelativePositionAtUT(VSL.Physics.UT+VesselOrbit.timeToAp);
			var hv   = Vector3d.Exclude(VesselOrbit.pos, target-VesselOrbit.pos).normalized;
			var arc  = Utils.ProjectionAngle(cApV, target, hv)*Mathf.Deg2Rad*cApV.magnitude;
			ErrorThreshold.Value = CorrectOnlyAltitude? dApA : dApA+arc;
			ApoapsisReached |= dApA < Dtol;
			THR.CorrectThrottle = ApoapsisReached;
			if(!ErrorThreshold)
			{
				var startF = Utils.Clamp((VSL.Altitude.Absolute-GravityTurnStart)/GLB.ORB.GTurnOffset, 0, 1);
				if(dApA > Dtol)
					vel += CorrectOnlyAltitude && ApoapsisReached? 
						VesselOrbit.vel.normalized.xzy*dApA :
						VSL.Physics.Up.xzy*dApA*gturn_curve;
				if(arc > Dtol && (!ApoapsisReached || !CorrectOnlyAltitude))
				{
					var hvel = Utils.ClampL(arc-dApA*gturn_curve, 0)*startF;
					if(Body.atmosphere) hvel *= Math.Sqrt(Utils.Clamp(VSL.Altitude.Absolute/Body.atmosphereDepth, 0, 1));
					vel += hv*hvel;
				}
				vel *= VSL.Physics.StG/Utils.G0*dist2vel;
				if(!vel.IsZero())
				{
					var norm = VesselOrbit.GetOrbitNormal();
					var dFi = (90-Vector3d.Angle(norm, target))*Mathf.Deg2Rad;
					vel += norm*Math.Sin(dFi)*vel.magnitude*startF
						*Utils.Clamp(VSL.VerticalSpeed.Absolute/VSL.Physics.G-MinClimbTime, 0, 100)
						*Utils.ClampL(Vector3d.Dot(hv, VesselOrbit.vel.normalized), 0);
				}
				vel = vel.xzy;
				CircularizationOffset = -1;
				if(Executor.Execute(vel, Utils.Clamp(1-VSL.Torque.MaxCurrent.AA_rad, 0.1f, 1)))
				{
					if(CFG.AT.Not(Attitude.KillRotation)) 
					{
						CFG.BR.OnIfNot(BearingMode.Auto);
						BRC.ForwardDirection = hv.xzy;
					}
					Status("Gravity turn...");
					return true;
				}
			}
			Status("Coasting...");
			CFG.BR.OffIfOn(BearingMode.Auto);
			CFG.AT.OnIfNot(Attitude.KillRotation);
			THR.Throttle = 0;
			if(CircularizationOffset < 0)
			{
				ApAUT = VSL.Physics.UT+VesselOrbit.timeToAp;
				CircularizationOffset = VSL.Engines.TTB((float)TrajectoryCalculator.dV4C(VesselOrbit, hV(ApAUT), ApAUT).magnitude)/2;
			}
			return VesselOrbit.timeToAp > ApA_offset+CircularizationOffset &&
				Body.atmosphere && VesselOrbit.radius < Body.Radius+Body.atmosphereDepth;
		}
示例#6
0
        void update_landing_site(LandingPath path)
        {
            var at_target_rot = TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToTarget);

            approach     = new Coordinates((at_target_rot * path.PointAtUT(path.EndUT - 1).pos).xzy + Body.position, Body);
            SurfacePoint = new WayPoint((at_target_rot * AtTargetPos).xzy + Body.position, Body);
            SurfacePoint.Pos.SetAlt2Surface(Body);
            SurfacePoint.Name = "Landing Site";
        }
        protected override void Update()
        {
            if (!IsActive)
            {
                return;
            }
            Vector3 dV;

            if (CFG.AP1[Autopilot1.MatchVel])
            {
                dV = CFG.Target.GetObtVelocity() - VSL.vessel.obt_velocity;
                VSL.Engines.RequestClusterActivationForManeuver(dV);
                Executor.Execute(dV, GLB.THR.MinDeltaV);
            }
            else
            {
                double ApprUT;
                var    tOrb = CFG.Target.GetOrbit();
                var    dist = TrajectoryCalculator.NearestApproach(VSL.orbit, tOrb, VSL.Physics.UT, VSL.Geometry.MinDistance + 10, out ApprUT);
                TTA = (float)(ApprUT - VSL.Physics.UT);
                switch (stage)
                {
                case Stage.Start:
                    if (dist > MVA.MaxApproachDistance)
                    {
                        Status(string.Format("<color=yellow>WARNING:</color> Nearest approach distance is <color=magenta><b>{0}</b></color>\n" +
                                             "<color=red><b>Push to proceed. At your own risk.</b></color>",
                                             Utils.formatBigValue((float)dist, "m")));
                        stage = Stage.Wait;
                        goto case Stage.Wait;
                    }
                    stage = Stage.Brake;
                    goto case Stage.Brake;

                case Stage.Wait:
                    if (!string.IsNullOrEmpty(TCAGui.StatusMessage))
                    {
                        break;
                    }
                    stage = Stage.Brake;
                    goto case Stage.Brake;

                case Stage.Brake:
                    dV = (tOrb.getOrbitalVelocityAtUT(ApprUT) - VSL.orbit.getOrbitalVelocityAtUT(ApprUT)).xzy;
                    VSL.Engines.RequestClusterActivationForManeuver(dV);
                    if (Executor.Execute(dV, GLB.THR.MinDeltaV, StartCondition))
                    {
                        break;
                    }
                    reset();
                    break;
                }
            }
        }
示例#8
0
            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
            }
示例#9
0
        protected override void Update()
        {
            Vector3 dV;

            if (CFG.AP1[Autopilot1.MatchVel])
            {
                Working = true;
                dV      = CFG.Target.GetObtVelocity() - VSL.vessel.obt_velocity;
                if (!Executor.Execute(dV, MinDeltaV))
                {
                    Executor.Reset();
                }
            }
            else
            {
                var tOrb = CFG.Target.GetOrbit();
                var dist = Working? 0 :
                           TrajectoryCalculator.NearestApproach(VSL.orbit, tOrb, VSL.Physics.UT, VSL.Geometry.MinDistance + 10, out ApprUT);
                TTA = (float)(ApprUT - VSL.Physics.UT);
                switch (stage)
                {
                case Stage.Start:
                    if (dist > C.MaxApproachDistance)
                    {
                        Status(Colors.Warning.Tag("WARNING: ") +
                               "Nearest approach distance is " +
                               Colors.Selected2.Tag("<b>{0}</b>\n") +
                               Colors.Danger.Tag("<b>Push to proceed. At your own risk.</b>"),
                               Utils.formatBigValue((float)dist, "m"));
                        stage = Stage.Wait;
                        goto case Stage.Wait;
                    }
                    stage = Stage.Brake;
                    goto case Stage.Brake;

                case Stage.Wait:
                    if (!string.IsNullOrEmpty(TCAGui.StatusMessage))
                    {
                        break;
                    }
                    stage = Stage.Brake;
                    goto case Stage.Brake;

                case Stage.Brake:
                    dV = (TrajectoryCalculator.NextOrbit(tOrb, ApprUT).GetFrameVelAtUT(ApprUT) - VSL.orbit.GetFrameVelAtUT(ApprUT)).xzy;
                    if (!Executor.Execute(dV, MinDeltaV, StartCondition))
                    {
                        Reset();
                    }
                    break;
                }
            }
        }
 protected BaseTrajectory(VesselWrapper vsl, Vector3d dV, double startUT)
 {
     VSL              = vsl;
     ManeuverDeltaV   = dV;
     ManeuverDuration = VSL.Engines.TTB((float)ManeuverDeltaV.magnitude);
     StartUT          = startUT;
     TimeToStart      = startUT - VSL.Physics.UT;
     Body             = VSL.vessel.orbitDriver.orbit.referenceBody;
     OrigOrbit        = VSL.vessel.orbitDriver.orbit;
     Orbit            = TrajectoryCalculator.NewOrbit(OrigOrbit, ManeuverDeltaV, StartUT);
     StartPos         = Orbit.getRelativePositionAtUT(StartUT);
     StartVel         = Orbit.getOrbitalVelocityAtUT(StartUT);
 }
 protected bool coast(Vector3d pg_vel)
 {
     Status("Coasting...");
     CFG.BR.OffIfOn(BearingMode.Auto);
     CFG.AT.OnIfNot(Attitude.Custom);
     ATC.SetThrustDirW(-pg_vel.xzy);
     THR.Throttle = 0;
     if (CircularizationOffset < 0)
     {
         ApAUT = VSL.Physics.UT + VesselOrbit.timeToAp;
         CircularizationOffset = VSL.Engines.TTB_Precise((float)TrajectoryCalculator.dV4C(VesselOrbit, hV(ApAUT), ApAUT).magnitude) / 2;
     }
     return(VesselOrbit.timeToAp > TimeToApA + CircularizationOffset &&
            Body.atmosphere && VesselOrbit.radius < Body.Radius + Body.atmosphereDepth);
 }
 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";
 }
示例#13
0
 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);
 }
示例#14
0
        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);
        }
 void update(bool with_brake)
 {
     update_from_orbit(Orbit, StartUT);
     //correct for brake maneuver
     if (with_brake)
     {
         BrakeEndUT    = AtTargetUT - GLB.LTRJ.CorrectionOffset;
         BrakeStartUT  = BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)AtTargetVel.magnitude, VSL, out BrakeDuration);
         brake_delta_v = -0.9 * Orbit.getOrbitalVelocityAtUT(BrakeEndUT);
         update_from_orbit(TrajectoryCalculator.NewOrbit(Orbit, BrakeDeltaV, BrakeEndUT), BrakeEndUT);
     }
     else
     {
         brake_delta_v = -(AtTargetVel + Vector3d.Cross(Body.zUpAngularVelocity, AtTargetPos));
         BrakeEndUT    = TrajectoryCalculator.FlyAboveUT(Orbit, Target.RelSurfPos(Body).xzy, StartUT);
         BrakeStartUT  = BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration);
     }
     //compute vessel coordinates at maneuver start
     if (VSL.LandedOrSplashed)
     {
         VslStartLat = Utils.ClampAngle(VSL.vessel.latitude);
         VslStartLon = Utils.ClampAngle(VSL.vessel.longitude);
     }
     else
     {
         var start_pos = (TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToStart) * StartPos).xzy + Body.position;
         VslStartLat = Utils.ClampAngle(Body.GetLatitude(start_pos));
         VslStartLon = Utils.ClampAngle(Body.GetLongitude(start_pos));
     }
     //compute distance to target
     DistanceToTarget = Target.AngleTo(SurfacePoint) * Body.Radius;
     BrakeEndDeltaAlt = Orbit.getRelativePositionAtUT(BrakeEndUT).magnitude - Body.Radius - TargetAltitude;
     //compute distance in lat-lon coordinates
     DeltaLat = Utils.AngleDelta(SurfacePoint.Pos.Lat, Target.Pos.Lat) *
                Math.Sign(Utils.AngleDelta(Utils.ClampAngle(VslStartLat), SurfacePoint.Pos.Lat));
     DeltaLon = Utils.AngleDelta(SurfacePoint.Pos.Lon, Target.Pos.Lon) *
                Math.Sign(Utils.AngleDelta(Utils.ClampAngle(VslStartLon), SurfacePoint.Pos.Lon));
     //compute distance in radial coordinates
     DeltaFi = 90 - Vector3d.Angle(Orbit.GetOrbitNormal(),
                                   TrajectoryCalculator.BodyRotationAtdT(Body, TimeToSurface) *
                                   Body.GetRelSurfacePosition(Target.Pos.Lat, Target.Pos.Lon, TargetAltitude).xzy);
     DeltaR = Utils.RadDelta(SurfacePoint.AngleTo(VslStartLat, VslStartLon), Target.AngleTo(VslStartLat, VslStartLon)) * Mathf.Rad2Deg;
 }
示例#16
0
        public Point FlyAbovePoint(Vector3d pos)
        {
            if (Utils.ProjectionAngle(Orbit.getRelativePositionAtUT(StartUT), pos,
                                      Orbit.getOrbitalVelocityAtUT(StartUT)) < 0)
            {
                return(newP(StartUT));
            }
            if (!HavePoints ||
                Utils.ProjectionAngle(Orbit.getRelativePositionAtUT(AtmoStartUT),
                                      TrajectoryCalculator.BodyRotationAtdT(Orbit.referenceBody, AtmoStartUT - UT0) * pos,
                                      Orbit.getOrbitalVelocityAtUT(AtmoStartUT)) < 0)
            {
                return(newP(TrajectoryCalculator.FlyAboveUT(Orbit, pos, StartUT)));
            }
            var p0     = Points[0];
            var angle0 = Utils.ProjectionAngle(p0.pos,
                                               TrajectoryCalculator
                                               .BodyRotationAtdT(Orbit.referenceBody, p0.UT - UT0) * pos,
                                               p0.vel);

            for (int i = 1, count = Points.Count; i < count; i++)
            {
                var p1     = Points[i];
                var angle1 = Utils.ProjectionAngle(p1.pos,
                                                   TrajectoryCalculator
                                                   .BodyRotationAtdT(Orbit.referenceBody, p1.UT - UT0) * pos,
                                                   p1.vel);
                if (angle1 > 0)
                {
                    angle0 = angle1;
                    continue;
                }
                p0 = Points[i - 1];
                var p = p0;
                var t = angle0 / (angle0 - angle1);
                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);
        }
示例#17
0
            public void Update()
            {
                Altitude    = pos.magnitude - Body.Radius;
                Atmosphere  = Body.atmosphere && Altitude < Body.atmosphereDepth;
                rel_pos     = Body.BodyFrame.WorldToLocal(TrajectoryCalculator.BodyRotationAtdT(Body, Path.UT0 - UT) * pos);
                srf_vel     = vel + Vector3d.Cross(Body.zUpAngularVelocity, pos);
                HorSrfSpeed = Vector3d.Exclude(rel_pos, srf_vel).magnitude;
                SrfSpeed    = srf_vel.magnitude;

                if (Atmosphere)
                {
                    Pressure = Body.GetPressure(Altitude);
                    AtmosphereTemperature = Body.GetTemperature(Altitude);
                    Density = Body.GetDensity(Pressure, AtmosphereTemperature);
                    Mach1   = Body.GetSpeedOfSound(Pressure, Density);

                    var Rho_v = Density * SrfSpeed;
                    DynamicPressure = Rho_v * SrfSpeed / 2;
                    Mach            = SrfSpeed / Mach1;
                    SpecificDrag    = AtmoSim.Cd * DynamicPressure *
                                      PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, VSL.OnPlanetParams.DragCurveK, (float)Mach) *
                                      PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)(Rho_v));

                    var convectiveMachLerp = Math.Pow(UtilMath.Clamp01((Mach - PhysicsGlobals.NewtonianMachTempLerpStartMach) /
                                                                       (PhysicsGlobals.NewtonianMachTempLerpEndMach - PhysicsGlobals.NewtonianMachTempLerpStartMach)),
                                                      PhysicsGlobals.NewtonianMachTempLerpExponent);
                    ShockTemperature = SrfSpeed * PhysicsGlobals.NewtonianTemperatureFactor;
                    if (convectiveMachLerp > 0.0)
                    {
                        double b = PhysicsGlobals.MachTemperatureScalar * Math.Pow(SrfSpeed, PhysicsGlobals.MachTemperatureVelocityExponent);
                        ShockTemperature = UtilMath.LerpUnclamped(ShockTemperature, b, convectiveMachLerp);
                    }
                    ShockTemperature *= (double)HighLogic.CurrentGame.Parameters.Difficulty.ReentryHeatScale * Body.shockTemperatureMultiplier;
                    ShockTemperature  = Math.Max(AtmosphereTemperature, ShockTemperature);
                    //calculate convective coefficient for speed > Mach1; lower speed is not a concern
                    ConvectiveCoefficient  = 1E-10 * PhysicsGlobals.MachConvectionFactor;
                    ConvectiveCoefficient *= Density > 1 ? Density : Math.Pow(Density, PhysicsGlobals.MachConvectionDensityExponent);
                    ConvectiveCoefficient *= Math.Pow(SrfSpeed, PhysicsGlobals.MachConvectionVelocityExponent) * Body.convectionMultiplier;
                }
            }
        void update()
        {
            if (TransferTime < 0)
            {
                TrajectoryCalculator.ClosestApproach(Orbit, TargetOrbit, StartUT, out AtTargetUT);
                TransferTime = AtTargetUT - StartUT;
            }
            else
            {
                AtTargetUT = StartUT + TransferTime;
            }
            AtTargetPos      = Orbit.getRelativePositionAtUT(AtTargetUT);
            AtTargetVel      = Orbit.getOrbitalVelocityAtUT(AtTargetUT);
            TargetPos        = TargetOrbit.getRelativePositionAtUT(AtTargetUT);
            DistanceToTarget = Utils.ClampL((AtTargetPos - TargetPos).magnitude - VSL.Geometry.R - TargetVessel.Radius(), 0);
            DeltaTA          = Utils.ProjectionAngle(AtTargetPos, TargetPos,
                                                     Vector3d.Cross(Orbit.GetOrbitNormal(), AtTargetPos)) *
                               Math.Sign(TargetOrbit.period - OrigOrbit.period);
            DeltaFi     = TrajectoryCalculator.RelativeInclination(Orbit, TargetPos);
            DeltaR      = Vector3d.Dot(TargetPos - AtTargetPos, AtTargetPos.normalized);
            KillerOrbit = Orbit.PeR < MinPeR && Orbit.timeToPe < TransferTime;
//			DebugUtils.Log("{}", this);//debug
        }
 private bool update_maneuver_node()
 {
     Node        = null;
     NodeCB      = null;
     TargetOrbit = null;
     if (Solver != null)
     {
         if (Solver.maneuverNodes.Count <= 0)
         {
             return(false);
         }
         Node = Solver.maneuverNodes[0];
     }
     else
     {
         if (VSL.vessel.flightPlanNode.nodes.Count <= 0)
         {
             return(false);
         }
         var node = VSL.vessel.flightPlanNode.nodes[0];
         Node = new ManeuverNode();
         Node.Load(node);
         Node.patch     = new Orbit(VSL.orbit);
         Node.nextPatch =
             TrajectoryCalculator.NewOrbit(VSL.orbit, Utils.Node2OrbitalDeltaV(Node), Node.UT);
         VSL.vessel.flightPlanNode.RemoveNode(node);
     }
     NodeCB      = Node.patch.referenceBody;
     TargetOrbit = Node.nextPatch;
     update_node_deltaV();
     if (VSL.Engines.MaxDeltaV < Node.DeltaV.magnitude)
     {
         Status(Colors.Warning,
                "WARNING: there may be not enough propellant for the maneuver");
     }
     return(true);
 }
        bool StartCondition(float dV)
        {
            if (Working)
            {
                return(true);
            }
            if (!CFG.AP1[Autopilot1.MatchVelNear])
            {
                return(true);
            }
            //calculate time to nearest approach
            double ApprUT;
            var    tOrb = Target.GetOrbit();

            TrajectoryCalculator.ClosestApproach(VSL.orbit, tOrb, VSL.Physics.UT, out ApprUT);
            TTA = (float)(ApprUT - VSL.Physics.UT);
            var ApprdV = (VSL.orbit.getOrbitalVelocityAtUT(ApprUT) - tOrb.getOrbitalVelocityAtUT(ApprUT)).xzy;

            dV = (float)ApprdV.magnitude;
            CFG.AT.OnIfNot(Attitude.Custom);
            ATC.SetThrustDirW(ApprdV);
            if (TTA > 0)
            {
                VSL.Info.Countdown = TTA - BrakingOffset(dV, VSL, out VSL.Info.TTB);
                if (VSL.Controls.CanWarp)
                {
                    VSL.Controls.WarpToTime = VSL.Physics.UT + VSL.Info.Countdown - VSL.Controls.MinAlignmentTime;
                }
                if (VSL.Info.Countdown > 0)
                {
                    return(false);
                }
            }
            VSL.Info.Countdown = 0;
            Working            = true;
            return(true);
        }
示例#21
0
 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);
 }
        protected BaseTrajectory(VesselWrapper vsl, Vector3d dV, double startUT)
        {
            VSL = vsl;
            var dVm = (float)dV.magnitude;

            ManeuverDeltaV = dV;
            if (dVm > 0)
            {
                ManeuverFuel     = VSL.Engines.FuelNeeded(dVm);
                NotEnoughFuel    = ManeuverFuel > VSL.Engines.GetAvailableFuelMass();
                ManeuverDuration = VSL.Engines.TTB(dVm);
            }
            else
            {
                ManeuverFuel     = 0;
                ManeuverDuration = 0;
            }
            StartUT   = startUT;
            Body      = VSL.vessel.orbitDriver.orbit.referenceBody;
            OrigOrbit = VSL.vessel.orbitDriver.orbit;
            Orbit     = TrajectoryCalculator.NewOrbit(OrigOrbit, ManeuverDeltaV, StartUT);
            StartPos  = Orbit.getRelativePositionAtUT(StartUT);
            StartVel  = Orbit.getOrbitalVelocityAtUT(StartUT);
        }
示例#23
0
 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);
     }
 }
        void update(bool with_brake)
        {
            update_from_orbit(Orbit, StartUT);
            LandingAngle = 90 - Vector3d.Angle(AtTargetPos, -AtTargetVel);
            //correct for brake maneuver
            if (with_brake)
            {
                //estimate time needed to rotate the ship downwards
                var rotation_time = VSL.Torque.NoEngines?
                                    VSL.Torque.NoEngines.MinRotationTime(90) :
                                    VSL.Torque.MaxPossible.RotationTime(90, 0.1f);
                //estimate amount fuel needed for the maneuver
                var vertical_vel = Vector3d.Project(AtTargetVel, AtTargetPos);
                SetBrakeEndUT(Math.Max(AtTargetUT - GLB.LTRJ.CorrectionOffset + rotation_time, StartUT));
                SetBrakeDeltaV(vertical_vel);
                if (BrakeFuel > 0)
                {
                    //calculate braking maneuver
                    var dV = (float)BrakeDeltaV.magnitude;
                    BrakeDuration  = VSL.Engines.AntigravTTB(dV);
                    BrakeDuration += rotation_time;
                    //find the appropriate point to perform the maneuver
                    var    brake_end_UT   = Math.Max(AtTargetUT - Mathf.Max(GLB.LTRJ.CorrectionOffset, BrakeDuration * 1.1f), StartUT);
                    var    vertical_speed = vertical_vel.magnitude;
                    double fly_over_error;
                    do
                    {
                        SetBrakeEndUT(brake_end_UT);
                        fly_over_error = BrakeEndDeltaAlt - GLB.LTRJ.FlyOverAlt;
                        brake_end_UT  -= Math.Abs(fly_over_error / vertical_speed);
                    } while(brake_end_UT > StartUT && fly_over_error < -1);
                    SetBrakeDeltaV(-0.9 * Orbit.getOrbitalVelocityAtUT(BrakeEndUT));
                    //calculate maneuver start time and update landing site
                    BrakeStartUT = Math.Max(BrakeEndUT - MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration), StartUT);
                    update_from_orbit(TrajectoryCalculator.NewOrbit(Orbit, BrakeDeltaV, BrakeEndUT), BrakeEndUT);
                }
                else
                {
                    BrakeStartUT  = BrakeEndUT;
                    BrakeDuration = 0;
                }
            }
            else
            {
                SetBrakeEndUT(TrajectoryCalculator.FlyAboveUT(Orbit, Target.RelOrbPos(Body), StartUT));
                SetBrakeDeltaV(-(AtTargetVel + Vector3d.Cross(Body.zUpAngularVelocity, AtTargetPos)));
                if (BrakeFuel > 0)
                {
                    var offset = MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration);
                    BrakeStartUT = Math.Max(BrakeEndUT - offset, StartUT);
                }
                else
                {
                    BrakeStartUT  = BrakeEndUT;
                    BrakeDuration = 0;
                }
            }
            BrakeOffset = (float)Utils.ClampL(BrakeEndUT - BrakeStartUT, 0);
            //compute vessel coordinates at maneuver start
            if (VSL.LandedOrSplashed)
            {
                VslStartLat = Utils.ClampAngle(VSL.vessel.latitude);
                VslStartLon = Utils.ClampAngle(VSL.vessel.longitude);
            }
            else
            {
                var start_pos = (TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToStart) * StartPos).xzy + Body.position;
                VslStartLat = Utils.ClampAngle(Body.GetLatitude(start_pos));
                VslStartLon = Utils.ClampAngle(Body.GetLongitude(start_pos));
            }
            //compute distance to target
            DistanceToTarget   = Target.AngleTo(SurfacePoint) * Body.Radius;
            SurfacePoint.Name += string.Format("\n{0} from target", Utils.formatBigValue((float)DistanceToTarget, "m"));
            //compute distance in lat-lon coordinates
            DeltaLat = Utils.AngleDelta(SurfacePoint.Pos.Lat, Target.Pos.Lat) *
                       Math.Sign(Utils.AngleDelta(approach.Lat, SurfacePoint.Pos.Lat));
            DeltaLon = Utils.AngleDelta(SurfacePoint.Pos.Lon, Target.Pos.Lon) *
                       Math.Sign(Utils.AngleDelta(approach.Lon, SurfacePoint.Pos.Lon));
            //compute distance in radial coordinates
            DeltaFi = 90 - Vector3d.Angle(Orbit.GetOrbitNormal(),
                                          TrajectoryCalculator.BodyRotationAtdT(Body, TimeToTarget) *
                                          Body.GetRelSurfacePosition(Target.Pos.Lat, Target.Pos.Lon, TargetAltitude).xzy);
            DeltaR = Utils.RadDelta(SurfacePoint.AngleTo(VslStartLat, VslStartLon), Target.AngleTo(VslStartLat, VslStartLon)) * Mathf.Rad2Deg;
//            Utils.Log("{}", this);//debug
        }
        public IEnumerable <double> FromSurfaceTTA(float ApA_offset, double ApA, double alpha, float maxG, float angularV)
        {
            //Log("FromSurfaceTTA: ApA_offset {}, ApA {}, alpha {}, maxG {}, angularV {}",
            //ApA_offset, ApA, alpha*Mathf.Rad2Deg, maxG, angularV*Mathf.Rad2Deg);//debug
            var    t            = 0.0;
            var    BR           = Body.Radius;
            var    ApR          = BR + ApA;
            var    v            = new Vector2d(1e-3, 1e-3);
            var    r0n          = new Vector2d(0, 1);
            var    r            = new Vector2d(0, VSL.orbit.radius);
            var    r1n          = new Vector2d(Math.Sin(alpha), Math.Cos(alpha));
            var    r1           = r1n * ApR;
            var    T            = new Vector2d(0, 1);
            var    m            = (double)VSL.Physics.M;
            var    m0           = m;
            var    mT           = eStats.MaxThrust;
            var    mTm          = mT.magnitude;
            var    mflow        = eStats.MaxMassFlow;
            var    AA           = eStats.TorqueInfo.AA_rad;
            var    s            = VSL.Geometry.AreaInDirection(mT);
            var    thrust       = true;
            var    R            = r.magnitude;
            var    prev_r       = r;
            var    maxR         = ApR * 2;
            double turn_start   = VSL.Altitude.Absolute;
            bool   turn_started = false;
            Orbit  obt          = null;

            while (R > BR && R < maxR &&
                   Utils.Angle2(r0n, r1n) > Utils.Angle2(r0n, r))
            {
                yield return(-1);

                prev_r = r;
                R      = r.magnitude;
                var    h = R - BR;
                double time2ApA;
                var    ApV = getApV(m, s, r, v, C.DeltaTime * 4, out time2ApA);
                thrust &= Vector2d.Dot(ApV - r1, r1 - r) < 0;
                var srf_dir = -r.Rotate90().normalized;
                var thr     = thrust ? max_G_throttle((float)Vector2d.Dot(T, r.normalized), m, maxG) : 0;
                var nV      = v;
                if (thrust &&
                    Vector2d.Dot(r.normalized, v) / VSL.Physics.StG > ToOrbitExecutor.C.MinClimbTime)
                {
                    var rr1 = r1 - r;
                    solver.Init(Body, r, v, r1);
                    var minT = solver.ParabolicTime;
                    var maxT = solver.MinEnergyTime;
                    nV = solver.dV4TransferME();
                    while (maxT - minT > 0.1)
                    {
                        var curT = (maxT + minT) / 2;
                        nV  = solver.dV4Transfer(curT);
                        obt = TrajectoryCalculator.NewOrbit(Body, r, v + nV, VSL.Physics.UT, obt);
                        if (obt.timeToAp > curT)
                        {
                            minT = curT;
                        }
                        else
                        {
                            maxT = curT;
                        }
                    }
                    var neededAoA = Utils.ClampH(Utils.Angle2(rr1, r) / 2, 45);
                    var angle2Hor = 90 - Utils.Angle2(nV, r);
                    var AoA       = Utils.Angle2(r, v);
                    pitch.Max = AoA < neededAoA ? 0 : (float)AoA;
                    pitch.Update((float)angle2Hor);
                    correction_started.Update(angle2Hor >= 0);
                    if (AoA < neededAoA && !correction_started)
                    {
                        pitch.Action = (float)Utils.Clamp(AoA - neededAoA + angle2Hor,
                                                          -AttitudeControlBase.C.MaxAttitudeError,
                                                          AoA);
                    }
                    if (!turn_started && h < Body.atmosphereDepth)
                    {
                        var atm = Body.AtmoParamsAtAltitude(h);
                        if (atm.Rho > ToOrbitExecutor.C.AtmDensityOffset)
                        {
                            turn_start = h;
                        }
                        else
                        {
                            turn_started = true;
                        }
                    }
                    var startF = Utils.Clamp((h - turn_start) / ApA / ToOrbitExecutor.C.GTurnOffset, 0, 1);
                    var nT     = v.Rotate(pitch.Action * startF);
                    var atErr  = Utils.Angle2Rad(r, T) - Utils.Angle2Rad(r, nT);
                    T = T.RotateRad(atErr /
                                    Math.Max(C.DeltaTime,
                                             eStats.TorqueInfo.RotationTime3Phase((float)Math.Abs(atErr * Mathf.Rad2Deg),
                                                                                  (float)(AA * m0 / m),
                                                                                  C.RotAccelPhase,
                                                                                  1)) *
                                    C.DeltaTime)
                        .normalized;
                    if (Vector2d.Dot(T, r) < 0)
                    {
                        T = srf_dir;
                    }
                    throttle_correction.Update((float)angle2Hor);
                    throttle.Update(ApA_offset + throttle_correction.Action - (float)time2ApA);
                    thr = Utils.ClampH(0.5f + throttle, thr);
                }
                if (thrust && thr > 0)
                {
                    if (!CheatOptions.InfinitePropellant)
                    {
                        var dm = mflow * thr * C.DeltaTime;
                        if (m < dm)
                        {
                            thrust = false;
                        }
                        else
                        {
                            m -= dm;
                        }
                    }
                    if (thrust)
                    {
                        v += T * mTm / m * thr * C.DeltaTime;
                    }
                }
                v -= r * Body.gMagnitudeAtCenter / R / R / R * C.DeltaTime;
                if (h < Body.atmosphereDepth)
                {
                    var vm = v.magnitude;
                    if (vm > 0)
                    {
                        v -= v / vm * drag(s, h, vm) / m * C.DeltaTime;
                    }
                }
                r  += v * C.DeltaTime;
                r1n = r1n.RotateRad(angularV * C.DeltaTime).normalized;
                r1  = r1n * ApR;
                t  += C.DeltaTime;
                //DebugUtils.CSV("ToOrbitSim.csv", t, r);//debug
                //DebugUtils.CSV("ToOrbitSim.csv", t, r, v, rel_v, T*mTm/m*thr, h, m, thr, r1, nV);//debug
            }
            //Log("TimeToApA: {}", t);//debug
            yield return(t);
        }
示例#26
0
        void update(bool with_brake, bool brake_at_fly_above)
        {
            reset();
            //update everything
            update_from_orbit();
            update_landing_steepness();
            ActualLandingAngle = 90 - Utils.Angle2(AtTargetPos, -AtTargetVel);
            var AerobrakeStartUT = Path.Atmosphere ? Path.AtmoStartUT : AtTargetUT - 1;

            //correct for brake maneuver
            if (with_brake)
            {
                //estimate time needed to rotate the ship downwards
                var rotation_time = VSL.Torque.NoEngines ?
                                    VSL.Torque.NoEngines.RotationTime2Phase(90) :
                                    VSL.Torque.MaxPossible.RotationTime2Phase(90, 0.1f);
                //estimate amount of fuel needed for the maneuver
                var vertical_vel = Vector3d.Project(AtTargetVel, AtTargetPos);
                SetBrakeEndUT(Math.Max(AtTargetUT - LandingTrajectoryAutopilot.C.CorrectionOffset + rotation_time, StartUT));
                SetBrakeDeltaV(vertical_vel);
                if (BrakeFuel > 0)
                {
                    //calculate braking maneuver
                    BrakeDuration = VSL.Engines.OnPlanetTTB(BrakeDeltaV,
                                                            Orbit.getRelativePositionAtUT(BrakeEndPoint.UT),
                                                            (float)(BrakeEndPointDeltaAlt + TargetAltitude));
                    BrakeDuration += rotation_time;
                    if (FullBrake)
                    {
                        if (brake_at_fly_above)
                        {
                            FlyAbovePoint = Path.FlyAbovePoint(Target.OrbPos(Body));
                            if (WillOverheat)
                            {
                                SetBrakeEndPoint(Path.PointAtShipTemp(VSL.Physics.MinMaxTemperature - 100));
                            }
                            else
                            {
                                SetBrakeEndPoint(FlyAbovePoint);
                            }
                        }
                        else
                        {
                            //find appropriate point to perform the maneuver
                            var brake_end_UT = Math.Max(AtTargetUT - Mathf.Max(LandingTrajectoryAutopilot.C.CorrectionOffset, BrakeDuration * 1.1f), StartUT);
                            var fly_over_alt = TargetAltitude + LandingTrajectoryAutopilot.C.FlyOverAlt;
                            if (WillOverheat)
                            {
                                SetBrakeEndPoint(Path.PointAtShipTemp(VSL.Physics.MinMaxTemperature - 100));
                            }
                            else if (Path.UT2Altitude(brake_end_UT) < fly_over_alt)
                            {
                                SetBrakeEndPoint(Path.PointAtAltitude(fly_over_alt));
                            }
                            else
                            {
                                SetBrakeEndUT(brake_end_UT);
                            }
                        }
                    }
                    else
                    {
                        SetBrakeEndUT(AerobrakeStartUT);
                    }
                    //update landing site
                    update_landing_site_after_brake();
                }
                else //no brake maneuver
                {
                    SetBrakeEndUT(AerobrakeStartUT);
                    BrakeStartPoint = BrakeEndPoint;
                    BrakeDuration   = 0;
                }
            }
            else
            {
                FlyAbovePoint = Path.FlyAbovePoint(Target.OrbPos(Body));
                if (WillOverheat)
                {
                    SetBrakeEndPoint(Path.PointAtShipTemp(VSL.Physics.MinMaxTemperature - 100));
                }
                else
                {
                    SetBrakeEndPoint(FlyAbovePoint);
                }
                SetBrakeDeltaV(-AtTargetVel - Vector3d.Cross(Body.zUpAngularVelocity, AtTargetPos));
                if (BrakeFuel > 0)
                {
                    var offset = MatchVelocityAutopilot.BrakingOffset((float)BrakeDeltaV.magnitude, VSL, out BrakeDuration);
                    BrakeStartPoint = Path.PointAtUT(Math.Max(BrakeEndPoint.UT - offset, StartUT));
                }
                else
                {
                    SetBrakeEndUT(AerobrakeStartUT);
                    BrakeStartPoint = BrakeStartPoint;
                    BrakeDuration   = 0;
                }
            }
            BrakeOffset = (float)Utils.ClampL(BrakeEndPoint.UT - BrakeStartPoint.UT, 0);
            //compute vessel coordinates at maneuver start
            if (VSL.LandedOrSplashed)
            {
                VslStartLat = Utils.ClampAngle(VSL.vessel.latitude);
                VslStartLon = Utils.ClampAngle(VSL.vessel.longitude);
            }
            else
            {
                var start_pos = (TrajectoryCalculator.BodyRotationAtdT(Body, -TimeToStart) * StartPos).xzy + Body.position;
                VslStartLat = Utils.ClampAngle(Body.GetLatitude(start_pos));
                VslStartLon = Utils.ClampAngle(Body.GetLongitude(start_pos));
            }
            //compute distance to target
            DistanceToTarget   = Target.AngleTo(SurfacePoint) * Body.Radius;
            SurfacePoint.Name += string.Format("\n{0} from target", Utils.formatBigValue((float)DistanceToTarget, "m"));
            //compute distance in lat-lon coordinates
            DeltaLat = Utils.AngleDelta(SurfacePoint.Pos.Lat, Target.Pos.Lat) *
                       Math.Sign(Utils.AngleDelta(approach.Lat, SurfacePoint.Pos.Lat));
            DeltaLon = Utils.AngleDelta(SurfacePoint.Pos.Lon, Target.Pos.Lon) *
                       Math.Sign(Utils.AngleDelta(approach.Lon, SurfacePoint.Pos.Lon));
            //compute distance in radial coordinates
            DeltaFi = 90 - Utils.Angle2(Orbit.GetOrbitNormal(),
                                        TrajectoryCalculator.BodyRotationAtdT(Body, TimeToTarget) * Target.OrbPos(Body));
            DeltaR = Utils.RadDelta(SurfacePoint.AngleTo(VslStartLat, VslStartLon), Target.AngleTo(VslStartLat, VslStartLon)) * Mathf.Rad2Deg;
//            Utils.Log("{}", this);//debug
        }
        public bool TargetedGravityTurn(float Dtol)
        {
            UpdateTargetPosition();
            VSL.Engines.ActivateNextStageOnFlameout();
            update_state(Dtol);
            var pg_vel = get_pg_vel();

            if (!ErrorThreshold)
            {
                CircularizationOffset = -1;
                tune_THR();
                var startF    = getStartF();
                var vel       = TrajectoryCalculator.dV4ApV(VesselOrbit, target, VSL.Physics.UT);
                var AoA       = Utils.Angle2(pg_vel, VesselOrbit.pos);
                var neededAoA = Utils.ClampH(Utils.Angle2(target - VesselOrbit.pos, VesselOrbit.pos) / 2, 45);
                var angle2Hor = angle2hor_filter.Update(90 - Utils.Angle2(vel, VesselOrbit.pos));
                pitch.Max = AoA < neededAoA ? 0 : (float)AoA;
                pitch.Update((float)angle2Hor);
                correction_started.Update(angle2Hor >= 0);
                if (AoA < neededAoA && !correction_started)
                {
                    pitch.Action = (float)Utils.Clamp(AoA - neededAoA + angle2Hor,
                                                      -AttitudeControlBase.C.MaxAttitudeError,
                                                      AoA);
                }
                vel = QuaternionD.AngleAxis(pitch.Action * startF,
                                            Vector3d.Cross(target, VesselOrbit.pos))
                      * pg_vel;
                if (Vector3d.Dot(vel, VesselOrbit.pos) < 0)
                {
                    vel = Vector3d.Exclude(VesselOrbit.pos, vel);
                }
                vel = tune_needed_vel(vel, pg_vel, startF);
                throttle_correction.setClamp(Utils.ClampL(TimeToApA - 10, 1));
                throttle_correction.Update((float)angle2Hor);
                throttle.Update(TimeToApA + throttle_correction - (float)TimeToClosestApA);
                throttle_filter.Update(Utils.Clamp(0.5f + throttle, 0, max_G_throttle()));
                THR.Throttle = throttle_filter * (float)Utils.ClampH(ErrorThreshold.Value / Dtol / 10, 1);
                //Log("alt {}, ApA {}, dApA {}, dArc {}, Err {}, angle2Hor {}, AoA {} < {}, startF {}, THR {}\n" +
                //"thr.correction {}\nthrottle {}\npitch {}",
                //VSL.Altitude.Absolute, VesselOrbit.ApA, dApA, dArc, ErrorThreshold,
                //angle2Hor, AoA, neededAoA, startF, THR.Throttle,
                //throttle_correction, throttle, pitch);//debug
                CFG.AT.OnIfNot(Attitude.Custom);
                ATC.SetThrustDirW(-vel.xzy);
                if (CFG.AT.Not(Attitude.KillRotation))
                {
                    if (AoA < 85)
                    {
                        CFG.BR.OnIfNot(BearingMode.Auto);
                        BRC.ForwardDirection = htdir.xzy;
                    }
                    else
                    {
                        CFG.BR.OffIfOn(BearingMode.Auto);
                    }
                }
                Status("Gravity turn...");
                return(true);
            }
            return(coast(pg_vel));
        }
示例#28
0
        protected BaseTrajectory(VesselWrapper vsl, Vector3d dV, double startUT)
        {
            VSL = vsl;
            var dVm = (float)dV.magnitude;

            if (dVm > 0)
            {
                ManeuverFuel     = VSL.Engines.FuelNeeded(dVm);
                FullManeuver     = ManeuverFuel < VSL.Engines.AvailableFuelMass;
                ManeuverDuration = VSL.Engines.TTB_Precise(dVm);
            }
            else
            {
                ManeuverFuel     = 0;
                ManeuverDuration = 0;
                FullManeuver     = true;
            }
            StartUT   = startUT;
            OrigOrbit = VSL.vessel.orbitDriver.orbit;
            var obt = StartOrbit;

            Body = obt.referenceBody;
            if (dVm > 0)
            {
                ManeuverDeltaV = dV;
                NodeDeltaV     = Utils.Orbital2NodeDeltaV(obt, ManeuverDeltaV, StartUT);
                try
                {
                    Orbit = TrajectoryCalculator.NewOrbit(obt, ManeuverDeltaV, StartUT);
                    var prev = Orbit;
                    for (int i = 0; i < 3; i++)
                    {
                        if (!PatchedConics.CalculatePatch(prev, prev.nextPatch ?? new Orbit(), prev.epoch, new PatchedConics.SolverParameters(), null))
                        {
                            break;
                        }
                        prev = prev.nextPatch;
                    }
                    Body = Orbit.referenceBody;
//                    if(Orbit.patchEndTransition != Orbit.PatchTransitionType.FINAL)//debug
//                    {
//                        Utils.Log("**************************************************************************************************");//debug
//                        RendezvousAutopilot.log_patches(Orbit, "Orbit");//deubg
//                    }
                }
                catch (ArithmeticException)
                {
                    Orbit            = OrigOrbit;
                    StartUT          = VSL.Physics.UT;
                    ManeuverFuel     = 0;
                    ManeuverDuration = 0;
                    ManeuverDeltaV   = Vector3d.zero;
                    FullManeuver     = true;
                }
            }
            else
            {
                Orbit = OrigOrbit;
            }
            StartPos      = obt.getRelativePositionAtUT(StartUT);
            StartVel      = obt.getOrbitalVelocityAtUT(StartUT);
            AfterStartVel = Orbit.getOrbitalVelocityAtUT(StartUT);
        }
示例#29
0
 public Orbit OrbitFromHere()
 {
     return(TrajectoryCalculator.NewOrbit(Body, pos, vel, UT));
 }