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));
        }
Пример #2
0
        protected override void Update()
        {
            if (landing)
            {
                do_land(); return;
            }
            switch (stage)
            {
            case Stage.Start:
                VSC_ON(HFlight.Stop);
                if (VSL.LandedOrSplashed || VSL.Altitude.Relative < StartAltitude)
                {
                    CFG.DesiredAltitude = StartAltitude;
                }
                else
                {
                    CFG.DesiredAltitude = VSL.Altitude.Relative;
                }
                if (!VSL.LandedOrSplashed)
                {
                    compute_initial_trajectory();
                }
                break;

            case Stage.GainAltitude:
                Status("Gaining altitude...");
                VSC_ON(HFlight.Level);
                if (VSL.Altitude.Relative > CFG.DesiredAltitude - 10)
                {
                    compute_initial_trajectory();
                }
                break;

            case Stage.Compute:
                double obstacle;
                if (!trajectory_computed())
                {
                    break;
                }
                if (find_biggest_obstacle_ahead(BJ.StartAltitude, out obstacle))
                {
                    break;
                }
                if (obstacle > 0)
                {
                    StartAltitude      += (float)obstacle + BJ.ObstacleOffset;
                    CFG.DesiredAltitude = StartAltitude;
                    stage = Stage.GainAltitude;
                }
                else if (VSL.Altitude.Relative < BJ.StartAltitude - 10)
                {
                    stage = Stage.GainAltitude;
                }
                else if (check_initial_trajectory())
                {
                    accelerate();
                }
                else
                {
                    stage = Stage.Wait;
                }
                break;

            case Stage.Wait:
                if (!string.IsNullOrEmpty(TCAGui.StatusMessage))
                {
                    break;
                }
                accelerate();
                break;

            case Stage.Accelerate:
                CFG.AT.OnIfNot(Attitude.Custom);
                var dV = (trajectory.Orbit.GetFrameVelAtUT(trajectory.StartUT) -
                          VSL.orbit.GetFrameVelAtUT(trajectory.StartUT)).xzy;
                if (VSL.Controls.AlignmentFactor > 0.9 || !CFG.VSCIsActive)
                {
                    CFG.DisableVSC();
                    var dVv = -VSL.Altitude.Absolute;//Vector3d.Dot(dV, VSL.Physics.Up);
                    if (RAD != null)
                    {
                        var dH = VSL.Altitude.Relative - VSL.Altitude.Ahead - VSL.Geometry.H;
                        if (dH < 0)
                        {
                            dVv -= dH / RAD.TimeAhead * 1.1f;
                        }
                    }
                    if (dVv > 0)
                    {
                        fall_correction.I = BJ.FallCorrectionPID.I * Utils.ClampL(100 / VSL.Altitude.Relative, 1);
                        fall_correction.Update(-VSL.Altitude.Absolute);
                    }
                    else
                    {
                        fall_correction.IntegralError *= Utils.ClampL(1 - fall_correction.I / 10 * TimeWarp.fixedDeltaTime, 0);
                        fall_correction.Update(0);
                    }
//                    Log("dV {}, dVv {}, correction {}, I {}", dV, dVv, fall_correction.Action, fall_correction.I);//debug
                    if (Executor.Execute(dV + fall_correction * VSL.Physics.Up, 10))
                    {
                        Status("white",
                               "Accelerating: <color=yellow><b>{0}</b> m/s</color>",
                               (dV.magnitude - 10).ToString("F1"));
                    }
                    else
                    {
                        fine_tune_approach();
                    }
                }
                else
                {
                    ATC.SetThrustDirW(-dV);
                }
                break;

            case Stage.CorrectTrajectory:
                VSL.Info.Countdown = landing_trajectory.BrakeStartPoint.UT - VSL.Physics.UT - ManeuverOffset;
                if (VSL.Info.Countdown > 0)
                {
                    warp_to_coundown();
                    if (!trajectory_computed())
                    {
                        break;
                    }
                    add_correction_node_if_needed();
                    stage = Stage.Coast;
                }
                else
                {
                    stage = Stage.None;
                    start_landing();
                }
                break;

            case Stage.Coast:
                if (!coast_to_start())
                {
                    stage = Stage.None;
                }
                break;
            }
        }