本文整理汇总了C#中Orbit.PerturbedOrbit方法的典型用法代码示例。如果您正苦于以下问题:C# Orbit.PerturbedOrbit方法的具体用法?C# Orbit.PerturbedOrbit怎么用?C# Orbit.PerturbedOrbit使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Orbit
的用法示例。
在下文中一共展示了Orbit.PerturbedOrbit方法的8个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: DeltaVAndTimeForCheapestCourseCorrection
public static Vector3d DeltaVAndTimeForCheapestCourseCorrection(Orbit o, double UT, Orbit target, CelestialBody targetBody, double finalPeR, out double burnUT)
{
Vector3d collisionDV = DeltaVAndTimeForCheapestCourseCorrection(o, UT, target, out burnUT);
Orbit collisionOrbit = o.PerturbedOrbit(burnUT, collisionDV);
double collisionUT = collisionOrbit.NextClosestApproachTime(target, burnUT);
Vector3d collisionPosition = target.SwappedAbsolutePositionAtUT(collisionUT);
Vector3d collisionRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(collisionUT) - target.SwappedOrbitalVelocityAtUT(collisionUT);
double soiEnterUT = collisionUT - targetBody.sphereOfInfluence / collisionRelVel.magnitude;
Vector3d soiEnterRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(soiEnterUT) - target.SwappedOrbitalVelocityAtUT(soiEnterUT);
double E = 0.5 * soiEnterRelVel.sqrMagnitude - targetBody.gravParameter / targetBody.sphereOfInfluence; //total orbital energy on SoI enter
double finalPeSpeed = Math.Sqrt(2 * (E + targetBody.gravParameter / finalPeR)); //conservation of energy gives the orbital speed at finalPeR.
double desiredImpactParameter = finalPeR * finalPeSpeed / soiEnterRelVel.magnitude; //conservation of angular momentum gives the required impact parameter
Vector3d displacementDir = Vector3d.Cross(collisionRelVel, o.SwappedOrbitNormal()).normalized;
Vector3d interceptTarget = collisionPosition + desiredImpactParameter * displacementDir;
Vector3d velAfterBurn;
Vector3d arrivalVel;
LambertSolver.Solve(o.SwappedRelativePositionAtUT(burnUT), interceptTarget - o.referenceBody.position, collisionUT - burnUT, o.referenceBody, true, out velAfterBurn, out arrivalVel);
Vector3d deltaV = velAfterBurn - o.SwappedOrbitalVelocityAtUT(burnUT);
return deltaV;
}
示例2: DeltaVToChangePeriapsis
//Computes the delta-V of the burn required to attain a given periapsis, starting from
//a given orbit and burning at a given UT. Throws an ArgumentException if given an impossible periapsis.
//The computed burn is always horizontal, though this may not be strictly optimal.
public static Vector3d DeltaVToChangePeriapsis(Orbit o, double UT, double newPeR)
{
double radius = o.Radius(UT);
//sanitize input
newPeR = MuUtils.Clamp(newPeR, 0 + 1, radius - 1);
//are we raising or lowering the periapsis?
bool raising = (newPeR > o.PeR);
Vector3d burnDirection = (raising ? 1 : -1) * o.Horizontal(UT);
double minDeltaV = 0;
double maxDeltaV;
if (raising)
{
//put an upper bound on the required deltaV:
maxDeltaV = 0.25;
while (o.PerturbedOrbit(UT, maxDeltaV * burnDirection).PeR < newPeR)
{
maxDeltaV *= 2;
if (maxDeltaV > 100000) break; //a safety precaution
}
}
else
{
//when lowering periapsis, we burn horizontally, and max possible deltaV is the deltaV required to kill all horizontal velocity
maxDeltaV = Math.Abs(Vector3d.Dot(o.SwappedOrbitalVelocityAtUT(UT), burnDirection));
}
//now do a binary search to find the needed delta-v
while (maxDeltaV - minDeltaV > 0.01)
{
double testDeltaV = (maxDeltaV + minDeltaV) / 2.0;
double testPeriapsis = o.PerturbedOrbit(UT, testDeltaV * burnDirection).PeR;
if ((testPeriapsis > newPeR && raising) || (testPeriapsis < newPeR && !raising))
{
maxDeltaV = testDeltaV;
}
else
{
minDeltaV = testDeltaV;
}
}
return ((maxDeltaV + minDeltaV) / 2) * burnDirection;
}
示例3: DeltaVAndTimeForCheapestCourseCorrection
public static Vector3d DeltaVAndTimeForCheapestCourseCorrection(Orbit o, double UT, Orbit target, double caDistance, out double burnUT)
{
Vector3d collisionDV = DeltaVAndTimeForCheapestCourseCorrection(o, UT, target, out burnUT);
Orbit collisionOrbit = o.PerturbedOrbit(burnUT, collisionDV);
double collisionUT = collisionOrbit.NextClosestApproachTime(target, burnUT);
Vector3d position = o.SwappedAbsolutePositionAtUT(collisionUT);
Vector3d targetPos = target.SwappedAbsolutePositionAtUT(collisionUT);
Vector3d direction = targetPos - position;
Vector3d interceptTarget = targetPos + target.NormalPlus(collisionUT) * caDistance;
Vector3d velAfterBurn;
Vector3d arrivalVel;
LambertSolver.Solve(o.SwappedRelativePositionAtUT(burnUT), interceptTarget - o.referenceBody.position, collisionUT - burnUT, o.referenceBody, true, out velAfterBurn, out arrivalVel);
Vector3d deltaV = velAfterBurn - o.SwappedOrbitalVelocityAtUT(burnUT);
return deltaV;
}
示例4: DeltaVAndTimeForHohmannTransfer
//Computes the time and dV of a Hohmann transfer injection burn such that at apoapsis the transfer
//orbit passes as close as possible to the target.
//The output burnUT will be the first transfer window found after the given UT.
//Assumes o and target are in approximately the same plane, and orbiting in the same direction.
//Also assumes that o is a perfectly circular orbit (though result should be OK for small eccentricity).
public static Vector3d DeltaVAndTimeForHohmannTransfer(Orbit o, Orbit target, double UT, out double burnUT)
{
double synodicPeriod = o.SynodicPeriod(target);
Vector3d burnDV = Vector3d.zero;
burnUT = UT;
double bestApproachDistance = Double.MaxValue;
double minTime = UT;
double maxTime = UT + 1.1 * synodicPeriod;
int numDivisions = 20;
for (int iter = 0; iter < 8; iter++)
{
double dt = (maxTime - minTime) / numDivisions;
for (int i = 0; i < numDivisions; i++)
{
double t = minTime + i * dt;
Vector3d apsisDirection = -o.SwappedRelativePositionAtUT(t);
double desiredApsis = target.RadiusAtTrueAnomaly(target.TrueAnomalyFromVector(apsisDirection));
double approachDistance;
Vector3d burn;
if (desiredApsis > o.ApR)
{
burn = DeltaVToChangeApoapsis(o, t, desiredApsis);
Orbit transferOrbit = o.PerturbedOrbit(t, burn);
approachDistance = transferOrbit.Separation(target, transferOrbit.NextApoapsisTime(t));
}
else
{
burn = DeltaVToChangePeriapsis(o, t, desiredApsis);
Orbit transferOrbit = o.PerturbedOrbit(t, burn);
approachDistance = transferOrbit.Separation(target, transferOrbit.NextPeriapsisTime(t));
}
if (approachDistance < bestApproachDistance)
{
bestApproachDistance = approachDistance;
burnUT = t;
burnDV = burn;
}
}
minTime = MuUtils.Clamp(burnUT - dt, UT, UT + synodicPeriod);
maxTime = MuUtils.Clamp(burnUT + dt, UT, UT + synodicPeriod);
}
return burnDV;
}
示例5: DeltaVToChangeApoapsis
//Computes the delta-V of the burn at a given UT required to change an orbits apoapsis to a given value.
//The computed burn is always prograde or retrograde, though this may not be strictly optimal.
//Note that you can pass in a negative apoapsis if the desired final orbit is hyperbolic
public static Vector3d DeltaVToChangeApoapsis(Orbit o, double UT, double newApR)
{
double radius = o.Radius(UT);
//sanitize input
if (newApR > 0) newApR = Math.Max(newApR, radius + 1);
//are we raising or lowering the periapsis?
bool raising = ApoapsisIsHigher(newApR, o.ApR);
Vector3d burnDirection = (raising ? 1 : -1) * o.Prograde(UT);
double minDeltaV = 0;
double maxDeltaV;
if (raising)
{
//put an upper bound on the required deltaV:
maxDeltaV = 0.25;
double ap = o.ApR;
while (ApoapsisIsHigher(newApR, ap))
{
maxDeltaV *= 2;
ap = o.PerturbedOrbit(UT, maxDeltaV * burnDirection).ApR;
if (maxDeltaV > 100000) break; //a safety precaution
}
}
else
{
//when lowering apoapsis, we burn retrograde, and max possible deltaV is total velocity
maxDeltaV = o.SwappedOrbitalVelocityAtUT(UT).magnitude;
}
//now do a binary search to find the needed delta-v
while (maxDeltaV - minDeltaV > 0.01)
{
double testDeltaV = (maxDeltaV + minDeltaV) / 2.0;
double testApoapsis = o.PerturbedOrbit(UT, testDeltaV * burnDirection).ApR;
bool above = ApoapsisIsHigher(testApoapsis, newApR);
if ((raising && above) || (!raising && !above))
{
maxDeltaV = testDeltaV;
}
else
{
minDeltaV = testDeltaV;
}
}
return ((maxDeltaV + minDeltaV) / 2) * burnDirection;
}
示例6: DeltaVForSemiMajorAxis
public static Vector3d DeltaVForSemiMajorAxis(Orbit o, double UT, double newSMA)
{
bool raising = o.semiMajorAxis < newSMA;
Vector3d burnDirection = (raising ? 1 : -1) * o.Prograde(UT);
double minDeltaV = 0;
double maxDeltaV;
if (raising)
{
//put an upper bound on the required deltaV:
maxDeltaV = 0.25;
while (o.PerturbedOrbit(UT, maxDeltaV * burnDirection).semiMajorAxis < newSMA)
{
maxDeltaV *= 2;
if (maxDeltaV > 100000)
break; //a safety precaution
}
}
else
{
//when lowering the SMA, we burn horizontally, and max possible deltaV is the deltaV required to kill all horizontal velocity
maxDeltaV = Math.Abs(Vector3d.Dot(o.SwappedOrbitalVelocityAtUT(UT), burnDirection));
}
// Debug.Log (String.Format ("We are {0} SMA to {1}", raising ? "raising" : "lowering", newSMA));
// Debug.Log (String.Format ("Starting SMA iteration with maxDeltaV of {0}", maxDeltaV));
//now do a binary search to find the needed delta-v
while (maxDeltaV - minDeltaV > 0.01)
{
double testDeltaV = (maxDeltaV + minDeltaV) / 2.0;
double testSMA = o.PerturbedOrbit(UT, testDeltaV * burnDirection).semiMajorAxis;
// Debug.Log (String.Format ("Testing dV of {0} gave an SMA of {1}", testDeltaV, testSMA));
if ((testSMA < 0) || (testSMA > newSMA && raising) || (testSMA < newSMA && !raising))
{
maxDeltaV = testDeltaV;
}
else
{
minDeltaV = testDeltaV;
}
}
return ((maxDeltaV + minDeltaV) / 2) * burnDirection;
}
示例7: DeltaVAndTimeForHohmannLambertTransfer
//Like DeltaVAndTimeForHohmannTransfer, but adds an additional step that uses the Lambert
//solver to adjust the initial burn to produce an exact intercept instead of an approximate
public static Vector3d DeltaVAndTimeForHohmannLambertTransfer(Orbit o, Orbit target, double UT, out double burnUT, double subtractProgradeDV = 0)
{
Vector3d hohmannDV = DeltaVAndTimeForHohmannTransfer(o, target, UT, out burnUT);
Vector3d subtractedProgradeDV = subtractProgradeDV * hohmannDV.normalized;
Orbit hohmannOrbit = o.PerturbedOrbit(burnUT, hohmannDV);
double apsisTime; //approximate target intercept time
if (hohmannOrbit.semiMajorAxis > o.semiMajorAxis) apsisTime = hohmannOrbit.NextApoapsisTime(burnUT);
else apsisTime = hohmannOrbit.NextPeriapsisTime(burnUT);
Debug.Log("hohmannDV = " + (Vector3)hohmannDV + ", apsisTime = " + apsisTime);
Vector3d dV = Vector3d.zero;
double minCost = 999999;
double minInterceptTime = apsisTime - hohmannOrbit.period / 4;
double maxInterceptTime = apsisTime + hohmannOrbit.period / 4;
const int subdivisions = 30;
for (int i = 0; i < subdivisions; i++)
{
double interceptUT = minInterceptTime + i * (maxInterceptTime - minInterceptTime) / subdivisions;
Debug.Log("i + " + i + ", trying for intercept at UT = " + interceptUT);
//Try both short and long way
bool shortway = true;
Vector3d interceptBurn = DeltaVToInterceptAtTime(o, burnUT, target, interceptUT, 0, shortway);
double cost = (interceptBurn - subtractedProgradeDV).magnitude;
Debug.Log("short way dV = " + interceptBurn.magnitude + "; subtracted cost = " + cost);
if (cost < minCost)
{
dV = interceptBurn;
minCost = cost;
}
shortway = false;
interceptBurn = DeltaVToInterceptAtTime(o, burnUT, target, interceptUT, 0, shortway);
cost = (interceptBurn - subtractedProgradeDV).magnitude;
Debug.Log("long way dV = " + interceptBurn.magnitude + "; subtracted cost = " + cost);
if (cost < minCost)
{
dV = interceptBurn;
minCost = cost;
}
}
return dV;
}
示例8: DeltaVAndApsisPhaseAngleOfHohmannTransfer
//Computes the dV of a Hohmann transfer burn at time UT that will put the apoapsis or periapsis
//of the transfer orbit on top of the target orbit.
//The output value apsisPhaseAngle is the phase angle between the transferring vessel and the
//target object as the transferring vessel crosses the target orbit at the apoapsis or periapsis
//of the transfer orbit.
//Actually, it's not exactly the phase angle. It's a sort of mean anomaly phase angle. The
//difference is not important for how this function is used by DeltaVAndTimeForHohmannTransfer.
private static Vector3d DeltaVAndApsisPhaseAngleOfHohmannTransfer(Orbit o, Orbit target, double UT, out double apsisPhaseAngle)
{
Vector3d apsisDirection = -o.SwappedRelativePositionAtUT(UT);
double desiredApsis = target.RadiusAtTrueAnomaly(MathExtensions.Deg2Rad * target.TrueAnomalyFromVector(apsisDirection));
Vector3d dV;
if (desiredApsis > o.ApR)
{
dV = DeltaVToChangeApoapsis(o, UT, desiredApsis);
Orbit transferOrbit = o.PerturbedOrbit(UT, dV);
double transferApTime = transferOrbit.NextApoapsisTime(UT);
Vector3d transferApDirection = transferOrbit.SwappedRelativePositionAtApoapsis(); // getRelativePositionAtUT was returning NaNs! :(((((
double targetTrueAnomaly = target.TrueAnomalyFromVector(transferApDirection);
double meanAnomalyOffset = 360 * (target.TimeOfTrueAnomaly(targetTrueAnomaly, UT) - transferApTime) / target.period;
apsisPhaseAngle = meanAnomalyOffset;
}
else
{
dV = DeltaVToChangePeriapsis(o, UT, desiredApsis);
Orbit transferOrbit = o.PerturbedOrbit(UT, dV);
double transferPeTime = transferOrbit.NextPeriapsisTime(UT);
Vector3d transferPeDirection = transferOrbit.SwappedRelativePositionAtPeriapsis(); // getRelativePositionAtUT was returning NaNs! :(((((
double targetTrueAnomaly = target.TrueAnomalyFromVector(transferPeDirection);
double meanAnomalyOffset = 360 * (target.TimeOfTrueAnomaly(targetTrueAnomaly, UT) - transferPeTime) / target.period;
apsisPhaseAngle = meanAnomalyOffset;
}
apsisPhaseAngle = MuUtils.ClampDegrees180(apsisPhaseAngle);
return dV;
}