Plan your (Space) Flight! Fly your Plan! Handy tools to help you set up maneuver nodes that will get you where you want to be. Making spaceflight planning easier for Kerbal Space Program 2 one mission at a time.
NOTE: This mod draws heavily on some core MechJeb2 code that has been adapted to work in KSP2, and would not be possible without the kind and generous contributions of Sarbian and the MechJeb development team! It is not the intent to replicate all MechJeb2 features and functions in this mod, but merely to make some handy maneuver planning tools available for KSP2 players. While you may be able to create some useful nodes with this mod, you'll still need to execute them accurately! Also, understanding some basic mission planning will be very useful for those employing the tools in this toolbox.
Note: Version 0.8.0 has received significant updates and improvements in the GUI from cfloutier who richly deserves the credit for those parts. His contributions have dramatically improved the quality of the user interface and made the mod not only more modern and visually pleasing but also easier and more fun to use.
PREFERRED: Please use CKAN and that makes things far easier and will ensure you've got all the necessary dependencies. If you would like to perform a manual install here are the instructions
C:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program 2
. If you complete this step correctly you'll have a BepInEx subfolder in that directory along with the following files (in addition to what was there before): changelog.txt, doorstop_config.ini, winhttp.dllBepInEx
folder on top of your game's install folder. If done correctly, you should have the following folder structure within your KSP2 game folder: ...\Kerbal Space Program 2\BepInEx\plugins\node_manager
.BepInEx
folder on top of your game's install folder. If done correctly, you should have the following folder structure within your KSP2 game folder: ...\Kerbal Space Program 2\BepInEx\plugins\flight_plan
....\Kerbal Space Program 2\BepInEx\plugins\K2D2
....\Kerbal Space Program 2\BepInEx\plugins\maneuver_node_controller
.Flight Plan employs a tabbed interface to help organize its features. The list of available tabs updates dynamically based on your current situation. Some tabs will always be available (e.g., Ownship Maneuvers and Resonant Orbit Maneuvers), while others will be offered to you based on the orbit you're in and the type/location of your currently selected target. For example, if your current target is another vessel, and that vessel is in orbit about the same body as your active vessel, then the Target Relative Maneuvers tab will be available to you and it will have the sorts of maneuvers that are configured relative to a target (e.g., Match Planes with the target, etc.).
The basic workflow you'll want to follow when using Flight Plan is this.
Only available if a target vessel or part is selected and both active vessel and target are in the same SOI
Only available if a celestial target is selected and both active vessel and target are in the same SOI
Only available when in orbit about a moon
Only available when orbiting a planet targeting another planet
The Flight Plan GUI will always display all Ownship maneuvers available in the current orbital situation. These are maneuvers that don't require a target and so are relative to your current vessel's orbit alone. Each Maneuver Type may be customized by making a selection from the Burn options menu (right below the Celestial Target Selection Menu). For example, selecting Circularize as the Maneuver Type will result in having Burn Time options for at the next Ap, at the next Pe, at an altitude, and after a fixed time. In the case of the latter two options, these will cause an additional input field to be presented where you can specify the Maneuver Altitude or Time From Now.
Similarly, selecting Match Planes will give Burn Time options for at the cheapest AN/DN w/Target, at the nearest AN/DN w/Target, at the next AN w/Target, and at the next DN w/Target. NOTE: in the Match Planes example above the Make Node button has been pressed and Flight Plan is showing a status indicating the node is ready. In this example, with K2-D2 installed, the K2-D2 Astromech Icon is displayed in the lower right indicating that K2-D2 is ready to help you fly the node.
In addition to the basic UI screens above, the UI will automatically adjust to offer capabilities relevant to the current orbit and selected target. Some options such as Interplanetary Transfer (above far right example) are only available if the Experimental Features option has been selected in the Flight Plan configuration options menu.
This mod includes several user-configurable parameters which can be accessed through the SpaceWarp configuration screen. Press Alt + M to pull up the SpaceWarp Mod dialog, and select the Open Configuration Manager button at the bottom to display the list of installed mods with configurable settings. Clicking on the Flight Plan entry will display the interface shown above. There are tooltip strings that describe what each setting does. Using the configuration parameters you can change a variety of things such as how long a status message sticks around before it starts to fade, and also how long it will take to fade.
NOTE: The following settings are dynamically managed and may be set by the user while the game is running. All others will require exiting and restart to take effect.
Work In Progress developmental features may be enabled by switching on the Experimental Features in the mod's configuration screen. You do not need to restart the game for this setting to take effect, and it will allow you to play with some broken toys if you like. As these features mature and become reliable enough to use they will be moved up into the main feature set available without turning on the Experimental Features setting.
Always Available
Available If Selected Target is a Vessel
Available If Selected Target is a Celestial Body
Available If Active Vessel is Orbiting a Planet and Another Planet is the Selected Target
Here we're starting in a nicely equatorial Low Kerbin Orbit. As we want to go to Minmus, the first step is to get into a new circular orbit that's co-planar with the target. We can see that the necessary plane change maneuver has been planned and is ready to execute.
Here we can see that K2-D2 has been activated. The Flight Plan status has been updated to show that we're executing the planned maneuver, and K2-D2 is reporting its status indicating the vessel is turning to point in the right direction for the planned burn.
Here we can see K2-D2's status indicates we're warping to the burn. The Flight Plan status is unchanged.
Here we can see K2-D2's status indicates we're executing the burn. The Flight Plan status is unchanged.
Here we can see the plane change burn is done, the old node has been deleted, and we're now in a co-planar orbit with the target: Minmus.
Now that we're in a co-planar orbit with our target we're ready to plan a Hohmann Transfer. Note that Flight Plan generated Hohmann Transfer maneuvers are not always spot on but will get you close. For this reason, Flight Plan will bring up the Maneuver Node Controller mod if it's installed any time it produces a Hohmann Transfer. You may need to make minor adjustments to the prograde burn component or the node time but should find that it's easy to get the transfer orbit you need with only a few clicks and no need to manually tweak the node. This example produced a good initial orbit that only required a few m/s more prograde delta-v and a slightly earlier burn time to get the result shown below.
Here we can see K2-D2 has been commanded to execute the node and we're warping to the starting point for the burn.
Here we can see K2-D2 executing the transfer burn.
Sometimes in the game, as in life, things don't go quite as planned. What if you overshot the planned burn slightly as shown below? This can easily happen when executing a burn manually, and may also happen in some isolated cases when executing an automated burn.
Here we can see a Course Correction burn has been planned. Like the Hohmann Transfer option, this option will also bring up the Maneuver Node Controller mod so you can fine-tune things to make sure you've got the exact node you want. In this case, very small prograde adjustments were made to get a good Pe at the Minmus flyby encounter.
Here we can see K2-D2 performing a flawless Course Correction burn to get us back on track and headed for the encounter we want.
Here we can see that we've arrived inside the Minmus SOI and are on track for a nearly equatorial flyby with a nice low Pe in a prograde orbit. What if we'd like to have an inclined orbit when we get to Minmus? Easy! Use Flight Plan to set up a New Inclination at a burn time 30 seconds from now (this offset ensures we'll have sufficient time to point in the direction we need before the start of the burn).
Here we can see we're in a 60-degree inclined flyby orbit and we've got a Circularization burn planned for the periapsis of the Minmus encounter.
Here we are approaching Pe in our Minmus Flyby with a Circularization burn planned to put us into a 60-degree inclined low circular orbit about Minmus. Perfect for picking a landing spot almost anywhere we may want to go. In this view, you can also see the Maneuver Node Controller's GUI showing that our planned maneuver will place us in the orbit we want.
The following images show more details illustrating Flight Plan's features and capabilities. Although the GUI has since been updated, these images still show relevant performance characteristics for the nodes you can generate.
Flight Plan's orbital maneuver node creation methods are public, and so may be called from other mods. In this sense, Flight Plan can be accessed like a library whether the Flight Plan GUI is visible or not.
This mod is primarily meant as a direct aid to the player but can also be used as a service provider to other mods which can call functions in this one without needing to recreate all these functions in the base mod. Creating maneuver nodes from a KSP2 mod is not necessarily an intuitive thing to code, so having this as a resource you can call may save you time developing those capabilities internally for your mod.
NOTE 1: All of the orbital maneuver node creation methods in Flight Plan take a (double) burnUT, and an optional (double) burnOffsetFactor parameter. This factor is used with the node's burn duration (as estimated by the game) to allow you to offset the start time of the node. By default in KSP2 nodes begin at the time you've created them unlike in KSP1 where they would bracket the requested start time. This optional parameter allows you to plan maneuver nodes that will start earlier so that the applied Delta-v occurs centered on the intended time.
NOTE 2: All of the orbital maneuver node creation methods in Flight Plan return a Boolean value which is true if the node creation was successful and false otherwise.
These methods can be accessed either directly (in the case of KSP2 native parameters) or by calling Flight Plan to get them. They are useful to determine the burnUT you may wish to use in a call to one of Flight Plan's maneuver node creation methods above.
To use this mod from your mod you will need to do one of the following:
If core capabilities in your mod will rely on calling Flight Plan methods, then setting up a hard dependency like this is the way to go as it's easier to develop your mod this way. There are two ways to set up your mod for development with Flight Plan as a hard dependency, and this is the easiest of the two, so is the recommended way. Fundamentally, it works just like what you're already doing to reference BepInEx and SpaceWarp.
In your csproj file, you may already have an ItemGroup where BepInEx, HarmonyX, and SpaceWarp are added as PackageReference includes. If so, all you need to do is add PackageReferences for FlightPlan and NodeManager as shown below.
<ItemGroup Label="NuGet package references">
<!-- Add references to any NuGet packages you want to use in your mod here -->
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all"/>
<PackageReference Include="BepInEx.AssemblyPublicizer.MSBuild" Version="0.4.1" PrivateAssets="all"/>
<PackageReference Include="BepInEx.Core" Version="5.*"/>
<PackageReference Include="HarmonyX" Version="2.10.1"/>
<PackageReference Include="KerbalSpaceProgram2.GameLibs" Version="0.2.0" PrivateAssets="all" Publicize="true"/>
<PackageReference Include="NodeManager" Version="0.7.2"/>
<PackageReference Include="FlightPlan" Version="0.10.0" />
<PackageReference Include="SpaceWarp" Version="1.8.0"/>
<PackageReference Include="SpaceWarp.PluginInfoProps" Version="1.*"/>
<PackageReference Include="UitkForKsp2" Version="2.4.0"/>
<PackageReference Include="UnityEngine.Modules" Version="2022.3.5"/>
</ItemGroup>
Bring in the FlightPlan namespace in the class you want to call it from and add both Flight Plan and Node Manager as BepInDependencies. You won't need the NodeManger namespace unless you plan to also call Node Manager directly.
using FlightPlan;
namespace MyCoolModsNameSpace;
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
[BepInDependency(SpaceWarpPlugin.ModGuid, SpaceWarpPlugin.ModVer)]
[BepInDependency(FlightPlanPlugin.ModGuid, FlightPlanPlugin.ModVer)]
[BepInDependency(NodeManagerPlugin.ModGuid, NodeManagerPlugin.ModVer)]
public class MyCoolModName : BaseSpaceWarpPlugin
You can now call any of Node Manager's public methods directly and easily from your code. Here are some examples:
pass = FlightPlanPlugin.Instance.Circularize(burnUT, burnOffsetFactor) // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.SetNewPe(burnUT, newPeR, burnOffsetFactor); // double, double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.SetNewAp(burnUT, newApR, burnOffsetFactor); // double, double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.Ellipticize(burnUT, newApR, newPeR, burnOffsetFactor); // double, double, double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.SetInclination(burnUT, newIncDeg, burnOffsetFactor); // double, double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.MatchPlanes(burnUT, burnOffsetFactor); // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.HohmannTransfer(burnUT, burnOffsetFactor); // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.InterceptTgt(burnUT, deltaUT, burnOffsetFactor); // double, double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.CourseCorrection(burnUT, burnOffsetFactor); // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.MoonReturn(burnUT, burnOffsetFactor); // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.MatchVelocity(burnUT, burnOffsetFactor); // double, double (default = -0.5)
pass = FlightPlanPlugin.Instance.PlanetaryXfer(burnUT, burnOffsetFactor); // double, double (default = -0.5)
This way works like the method above with a few minor differences in your csproj and what you need to do in your mod's development folder.
Add a copy of the flight_plan.dll and node_manager.dll to your mod's list of Assemblies. Generally, this means two things. First, put copies of the flight_plan.dll and node_manager.dll in a folder where your mod can find them. You may want to put them in the same folder you have Assembly-CSharp.dll. Secondly, add them to your csproj file similarly to how you're already referencing Assembly-CSharp.dll. Your mod will need to have access to them and know where to find them when you compile your mod. At run time your mod will be accessing the flight_plan.dll from the flight_plan plugins folder where Flight Plan is installed, so you don't need to distribute the Flight Plan or Node Manager DLLs with your mod, but both of those mods will need to be installed in the players game for your to be able to access Flight Plan.
In your csproj file locate the ItemGroup where you have local References defined. There will be at least one for Assembly-CSharp.dll. You'll need to add one for Flight Plan and one for Node Manager like this.
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\external_dlls\Assembly-CSharp.dll</HintPath>
<Publicize>true</Publicize>
<Private>false</Private>
</Reference>
<Reference Include="flight_plan">
<HintPath>..\external_dlls\flight_plan.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="node_manager">
<HintPath>..\external_dlls\node_manager.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
See Step 2 above as there is no difference.
See Step 3 above as there is no difference.
This is the way to go if optional capabilities in your mod will rely on functions in this Flight Plan, and you don't want your mod to have a hard dependency on Flight Plan.
This is the same as for Hard Dependency above as you'll not be able to compile without this.
Bring in the NodeManger namespace and create some variables in the class you want to call it from. This is almost the same as above.
using FlightPlan;
private bool FPLoaded;
PluginInfo FP;
Somewhere in your mod, you need to check to make sure Flight Plan is loaded before you use it (e.g., OnInitialized()). You don't need this with a hard dependency, but it's essential for a soft one.
if (Chainloader.PluginInfos.TryGetValue(FlightPlanPlugin.ModGuid, out FP))
{
FPLoaded = true;
Logger.LogInfo("Flight Plan installed and available");
Logger.LogInfo($"FP = {FP}");
}
else FPLoaded = false;
This is where things get different for you compared to what's needed to call Flight Plan methods using a hard dependency. For a soft dependency to work you're going to need to create a reflection calling method for each of the Flight Plan methods that you would like to call from your mod. Here's an example of one for calling Flight Plan's SetNewPe method which will pass it the new Pe you would like to have, and optionally a burn time offset. Note: Using a burn time offset of -0.5 will cause the maneuver node to be centered on the nominal time for the burn (next Ap in this case).
private void SetNewPe(double burnUT, double newPeR, double burnOffsetFactor = -0.5)
{
if (FPLoaded)
{
// Reflections method to call Node Manager methods from your mod
var nmType = Type.GetType($"FlightPlan.FlightPlanPlugin, {FlightPlanPlugin.ModGuid}");
Logger.LogDebug($"Type name: {nmType!.Name}");
var instanceProperty = nmType!.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
Logger.LogDebug($"Property name: {instanceProperty!.Name}");
var methodInfo = instanceProperty!.PropertyType.GetMethod("SetNewPe");
Logger.LogDebug($"Method name: {methodInfo!.Name}");
methodInfo!.Invoke(instanceProperty.GetValue(null), new object[] { burnUT, newPeR, burnOffsetFactor });
}
}
This example includes some (optional) debug logging that may be helpful if you are having trouble with the reflection calling method. You can safely remove those once it's working to your satisfaction.
Call your reflection method wherever you need to invoke the corresponding Node Manager method.
SetNewPe(newPeR, -0.5);