Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions MechJeb2/MechJeb2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,11 @@
<ProjectReference Include="..\MechJebLib\MechJebLib.csproj"/>
</ItemGroup>

<Target Name="MechJebCopyBuild" AfterTargets="Build" Condition=" '$(OS)' == 'Windows_NT' ">
<Exec Command="call &quot;$(ProjectDir)copy_build.bat&quot; &quot;$(TargetPath)&quot; &quot;$(TargetDir)&quot; &quot;$(TargetName)&quot; &quot;$(ProjectDir)&quot;"/>
</Target>

<Target Name="MechJebCopyBuild" AfterTargets="Build" Condition=" '$(OS)' != 'Windows_NT' ">
<Exec Command="'$(ProjectDir)/copy_build.sh' '$(TargetPath)' '$(TargetDir)' '$(TargetName)' '$(ProjectDir)' '$(KspDir)'"/>
<Target Name="MechJebCopyBuild" AfterTargets="Build">
<Exec Condition=" '$(OS)' == 'Windows_NT' "
Command="call &quot;$(ProjectDir)copy_build.bat&quot; &quot;$(TargetPath)&quot; &quot;$(TargetDir)&quot; &quot;$(TargetName)&quot; &quot;$(ProjectDir)&quot;"/>
<Exec Condition=" '$(OS)' != 'Windows_NT' "
Command="'$(ProjectDir)/copy_build.sh' '$(TargetPath)' '$(TargetDir)' '$(TargetName)' '$(ProjectDir)' '$(KspDir)'"/>
</Target>

</Project>
14 changes: 10 additions & 4 deletions MechJeb2/OrbitalManeuverCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,22 @@ public static Vector3d DeltaVAndTimeToMatchPlanesDescending(Orbit o, Orbit targe
//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 dV1, double UT1, Vector3d dV2, double UT2) DeltaVAndTimeForHohmannTransfer(Orbit o, Orbit target, double ut,
public static (Vector3d dV1, double UT1, Vector3d dV2, double UT2) DeltaVAndTimeForHohmannTransfer(Orbit o, Orbit target, double ut,
double lagTime = double.NaN, bool fixedTime = false,
bool coplanar = true, bool rendezvous = true, bool capture = true)
{
(V3 r1, V3 v1) = o.RightHandedStateVectorsAtUT(ut);
(V3 r2, V3 v2) = target.RightHandedStateVectorsAtUT(ut);

double minPeR = double.NegativeInfinity;
if (o.referenceBody.atmosphere)
{
minPeR = o.referenceBody.Radius + o.referenceBody.atmosphereDepth;
}

(V3 dv1, double dt1, V3 dv2, double dt2) =
TwoImpulseTransfer.NextManeuver(o.referenceBody.gravParameter, r1, v1, r2, v2, lagTime: lagTime, coplanar: coplanar,
rendezvous: rendezvous, capture: capture);
rendezvous: rendezvous, capture: capture, fixedTime: fixedTime, minPeR: minPeR);

return (dv1.V3ToWorld(), ut + dt1, dv2.V3ToWorld(), ut + dt2);
}
Expand Down Expand Up @@ -429,8 +435,8 @@ public static Vector3d DeltaVToShiftNodeLongitude(Orbit o, double UT, double new
//

public static readonly Pool<Orbit> OrbitPool = new Pool<Orbit>(createOrbit, resetOrbit);
private static Orbit createOrbit() => new Orbit();
private static void resetOrbit(Orbit o) { }
private static Orbit createOrbit() => new Orbit();
private static void resetOrbit(Orbit o) { }

private static readonly PatchedConics.SolverParameters solverParameters = new PatchedConics.SolverParameters();

Expand Down
20 changes: 10 additions & 10 deletions MechJeb2/copy_build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,34 @@ IF NOT EXIST "%KSPDIR%\*" (
echo:
echo Copying to "%KSPDIR%"
echo:
IF EXIST %TargetPath% xcopy /Y /I %TargetPath% "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetPath%" xcopy /Y /I "%TargetPath%" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%%TargetName%.pdb xcopy /Y /I "%TargetDir%%TargetName%.pdb" "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%%TargetName%.pdb" xcopy /Y /I "%TargetDir%%TargetName%.pdb" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%JetBrains.Annotations.dll xcopy /Y /I "%TargetDir%JetBrains.Annotations.dll "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%JetBrains.Annotations.dll" xcopy /Y /I "%TargetDir%JetBrains.Annotations.dll" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%JetBrains.Annotations.xml xcopy /Y /I "%TargetDir%JetBrains.Annotations.xml "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%JetBrains.Annotations.xml" xcopy /Y /I "%TargetDir%JetBrains.Annotations.xml" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%MechJebLib.dll xcopy /Y /I "%TargetDir%MechJebLib.dll "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%MechJebLib.dll" xcopy /Y /I "%TargetDir%MechJebLib.dll" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%MechJebLib.pdb xcopy /Y /I "%TargetDir%MechJebLib.pdb "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%MechJebLib.pdb" xcopy /Y /I "%TargetDir%MechJebLib.pdb" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%MechJebLibBindings.dll xcopy /Y /I "%TargetDir%MechJebLibBindings.dll "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%MechJebLibBindings.dll" xcopy /Y /I "%TargetDir%MechJebLibBindings.dll" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%MechJebLibBindings.pdb xcopy /Y /I "%TargetDir%MechJebLibBindings.pdb "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%MechJebLibBindings.pdb" xcopy /Y /I "%TargetDir%MechJebLibBindings.pdb" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%alglib.dll xcopy /Y /I "%TargetDir%alglib.dll "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%alglib.dll" xcopy /Y /I "%TargetDir%alglib.dll" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %TargetDir%alglib.pdb xcopy /Y /I "%TargetDir%alglib.pdb "%KSPDIR%\GameData\MechJeb2\Plugins\"
IF EXIST "%TargetDir%alglib.pdb" xcopy /Y /I "%TargetDir%alglib.pdb" "%KSPDIR%\GameData\MechJeb2\Plugins\"
echo:

IF EXIST %ProjectDir%..\Bundles xcopy /S /Y /I "%ProjectDir%..\Bundles" "%KSPDIR%\GameData\MechJeb2\Bundles"
Expand Down
41 changes: 27 additions & 14 deletions MechJebLib/Maneuvers/TwoImpulseTransfer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ private struct Args
public V3 R2;
public V3 V2;
public bool Capture;
public double MinPeR;
}

private static (V3 dv1, V3 dv2) LambertFunction(double dt, double tt, double offset, Args args)
private static (V3 dv1, V3 dv2, double peR) LambertFunction(double dt, double tt, double offset, Args args)
{
V3 r1 = args.R1;
V3 v1 = args.V1;
Expand All @@ -37,7 +38,8 @@ private static (V3 dv1, V3 dv2) LambertFunction(double dt, double tt, double off
(V3 rf2, V3 vf2) = Shepperd.Solve(1.0, dt + tt + offset, r2, v2);
(V3 vi, V3 vf) = Izzo.Solve(1.0, rburn, rf2, tt, TransferGeometry.Prograde, 0, V3.Cross(rburn, vburn));

return (vi - vburn, vf2 - vf);
double peR = Astro.PeriapsisFromStateVectors(1.0, rburn, vi);
return (vi - vburn, vf2 - vf, peR);
}

private static void NLPFunction(double[] x, ref double func, object obj)
Expand All @@ -55,7 +57,16 @@ private static void NLPFunction(double[] x, ref double func, object obj)
return;
}

(V3 dv1, V3 dv2) = LambertFunction(dt, tt, offset, args);
(V3 dv1, V3 dv2, double peR) = LambertFunction(dt, tt, offset, args);

if (IsFinite(args.MinPeR) && peR < args.MinPeR)
{
double shortfall = args.MinPeR - peR;

// Keep a gradient toward valid space instead of returning a completely flat 1e300 region to the numerical optimizer.
func = 1e6 + shortfall * shortfall * 1e6;
return;
}

if (args.Capture)
func = dv1.magnitude + dv2.magnitude;
Expand All @@ -64,7 +75,7 @@ private static void NLPFunction(double[] x, ref double func, object obj)
}

private static (V3 dv1, double dt1, V3 dv2, double dt2) Maneuver(double mu, V3 r1, V3 v1, V3 r2, V3 v2, double dtguess, double offsetGuess,
bool coplanar = true, bool capture = true, double dtmin = double.NegativeInfinity,
bool coplanar = true, bool capture = true, double dtmin = double.NegativeInfinity, double minPeR = double.NegativeInfinity,
double dtmax = double.PositiveInfinity,
double ttmin = double.NegativeInfinity, double ttmax = double.PositiveInfinity, double offsetMin = double.NegativeInfinity,
double offsetMax = double.PositiveInfinity, bool optguard = false)
Expand Down Expand Up @@ -113,6 +124,7 @@ private static (V3 dv1, double dt1, V3 dv2, double dt2) Maneuver(double mu, V3 r
ttmax /= scale.TimeScale;
offsetMin /= scale.TimeScale;
offsetMax /= scale.TimeScale;
minPeR /= scale.LengthScale;

(_, _, double ttguess, _) = Astro.HohmannTransferParameters(1.0, r1, r2);

Expand All @@ -126,7 +138,8 @@ private static (V3 dv1, double dt1, V3 dv2, double dt2) Maneuver(double mu, V3 r
V1 = v1,
R2 = r2,
V2 = v2,
Capture = capture
Capture = capture,
MinPeR = minPeR
};

double[] bndl = { dtmin, ttmin, offsetMin };
Expand Down Expand Up @@ -161,14 +174,14 @@ private static (V3 dv1, double dt1, V3 dv2, double dt2) Maneuver(double mu, V3 r
throw new MechJebLibException("nonc1suspected error");
}

(V3 dv1, V3 dv2) = LambertFunction(x[0], x[1], x[2], args);
(V3 dv1, V3 dv2, _) = LambertFunction(x[0], x[1], x[2], args);

return (dv1 * scale.VelocityScale, x[0] * scale.TimeScale, dv2 * scale.VelocityScale, (x[0] + x[1]) * scale.TimeScale);
}

private static (V3 dv1, double dt1, V3 dv2, double dt2) ManeuverInternal(double mu, V3 r1, V3 v1, V3 r2, V3 v2, double dtguess,
double lagTime = double.NaN, bool coplanar = true, bool rendezvous = true, bool capture = true,
bool fixedtime = false, bool optguard = false)
bool fixedtime = false, bool optguard = false, double minPeR = double.NegativeInfinity)
{
V3 dv1, dv2;
double dt1, dt2;
Expand Down Expand Up @@ -196,20 +209,20 @@ private static (V3 dv1, double dt1, V3 dv2, double dt2) ManeuverInternal(double

(dv1, dt1, dv2, dt2) =
Maneuver(mu, r1, v1, r2, v2, dtguess, offsetGuess, dtmin: dtmin, dtmax: dtmax, offsetMin: offsetMin, offsetMax: offsetMax,
coplanar: coplanar, capture: capture, optguard: optguard);
coplanar: coplanar, capture: capture, optguard: optguard, minPeR: minPeR);
}
else
{
(dv1, dt1, dv2, dt2) =
Maneuver(mu, r1, v1, r2, v2, dtguess, 0, dtmin: dtmin, dtmax: dtmax, coplanar: coplanar, capture: capture, optguard: optguard);
Maneuver(mu, r1, v1, r2, v2, dtguess, 0, dtmin: dtmin, dtmax: dtmax, coplanar: coplanar, capture: capture, optguard: optguard, minPeR: minPeR);

// we have to try the other side of the target orbit since we might get eg. the DN instead of the AN when the AN is closer
// (this may be insufficient and may need more of a search box but then we're O(N^2) and i think basinhopping or porkchop
// plots will be the better solution)
double targetPeriod = Astro.PeriodFromStateVectors(mu, r2, v2);

(V3 a, double b, V3 c, double d) =
Maneuver(mu, r1, v1, r2, v2, dtguess, targetPeriod * 0.5, coplanar, capture, optguard: optguard);
Maneuver(mu, r1, v1, r2, v2, dtguess, targetPeriod * 0.5, coplanar, capture, optguard: optguard, minPeR: minPeR);

if (b > 0 && (b < dt1 || dt1 < 0))
{
Expand All @@ -225,21 +238,21 @@ private static (V3 dv1, double dt1, V3 dv2, double dt2) ManeuverInternal(double

public static (V3 dv1, double dt1, V3 dv2, double dt2) NextManeuver(double mu, V3 r1, V3 v1, V3 r2, V3 v2, int maxiter = 50,
double lagTime = double.NaN, bool coplanar = true, bool rendezvous = true, bool capture = true,
bool fixedTime = false, bool optguard = false)
bool fixedTime = false, bool optguard = false, double minPeR = double.NegativeInfinity)
{
Print($"[MechJebLib] Maneuvers.NextManeuver.TwoImpulseTransfer({mu}, {r1}, {r2}, {v1}, {v2}, maxiter: {maxiter}, lagTime: {lagTime}, coplanar: {coplanar}, rendezvous: {rendezvous}, capture: {capture}, fixedTime: {fixedTime}, optguard: {optguard})");
Print($"[MechJebLib] Maneuvers.NextManeuver.TwoImpulseTransfer({mu}, {r1}, {r2}, {v1}, {v2}, maxiter: {maxiter}, lagTime: {lagTime}, coplanar: {coplanar}, rendezvous: {rendezvous}, capture: {capture}, fixedTime: {fixedTime}, optguard: {optguard}, minPeR: {minPeR})");

double synodicPeriod = Astro.SynodicPeriod(mu, r1, v1, r2, v2);

if (fixedTime)
return ManeuverInternal(mu, r1, v1, r2, v2, 0, coplanar: coplanar, rendezvous: rendezvous, capture: capture, optguard: optguard,
lagTime: lagTime, fixedtime: true);
lagTime: lagTime, fixedtime: true, minPeR: minPeR);

double dtguess = 0;
for (int iter = 0; iter < maxiter; iter++)
{
(V3 dv1, double dt1, V3 dv2, double dt2) = ManeuverInternal(mu, r1, v1, r2, v2, dtguess, coplanar: coplanar, rendezvous: rendezvous,
capture: capture, optguard: optguard, lagTime: lagTime);
capture: capture, optguard: optguard, lagTime: lagTime, minPeR: minPeR);

if (dt1 > 0)
return (dv1, dt1, dv2, dt2);
Expand Down