void start_orbit()
        {
            ToOrbit = null;
            var dV      = Vector3d.zero;
            var old     = VesselOrbit;
            var StartUT = VSL.Physics.UT + CorrectionOffset;

            CFG.BR.OffIfOn(BearingMode.Auto);
            update_trajectory();
            if (VesselOrbit.PeR < MinPeR)
            {
                StartUT = Math.Min(trajectory.AtTargetUT, VSL.Physics.UT + (VesselOrbit.ApAhead()? VesselOrbit.timeToAp : CorrectionOffset));
                if (trajectory.DistanceToTarget < REN.ApproachThreshold * 2 && StartUT.Equals(trajectory.AtTargetUT))
                {                 //approach is close enough to directly match orbits
                    match_orbits();
                    return;
                }
                var transfer_time = Utils.ClampL(TargetOrbit.period * (0.25 - AngleDelta(VesselOrbit, TargetOrbit, StartUT) / 360), 1);
                var solver        = new LambertSolver(VesselOrbit, TargetOrbit.getRelativePositionAtUT(StartUT + transfer_time), StartUT);
                dV = solver.dV4Transfer(transfer_time);
                var trj = new RendezvousTrajectory(VSL, dV, StartUT, CFG.Target, MinPeR, transfer_time);
                if (!dV.IsZero() && !trj.KillerOrbit)
                {                 //approach orbit is possible
                    compute_start_orbit(StartUT);
                    return;
                }
                //starting from circular orbit and proceeding to TTR fitting...
                StartUT = VesselOrbit.ApAhead()? VSL.Physics.UT + VesselOrbit.timeToAp : VSL.Physics.UT + CorrectionOffset;
                dV      = dV4C(old, hV(StartUT), StartUT);
                old     = NewOrbit(old, dV, StartUT);
            }
            else if (trajectory.RelDistanceToTarget < REN.CorrectionStart || TargetLoaded)
            {
                if (trajectory.RelDistanceToTarget > REN.CorrectionStart / 4 && !TargetLoaded)
                {
                    fine_tune_approach();
                }
                else
                {
                    match_orbits();
                }
                return;
            }
            //compute orbit with desired TTR and activate maneuver autopilot
            dV += dV4TTR(old, TargetOrbit, REN.MaxTTR, REN.MaxDeltaV, MinPeR, StartUT);
            if (!dV.IsZero())
            {
                add_node(dV, StartUT);
                CFG.AP1.On(Autopilot1.Maneuver);
            }
            stage = Stage.StartOrbit;
        }
        protected override void Update()
        {
            if (!IsActive)
            {
                CFG.AP2.OffIfOn(Autopilot2.BallisticJump); return;
            }
            if (landing)
            {
                do_land(); return;
            }
            switch (stage)
            {
            case Stage.Start:
                CFG.HF.OnIfNot(HFlight.Stop);
                CFG.AltitudeAboveTerrain = true;
                CFG.VF.OnIfNot(VFlight.AltitudeControl);
                if (VSL.LandedOrSplashed || VSL.Altitude.Relative < StartAltitude)
                {
                    CFG.DesiredAltitude = StartAltitude;
                }
                else
                {
                    CFG.DesiredAltitude = VSL.Altitude.Relative;
                }
                if (VSL.Altitude.Relative > StartAltitude - 5)
                {
                    compute_initial_trajectory();
                }
                else
                {
                    Status("Gaining initial altitude...");
                }
                break;

            case Stage.Compute:
                if (!trajectory_computed())
                {
                    break;
                }
                var obst = obstacle_ahead(trajectory);
                if (obst > 0)
                {
                    StartAltitude += (float)obst + BJ.ObstacleOffset;
                    stage          = Stage.Start;
                }
                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:
                if (!VSL.HasManeuverNode)
                {
                    CFG.AP2.Off(); break;
                }
                if (VSL.Controls.AlignmentFactor > 0.9 || !CFG.VSCIsActive)
                {
                    CFG.DisableVSC();
                    if (!Executor.Execute(VSL.FirstManeuverNode.GetBurnVector(VesselOrbit), 10))
                    {
                        fine_tune_approach();
                    }
                    Status("white", "Accelerating...");
                }
                break;

            case Stage.CorrectTrajectory:
                if (!trajectory_computed())
                {
                    break;
                }
                add_correction_node_if_needed();
                stage = Stage.Coast;
                break;

            case Stage.Coast:
                var ap_ahead = VesselOrbit.ApAhead();
                if (CFG.AP1[Autopilot1.Maneuver])
                {
                    if (ap_ahead)
                    {
                        Status("Correcting trajectory...");
                        break;
                    }
                }
                Status("Coasting...");
                if (ap_ahead && !correct_trajectory())
                {
                    break;
                }
                stage = Stage.None;
                start_landing();
                break;
            }
        }