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); }
void ComputeDeltaV(object args) { CelestialBody origin_planet = origin.referenceBody; for (int date_index = TakeDateIndex(); date_index >= 0; date_index = TakeDateIndex()) { double t0 = DateFromIndex(date_index); Vector3d V1_0 = origin_planet.orbit.getOrbitalVelocityAtUT(t0); Vector3d R1 = origin_planet.orbit.getRelativePositionAtUT(t0); int duration_samples = DurationSamplesForDate(date_index); for (int duration_index = 0; duration_index < duration_samples; duration_index++) { if (stop) { break; } double dt = DurationFromIndex(duration_index); double t1 = t0 + dt; Vector3d R2 = destination.getRelativePositionAtUT(t1); bool short_way = Vector3d.Dot(Vector3d.Cross(R1, R2), origin_planet.orbit.GetOrbitNormal()) > 0; try { Vector3d V1, V2; #if DEBUG log[date_index, duration_index] = dt + "," + R1.x + "," + R1.y + "," + R1.z + "," + R2.x + "," + R2.y + "," + R2.z + "," + V1_0.x + "," + V1_0.y + "," + V1_0.z; #endif LambertSolver.Solve(R1, R2, dt, origin_planet.referenceBody, short_way, out V1, out V2); #if DEBUG log[date_index, duration_index] += "," + V1.x + "," + V1.y + "," + V1.z; #endif Vector3d soi_exit_velocity = V1 - V1_0; var maneuver = ComputeEjectionManeuver(soi_exit_velocity, origin, t0); if (!double.IsNaN(maneuver.dV.sqrMagnitude) && !double.IsNaN(maneuver.UT)) { computed[date_index, duration_index] = maneuver; } #if DEBUG log[date_index, duration_index] += "," + maneuver.dV.magnitude; #endif } catch (Exception) {} } } JobFinished(); }
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); }
//Computes the delta-V of a burn at a given time that will put an object with a given orbit on a //course to intercept a target at a specific interceptUT. public static Vector3d DeltaVToInterceptAtTime(Orbit o, double UT, Orbit target, double interceptUT, double leadDistance = 0) { double initialT = UT; Vector3d initialRelPos = o.SwappedRelativePositionAtUT(initialT); double finalT = interceptUT; Vector3d finalRelPos = target.SwappedRelativePositionAtUT(finalT); finalRelPos += leadDistance * target.SwappedOrbitalVelocityAtUT(finalT).normalized; double targetOrbitalSpeed = o.SwappedOrbitalVelocityAtUT(finalT).magnitude; double deltaTPrecision = 20.0 / targetOrbitalSpeed; Vector3d initialVelocity, finalVelocity; LambertSolver.Solve(initialRelPos, finalRelPos, finalT - initialT, o.referenceBody, true, out initialVelocity, out finalVelocity); Vector3d currentInitialVelocity = o.SwappedOrbitalVelocityAtUT(initialT); return(initialVelocity - currentInitialVelocity); }
//Computes the delta-V of a burn at a given time that will put an object with a given orbit on a //course to intercept a target at a specific interceptUT. public static Vector3d DeltaVToInterceptAtTime(Orbit o, double UT, Orbit target, double interceptUT, double offsetDistance = 0, bool shortway = true) { double initialT = UT; Vector3d initialRelPos = o.SwappedRelativePositionAtUT(initialT); double finalT = interceptUT; Vector3d finalRelPos = target.SwappedRelativePositionAtUT(finalT); Vector3d initialVelocity, finalVelocity; LambertSolver.Solve(initialRelPos, finalRelPos, finalT - initialT, o.referenceBody, shortway, out initialVelocity, out finalVelocity); if (offsetDistance != 0) { finalRelPos += offsetDistance * Vector3d.Cross(finalVelocity, finalRelPos).normalized; LambertSolver.Solve(initialRelPos, finalRelPos, finalT - initialT, o.referenceBody, shortway, out initialVelocity, out finalVelocity); } Vector3d currentInitialVelocity = o.SwappedOrbitalVelocityAtUT(initialT); return(initialVelocity - currentInitialVelocity); }