public override void OnFixedUpdate() { if (markUT == 0) { Mark(); } timeSinceMark = vesselState.time - markUT; if (vessel.situation == Vessel.Situations.PRELAUNCH) { Mark(); //keep resetting stats until we launch return; } gravityLosses += vesselState.deltaT * Vector3d.Dot(-vessel.srf_velocity.normalized, vesselState.gravityForce); gravityLosses -= vesselState.deltaT * Vector3d.Dot(vessel.srf_velocity.normalized, vesselState.up * vesselState.radius * Math.Pow(2 * Math.PI / part.vessel.mainBody.rotationPeriod, 2)); double dragAccel = mainBody.DragAccel(vesselState.CoM, vessel.obt_velocity, vesselState.massDrag / vesselState.mass).magnitude; dragLosses += vesselState.deltaT * dragAccel; maxDragGees = Math.Max(maxDragGees, dragAccel / 9.81); double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius); double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod; phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); var dV = OrbitalManeuverCalculator.DeltaVToShiftNodeLongitude(o, UT, target.targetLongitude); return(new ManeuverParameters(dV, UT)); }
void DriveCircularizationBurn(FlightCtrlState s) { if (!vessel.patchedConicsUnlocked() || skipCircularization) { this.users.Clear(); return; } DriveDeployableComponents(s); if (placedCircularizeNode) { if (vessel.patchedConicSolver.maneuverNodes.Count == 0) { MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>(); if (recorder != null) { launchPhaseAngle = recorder.phaseAngleFromMark; } if (recorder != null) { launchLANDifference = vesselState.orbitLAN - recorder.markLAN; } //finished circularize this.users.Clear(); return; } } else { //place circularization node vessel.RemoveAllManeuverNodes(); double UT = orbit.NextApoapsisTime(vesselState.time); //During the circularization burn, try to correct any inclination errors because it's better to combine the two burns. // For example, if you're about to do a 1500 m/s circularization burn, if you combine a 200 m/s inclination correction // into it, you actually only spend 1513 m/s to execute combined manuver. Mechjeb should also do correction burns before // this if possible, and this can't correct all errors... but it's better then nothing. // (A better version of this should try to match inclination & LAN if target is specified) // FIXME? this inclination correction is unlikely to be at tha AN/DN and will throw the LAN off with anything other than high // TWR launches from equatorial launch sites -- should probably be made optional (or clip it if the correction is too large). Vector3d inclinationCorrection = OrbitalManeuverCalculator.DeltaVToChangeInclination(orbit, UT, Math.Abs(desiredInclination)); Vector3d smaCorrection = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit.PerturbedOrbit(UT, inclinationCorrection), UT, desiredOrbitAltitude + mainBody.Radius); Vector3d dV = inclinationCorrection + smaCorrection; vessel.PlaceManeuverNode(orbit, dV, UT); placedCircularizeNode = true; core.node.ExecuteOneNode(this); } if (core.node.burnTriggered) { status = Localizer.Format("#MechJeb_Ascent_status7"); //"Circularizing" } else { status = Localizer.Format("#MechJeb_Ascent_status8"); //"Coasting to circularization burn" } }
public override ManeuverParameters MakeNodeImpl(Orbit o, double UT, MechJebModuleTargetController target) { if (!target.NormalTargetExists) { throw new Exception("must select a target for the Hohmann transfer."); } else if (o.referenceBody != target.TargetOrbit.referenceBody) { throw new Exception("target for Hohmann transfer must be in the same sphere of influence."); } else if (o.eccentricity > 1) { throw new Exception("starting orbit for Hohmann transfer must not be hyperbolic."); } else if (target.TargetOrbit.eccentricity > 1) { throw new Exception("target orbit for Hohmann transfer must not be hyperbolic."); } else if (o.RelativeInclination(target.TargetOrbit) > 30 && o.RelativeInclination(target.TargetOrbit) < 150) { errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(target.TargetOrbit).ToString("F0") + "º angle to starting orbit's plane (recommend at most 30º). Planned transfer may not intercept target properly."; } else if (o.eccentricity > 0.2) { errorMessage = "Warning: Recommend starting Hohmann transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly."; } Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(o, target.TargetOrbit, UT, out UT); return(new ManeuverParameters(dV, UT)); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (!target.NormalTargetExists) { throw new Exception("must select a target to match planes with."); } else if (o.referenceBody != target.TargetOrbit.referenceBody) { throw new Exception("can only match planes with an object in the same sphere of influence."); } else if (timeSelector.timeReference == TimeReference.REL_ASCENDING) { if (!o.AscendingNodeExists(target.TargetOrbit)) { throw new Exception("ascending node with target doesn't exist."); } } else { if (!o.DescendingNodeExists(target.TargetOrbit)) { throw new Exception("descending node with target doesn't exist."); } } Vector3d dV = (timeSelector.timeReference == TimeReference.REL_ASCENDING) ? OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(o, target.TargetOrbit, UT, out UT): OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(o, target.TargetOrbit, UT, out UT); return(new ManeuverParameters(dV, UT)); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); var dV = OrbitalManeuverCalculator.DeltaVToResonantOrbit(o, UT, (double)resonanceNumerator.val / resonanceDenominator.val); return(new ManeuverParameters(dV, UT)); }
public override List <ManeuverParameters> MakeNodesImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); List <ManeuverParameters> NodeList = new List <ManeuverParameters>(); NodeList.Add(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToCircularize(o, UT), UT)); return(NodeList); }
public override void OnFixedUpdate() { if (markUT == 0) { Mark(); } timeSinceMark = vesselState.time - markUT; if (vessel.situation == Vessel.Situations.PRELAUNCH) { Mark(); //keep resetting stats until we launch return; } if (vesselState.currentThrustAccel > 0) { gravityLosses += vesselState.deltaT * Vector3d.Dot(-vesselState.orbitalVelocity.normalized, vesselState.gravityForce); } dragLosses += vesselState.deltaT * vesselState.drag; deltaVExpended += vesselState.deltaT * vesselState.currentThrustAccel; steeringLosses += vesselState.deltaT * vesselState.currentThrustAccel * (1 - Vector3d.Dot(vesselState.orbitalVelocity.normalized, vesselState.forward)); maxDragGees = Math.Max(maxDragGees, vesselState.drag / 9.81); double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius); double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod; phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed); if (paused) { return; } //int oldHistoryIdx = historyIdx; //historyIdx = Mathf.Min(Mathf.FloorToInt((float)(timeSinceMark / precision)), history.Length - 1); if (vesselState.time >= (lastRecordTime + precision) && historyIdx < history.Length - 1) { lastRecordTime = vesselState.time; historyIdx++; Record(historyIdx); #if DEBUG if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH) { Log.dbg("WRP {0} {1:0} {2:0.00}", historyIdx, history[historyIdx].downRange, history[historyIdx].AoA); } else { Log.dbg("STD {0} {1:0} {2:0.00}", historyIdx, history[historyIdx].downRange, history[historyIdx].AoA); } #endif } }
void DriveCircularizationBurn(FlightCtrlState s) { if (!vessel.patchedConicsUnlocked() || skipCircularization) { this.users.Clear(); return; } if (placedCircularizeNode) { if (!vessel.patchedConicSolver.maneuverNodes.Any()) { MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>(); if (recorder != null) { launchPhaseAngle = recorder.phaseAngleFromMark; } if (recorder != null) { launchLANDifference = vesselState.orbitLAN - recorder.markLAN; } //finished circularize this.users.Clear(); return; } } else { //place circularization node vessel.RemoveAllManeuverNodes(); double UT = orbit.NextApoapsisTime(vesselState.time); //During the circularization burn, try to correct any inclination errors because it's better to combine the two burns. // For example, if you're about to do a 1500 m/s circularization burn, if you combine a 200 m/s inclination correction // into it, you actually only spend 1513 m/s to execute combined manuver. Mechjeb should also do correction burns before // this if possible, and this can't correct all errors... but it's better then nothing. // (A better version of this should try to match inclination & LAN if target is specified) Vector3d inclinationCorrection = OrbitalManeuverCalculator.DeltaVToChangeInclination(orbit, UT, desiredInclination); Vector3d smaCorrection = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit.PerturbedOrbit(UT, inclinationCorrection), UT, desiredOrbitAltitude + mainBody.Radius); Vector3d dV = inclinationCorrection + smaCorrection; vessel.PlaceManeuverNode(orbit, dV, UT); placedCircularizeNode = true; core.node.ExecuteOneNode(this); } if (core.node.burnTriggered) { status = "Circularizing"; } else { status = "Coasting to circularization burn"; } }
// provides AoA limiting and ground track steering to pitch controllers (possibly should be moved into the attitude controller, but // right now it collaborates too heavily with the ascent autopilot) // protected void attitudeTo(double desiredPitch) { double desiredHeading = OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel, vesselState, autopilot.desiredInclination); Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north; Vector3d desiredThrustVector = Math.Cos(desiredPitch * UtilMath.Deg2Rad) * desiredHeadingVector + Math.Sin(desiredPitch * UtilMath.Deg2Rad) * vesselState.up; thrustVectorForNavball = desiredThrustVector; desiredThrustVector = desiredThrustVector.normalized; if (autopilot.limitAoA) { float fade = vesselState.dynamicPressure < autopilot.aoALimitFadeoutPressure ? (float)(autopilot.aoALimitFadeoutPressure / vesselState.dynamicPressure) : 1; autopilot.currentMaxAoA = Math.Min(fade * autopilot.maxAoA, 180d); autopilot.limitingAoA = vessel.altitude <mainBody.atmosphereDepth && Vector3.Angle(vesselState.surfaceVelocity, desiredThrustVector)> autopilot.currentMaxAoA; if (autopilot.limitingAoA) { desiredThrustVector = Vector3.RotateTowards(vesselState.surfaceVelocity, desiredThrustVector, (float)(autopilot.currentMaxAoA * Mathf.Deg2Rad), 1).normalized; } } double pitch = 90 - Vector3d.Angle(desiredThrustVector, vesselState.up); double hdg; if (pitch > 89.9) { hdg = desiredHeading; } else { hdg = MuUtils.ClampDegrees360(UtilMath.Rad2Deg * Math.Atan2(Vector3d.Dot(desiredThrustVector, vesselState.east), Vector3d.Dot(desiredThrustVector, vesselState.north))); } if (autopilot.forceRoll) { core.attitude.AxisControl(!vessel.Landed, !vessel.Landed, !vessel.Landed && vesselState.altitudeBottom > 50); if (desiredPitch == 90.0) { core.attitude.attitudeTo(hdg, pitch, autopilot.turnRoll, this); } else { core.attitude.attitudeTo(hdg, pitch, autopilot.verticalRoll, this); } } else { core.attitude.attitudeTo(desiredThrustVector, AttitudeReference.INERTIAL, this); } }
override public void activateAction(int actionIndex) { base.activateAction(actionIndex); double UT; Vessel vessel = FlightGlobals.ActiveVessel; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(this.scriptModule.orbit, core.target.TargetOrbit, this.scriptModule.vesselState.time, out UT); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(this.scriptModule.orbit, dV, UT); this.endAction(); }
private PontryaginLaunch NewPontryaginForLaunch(double inc, double sma) { lambdaDot = Vector3d.zero; double desiredHeading = OrbitalManeuverCalculator.HeadingForInclination(inc, vesselState.latitude); Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north; Vector3d desiredThrustVector = Math.Cos(45 * UtilMath.Deg2Rad) * desiredHeadingVector + Math.Sin(45 * UtilMath.Deg2Rad) * vesselState.up; /* 45 pitch guess */ lambda = desiredThrustVector; Log.info("sma = {0}; deltaV guess = {1}", sma, approximateDeltaV(sma)); return(new PontryaginLaunch(core: core, mu: mainBody.gravParameter, r0: vesselState.orbitalPosition, v0: vesselState.orbitalVelocity, pv0: lambda, dV: approximateDeltaV(sma))); }
public override void OnFixedUpdate() { if (NavBallGuidance && autopilot != null && autopilot.ascentPath != null) { double angle = UtilMath.Deg2Rad * autopilot.ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface); double heading = UtilMath.Deg2Rad * OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel, vesselState, autopilot.desiredInclination); Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east; Vector3d dir = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up; core.target.UpdateDirectionTarget(dir); } }
public override void OnFixedUpdate() { if (NavBallGuidance && autopilot != null && autopilot.ascentPath != null) { double angle = Math.PI / 180 * autopilot.ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface); double heading = Math.PI / 180 * OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel.mainBody, autopilot.desiredInclination, launchLatitude, OrbitalManeuverCalculator.CircularOrbitSpeed(vessel.mainBody, autopilot.desiredOrbitAltitude + mainBody.Radius)); Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east; Vector3d dir = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up; core.target.UpdateDirectionTarget(dir); } }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { if (o.inclination < 10) { errorMessage = Localizer.Format("#MechJeb_AN_error", o.inclination);//"Warning: orbital plane has a low inclination of <<1>>º (recommend > 10º) and so maneuver may not be accurate" } double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); var dV = OrbitalManeuverCalculator.DeltaVToShiftLAN(o, UT, target.targetLongitude); return(new ManeuverParameters(dV, UT)); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (o.referenceBody.Radius + newApA < o.Radius(UT)) { string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m"; throw new OperationException(Localizer.Format("#MechJeb_Ap_Exception", burnAltitude));//new apoapsis cannot be lower than the altitude of the burn (<<1>>) } return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangeApoapsis(o, UT, newApA + o.referenceBody.Radius), UT)); }
/// <summary> /// Find the time to a target plane defined by the LAN and inc for a rocket on the ground. /// </summary> /// /// <param name="rotationPeriod">Rotation period of the central body (seconds).</param> /// <param name="latitude">Latitude of the launchite (degrees).</param> /// <param name="celestialLongitude">Celestial longitude of the current position of the launchsite.</param> /// <param name="LAN">Longitude of the Ascending Node of the target plane (degrees).</param> /// <param name="inc">Inclination of the target plane (degrees).</param> /// public static double TimeToPlane(double rotationPeriod, double latitude, double celestialLongitude, double LAN, double inc) { // alpha is the 90 degree angle between the line of longitude and the equator and omitted double beta = OrbitalManeuverCalculator.HeadingForInclination(inc, latitude) * UtilMath.Deg2Rad; double c = Math.Abs(latitude) * UtilMath.Deg2Rad; // Abs for south hemisphere launch sites // b is how many radians to the west of the launch site that the LAN is (east in south hemisphere) double b = Math.Atan2(2 * Math.Sin(beta), Math.Cos(beta) / Math.Tan(c / 2) + Math.Tan(c / 2) * Math.Cos(beta)); // napier's analogies // LAN if we launched now double LANnow = celestialLongitude - Math.Sign(latitude) * b * UtilMath.Rad2Deg; return(MuUtils.ClampDegrees360(LAN - LANnow) / 360 * rotationPeriod); }
void zeroMissObjectiveFunction(double[] x, double[] fi, object obj, Orbit initial_orbit, CelestialBody target, double UT_transfer, double UT_arrival) { Vector3d DV = new Vector3d(x[0], x[1], x[2]); Orbit orbit; OrbitalManeuverCalculator.PatchedConicInterceptBody(initial_orbit, target, DV, UT_transfer, UT_arrival, out orbit); Vector3d err = orbit.getTruePositionAtUT(UT_arrival) - target.orbit.getTruePositionAtUT(UT_arrival); fi[0] = err.x; fi[1] = err.y; fi[2] = err.z; }
void DriveCircularizationBurn(FlightCtrlState s) { if (!vessel.patchedConicsUnlocked() || skipCircularization) { this.users.Clear(); return; } if (placedCircularizeNode) { if (!vessel.patchedConicSolver.maneuverNodes.Any()) { MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>(); if (recorder != null) { launchPhaseAngle = recorder.phaseAngleFromMark; } if (recorder != null) { launchLANDifference = vesselState.orbitLAN - recorder.markLAN; } //finished circularize this.users.Clear(); return; } } else { //place circularization node vessel.RemoveAllManeuverNodes(); double UT = orbit.NextApoapsisTime(vesselState.time); //Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); Vector3d dV = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit, UT, desiredOrbitAltitude + mainBody.Radius); vessel.PlaceManeuverNode(orbit, dV, UT); placedCircularizeNode = true; core.node.ExecuteOneNode(this); } if (core.node.burnTriggered) { status = "Circularizing"; } else { status = "Coasting to circularization burn"; } }
public override void OnFixedUpdate() { if (markUT == 0) { Mark(); } timeSinceMark = vesselState.time - markUT; if (vessel.situation == Vessel.Situations.PRELAUNCH) { Mark(); //keep resetting stats until we launch return; } gravityLosses += vesselState.deltaT * Vector3d.Dot(-vesselState.surfaceVelocity.normalized, vesselState.gravityForce); gravityLosses -= vesselState.deltaT * Vector3d.Dot(vesselState.surfaceVelocity.normalized, vesselState.up * vesselState.radius * Math.Pow(2 * Math.PI / part.vessel.mainBody.rotationPeriod, 2)); dragLosses += vesselState.deltaT * vesselState.drag; maxDragGees = Math.Max(maxDragGees, vesselState.drag / 9.81); double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius); double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod; phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed); if (paused) { return; } //int oldHistoryIdx = historyIdx; //historyIdx = Mathf.Min(Mathf.FloorToInt((float)(timeSinceMark / precision)), history.Length - 1); if (vesselState.time >= (lastRecordTime + precision) && historyIdx < history.Length - 1) { lastRecordTime = vesselState.time; historyIdx++; Record(historyIdx); //if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH) // print("WRP " + historyIdx + " " + history[historyIdx].downRange.ToString("F0") + " " + history[historyIdx].AoA.ToString("F2")); //else //{ // print("STD " + historyIdx + " " + history[historyIdx].downRange.ToString("F0") + " " + history[historyIdx].AoA.ToString("F2")); //} } }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { if (!target.NormalTargetExists) { throw new OperationException(Localizer.Format("#MechJeb_match_v_Exception1"));//must select a target to match velocities with. } else if (o.referenceBody != target.TargetOrbit.referenceBody) { throw new OperationException(Localizer.Format("#MechJeb_match_v_Exception2"));//target must be in the same sphere of influence. } double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); var dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(o, UT, target.TargetOrbit); return(new ManeuverParameters(dV, UT)); }
public override void OnFixedUpdate() { if (ascentPath == null) { return; } if (core.target.Target != null && core.target.Name == TARGET_NAME) { double angle = Math.PI / 180 * ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface); double heading = Math.PI / 180 * OrbitalManeuverCalculator.HeadingForInclination(desiredInclination, vesselState.latitude); Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east; Vector3d dir = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up; core.target.UpdateDirectionTarget(dir); } }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (2 * newSMA > o.Radius(UT) + o.referenceBody.sphereOfInfluence) { errorMessage = Localizer.Format("#MechJeb_Sa_errormsg");//Warning: new Semi-Major Axis is very large, and may result in a hyberbolic orbit } if (o.Radius(UT) > 2 * newSMA) { throw new OperationException(Localizer.Format("#MechJeb_Sa_Exception") + o.referenceBody.displayName + "(" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");//cannot make Semi-Major Axis less than twice the burn altitude plus the radius of } return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(o, UT, newSMA), UT)); }
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 Exception("new periapsis cannot be higher than the altitude of the burn (" + burnAltitude + ")"); } else if (newPeA < -o.referenceBody.Radius) { throw new Exception("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)); }
void DriveCoastToApoapsis(FlightCtrlState s) { core.thrust.targetThrottle = 0; double circularSpeed = OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, orbit.ApR); double apoapsisSpeed = orbit.SwappedOrbitalVelocityAtUT(orbit.NextApoapsisTime(vesselState.time)).magnitude; double circularizeBurnTime = (circularSpeed - apoapsisSpeed) / vesselState.limitedMaxThrustAccel; //Once we get above the atmosphere, plan and execute the circularization maneuver. //For orbits near the edge of the atmosphere, we can't wait until we break the atmosphere //to start the burn, so we also compare the timeToAp with the expected circularization burn time. //if ((vesselState.altitudeASL > mainBody.RealMaxAtmosphereAltitude()) // || (vesselState.limitedMaxThrustAccel > 0 && orbit.timeToAp < circularizeBurnTime / 1.8)) // Sarbian : removed the special case for now. Some ship where turning whil still in atmosphere if (vesselState.altitudeASL > mainBody.RealMaxAtmosphereAltitude()) { mode = AscentMode.CIRCULARIZE; core.warp.MinimumWarp(); return; } //if our apoapsis has fallen too far, resume the gravity turn if (orbit.ApA < desiredOrbitAltitude - 1000.0) { mode = AscentMode.GRAVITY_TURN; core.warp.MinimumWarp(); return; } //point prograde and thrust gently if our apoapsis falls below the target core.attitude.attitudeTo(Vector3d.forward, AttitudeReference.ORBIT, this); core.thrust.targetThrottle = 0; if (autoThrottle && orbit.ApA < desiredOrbitAltitude) { core.thrust.targetThrottle = ThrottleToRaiseApoapsis(orbit.ApR, desiredOrbitAltitude + mainBody.Radius); } if (core.node.autowarp) { //warp at x2 physical warp: core.warp.WarpPhysicsAtRate(2); } status = "Coasting to edge of atmosphere"; }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { if (!target.NormalTargetExists) { throw new Exception("must select a target to intercept."); } if (o.referenceBody != target.TargetOrbit.referenceBody) { throw new Exception("target must be in the same sphere of influence."); } double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); var dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(o, UT, target.TargetOrbit, UT + interceptInterval); return(new ManeuverParameters(dV, UT)); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { if (o.eccentricity > 0.2) { errorMessage = Localizer.Format("#MechJeb_return_errormsg_1") + o.eccentricity.ToString("F2") + Localizer.Format("#MechJeb_return_errormsg_2");//"Warning: Recommend starting moon returns from a near-circular orbit (eccentricity < 0.2). Planned return is starting from an orbit with eccentricity "" and so may not be accurate." } if (o.referenceBody.referenceBody == null) { throw new OperationException(o.referenceBody.displayName + Localizer.Format("#MechJeb_return_Exception"));// is not orbiting another body you could return to. } double UT; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForMoonReturnEjection(o, universalTime, o.referenceBody.referenceBody.Radius + moonReturnAltitude, out UT); return(new ManeuverParameters(dV, UT)); }
void DriveVerticalAscent(FlightCtrlState s) { if (timedLaunch) { status = "Awaiting liftoff"; core.attitude.AxisControl(false, false, false); return; } if (!ascentPath.IsVerticalAscent(vesselState.altitudeASL, vesselState.speedSurface)) { mode = AscentMode.GRAVITY_TURN; } if (autoThrottle && orbit.ApA > desiredOrbitAltitude) { mode = AscentMode.COAST_TO_APOAPSIS; } //during the vertical ascent we just thrust straight up at max throttle if (forceRoll) { // pre-align roll unless correctiveSteering is active as it would just interfere with that double desiredHeading = OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel.mainBody, desiredInclination, launchLatitude, OrbitalManeuverCalculator.CircularOrbitSpeed(vessel.mainBody, desiredOrbitAltitude + mainBody.Radius)); core.attitude.attitudeTo(desiredHeading, 90, verticalRoll, this); } else { core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, this); } core.attitude.AxisControl(!vessel.Landed, !vessel.Landed, !vessel.Landed && vesselState.altitudeBottom > 50); if (autoThrottle) { core.thrust.targetThrottle = 1.0F; } if (!vessel.LiftedOff() || vessel.Landed) { status = "Awaiting liftoff"; } else { status = "Vertical ascent"; } }
public void TargetPeInsertMatchInc(double PeA, double ApA, double inc, bool omitCoast) { if (status == PVGStatus.ENABLED) { return; } bool doupdate = false; double v0m, r0m, sma; ConvertToRadVel(PeA, ApA, out r0m, out v0m, out sma); if (r0m != old_r0m || v0m != old_v0m || inc != old_inc) { //Debug.Log("old settings changed"); doupdate = true; } if (p == null || doupdate) { if (p != null) { //Debug.Log("killing a thread if its there to kill"); p.KillThread(); } //Debug.Log("mainbody.Radius = " + mainBody.Radius); //Debug.Log("mainbody.gravParameter = " + mainBody.gravParameter); lambdaDot = Vector3d.zero; double desiredHeading = OrbitalManeuverCalculator.HeadingForInclination(inc, vesselState.latitude); Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north; Vector3d desiredThrustVector = Math.Cos(45 * UtilMath.Deg2Rad) * desiredHeadingVector + Math.Sin(45 * UtilMath.Deg2Rad) * vesselState.up; /* 45 pitch guess */ lambda = desiredThrustVector; PontryaginLaunch solver = new PontryaginLaunch(core: core, mu: mainBody.gravParameter, r0: vesselState.orbitalPosition, v0: vesselState.orbitalVelocity, pv0: lambda.normalized, pr0: Vector3d.zero, dV: v0m); solver.omitCoast = omitCoast; solver.flightangle4constraint(r0m, v0m, 0, inc * UtilMath.Deg2Rad); p = solver; } old_v0m = v0m; old_r0m = r0m; old_inc = inc; }
public override ManeuverParameters MakeNodeImpl(Orbit o, double UT, MechJebModuleTargetController target) { // Check preconditions if (!target.NormalTargetExists) { throw new Exception("must select a target for the interplanetary transfer."); } if (o.referenceBody.referenceBody == null) { throw new Exception("doesn't make sense to plot an interplanetary transfer from an orbit around " + o.referenceBody.theName + "."); } if (o.referenceBody.referenceBody != target.TargetOrbit.referenceBody) { if (o.referenceBody == target.TargetOrbit.referenceBody) { throw new Exception("use regular Hohmann transfer function to intercept another body orbiting " + o.referenceBody.theName + "."); } throw new Exception("an interplanetary transfer from within " + o.referenceBody.theName + "'s sphere of influence must target a body that orbits " + o.referenceBody.theName + "'s parent, " + o.referenceBody.referenceBody.theName + "."); } // Simple warnings if (o.referenceBody.orbit.RelativeInclination(target.TargetOrbit) > 30) { errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(target.TargetOrbit).ToString("F0") + "º angle to " + o.referenceBody.theName + "'s orbital plane (recommend at most 30º). Planned interplanetary transfer may not intercept target properly."; } else { double relativeInclination = Vector3d.Angle(o.SwappedOrbitNormal(), o.referenceBody.orbit.SwappedOrbitNormal()); if (relativeInclination > 10) { errorMessage = "Warning: Recommend starting interplanetary transfers from " + o.referenceBody.theName + " from an orbit in the same plane as " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + ". Starting orbit around " + o.referenceBody.theName + " is inclined " + relativeInclination.ToString("F1") + "º with respect to " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + " (recommend < 10º). Planned transfer may not intercept target properly."; } else if (o.eccentricity > 0.2) { errorMessage = "Warning: Recommend starting interplanetary transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly."; } } var dV = OrbitalManeuverCalculator.DeltaVAndTimeForInterplanetaryTransferEjection(o, UT, target.TargetOrbit, waitForPhaseAngle, out UT); return(new ManeuverParameters(dV, UT)); }