Beispiel #1
0
            public override AutopilotStep OnFixedUpdate()
            {
                //if we don't want to deorbit but we're already on a reentry trajectory, we can't wait until the ideal point
                //in the orbit to deorbt; we already have deorbited.
                if (orbit.ApA < mainBody.RealMaxAtmosphereAltitude())
                {
                    core.thrust.targetThrottle = 0;
                    return(doAfterExecution);
                }

                if (node == null)
                {
                    //We aim for a trajectory that
                    // a) has the same vertical speed as our current trajectory
                    // b) has a horizontal speed that will give it a periapsis of -10% of the body's radius
                    // c) has a heading that points toward where the target will be at the end of free-fall, accounting for planetary rotation
                    Vector3d   horizontalDV                  = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, vesselState.time, 0.9 * mainBody.Radius);                //Imagine we are going to deorbit now. Find the burn that would lower our periapsis to -10% of the planet's radius
                    Orbit      forwardDeorbitTrajectory      = orbit.PerturbedOrbit(vesselState.time, horizontalDV);                                                             //Compute the orbit that would put us on
                    double     freefallTime                  = forwardDeorbitTrajectory.NextTimeOfRadius(vesselState.time, mainBody.Radius) - vesselState.time;                  //Find how long that orbit would take to impact the ground
                    double     planetRotationDuringFreefall  = 360 * freefallTime / mainBody.rotationPeriod;                                                                     //Find how many degrees the planet will rotate during that time
                    Vector3d   currentTargetRadialVector     = mainBody.GetWorldSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0) - mainBody.position; //Find the current vector from the planet center to the target landing site
                    Quaternion freefallPlanetRotation        = Quaternion.AngleAxis((float)planetRotationDuringFreefall, mainBody.angularVelocity);                              //Construct a quaternion representing the rotation of the planet found above
                    Vector3d   freefallEndTargetRadialVector = freefallPlanetRotation * currentTargetRadialVector;                                                               //Use this quaternion to find what the vector from the planet center to the target will be when we hit the ground
                    Vector3d   freefallEndTargetPosition     = mainBody.position + freefallEndTargetRadialVector;                                                                //Then find the actual position of the target at that time
                    Vector3d   freefallEndHorizontalToTarget = Vector3d.Exclude(freefallEndTargetRadialVector, freefallEndTargetPosition - vesselState.CoM).normalized;          //Find a horizontal unit vector that points toward where the target will be when we hit the ground
                    Vector3d   currentHorizontalVelocity     = Vector3d.Exclude(vesselState.up, vesselState.orbitalVelocity);                                                    //Find our current horizontal velocity
                    double     finalHorizontalSpeed          = (currentHorizontalVelocity + horizontalDV).magnitude;                                                             //Find the desired horizontal speed after the deorbit burn
                    Vector3d   finalHorizontalVelocity       = finalHorizontalSpeed * freefallEndHorizontalToTarget;                                                             //Combine the desired speed and direction to get the desired velocity after the deorbi burn

                    //Compute the angle between the location of the target at the end of freefall and the normal to our orbit:
                    Vector3d currentRadialVector      = vesselState.CoM - mainBody.position;
                    double   targetAngleToOrbitNormal = Vector3d.Angle(orbit.SwappedOrbitNormal(), freefallEndTargetRadialVector);
                    targetAngleToOrbitNormal = Math.Min(targetAngleToOrbitNormal, 180 - targetAngleToOrbitNormal);

                    float targetAheadAngle = Vector3.SignedAngle(currentRadialVector, freefallEndTargetRadialVector, orbit.SwappedOrbitNormal()); //How far ahead the target is, in degrees
                    if (targetAheadAngle < 60)
                    {
                        targetAheadAngle += 360;
                    }

                    float planeChangeAngle = Vector3.Angle(currentHorizontalVelocity, freefallEndHorizontalToTarget); //The plane change required to get onto the deorbit trajectory, in degrees

                    vessel.RemoveAllManeuverNodes();

                    //If the target is basically almost normal to our orbit, it doesn't matter when we deorbit; might as well do it now
                    //Otherwise, wait until the target is ahead
                    if (targetAngleToOrbitNormal < 10 ||
                        (targetAheadAngle < 90 && planeChangeAngle < 90))
                    {
                        vessel.PlaceManeuverNode(vessel.orbit, horizontalDV, vesselState.time);
                    }
                    else
                    {
                        double deorbitTime = vesselState.time + (targetAheadAngle - 90) * orbit.period / 360f;
                        vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, deorbitTime, 0.9 * mainBody.Radius), deorbitTime);
                    }
                }

                return(base.OnFixedUpdate());
            }
Beispiel #2
0
            // find orbit round with min normalDiff to target, makes only sense if we are in inclined orbit
            bool minOrbit()
            {
                ManeuverNode plannedNode = vessel.patchedConicSolver.maneuverNodes[0];

                if (Math.Abs(orbit.inclination) < 5)
                {
                    return(true);
                }
                Debug.Log(String.Format("Current deorbit round at t={0:F0} has normalDiff={1:F1}", plannedNode.UT - Planetarium.GetUniversalTime(), targetInfo.normalDifference));
                if (iteration == 0 || Math.Abs(targetInfo.normalDifference) < minDiff)
                {
                    Debug.Log(String.Format("Found new optimum deorbit round at t={0:F0} for normalDiff={1:F1} ", plannedNode.UT - Planetarium.GetUniversalTime(), targetInfo.normalDifference));
                    minDiff = Math.Abs(targetInfo.normalDifference);
                    minUT   = plannedNode.UT;
                }
                iteration++;
                if (iteration > maxIterations)
                {
                    plannedNode.RemoveSelf();
                    vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, minUT, mainBody.Radius + core.landing.reentryTargetHeight), minUT);
                    targetInfo.invalidateCalculation();
                    return(true);
                }
                // factor accounts for ground movement during orbit round
                double nextRound = plannedNode.UT + orbit.period * vessel.mainBody.rotationPeriod / (vessel.mainBody.rotationPeriod - orbit.period);

                plannedNode.RemoveSelf();
                vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, nextRound, mainBody.Radius + core.landing.reentryTargetHeight), nextRound);
                targetInfo.invalidateCalculation();
                return(false);
            }
Beispiel #3
0
            bool optimizeDeorbit()
            {
                //Debug.Log(String.Format("Autoland: currentImpactRadialVector={0} currentTargetRadialVector={1} differenceTarget={2}", targetInfo.currentImpactRadialVector, targetInfo.currentTargetRadialVector, targetInfo.differenceTarget));
                //Debug.Log(String.Format("Autoland: orbitClosestToTarget={0} orbitNormal={1} targetForward={2} ", targetInfo.orbitClosestToTarget, orbit.SwappedOrbitNormal(), targetForward.ToString("F3")));
                //Debug.Log(String.Format("Autoland: normalDiff={0:F1}, backwardDiff={1:F1}", targetInfo.normalDifference, targetInfo.backwardDifference));

                if (Math.Abs(targetInfo.targetAheadAngle) < 0.5 && Math.Abs(targetInfo.backwardDifference) < deorbitprecision)
                {
                    return(true); // execute plannedNode
                }
                else
                {
                    //move Node
                    ManeuverNode plannedNode = vessel.patchedConicSolver.maneuverNodes[0];
                    double       deorbitTime = plannedNode.UT;
                    double       timedelta;

                    if (Math.Abs(targetInfo.targetAheadAngle) < 0.5) // for small changes use tangential calculation, otherwise angluar
                    {
                        timedelta = targetInfo.backwardDifference / vesselState.speedSurfaceHorizontal;
                    }
                    else
                    {
                        timedelta = targetInfo.targetAheadAngle * orbit.period / 360f;
                    }

                    if (timedelta < 0) // asymetric to avoid jumping between two points without improvement. Observed with inclined trajectory.
                    {
                        deorbitTime -= timedelta;
                    }
                    else
                    {
                        deorbitTime -= 0.5 * timedelta;
                    }

                    if (deorbitTime < vesselState.time)
                    {
                        deorbitTime += orbit.period;
                    }
                    if (deorbitTime > vesselState.time + 1.5 * orbit.period)
                    {
                        deorbitTime -= orbit.period;
                    }

                    status = String.Format("Optimizing deorbit time based on trajectory prediction, shift by {0:F4} degree, {1:F0} m equals {2:F1} seconds", targetInfo.targetAheadAngle, targetInfo.backwardDifference, deorbitTime - plannedNode.UT);
                    Debug.Log("Autoland: " + status);

                    // deltaV needs to rotate
                    plannedNode.RemoveSelf();
                    vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, deorbitTime, mainBody.Radius + core.landing.reentryTargetHeight), deorbitTime);
                    targetInfo.invalidateCalculation();
                    iteration++;
                }

                return(false);
            }
Beispiel #4
0
        public static void MPPea(double time, double pea)
        {
            MechJebCore activejeb = GetJeb();

            if (activejeb != null)
            {
                Vector3d deltav = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(activejeb.vessel.orbit, time, pea);
                activejeb.vessel.PlaceManeuverNode(activejeb.vessel.orbit, deltav, time);
            }
        }
Beispiel #5
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            if (o.referenceBody.Radius + newPeA > o.Radius(UT))
            {
                string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m";
                throw new OperationException("new periapsis cannot be higher than the altitude of the burn (" + burnAltitude + ")");
            }
            else if (newPeA < -o.referenceBody.Radius)
            {
                throw new OperationException("new periapsis cannot be lower than minus the radius of " + o.referenceBody.theName + "(-" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");
            }

            return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangePeriapsis(o, UT, newPeA + o.referenceBody.Radius), UT));
        }
            public override AutopilotStep OnFixedUpdate()
            {
                //if we don't want to deorbit but we're already on a reentry trajectory, we can't wait until the ideal point
                //in the orbit to deorbt; we already have deorbited.
                if (orbit.ApA < mainBody.RealMaxAtmosphereAltitude())
                {
                    core.thrust.targetThrottle = 0;
                    return(new CourseCorrection(core));
                }

                //We aim for a trajectory that
                // a) has the same vertical speed as our current trajectory
                // b) has a horizontal speed that will give it a periapsis of -10% of the body's radius
                // c) has a heading that points toward where the target will be at the end of free-fall, accounting for planetary rotation
                Vector3d   horizontalDV                  = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, vesselState.time, 0.9 * mainBody.Radius);                //Imagine we are going to deorbit now. Find the burn that would lower our periapsis to -10% of the planet's radius
                Orbit      forwardDeorbitTrajectory      = orbit.PerturbedOrbit(vesselState.time, horizontalDV);                                                             //Compute the orbit that would put us on
                double     freefallTime                  = forwardDeorbitTrajectory.NextTimeOfRadius(vesselState.time, mainBody.Radius) - vesselState.time;                  //Find how long that orbit would take to impact the ground
                double     planetRotationDuringFreefall  = 360 * freefallTime / mainBody.rotationPeriod;                                                                     //Find how many degrees the planet will rotate during that time
                Vector3d   currentTargetRadialVector     = mainBody.GetWorldSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0) - mainBody.position; //Find the current vector from the planet center to the target landing site
                Quaternion freefallPlanetRotation        = Quaternion.AngleAxis((float)planetRotationDuringFreefall, mainBody.angularVelocity);                              //Construct a quaternion representing the rotation of the planet found above
                Vector3d   freefallEndTargetRadialVector = freefallPlanetRotation * currentTargetRadialVector;                                                               //Use this quaternion to find what the vector from the planet center to the target will be when we hit the ground
                Vector3d   freefallEndTargetPosition     = mainBody.position + freefallEndTargetRadialVector;                                                                //Then find the actual position of the target at that time
                Vector3d   freefallEndHorizontalToTarget = Vector3d.Exclude(vesselState.up, freefallEndTargetPosition - vesselState.CoM).normalized;                         //Find a horizontal unit vector that points toward where the target will be when we hit the ground
                Vector3d   currentHorizontalVelocity     = Vector3d.Exclude(vesselState.up, vesselState.orbitalVelocity);                                                    //Find our current horizontal velocity
                double     finalHorizontalSpeed          = (currentHorizontalVelocity + horizontalDV).magnitude;                                                             //Find the desired horizontal speed after the deorbit burn
                Vector3d   finalHorizontalVelocity       = finalHorizontalSpeed * freefallEndHorizontalToTarget;                                                             //Combine the desired speed and direction to get the desired velocity after the deorbi burn

                //Compute the angle between the location of the target at the end of freefall and the normal to our orbit:
                Vector3d currentRadialVector      = vesselState.CoM - mainBody.position;
                double   targetAngleToOrbitNormal = Vector3d.Angle(orbit.SwappedOrbitNormal(), freefallEndTargetRadialVector);

                targetAngleToOrbitNormal = Math.Min(targetAngleToOrbitNormal, 180 - targetAngleToOrbitNormal);

                double targetAheadAngle = Vector3d.Angle(currentRadialVector, freefallEndTargetRadialVector);       //How far ahead the target is, in degrees
                double planeChangeAngle = Vector3d.Angle(currentHorizontalVelocity, freefallEndHorizontalToTarget); //The plane change required to get onto the deorbit trajectory, in degrees

                //If the target is basically almost normal to our orbit, it doesn't matter when we deorbit; might as well do it now
                //Otherwise, wait until the target is ahead
                if (targetAngleToOrbitNormal < 10 ||
                    (targetAheadAngle < 90 && targetAheadAngle > 60 && planeChangeAngle < 90))
                {
                    deorbitBurnTriggered = true;
                }

                if (deorbitBurnTriggered)
                {
                    if (!MuUtils.PhysicsRunning())
                    {
                        core.warp.MinimumWarp();
                    }                                                           //get out of warp

                    Vector3d deltaV = finalHorizontalVelocity - currentHorizontalVelocity;
                    core.attitude.attitudeTo(deltaV.normalized, AttitudeReference.INERTIAL, core.landing);

                    if (deltaV.magnitude < 2.0)
                    {
                        return(new CourseCorrection(core));
                    }

                    status = "Doing high deorbit burn";
                }
                else
                {
                    core.attitude.attitudeTo(Vector3d.back, AttitudeReference.ORBIT, core.landing);
                    if (core.node.autowarp)
                    {
                        core.warp.WarpRegularAtRate((float)(orbit.period / 10));
                    }

                    status = "Moving to high deorbit burn point";
                }

                return(this);
            }
Beispiel #7
0
            // calculate deorbit node and if node is acceptable base class will excute it
            public override AutopilotStep OnFixedUpdate()
            {
                //if we don't want to deorbit but we're already on a reentry trajectory, we can't wait until the ideal point
                //in the orbit to deorbt; we already have deorbited.
                if (orbit.ApA < mainBody.RealMaxAtmosphereAltitude())
                {
                    core.thrust.targetThrottle = 0;
                    return(doAfterExecution);
                }

                switch (phase)
                {
                case Phase.init:
                    //core.attitude.attitudeTo(Quaternion.identity, AttitudeReference.SURFACE_HORIZONTAL, this);
                    vessel.RemoveAllManeuverNodes();
                    vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, vesselState.time, mainBody.Radius + core.landing.reentryTargetHeight), vesselState.time);
                    TrajectoriesConnector.API.SetTarget(core.target.targetLatitude, core.target.targetLongitude);
                    status    = "Calculating deorbit trajectory";
                    phase     = Phase.deorbit;
                    iteration = 0;
                    break;

                case Phase.deorbit:
                    targetInfo.update();
                    if (targetInfo.isValid && optimizeDeorbit())
                    {
                        iteration = 30;
                        phase     = Phase.minOrbit;
                    }
                    else
                    {
                        if (iteration > maxIterations)
                        {
                            status = "Deorbit giving up in search for node, do manual deorbit";
                            core.landing.StopLanding();
                            return(null);
                        }
                    }
                    break;

                case Phase.minOrbit:
                    targetInfo.update();
                    if (targetInfo.isValid && minOrbit())
                    {
                        phase = Phase.planeChange;
                    }
                    break;

                case Phase.planeChange:
                    targetInfo.update();
                    if (targetInfo.isValid && optimizePlaneChange())
                    {
                        phase = Phase.execute;
                    }
                    break;

                case Phase.execute:
                    return(base.OnFixedUpdate());
                }

                return(this);
            }