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);
 }
 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;
 }
 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);
 }
        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);
        }
        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
        }
Beispiel #6
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);
        }
        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);
        }
Beispiel #8
0
 public Orbit OrbitFromHere()
 {
     return(TrajectoryCalculator.NewOrbit(Body, pos, vel, UT));
 }