#Flight Plan
1 messages · Page 3 of 1
OK then, I'll just focus on making sure normal operations are working.
I think I'll probably wait with adding the localization until I have a chance to update UITK to support previewing localized terms inside Unity
so that you can make sure everything looks ok in all languages
GitHub desktop is a bit confused. I switched my branch from master to Dev and did a Fetch and now it thinks I've got 8258 changed files - looks like all additions. I assume what this means is that in my local folder I've got a fetch of the new Dev on top of and old master and so there are 8258 things that left over from the old master that are presumably not needed now.
Is there an easy way to make it get rid of all that so I can just build?
it looks to mostly be the build files from the previous version which are no longer ignored, because the template has a completely different structure for build folders
Not entirely, there are other things like this too
And a ton of UI stuff that must have been moved
well, yeah, those are also files that are not ignored by the template
I would advise just backing this folder up somewhere into a zip or something, just so you have it if you need it, and cloning the fresh project from GitHub
The folder looks like this
Good idea
And since your advice is arriving from the future, I must respect it!
that it is 😆
I may have done the cloning part wrong. When I did it, it cloned the master branch and when I switched to the Dev branch it thinks I need some massive PR - presumably the difference between the two.
What do I need to do to clone the Dev branch rather than the master - or am I just not understanding what this is doing?
the app is probably just stupid
you should be able to switch from master to Dev after cloning with no issues
The first time I did the clone I was able to switch, but switching made it think there would be some sort of massive PR
did it look like this?
if there were 0 changed files in the left pane, then that's how it's supposed to be
the pull request blue box is just suggesting that you can make a PR from dev to master
which you only need to do if you want to make a new release
oh yeah one more thing
you probably haven't made any new projects with the later template versions right?
you'll probably need to set up the KSP2DIR environment variable
the setup script for a new project does it automatically, but since you're not making a new project, you'll need to do it manually
I did some stuff with CF, but I don't think I set up a KSP2DIR environment variable
you can quickly check
just type something like "variable" into the Windows search box
the correct setting should pop up
Like this?
yep, so, create a new one like this
in the user variables
with the path to your KSP2 debug folder
I think you had a separate one, right?
alright, that should be all
now you should be able to just open the solution in Visual Studio, switch configuration to DeployAndRun, rebuild the solution, and it should automatically start the game with the new mod version loaded
Looks like it built
Does building with this template automatically put it in my game at teh KSP2DIR folder?
Or do I need to install it after building?
only in the Deploy and DeployAndRun configurations
Debug just compiles a debug build and places it into the dist folder, Release compiles a release build and packs it up into a zip in the dist folder, Deploy compiles a debug build into the dist folder, deletes the old version from your game and copies the new version into its place, and DeployAndRun does the same thing as Deploy, plus it runs the game
Oh nice! So DeployAndRun to make life easy testing a debug version, and Release to prepare something for upload to GH and SpaceDock then
yep
and speaking of Release, all of that is now automated
so you don't need to build a release and upload it anywhere
it all happens in the cloud using GitHub actions
for both GitHub releases and SpaceDock
you'll just need to do a tiny bit of setup first to add support for SpaceDock
Something is amiss. It's running the game, but it's runing a completely unmodded version of the game
that is definitely weird
I'm fairly sure I pointed that environment variable at my highly modded debug version of the game
oh wait, did you already have VS open when you added the variable?
Do I need to reboot or something because of the environment variable?
it can only use it after you restart VS
Yep
Huh, so it somehow found my steam install!
this is set as the default
so if your Steam install is there and it can't find the environment variable, that's where it gets copied
Yeah, that's probably where my steam install is...
Shit. It's still fucked up.
I closed VS all the way down and then relaunched it and the GD thing still ran my steam game
then I would try rebooting the computer, just in case
but it shouldn't be causing issues
Screw it. brb
one more potential cause I can think of is if you accidentally closed the environment variables window without saving it (aka clicking OK)
I'm off to bed, have a long day of studying for exams in front of me, but here's a link to the section about GitHub actions and how to set up the SpaceDock integration: https://github.com/SpaceWarpDev/SpaceWarp.Template?tab=readme-ov-file#github-actions
if you have any other issues or questions, feel free to ask, I'll respond in the morning
Success with building and launching!
I'll play around with it now.
Here's an issue. On the Resonant Orbit Maneuvers tab, if you click the + or - buttons, it should just add or subtract 1 from the number of payloads or the number of deploy orbits. Instead I'm getting this odd text.
The Payloads increment buttons work OK, it's just the Deploy Orbits buttons that are misbehaving.
Also on that same tab, the Atm and Vac are pre-filling with "filler text". Should be defaulting to 0.75 and 0.9 respectively.
You can manually enter those numbers, but they should be there by default.
I have no idea what's going on with New Pe, or even if it might be related to anything in the Dev branch, but this is certainly wrong.
OK, I've got a theory what was happening there, but I suspect FP may have had this problem separately from your updates. The first time I tried setting the Pe to 100 I think I had a bad Burn Option set and got a 0 dV maneuver. I changed that, but kept getting the 0 dV manuever. Once I changed the New Pe value to something else (400 as it happens), then it worked fine. My theory is that something is gettign FP or Node Manager or something into a state where you've got stale data from a bad node and if you keep asking for the same thing, you just keep getting the stale data.
Asking for 400, and then going back to 100 gives a reasonable result for the 100 Pe solution
So there's some issue here, but I honestly don't think this one has anything to do with your efforts.
I love love love the new orbit colors!
I do not see what's wrong here:
private void IncrementPayloads(int increment)
{
if (NumSats + increment > 1) NumSats += increment;
NumPayloads.text = NumSats.ToString();
updateResonance();
FlightPlanPlugin.Logger.LogInfo($"IncrementPayloads: {NumSats}");
}
private void IncrementOrbits(int increment)
{
if (NumOrb + increment > 0) NumOrb += increment;
NumOrbits.text = NumOrbits.ToString();
updateResonance();
FlightPlanPlugin.Logger.LogInfo($"IncrementOrbits: {NumOrb}");
}
It seems clear that clicking on the +/- buttons will call this here:
IncreaseOrbitsButton.clicked += () => IncrementOrbits(+1);
DecreaseOrbitsButton.clicked += () => IncrementOrbits(-1);
Why on earth would that put anything other than an integer in the display?
I'm pretty sure the issue here is that you have
if (NumOrb + increment > 0) NumOrb += increment;
NumOrbits.text = NumOrbits.ToString();
but it actually needs to be
if (NumOrb + increment > 0) NumOrb += increment;
NumOrbits.text = NumOrb.ToString();
to avoid confusing similar variables like this in the future, I would definitely recommend more clear naming, like "NumOrbitsLabel" instead of "NumOrbits"
Yep, that would have been more clear.
as for "filler text", you've had that in a couple of places in your UXML
all that should be needed to do is get rid of the "text" property and instead set "value" to the desired number
which reminds me of another thing that I added to the template - when you're in Unity and you click Build AssetBundles in the Assets menu, they now get automatically copied to your plugin_template folder, so you don't have to go around manually copying anything
you can just click Build AssetBundles in Unity, and then immediately rebuild the solution in VS and everything will be deployed to the game correctly
Yeah, I think I encountered that in CF - that's an awesome feature!
On the value vs. text properties, I vaguely recall there might have been some reason for why I did it that way. There was some problem I was avoiding, but I don't recall now. I suspoect if I look at the C# code for that panel it might com back to me, but other than that I don't see a reason not to do it as you've described.
I can give this a shot and see if anything breaks
In the worst case scenario, you can use both, if just value alone doesn't work
True. that should be safe
The code fix on the button is working fine. Now I just need to rebuild the bundle so the filler text can be sorted.
Template question for you. Why is the folder for the UI project F:\KSP2Mods\FlightPlan\src\FlightPlan.Unity\FlightPlan.Unity? Why not just F:\KSP2Mods\FlightPlan\src\FlightPlan.Unity?
Nope, that didn't work...
Pointing Unity Hub at either of those folders does not give the result I was hoping for
There's a good reason for it! The nested folder is the one that contains the Unity project itself, and the outer folder with the same name contains a C# project file that gets compiled along with the main solution, which compiles code from inside the Unity project
That's definitely weird, the inner folder should work just fine
It does for me
The reason for this is so that you can have shared code between your main C# project and your Unity project
I get this:
Putting the .csproj file inside the inner folder wouldn't work, because Unity generates its own project files
That looks fine to me
No errors
And that one warning is expected
Just switch to the Project tab
Oh, I was expecting it to open with a view of my UI. That's how I always saw it. Must be n opening the first time kind of thing
Yeah I think it just doesn't know which scene it should open by default
There should be a TestScene in assets that you can double click to open
And then that should become the default on subsequent launches of Unity
Still not seeing what I hope to see. I must be forgetting what I need to do to get to the view I want
There's some step where you need to open something inside the project to get this view...
OK I found it, but dang is it goofed up by default
I think what I need to do is spend some time getting the various things arranged and docked the way I want them, then I can probably save the project and it will come back the way I expect it to.
If you want to be able to easily reuse layout for different projects, then you should definitely save it
Can I save the layout I want from MNC and then import that into this one?
In the top right of Unity, there's an option to either switch layouts, or to save a custom one
Because that one should be exactly as I want it
Then you can use it anywhere
Well rebuilding the assets worked perfectly (as advertised!)
Here I kept both text and value just to be on the safe side
Oh this is wild! I apparently had save the layout I wanted! I found this already there
Problem solved!
nice
Well, nearly solved. The Viewpoint was smushed in the vertical, so I guess the layout I saved didn't specify that setting or specified it wrong, but it seems to have salved pretty much all the other issues I had with the layout
I'm sure I can sort that one out. This is awesome!
Thank you Soooo much for all your work dragging FP into the new template!
I'm certain this will be making my life easier in lots of ways
I definitely hope so, that's my main goal with all these template updates!
Fit Canvas solved my smushed viewpoint!
A one-click solution! That's my style!
Well, sort of... I may have a little more work here - but nothing big.
well then, after I'm done with my last exam on Saturday, I could do this same process for MNC if you want
you should be able to just drag the bottom right corner to make the canvas larger (it only affects the preview, nothing else)
I feel like there's something possibly set wrong here, but when I built assets and then rebuilt in VS (amazing!) it worked fine in the game. I'd just like the Unity project to really show me what I should expect in the game.
That helped, but it's still too short. Is there a way to tell it the canvas size I want? I recall that there is
yeah, when you click on the header, you should be able to manually edit the size in the inspector on the right
Yeah, that's it!
I wonder why Fit Canvas doesn't work? Maybe that's just a Unity thing. You'd think it would be able to work out what the minimum height is based on the height of all the stuff that's visible
Using that it always goes to 924 px height
It seems I need something more like 1000 or 1100
I think that it might be some sort of an issue with the FP styles
for example, when you look at the buttons here, it seems to think that the largest button is the one on the left with the text, and positions everything around it accordingly
oh and it also seems like you don't have KerbalUI set as the preview stylesheet?
Yeah! That button should have a fixed height. There are some other similar issues, but this is a good example
I bet I've got a little style cleanup I should do here
that might also help out a bit
That does seem to help. Poking around with the height it seems that any value north of 975 gives me essentially the same result for the visible parts. Any value above this gives me more canvas, but not taller stuff
Of course, the FP UI has a variable height depending on the tab, so this is just what Interplanetary Transfer needs.
I need to get going for work. Good luck on your exams! I doubt that you'll need luck though. I hope you ace them!
Thanks 😆 I hope so too, though the odds are not great
@wind mica can I suggest updating the Flight Plan readme? it's quite outdated by now
oh by the way, did you use the automated GitHub actions for the GitHub and SpaceDock uploads?
those are new in the new template
Yeah, both this and the SpaceDock page need some attention. I'll work on that.
seems like no
I have not used these. I'm not sure how to set them up or use them so I've just been doing things the old way for now
basically, when you go to Releases on GitHub and create a new release, don't upload any zip file
just write the text and publish it
the action will automatically build the mod in the cloud and attach the zip to the release
Dang, I had no idea that was even possible
so like this:
We should do this for MNC and NM for sure!
it will use the code from the specified Target at the top
so you just have to make sure that the main/master branch contains the code you want to release
and it can also upload to SpaceDock for you, it just needs some extra setup (since the template obviously can't log in to your SpaceDock account without knowing the credentials): https://github.com/SpaceWarpDev/SpaceWarp.Template?tab=readme-ov-file#spacedock-integration
Hmm... GitHub preview isn't showing the banner image
oh yes, it's because I put the image files into the "media" folder in the new project
instead of "Images"
I can make a quick PR to Dev to fix it if you want
OK, I'll fix the readme - not a big deal and I'd like to conform to the mod template
For installation I added this
Perhaps a link to CKAN could be added?
Excellent! Thanks!
OK, I've updated the readme - although I'll bet the guidance at the end for hardcoding and softcoding dependencies is probably a bit out of date. All the images link, and for the most part it's OK now. I'll work on what on SpaceDock, and I think I need to update some graphics in the media folder - but as the images link to the right places that will be a simple thing.
I commited my changes direct to the master since it's the readme and it needs to work there.
Is there an alternative to F2 that would hide the UI except for my mod? I want to update some graphics for Flight Plan, so I'd like to hide the UI except for FP. Apparently that used to be possible (probably pre UITK in FP)
vs this
yeah, that was an intentional change, since many people complained about this being a bug in UITK
lol
Well, there's a use case where it would be helpful to only hide the stock UI and not mods. I can always control what mods are in view.
but yes, it is possible to specifically leave out your window when hiding everything else
though beware that you'll probably get users complaining about the "bug"
😆
Could there be both options? I can see use cases for both. So: Normal (it's all visible), Mods Only, and Clean?
Then there's no bug, just pick the one you want
I personally can't see the use case for it for normal users
so I don't know how I feel about adding something like that
you could make it a setting for your mods though
I can? That would be interesting. I might do that for debug builds so that users don't generally encounter it.
There is - I Wish They Made UI Customizable 🙂
I used it once or twice to hide everything except my window when taking screenshots
That and, well, Photoshop 😉
I'll give IWTMUIC a shot
Black sky is easy to photoshop
True, but using your mod is probably cleaner andeasier.
Updated the graphics and readme on GitHub
Updated the banner on SpaceDock, but those graphics are a PITA to update
Update graphics and text on SpaceDock
Updated graphics on Forum! Whew... That will keep this up to date for a while I hope. Of course, once @grizzled vale does the localization I'll may have to do some of this again...
Just in time for the KSP2 update coming this Tuesday
I've got a new theory for what may be causing the misbehavior in my interplanetary transfer. There are not a lot of differences between my code what's in MechJeb, but there is a difference in how OrbitFromStateVectors is done, and that method gets called from DeltaVAndTimeForInterplanetaryTransferEjection.
The OrbitFromStateVectors lives in Node Manager, and going back over the code I see the translation from KSP1 to KSP2 was bumpy for this one. It's suspicious for that reason and because it's ued in Flight Plan to compute a sampleEjectionOrbit, which ultimately gives a turningAngle that leads to the ejectionTrueAnomalyRad. That value determines the burnUT - and one thing that I've noticed is that the burn times seem to be off the further in the future the node is.
The old MJ code for this function is this
public static Orbit OrbitFromStateVectors(Vector3d pos, Vector3d vel, CelestialBody body, double UT)
{
var ret = new Orbit();
ret.UpdateFromStateVectors((pos - body.position).xzy, vel.xzy, body, UT);
if (double.IsNaN(ret.argumentOfPeriapsis))
{
Vector3d vectorToAN = Quaternion.AngleAxis(-(float)ret.LAN, Planetarium.up) * Planetarium.right;
Vector3d vectorToPe = ret.eccVec.xzy;
double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, vectorToPe) / (vectorToAN.magnitude * vectorToPe.magnitude);
//Squad's UpdateFromStateVectors is missing these checks, which are needed due to finite precision arithmetic:
if (cosArgumentOfPeriapsis > 1)
{
ret.argumentOfPeriapsis = 0;
}
else if (cosArgumentOfPeriapsis < -1)
{
ret.argumentOfPeriapsis = 180;
}
else
{
ret.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis);
}
}
return ret;
}```
And the code I derrived from that is this hot mess
public static PatchedConicsOrbit OrbitFromStateVectors(Vector3d pos, Vector3d vel, ICoordinateSystem coordinateSystem, CelestialBodyComponent body, double UT)
{
PatchedConicsOrbit ret = new PatchedConicsOrbit(Game.UniverseModel);
// Create the type Position and Velocty inputs needed for KSP2's UpdateFromStateVectors
Position position = new(body.SimulationObject.transform.celestialFrame, (pos - body.Position.localPosition).SwapYAndZ); // OrbitExtensions.SwapYZ(pos - body.Position.localPosition)
Velocity velocity = new(body.SimulationObject.transform.celestialFrame.motionFrame, vel.SwapYAndZ); // OrbitExtensions.SwapYZ(vel)
ret.UpdateFromStateVectors(position, velocity, body, UT);
if (double.IsNaN(ret.argumentOfPeriapsis))
{
Vector3d vectorToAN = Quaternion.AngleAxis(-(float)ret.longitudeOfAscendingNode, body.Orbit.ReferenceFrame.up.vector) * body.Orbit.ReferenceFrame.right.vector;
Vector3d vectorToPe = ret.eccVec.SwapYAndZ; // OrbitExtensions.SwapYZ(ret.eccVec);
double cosArgumentOfPeriapsis = Vector3d.Dot(vectorToAN, vectorToPe) / (vectorToAN.magnitude * vectorToPe.magnitude);
//Squad's UpdateFromStateVectors is missing these checks, which are needed due to finite precision arithmetic:
if (cosArgumentOfPeriapsis > 1)
{
ret.argumentOfPeriapsis = 0;
}
else if (cosArgumentOfPeriapsis < -1)
{
ret.argumentOfPeriapsis = 180;
}
else
{
ret.argumentOfPeriapsis = Math.Acos(cosArgumentOfPeriapsis);
}
}
return ret;
}
I left some breadcrumbs for myself with these notes
// was: body.Position -> body.Position.localPosition
// was: ret.LAN -> longitudeOfAscendingNode
// was: Planetarium.up -> body.orbit.ReferenceFrame.up.vector
// was: Planetarium.right -> body.orbit.ReferenceFrame.right.vector
// OrbitFromStateVectors calls the KSP2 method UpdateFromStateVectors. The KSP1 version took pos and vel as Vector3d, but the
// KSP2 version requires these to be type Position and Velocity.
// pos = o.SwappedAbsolutePositionAtUT(UT);
// vel = o.SwappedOrbitalVelocityAtUT(UT) + dV;
// The MJ version of OrbitFromStateVectors peroforms a SwapYZ on (pos - body Position), and a SwapYZ on vel before passing them into
// the KSP1 version of UpdateFromStateVectors.
// ret.UpdateFromStateVectors(OrbitExtensions.SwapYZ(pos - body.Position), OrbitExtensions.SwapYZ(vel), body, UT);
The comments show my guesses/assumption/deductions - and they could be wrong
I see that I also had some test code in there that'd I'd commented out
// Position Position = new(body.SimulationObject.transform.celestialFrame, pos);
// Velocity velocity = new(body.SimulationObject.transform.celestialFrame.motionFrame, vel);
// ret.UpdateFromStateVectors(OrbitExtensions.SwapYZ(pos - body.Position), OrbitExtensions.SwapYZ(vel), body, UT);
// orbit.UpdateFromStateVectors(new Position(o.ReferenceBody.SimulationObject.transform.celestialFrame, Position), new Velocity(o.ReferenceBody.SimulationObject.transform.celestialFrame.motionFrame, velocity), o.ReferenceBody, UT);
Just following the code seems everything aligned, the only place some issue could arise (in my ignorance) is the celestialFrame
@grizzled vale I've noticed that changing mod settings (such as toggling experimental features on and off) has no effect post launch of game. Even an F5/F9 will not apply the effect. I thought I had that setup so that changes would take immediate effect. Has something changed in how these things are loaded? The problem is most likely on my end, but it's weird that even and F5/F9 won't apply the changed settings. It's like the settings are somehow cached and changes are only possible if you fully quit and then relaunch the game.
Nothing has changed, so there's most likely something wrong in how you're handling it
(to be blunt, sorry 😅)
Not terribly surprising.
One more thing to try to fix then in 0.10.1!
Right now, In my effort to try to solve moon return and interplanetary transfer I've managed to really hose calculation of the transfer window phase angle. I know that was working before... Now I get this for Duna.
Which is absolute shite. Should be 44-ish
This is interesting...
As is this
Picking different targets gives me different phase angles to the target (good...), but in each case the transfer window reported is the same (not so good... really very very bad)
The transfer time looks OK, so the hypothetical hohmann transfer orbit is presumably OK. The synodic period is also the same in all cases though.
private double TransferCalc(PatchedConicsOrbit targetOrbit, double UT, out double synodicPeriod, out double timeToClosestApproach,
out double closestApproach, out double relVelocityNow, out double relVelocityCA, out double relativeInc, out double phase,
out double transfer, out double _transferTime)
{
double nextWindow;
synodicPeriod = Orbit.SynodicPeriod(targetOrbit);
timeToClosestApproach = Orbit.NextClosestApproachTime(targetOrbit, UT + 1);
closestApproach = Orbit.RelativeDistance(targetOrbit, timeToClosestApproach);
// relVelocityNow = Orbit.RelativeSpeed(targetOrbit, UT);
relVelocityCA = Orbit.RelativeSpeed(targetOrbit, timeToClosestApproach);
relVelocityNow = Vector3d.Dot(Orbit.WorldOrbitalVelocityAtUT(UT) - targetOrbit.WorldOrbitalVelocityAtUT(UT), Orbit.WorldBCIPositionAtUT(UT) - targetOrbit.WorldBCIPositionAtUT(UT)) / (Orbit.WorldBCIPositionAtUT(UT) - targetOrbit.WorldBCIPositionAtUT(UT)).magnitude;
relativeInc = Orbit.RelativeInclination(targetOrbit);
phase = Orbit.PhaseAngle(targetOrbit, UT);
transfer = Orbit.Transfer(targetOrbit, out _transferTime);
if (transfer < phase)
nextWindow = synodicPeriod * MuUtils.ClampDegrees360(phase - transfer) / 360;
else
nextWindow = synodicPeriod * MuUtils.ClampDegrees360(transfer - phase) / 360;
return nextWindow;
}```
This looks OK...
If targetOrbit were goofed up (I don't think it is), then that would certainly screw up synodicPeriod, but it should also prevent _transferTime from being OK since that depends on targetOrbit
SynodicPeriod is just this, which hasn't changed.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double SynodicPeriod(this PatchedConicsOrbit a, PatchedConicsOrbit b)
{
int num = ((Vector3d.Dot(a.OrbitNormal(), b.OrbitNormal()) > 0.0) ? 1 : (-1));
return Math.Abs(1.0 / (1.0 / a.period - (double)num * 1.0 / b.period));
}```
Although I was playing around with the calculations for OrbitNormal, but I've backed out all those changes here:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d OrbitNormal(this PatchedConicsOrbit o) // KS2: OrbitNormal // was: SwappedOrbitNormal
{
// return -o.GetOrbitNormal().xzy.normalized;
Vector3d thisVec = -o.GetRelativeOrbitNormal().SwapYAndZ.normalized;
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, -o.GetRelativeOrbitNormal().SwapYAndZ).normalized; // From KS2
if (thisVec != thisVec2)
{
Debug.Log($"OrbitNormal(1): thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
Debug.Log($"OrbitNormal(1): thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
// return thisVec2;
return o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, -o.GetRelativeOrbitNormal().SwapYAndZ).normalized; // From KS2
}```
Previously, this was just
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d OrbitNormal(this PatchedConicsOrbit o) // KS2: OrbitNormal // was: SwappedOrbitNormal
{
// return -o.GetOrbitNormal().xzy.normalized;
return o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, -o.GetRelativeOrbitNormal().SwapYAndZ).normalized; // From KS2
}```
And when testing these two approaches for computing the orbit normal in every case I tested they gave the same result either way.
Also, the PhaseAngle to the target looks OK, and is at least does change from target to target, and it too uses OrbitNormal
public static double PhaseAngle(this PatchedConicsOrbit a, PatchedConicsOrbit b, double UT)
{
Vector3d vector3d = a.OrbitNormal();
Vector3d vector3d2 = a.WorldBCIPositionAtUT(UT);
Vector3d vector3d3 = Vector3d.Exclude(vector3d, b.WorldBCIPositionAtUT(UT));
double num = Vector3d.Angle(vector3d2, vector3d3);
if (Vector3d.Dot(Vector3d.Cross(vector3d, vector3d2), vector3d3) < 0.0)
{
num = 360.0 - num;
}
return num;
}```
I've similarly played around with WorldBCIPositionAtUT, but also backed those changes out
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d WorldBCIPositionAtUT(this PatchedConicsOrbit o, double UT) // KS2: RelativePosition // was: SwappedRelativePositionAtUT
{
// return o.getRelativePositionAtUT(UT).xzy;
Vector3d thisVec = o.GetRelativePositionAtUT(UT);
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
if (thisVec != thisVec2)
{
Debug.Log($"WorldBCIPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
Debug.Log($"WorldBCIPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
// return thisVec2;
return o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
}```
And also that one gives the same results regardless of which approach I take (though you may notice I needed to remove the .SwapYAndZ from the calculation for thisVec where the old MJ code had a .xzy. That shouldn't matter since I'm using the KS2 approach and have been for many months.
Hi,
Added fonts to the asset bundle in preparation for localization work - this makes the size of the download much bigger, but does not affect performance in the game otherwise and will enable localized versions of FP in the future.
I was wondering why you weren't packaging all those already into an external library-like-plugin which could be shared with others ?
it is how it works for most other mods, but the issue with this mod is that it doesn't use the default fonts provided with UITK for KSP2
it has custom fonts, and those need to have the fallback fonts set up separately
and Unity doesn't allow you to specify that you want to reference an existing asset from a different project (like the fallback fonts from the UITK for KSP2 package) without also copying them inside the current project's bundles
essentially we're hitting the limitations of Unity where from its point of view, it's like we're trying to create multiple different games, where they all reference assets from one central game
and that is just not possible without having the assets copied into each individual "game"
for the default fonts I provide in UITK for KSP2, there's a workaround - the fonts are assigned to USS variables, and through that abstraction, they are "hidden" from the bundling process
so when a mod uses any of the font variables, the font assets don't get copied
but, Flight Plan and Maneuver Node Controller use custom fonts, and since the fallback fonts have to be set directly as references in the font assets (as opposed to actually using fonts, which is done in USS and can be done with variables), it's impossible to do the same thing here
unless I were to include schlosrat's custom fonts in the main UITK for KSP2 library
but it doesn't really make sense that a general library that everyone uses would include assets for specific mods
another alternative would be to only set the fallback fonts at runtime, but it would mean that previewing for example how a Chinese UI would look in Unity's UI Builder would be impossible
...or through an sort-of UI emulator in charge of simple displaying. Anyway the binding should be limited to few fonts definition, no?
Currently there are three fallback fonts, one for Chinese, one for Japanese, one for Korean
Together they are around 45 MB
So that's the size increase for these mods with custom fonts if they want to make these languages usable
Not sure what to imagine under "UI emulator"
That's basically what the UI Builder (in its Preview mode) is
I'm in fact not very familiar with Unity dev, but I was used to UI library in old days.
But, would it be the same if KSP2 was referencing itself these extra font (in a latter more eloborated/localized release)?
We're using UI Toolkit, it's Unity's newest UI framework
While KSP2 itself uses the old framework, Unity UI
And the two are mostly completely separate and incompatible
If we could use KSP2's existing fonts, we absolutely would, it would make things much easier for us
However, the Unity UI system uses TextMeshPro font assets, and UI Toolkit uses TextCore font assets
And these are also incompatible
I see
So even though we can retrieve the game's fonts at runtime, we can't do anything with them
I was having a look at the latest related UitkForKsp2 commits and saw how the ui:label in the TestDocument.uxml was refering -unity-font-definition. Couldn't these url be more dynamic or refering a shared asset?
sadly, no, the issue is that the UXML and USS files get compiled when being bundled, including the paths, which are transformed to (most likely) reference the file IDs in the bundle
there's no way to explicitly reference paths from outside the current project
Ok. And we (mostly you in fact) don't want to rebuild a full font server. That's fair
yeah, that would be a lot of effort both inside Unity and in the game, and would be probably quite hard to maintain
I would basically have to reimplement many of the core functionalities of the whole UI framework to achieve that
however, what can be done relatively easily would be schlosrat making a separate mod that would act as a UI library for his other mods, which would be the only place where the font assets are defined, and then he could create USS variables for them and use them in his projects
though I'm not sure if it's worth doing all that to serve fonts for 2 mods
basically, at most it would save the user 45 MB if they use both Flight Plan and Maneuver Node Controller
That would be definitely a must. As soon as you have tested one of them, you're quickly in the need of both
The 3rd one being K2-D2
I'm curious, is there any strong opinion on the font used? Cause I think it would be nice to use all the same font
Aka: is there a reason why in Flight Plan you wanted a different font? There could be a perfectly reasonable reason, I'm just wondering
my guess would be to make the UI more compact
the monospaced font we use by default takes up quite a bit more space
I'd be curious to see if through some clever styling it could be possible to achieve same compactness but with the UITK look & feel
for example this is MNC with the default UITK for KSP2 font
compared to the custom font
this is with 1px smaller font and with some negative letter spacing
I love the last one
with the default background color could be a bit easier on eyes too
yeah I do agree that the background and foreground could have a bit less contrast
it makes me squint to read the text
Plus m/s could be written with ㎧
(not sure if the font supports it however)
but not super important
just checked, it doesn't
So, I want to change my inclination to 90°. There's no good option currently in Flight Plan to do that. Best option in this case would be "at the Apoapsis". Maybe adding that option would be good?
what would the new option be?
I can already see all the options I can think of in that menu
oh right I can't read lol
apoapsis and periapsis
makes sense
disregard 😆
Do you mean "I want to change my inclination from 0° to 90°"? Because if you were changing from any other value to 90 then I think AN and DN are still the best options are they not?
So, if I understand, your point is that when changing from 0 to 90 it may be desired to do this at Ap?
For anything else it will always be cheaper at AN or DN, though I suppose you may not care about cheaper in some situations
Ultimately, the answer is that I can very easily add other burn time options to any particular maneuver case. I believe I patterned the available options for each case off of what MJ offers.
I quite frequently use the "at a fixed time" option for changing inclination - particularly when I first arrive at a body. This can be adapted to Ap or Pe by merely warping to just before that point and then picking "at a fixed time" which defaults to 30s from now.
It's common that I may arrive at a body, and immediately set the inclination to something very high (85-is) either before or after setting the Pe, then set circularize at Pe. This is how I typically get into a polar orbit when arriving. No reason you can't do that for 90° inc too.
That's one reason, yes.
Another reason is that the font I picked looks freaking cool. I like it. I like it very much. That is most likely the main reason, although one of the things I happen to like about it is how it's compact - but that is only one aspect. I looked at a lot of free/OS fonts before settling on this one as the most cool and really beautiful one.
I definitely did not like how things looked with the default font. Granted, munix has shown some ways that even the default font could be salvaged - but I honestly still prefer the font I've got.
in the end, it comes down to whether you're going for consistency with the game's UI or not
I'm a bit more open to this suggestion. On the one hand, I happen to really like the high contrast look it has now. I also very much like how K2D2, MNC, and FP have managed to keep a mostly similar and consistent look. On the other hand, the actual game's UI is converging on it's own in terms of style and there's something to be said about aligning with that. Personally, I still like what I've got now better, but I do get that argument.
If K2D2 were to convert to be common with the game, then I would be more open to converting FP and MNC
But still, I really like this font...
basically, the default UITK styles attempt to make mods look like they are part of the stock game, and not stand out
but I do have to admit that MNC and FP have their own charm, too
I do get the value of that - truly I do.
I suppose I just wish I liked the standard the game is using more...
I recognize personal taste as an important factor especially when developing in your own spare time, so I understand it 😄
On the other side, what about two fonts options? So you don’t have to bundle the CJK font at least
since it’s USS it should be doable, but I’d suggest this only if easy enough
as in, configurable fonts where the custom ones will not work with CJK but the UITK ones will?
Yup
it's definitely doable
technically it would be the same font
pretty easily, too
could just make a class for the root element that when used, will switch the fonts to the UITK ones
and then toggle the class at runtime
this is what i was thinking
plus I think there are common classes like unity-button which could make the code smaller too
what do you think @wind mica ?
So, I think what you're suggesting is that there might be a user configurable option to switch between the cool font and the default one?
Yes something like that
the font is only set in two places in the whole MNC codebase, once for the heading and once for everything else
since they're two different fonts
so that can easily be done in FP too
And that with the cool font we do what, remove the CJK?
a Cool / Coherent font setting
it just wouldn't support CJK at all
I’d suggest so, yes
and anyone playing in Chinese, Korean or Japanese would have to switch to the default UITK font
since yours doesn't support them
that could even be done automatically based on the game's language
this could be easily auto-set too checking the current language
I was about to ask if this was possible...
What about this issue? Would it be easy to set/automate this so that if the UITK default faunt is used it also adjusts spacing and whatnot?
If you're changing inclinations to a lower value, you have to do it at AN or DN. Well you don't have to do it at AN/DN, but if you want 0° inclination, then you do. If you're changing to a higher value you can change it anywhere, and it that case it's always better to do it at the highest altitude possible since your speed is lowest then, so you need the least velocity to cancel out. So burning at AP is most deltav efficient.
Yeah, I don't really understand that...
it’s a variable too, like:
unity-font-definition: var(…)
letter-spacing: 0.8;
You mean if you're changing from 0° to 90°+ then do it at Ap, right? Becasue if you're changing from 85° to 90° or even just 5° to 90° then I think the lowest Dv is at the highest AN or DN is it not?
Nope 😆
Hold on, I'll test a bit
It's irrational, but I hesitate to do this. It's like giving up a bit of creative control over an aspect you really like in a particular way, but OTOH I get that it's probably more important that it works well for the player and is configurable to their liking. My hesitation is definitely irrational - but I'm OK with that as it's not the first or only irrational thing about me
then don't, it's your choice
I'm in a highly eccentric orbit around Jool. If I burn at AP, I only need around 600 m/s to change from near 0° to 90°.
really, what it would mostly accomplish is it would rid you of the extra 50 MB for both mods
If I try to change it at AN/DN, I don't nearly have enough fuel to do that. That's because my speed is really high at AN/DN, so canceling that requires a lot of energy
Sorry for initiating another topic while you're discussing this.
Ah, I get it. If you were in a perfectly 0° inc orbit then the AN/DN is undefined and you would clearly want the highest point. At any non-0 inc, there is an AN/DN, but in a highly eccentric orbit it's more advantageous (much more in this example) to say screw the AN/DN, I want to be at the highest point.
Of course you're never in a perfectly 0° inc orbit though you might be very close to that - but that doesn't matter because even in that case your orbit might be highly eccentric as in your example here.
That is a significant advantage!
I do prefer a smaller mod.
but there are other ways to accomplish that, too
and you do not need to actually let the user pick
And any intelligent person using a non-CJK language would clearly pick the cool font...
you can use this method we described, but only make the change when the game's language changes
and disallow manual configuration of it
You can always increase your inclination at any point in the orbit. AN/DN is for matching planes with another orbiting vessel, or if you want to change your inclination to 0°, because Ascending Node and Descending Nodes are points in the orbit where you're crossing the equator.
Yup, plus I think it's more about the gray vs black background color than the font
It would be coherent even if you don't want to make the font configurable
I'll pause this topic till you get to a conclusion,
yeah, the pure black background with near white text is quite hard to read for me
(Wish you could make threads in forum posts)
basically what I see is something like this (though that's exaggerated)
that's why I dislike dark mode in most places
astigmatism sucks lmao
true
I had no idea a baby platypus is a puggle! How cute!
Also, I'm more open to the whole color thing than the font thing, but I'd like to try it out as an experiment in a dev build and also see if we could talk @tulip quarry into aligning K2D2 for the color so that MNC, FP, and K2D2 could stay aligned.
honestly the best thing that could happen would be for K2-D2 to be converted into UITK, and then you two could literally just share a single .uss file
I'm a kind of afraid of the work involved in this convertion.
I do like the idea of having FP switch to default font if the language is CJK.
I've worked so much on the K2D2 UI that it will take time until to get the same level of details
schlosrat was as well, and in the end it wasn't nowhere near as terrible, right?
plus, you can already use his stylesheet as a starting point
since your UIs are similar
It was WORSE! No, actually it wasn't all that bad
plus, hidpi support!
some controllers like the compas or the curve renderer for the lift will be a bit difficult
it might be easier than it was to make the originals
That would be interesting to see...
yes probably because ImgUI is awfull
since UITK has libraries for vector drawing
you can embed imgui in uitk if you really have to, but I'd argue against doing as such
Heresy!
it could definitely be used at least for the first versions if reimplementing these advanced controls would seem too complicated
yes and it's quite easy to debug in UnityEditor
I was more on doing a better land and stage pilot for the moment. But I know I'll have to do this adaptation one day. The moment is perhaps now.....
🤔
I would definitely try to help you out however I could
I know you can be of great help @grizzled vale
Honestly, I think you'd find it's way worth it and would not look back once you've done it.
and I've got good examples in MNC Flightplan and all others. and the size adaptation is a huge argument too....
Count on me too if anything is needed! I'd be glad to help
yep, UITK for KSP2 has built-in support for scaling, localization, reusable styles, etc.
it's really easy to build with it, doing it visually furthermore speeds up the development a lot
Thanks a lot
now would be a good moment for a good ol' promotional video for UITK -
I think that becomes true, but initially there is a learning curve. It's not bad though.
@safe nimbus For you in the next FP release:
case ManeuverType.newInc:
Options.Add(TimeRef.EQ_HIGHEST_AD); // "at Cheapest eq AN/DN"
Options.Add(TimeRef.EQ_NEAREST_AD); // "at Nearest eq AN/DN"
Options.Add(TimeRef.EQ_ASCENDING); // "at Equatorial AN"
Options.Add(TimeRef.EQ_DESCENDING); // "at Equatorial DN"
Options.Add(TimeRef.X_FROM_NOW); // "after Fixed Time"
Options.Add(TimeRef.APOAPSIS); // "at Next Apoapsis"```
Cause it's just that freaking easy.
honestly I would also add Periapsis
if you have apoapsis, you should have periapsis
just for completeness
Periapsis is a gauranteed bad choice
Yeah, some love for Periapsis as well
what if I want to make bad choices 😠
but for changing inclination it's a bad choice, yes 🙂
let people be inneficient :3
In what use case is it wise to choose that?
Actually, it should be this:
case ManeuverType.newInc:
Options.Add(TimeRef.EQ_HIGHEST_AD); // "at Cheapest eq AN/DN"
Options.Add(TimeRef.EQ_NEAREST_AD); // "at Nearest eq AN/DN"
Options.Add(TimeRef.EQ_ASCENDING); // "at Equatorial AN"
Options.Add(TimeRef.EQ_DESCENDING); // "at Equatorial DN"
Options.Add(TimeRef.X_FROM_NOW); // "after Fixed Time"
if (ActiveVessel.Orbit.eccentricity < 1)
Options.Add(TimeRef.APOAPSIS); // "at Next Apoapsis"```
We can't have it allowing Ap when the ecc is >= 1
That would be really bad
Oh yeah, ecc >= 1 is an escape trajectory
I was about to say that makes no sense
hmm, is it possible to make it show a grayed out apoapsis button?
you call this on every Update?
No this gets called when you pick a maneuver type on a tab
but the eccentricity can change without you changing the maneuver type
so you'll also need to check for that
That's a fair point. Currently I call SetOptionList in 16 places, just where I'm handling the maneuver type button toggles like in this example
private void Circularize()
{
// Set the BurnTimeOptions
selectedManeuver = ManeuverType.circularize;
ManeuverTypeDesc = SetOptionsList(selectedManeuver);
// Unset all button toggles
UnsetToggles();
// Set this one
ToggleButtonTextColor(CircularizeButtonOSM, true);
ToggleButtonTextColor(CircularizeButtonTRMS, true);
FlightPlanPlugin.Logger.LogInfo($"Circularize: selectedManeuver = {selectedManeuver} {_burnTimeOption}");
}
So, if you click a Circularize button this code runs just once and the options are set.
However, you're right - this could lead to a case when eccentricity changes leaving you with a nonsense option for Ap.
I could move this to be called on update so that it's only called from one place and just considers whatever the currently selected ManeuverType is - which can be none, so that case would need to be handled.
The plus side would be that the option list might be more robust, and the minus would be a little more code to run each update.
it would probably make sense
you could just check whether the eccentricity is over 1, or whether the selected maneuver type changed
if not, just don't do anything
Not as far as I know. But I know very little.
the native dropdown sucks
Really need a custom one
If we had a custom one I could just set this list once when a maneuver type is selected and the only thing I'd need to do on update grayout the Ap option if it's there
But for now I think I'd like to keep it simpler. It should be more robust than it is though.
@grizzled vale , what does the AD mean in CKAN?
This is in a brand new copy of 0.2.1 where I'm freshly installing mods
it means "Automatically detected"
aka you had the mod installed but not through CKAN
Oh, I bet I know what happened!
When I was first using the new template I didn't have my environment variable set and VS must have put a copy of FP into my steam game!
I'll need to fix that.
ah yeah that's definitely possible
Well this is not good...
That should be a clean install of FP 0.10.0 from CKAN and an clean install of NM 0.7.2 also from CKAN
So the problem I'm getting goes back a bit further than my recent work.
And what's released for all to use is clealy f-ed up.
Yuk, and I need to leave tomorrow for a trip where I won't be able to work on this until some time on Friday.
@grizzled vale Would you mind testing what your fork is doing? from any Kerbin orbit please use FP to target any other planet and just see what it says for the transfer window phase angle and the synodic period on the PTM: Planet tab
I'm getting this from a circular 300 km orbit I teleported to, but I would expect the same result (if this bug is present) at any orbit.
looks fine for me
That's such good news! Now I can pull your source code and diff to see what I've stepped on
Hey I'm so stupid. How can I do a compare between either of my branches (master or Dev) and your fork? I've googled this but still don't understand.
Thanks! This is a big help
OK, it's pretty much got to be the work I did in FpUiController.cs. Of all the diffs, that's all there really is that I think it could be - and there aren't all that much for diffs.
That fixed it. I was able to revert enough of it back that it works now. I still don't understand what I did wrong, but clearly I did something wrong.
Fundamentally, I had three nearly identical blocks of code in the same method that I tried to breack out into one common method that I'd call from those three places. I somehow botched that and made the mess I did.
Now I'm back to having the three nearly identical blocks, but at least it works
I'm in bed now, but I can take a look at it tomorrow to see what the reason was
I'm sure it's something really stupid. I seem to be really good at that 😉
Oh, BTW, @west slate I've implemented your lovely clickthrough blocking technique in Flight Plan now, too. I'll put this out soon since having a clickthrough blocking technique is so especially useful for any mod - especially one with a lot of buttons like FP.
Happy to hear this! *especially since I use Flight Plan continously 😄 *
Released!
Côooooooool
@grizzled vale do you know why CKAN would be reporting something silly like this for FP?
Here I've got the debug version of my game selected, which definitely has 0.10.1 installed, and yet CKAN is saying I've got 0.10.0 installed. Moreover, it's saying 0.10.0.1 is the latest even though I released 0.10.1 last night
I've done a refresh
I don't see anything wrong in the NetKAN for FP. It points to my GitHub repo and the right SpaceDock, both of which have 0.10.1
Similar question for MNC. Although CKAN does see that one as updated, it doesn't recognize that I've got that version installed. Shouldn't it show both of those as AD?
if you at some point installed/updated them with CKAN, and then replaced them with your dev versions again, CKAN has no way of knowing that
it just thinks you're using the CKAN versions you last installed
That's the thing, I did install them with CKAN in my non-debug game instance, but I don't believe I've ever installed them with CKAN in by debug game.
Maybe I'm wrong about that, but I don't think so.
then I have no clue, you can try to ask HebaruSan in the CKAN discord
I'll try uninstalling them in CKAN for this game instance and then reinstalling them via VS.
Will do.
Uninstalling in CKAN, and then rebuilding in VS did sort out CKAN's recognition of the install being AD, but CKAN does still think FP is current at 0.10.0.1. I'll take that question to HebaruSan on the CKAN discord.
yeah, they'll probably know better what's wrong
Problem solved. Turns out I was just in idiot QA mode again. I did the build on GH before checking my release.yml, and then found that I needed to do a bit more work there in order to get the auto-push to SpaceDock. I foolishly attempted to solve this by doing a Release build on my PC and then posting that to SpaceDock, but it had a slightly different file size owing to being built on Windows vs. Linux. CKAN did not like the file size mismatch.
Problem solved by downloading the zip from GH and replacing the one on SpaceDock with that.
@wind mica I'm getting an error when trying to update to 0.10.2
CKAN.InvalidModuleFileKraken: FlightPlan 0.10.2: C:\Users\nikit\AppData\Local\CKAN\downloads\downloading\B8934B49-FlightPlan-0.10.2.zip has SHA1 0BBDC9A7D9FB356D139FF7FCE5D0E4009BA91DA7, should be 07737EEE69A10698037C3DF4B1DEAC1B84AC1284
at CKAN.NetModuleCache.Store(CkanModule module, String path, IProgress`1 progress, String description, Boolean move, CancellationToken cancelToken)
at CKAN.NetAsyncModulesDownloader.ModuleDownloadComplete(Uri url, String filename, Exception error, String etag)
I've confirmed this error on my end. I'll look into what needs to be done to correct it.
Hopefully you’re all set now. I released 0.10.2.1 earlier today to fix this. Please refresh your CKAN and try that version
Hi! This is a bit nit-picky, but is there a reason that the maneuver altitude when you choose circularize at an altitude is measured from the center of the body, but the new Pe and new Ap is measured from "sea level"? To me, it would be nice if the maneuver altitude input used the "sea level" altitude that everything else (like the Ap and Pe's displayed in game) uses. I often am targeting circularize at a particular altitude when positioning orbital survey satellites into optimal orbits, and right now I usually start by creating a dummy test maneuver to determine the sea level offset and then calculate the needed value for this field.
This is relatively minor... thanks so much for the mod, I use it CONSTANTLY
Yep, all good!
Thanks for pointing this out! I had not realized this was malfunctioning, but by Jove it is! I believe I've traced the problem and am testing a solution now...
no problem, thank YOU!
How's this look? A bit better?
perfect!
0.10.3 will be coming to a CKAN near you shortly...
It out there! CKAN may take a bit to catch up, but give it a bit of time and it will. https://spacedock.info/mod/3359/Flight Plan#changelog
Thanks so much! It's working great!!!
Do you also use the Resonant Orbit Maneuvers tab to help deploy your sats?
I haven't yet, but maybe I should look at it. I pretty much just use micro engineer to validate the current inclination is close to 90 degrees and then circularize at the optimal altitude.
It would be cool if we had to care about orbit resonance, but KSP's one SOI at a time thing seems to make it mostly roll play, right?
yeah, just realized there's a whole tab I haven't figured out yet in this mod! Some of that stuff looks cool, I might need to learn a bit more orbital science. There's some useful stuff there if I want to say make a geosynchronous orbit. What is Min LOS Alt? What does LOS stand for? Is it where the atmosphere effectively ends and you can timewarp beyond 4x? That would be really useful to have. The occlusion toggle seems to affect it, maybe taking into account how much the atmoshphere occludes? This stuff could be useful if using a mod to make satnet more realistic, maybe I should look at those
LOS means line of sight. There are modders working now on occlusion which is a necessary part of having a working comm net. A min LOS altitude is the altitude you need given the number of satellites in your constellation so that each satellite can see the ones that are immediately ahead and behind. This is useful when you want a very low altitude and is the lowest you can go
The occlusion toggle affects how atmosphere is accounted for with the min LOS altitude and allows you to have a margin of error in addition to considering the effects of atmosphere on satellite to satellite communication
I felt a disturbance in the force
ok, so now that I have installed CommNext, I have a reason (I think) to figure out the resonant orbit maneuvers. I'm a novice at this. I think this will help me deploy a constellation of satellites that are spaced evenly in an orbit. I understand the target altitude and I've set it to the synchronous alt. But I don't quite understand what "Fix Ap" / "Fix Pe" does. It seems to use a different altitude than what I put in the target, and I don't understand what it is doing. I suspect it is going to somehow use a different orbit to deploy the satellite(s).
Is there some docs beyond what's on SpaceDock for this tab in FlightPlan? I didn't see much there for that tab, other than to say that it had "Fix Ap" and "Fix Pe" and a screenshot. (It has great docs for the other tabs which I have mastered.)
Or... I probably could figure it out if I had a link to a wikipedia article or something talking about how deployment of constellations work.
ok, so now that I have installed CommNext, I have a reason (I think) to figure out the resonant orbit maneuvers. I'm a novice at this. I think this will help me deploy a constellation of satellites that are spaced evenly in an orbit.
This is exactly a good reason to use resonant orbits
I didn't try resonant orbit in Flight Plan, however the concept is "simple": one of Pe/Ap is going to be the target, and the other one will be different. The idea is to have an orbit "touching" the desired satellites orbit exactly after a specific period;
e.g. you want it to touch every 20 min (1/3 of the sync orbit period, supposing it is of 60 min), so that you can decouple one satellite each time you pass in Ap/Pe
the yellow line here is the "desired" orbit; the dark green line is the resonant orbit, which will allow you to touch the yellow every 1/3 of the yellow orbit
cool. Do you have a link to that website? It might help me in figuring it out, and then I think the FlightPlan stuff will make more sense to me
ah! So one side touching the final orbit and it just lets you space them
It's for KSP1, plus an in-game tool is definitely easier
but a good reference to "learn" about it
exactly!
that's what I was missing, thanks so much for explaining it to me
I think flightplan will make it much easier. I'll try it out.
OK, I think @west slate probably already helped you with this, but I'll be happy to take a shot at explaining what's going on in the ROM tab. It's all about helping you get your deployment vehicle into a resonant orbit - which is what the Payloads and Deploy Orbits part is about at the top. If you'd like to deploy 3 satellites total, and do each deployment needing just one swing through your resonant orbit then you'd have a 4/3 resonance for a non-diving orbit and you would be releasing each satellite at the Pe of your resonant orbit.
In the example above it's starting from a circular orbit with a 600 km altitude, so to get into a 4/3 resonant orbit you need to raise your Ap to 1107 km
You can see at the bottom of the tab where it's telling you the orbit you need, and right under that offering you a button to give you the node you need to get into it
In a non-diving resonant orbit you always release at the Pe and your resonant orbit flys higher than the orbit you want your satellites to be in (hense it's non-diving)
yes, thank you! I'm in the middle of deploying my first set now. I've had to reset back to VAB a couple times but not because of your tool, little design flaws unrelated to flightplan. I just didn't understand how the deploy orbits worked and once leonardfactory explained them your tool made perfect sense
If you wanted a do a diving orbit then the resonance would be 2/3 and you'd need to drop the Pe so that your Ap is at 600 and your resonant orbit "dives" below your target orbit
I'm currently using a 4/3 resonant orbit
Oh, OK. Sounds like you've got it!
yes, thanks so much!
You can always take a look at diving vs. non-diving to see which will take less delta v
Nice to have the Flight Plan explanation! Now putting relays should be easier 😄
I'll work on updating the documentation - I see now that that's a bit lacking for this tab!
Hi @wind mica I think when you fixed the target altitudes to use altitude from "sea level" instead of from the center of the body, you may have forgotten about the calculations for synchronous alt. It still shows 3463, which might be correct from the center of Kerbin but it should be around 2863 when measured from sea level I think.
My constellation is a bit slower than the rotation of Kerbin, but it will still work I think once it is fully deployed
Thanks! I'll take a look!
I got my constellation fully deployed. It works great now that I understand how to do it!
Awesome!!
Confirmed. I’ll have this sorted tomorrow as I’m already in bed now. Easy fix!
Okie dokie... Got ROM tab working better I think. Please give 0.10.4 a try
Thanks so much! I'll look when I play later today! Out and about now...
@wind mica said: Fixed Diving prohibition to account for atmosphere depth. You are now (correctly) prevented from setting up a diving resonant orbit around a body with an atmosphere where the Pe would be inside the atmosphere - which, I think we can all agree, would be bad.
This made me chuckle 😆
Previously the FixPe and FixAp buttons allowed all the same burn time options as a NewPe or New Ap, but I don't think all those options really make sense for this speciallized application. For now (and I can change this pretty easily) you get a default of "at next periapsis" when doing a FixAp, and a default of "at next apoapsis" for FixPe, but either one will let you pick "at a fixed time from now" which would let you do it right now or whatever. My thinking is that other options than "at next apoapsis" or "at next periapsis" could make sense with the first maneuver (if you need to do more than one), but if you have fixed one of these and then want to fix the other, then you really don't want any other options.
that sounds good to me
Yeah, I ran into that when it was letting me set up a diving orbit around Kerbin with a Pe of 32 km, cause after all that's not below the surface...
Thanks for helping surface bugs in FP! Your feedback is definitely helping to make this a better tool for everyone. I still need to go do a better write up so this tab is a little less mysterious to those not already familiar with the concepts. It's always my hope that FP gives the right amount of aid that it helps people learn more about orbital mechanics without robbing them of the fun of mission planning.
I confirm the issue with the sync orbit is resolved. Thanks so much!!!
(I saw that line and I was like, hey it does remember me something!)
That definitely doesn't look right. What it reminds me of, though are the results I've seen trying to get a Moon Return at Minmus where it places the node ~180 degrees from where it should be in the starting orbit and it has me headed off to a Kerbol orbit very similar to Kerbin's. If you can, could you go back and take a look to see which side of the orbit around Duna the node is on? It ought to be on the side facing Kerbol so that you depart loosing a lot of speed to give you a Pe somewhere near Kerbin.
yeah no, it was on the other side
Hmmm... well, scratch that theory.
not 180 degrees, I'd say like 120
but moving it around with MNC did give me a transfer
Oh you're saying it was on the wrong side, just only ~120 degrees from where it should have been?
yeah
If that's the case, then it makes me think these things could be related
That's a lot like what I've seen with MoonReturn at Minmus, and fundamentally they do the saem thing. Ejection velocity going into Hohmann transfer
So... Why would it be out of phase some times and not others? Very curious
yeah, that it is
Try that if you would. It's a debug build of NM that has a different approach to some functions that I've been testing.
I'm off to bed already, but I will try tomorrow
It goes back to something @safe nimbus pointed out a while back where planetary rotation was not being handled correctly.
There are several places where the code in OrbitExtensions.cs deviated from MJ. I had been using some stuff from KS2. I think it's all working this way now, but if for any reason the values differ we will get warnings in the log like this generates
public static Vector3d WorldOrbitalVelocityAtUT(this PatchedConicsOrbit o, double UT) // KS2: OrbitalVelocity // was: SwappedOrbitalVelocityAtUT
{
// return o.getOrbitalVelocityAtUT(UT).xzy;
Vector3d thisVec = o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ;
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ); // from KS2
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
return thisVec2;
}
return thisVec;
// return o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ); // from KS2
}
I believe this one was the one Falki found
public static Vector3d WorldBCIPositionAtUT(this PatchedConicsOrbit o, double UT) // KS2: RelativePosition // was: SwappedRelativePositionAtUT
{
// return o.getRelativePositionAtUT(UT).xzy;
Vector3d thisVec = o.GetRelativePositionAtUT(UT);
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
return thisVec2;
}
return thisVec;
// return o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
}
But there are 8 methods in OrbitExtensions where I previously had the KS2 lines, and now I have code blocks like these.
I need to scrub some of the code in FP to see if I need to do things like this there as well.
So, it seems the Minmus Moon Return problem also afflicts Gilly
Heads off in almost exactly the wrong direction...
With a bunch of pushing the node time around though, and no changes to the burn vector otherwise, I can get this
Further testing at other moons has not produced results like this - not even Bop or Pol. So, it's not the size of the moon you're at, though maybe it's how deep that moon is inside its primary's SOI. Perhaps the thing that Minmus and Gilly have in common here is just that they are not that deep in the SOI, and perhaps Bop and Pol are comparatively deeper?
You could try testing this by moving Gilly's orbit around using Shoemaker
I've done a bit more testing on this in that I've got a dev version of FP that's using updated code from the latest MJ2 dev version. That version of MJ has a completely different way of doing Hohmann transfers and moon return - they did a big overhaul of how a bunch of things are done. I've got a working copy of this MJ dev version compiled with some additional debug logging to spit out a lot of info verifying which functions are called and what they're computing when you perform a moon return or bi-impulsive hohmann transfer. I've got equivalent code in my Dev branch of FP on my local machine, so I can verify the same functions are called and what results they give.
Curiously, with this all-new code approach I'm getting essentially the same results as before, qualitatively speaking.
The same cases work and the same cases fail.
I can verify that in MJ2/KSP1 they work fine and see the new functions being called and see what they're computing in the calls.
I see the same functions and general behavior in the Dev version of FP where it will go through some number of optimization iterations in the new functions - and code-wise I believe they've got the same code now in these functions.
My operating hunch is that with my previous version and with this new Dev version, the same problem exists - which means it's probably not in ReturnFromMoon.cs, TwoImpulseTransfer.cs, OperationTransfer.cs, OperationMoonReturn.cs, the DeltaVAndTimeForHohmannTransfer method (in OrbitManeuverCalculator.cs) or the DeltaVAndTimeForMoonReturnEjection method (also in OrbitManeuverCalculator.cs).
Those are all new files and new/overhauled functions.
So, if the problem is not there (and why would it be?), and since both the previous version of MJ and the latest Dev version give excellent moon return results at Minmus and Gilly, and since FP is doing the same things in these functions, then the problem is with something these functions call or the inputs to them.
I think there may be something fundamentally wrong in FP in how I compute something needed by these functions. In MJ they're getting the right info and giving good/excellent results. In FP they do all the same things but give crap results in some cases. The inputs must be different.
The problem then is how to compare the differences in some meaningful way. How to spot where the problem is. As similar as I can make the test cases, they are never identical. The initial conditions for the orbits are always slightly different, and so there will always be small differences everywhere. How then to spot the difference that is actually meaningful?
@grizzled vale how would you suggest debugging this? Any ideas?
I can't say I have any better ideas than just testing out the math yourself outside of either MJ or FP
It's very complicated math as it's run through optimization functions. It's not at all like simple orbital mechanics equations. The simple maneuvers that are like that are sadly not the ones that are failing.
I mean, very complicated math in C# and in Python shouldn't be that different
Perhaps a painstaking debug mode single stepping through in both might reveal something
it's still just math
public static (Vector3d dv, double dt) DeltaVAndTimeForMoonReturnEjection(PatchedConicsOrbit o, double ut, double targetPrimaryRadius)
{
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: From {o.referenceBody.Name} to {o.referenceBody.referenceBody.Name}");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: UT = {FPUtility.SecondsToTimeString(ut)}, targetPrimaryRadius = {targetPrimaryRadius}");
var solver = new ReturnFromMoon();
CelestialBodyComponent moon = o.referenceBody;
CelestialBodyComponent primary = moon.referenceBody;
(V3 moonR0, V3 moonV0) = moon.Orbit.RightHandedStateVectorsAtUT(ut);
double moonSOI = moon.sphereOfInfluence;
(V3 r0, V3 v0) = o.RightHandedStateVectorsAtUT(ut);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: Calling ReturnFromMoon.NextManeuver");
(V3 dv, double dt, double newPeR) = solver.NextManeuver(primary.gravParameter, moon.gravParameter, moonR0,
moonV0, moonSOI, r0, v0, targetPrimaryRadius, 0);
FlightPlanPlugin.Logger.LogDebug($"Solved PeR from calculator: {newPeR}");
return (dv.V3ToWorld(), ut + dt);
}```
If RightHandedStateVectorsAtUT is wrong, then of course it will all fall apart.
Once you go into solver.NextManeuver things are not so easy
if I had to guess, these inaccuracies are probably caused by the differences in representations of orbits and coordinates in the two games
beyond that, I have no clue
I would have to do a deep dive into MechJeb's code to understand exactly how it works
and also into both of the games' orbital physics systems
The fact that you see the same issue with (i assume) a large portion of the code being different, give a clue. The issue is likely not in the part that changed
I've been reading through the MJ code in FP, and it does not seem that complicated, it's just a lot, and I have the feeling that there are many redundent functions in there
yeah, it means the issue is in the inputs, or the interpretation of the outputs
The outputs are deltaV and time for burn. If the outputs were not working then I think all of FP would be failing, so I suspect it's the inputs.
My current hope is that it's in RightHandedStateVectorsAtUT since I don't think I'm using that one in the stuff that does work.
my eye was on the right state vector
it's definition can be slightly arbitrary (as it just has to be in the plane defined by the up vector)
get we get some debug data from MJ running in KSP1?, like values for inputs in a given gamestate
Yeah, I can get that. I'm aiming to set up as close to the same initial conditions as I can by using the cheat menues to teleport to a starting condition and trying to make sure the UT is very lose to the same.
Then I make saves at those points and do a load-and-test approach
I notice that there are lots of direction vectors changing rapidly when you pass 20km altitude, so, I mean, quite likely that some objects are still bugged in ksp2
Here's a sample from FP
I'll try to get the same one from MJ and post that.
This one gives a typically borked return
Here's the same thing from MJ
Although I'm puzzled by the time... In FP the UT was 5:45:46, in MJ it reports as 1d 00h 15m 20s, although the screen shot clearly shows it's 5:45:24-ish
Could this be a timing issue like CommNext had? It sounds similar... the right computations, but if you get coordinates for different things at different times, things could be way off especially when you are far from Kerbol because of the speed of the SOIs
I do not think it is as I renamed my Update function to be LateUpdate in FP and that had no effect.
k
private void LateUpdate()
{
if ((_keybind != null && _keybind.Value.IsDown()) || (_keybind2 != null && _keybind2.Value.IsDown()))
{
ToggleButton(!InterfaceEnabled);
if (_keybind != null && _keybind.Value.IsDown())
Logger.LogDebug($"Update: UI toggled with _keybind, hotkey {_keybind.Value}");
if (_keybind2 != null && _keybind2.Value.IsDown())
Logger.LogDebug($"Update: UI toggled with _keybind2, hotkey {_keybind2.Value}");
}
//if (_keybind != null && _keybind.Value.IsDown())
//{
// ToggleButton(!_interfaceEnabled);
// Logger.LogInfo($"Update: UI toggled with _keybind, hotkey {_keybind.Value}");
//}
//if (_keybind2 != null && _keybind2.Value.IsDown())
//{
// ToggleButton(!_interfaceEnabled);
// Logger.LogInfo($"Update: UI toggled with _keybind2, hotkey {_keybind2.Value}");
//}
//if (MainUI != null)
// MainUI.Update();
}```
That used to be Update
But then it may be the wrong thing to test..
You're over my head but it might be worth pinging @west slate to see if he has any ideas based on his experience
Maybe I need to also change from Update to LateUpdate in FpUiController? The above is in FlightPlanPlugin
Hi @wind mica
You need to check from my experience everywhere you use <simObj>.Position
If you access it, you need to be sure that code is run in LateUpdate
Are you running everything in the main thread or are you using Coroutines?
Well, I access that alot. How do I ensure it's only accessed in a LateUpdate?
in this case it doesn't seem like that is relevant
I have a few of those (Coroutines), but not many
And not here
since your Update/LateUpdate doesn't seem to be doing anything else than opening/closing the window
you're not running any simulation code in it
so it's irrelevant
If positions are grabbed during Update they are messed up
this is the thing I noticed
yeha but what I'm saying is, his Update doesn't do anything
other than toggling the UI visibility
I know, but if that code in the UI
starts grabbing positions
you cannot be sure they are all right
I'm not sure what you mean
Suppose you do this:
it's only changing visibility
Fine, so I changed that back. That makes sense
is to check that all code using simulation positions
is run not during an Update phase
But how can I make sure I only access <simObj>.Position in a LateUpdate?
I understand that conceptually, but not practically.
I've got zero clue how to make that happen
well, the code runs presumably in the event handlers for UI elements like buttons
so it depends on when Unity fires those events
This was my main doubit
doubt*
I'll try changing from Update to LateUpdate in FpUiController. Maybe that will have an effect
How do you start the computations?
Buttons trigger it from the UI
Ok
Well that didn't make it happy
Disregard, I think it had a pre-existing node where it was trying to create one
Clearing the node and starting again I get this
Which is to say the same horrible junk as always when at Minmus
I'd try, for testing at least, to do something like this
private bool _shouldRunCommand;
// ...
private void Initialize() {
button.clicked += () => _shouldRunCommand = true;
}
// ...
private LateUpdate() {
if (_shouldRunCommand) RunYourComputations();
}
very, very, very wrong node position
and then setting _shouldRunCommand to false after RunYourComputation()
I can take a shot at that.
also, looking at the two logfiles, it does seem that the coordinate systems are very different.
[Info : Unity Log] [MechJeb2] ReturnFromMoon.NextManeuver: moonR0 = [39,546,587.103, -24,925,876.922, 4,875,254.677] m
[Info : Unity Log] [MechJeb2] ReturnFromMoon.NextManeuver: moonV0 = [146.463, 231.682, -3.537] = 274.118 m/s
[Debug :Flight Plan] DeltaVAndTimeForMoonReturnEjection: moonR0 = [-45,666,090.976, 9,973,610.437, 4,912,761.936] m
[Debug :Flight Plan] DeltaVAndTimeForMoonReturnEjection: moonV0 = [-58.473, -267.808, 0.159] = 274.118 m/s
It's nice the vector magnitudes are the same.
[Info : Unity Log] [MechJeb2] Secondary celestial orbit: sma:47,000,000.000 ecc: 0.000 inc: 6.000 lan: 230.647 argp: 0.000 tanom: 97.092
[Info :Flight Plan] Secondary celestial orbit: sma:47,000,000.000 ecc:0.000 inc:6.000 lan:78.000 argp:277.213 tanom:172.469
I'd hoped that with a fairly similar initial time and orbit I might see most of the error being in a Swap Y and Z kind of thing or maybe a sign diff
it doesn't mean they are wrong necessarily, but the reference coordinate is definately a different one
that's very optimistic 😆
Exactly
Not necessarily, there are differences like that with KSP1 and KSP2
I'm hopeful that I've just got the wrong coordinate system selected somewhere and can change to have the right one
The game may well be doing all the math for me and I just need to fix something like that
well, one of the biggest things is whether you're in the same reference frame
the game does have conversion methods between them
It's pretty easy in reality
It's not always obvious as the game has very similar or same sounding methods which are not always same
body.celestialFrame.ToLocalPosition(otherPosition)
I'd buy a bottle of nice scotch for the first person who can beat the truth out of the devs for wth they did with that stuff
sourceTransform.celestialFrame.ToLocalPosition(body.transform.Position)
Or vodka if you prefer... I'm not picky
I was asking too, the main thing I suppose is that having different Frames it would be easier to implement N-body dynamics
Whiskey for me
So, I've computed the angle between the MoonR0 from MJ and FP, and this is what I get:
rad 2.736926968124578
deg 156.8143641090747
I was hoping for 90deg or something, but it's not
the angle between the velocities is also slightly off:
rad 2.7926104138145993
deg 160.00479053585886
and r0
rad 2.6269295365376197
deg 150.511975521863
and v0
rad 2.6269276478404753
deg 150.51186730748785
I have no idea to explain these angles, moreover, if it is only the reference frame that is changed, they should all be the same, and I think they are enough different to exclude computational precision
public static (V3 pos, V3 vel) RightHandedStateVectorsAtUT(this PatchedConicsOrbit o, double ut)
{
o.GetOrbitalStateVectorsAtUT(ut, out var localPositionZup, out var relativeVelocityZup);
return (localPositionZup.ToV3(), relativeVelocityZup.ToV3());
}```
That's what Node Manager has in it.
And this is what MJ has in the same bit
public static (V3 pos, V3 vel) RightHandedStateVectorsAtUT(this Orbit o, double ut)
{
o.GetOrbitalStateVectorsAtUT(ut, out Vector3d pos, out Vector3d vel);
return (pos.ToV3(), vel.ToV3());
}```
Where GetOrbitalStateVectorsAtUT is a KSP1/KSP2 function
are these righthandedvectors in the log too? didn't spot them
and, the orbits are defined differently too between KSP1 and KSP2, notice the argp here: #1091863665134796880 message
the difference in lan is 152 deg, sus...
do you have any idea why these two dv vectors are not equal:
[Info :Flight Plan] CreateManeuverNode: Solution Found: _deltaV1 [70.256, 0.416, 142.483] m/s = 158.863 m/s 1:12:28.86 from now
[Info :Flight Plan] CreateManeuverNode: newDeltaV [71.369, 0.420, 141.926] m/s = 158.861 m/s
I mean, they are close, but I don't see why they are not identical
So, i've encountered another, perhaps similar issue. I've put two craft in a circular orbit around kerbin. Then I ask FP for a hohmann transfer, and it gives me the one in the first screen (ending 2957_1.jpg), it has a closest approach of 1225km, which is less then optimal. Now, by just moving the time of the burn I can get the correct transfer with 290m of distance. Notice how the two are about 180deg apart. I've included the save, it's a bare sandbox with just the two vessels, perhaps this can be a nice testcase.
The log
Yes, both FP and MJ call RightHandedStateVectorAtUT to get a number of the values that are shown in #1091863665134796880 message and #1091863665134796880 message. Here's the code tha produces part of that log in FP, there is nearly identical code in MJ except that it calls a different logging function.
public static (Vector3d dv, double dt) DeltaVAndTimeForMoonReturnEjection(PatchedConicsOrbit o, double ut, double targetPrimaryRadius)
{
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: From {o.referenceBody.Name} to {o.referenceBody.referenceBody.Name}");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: UT = {FPUtility.SecondsToTimeString(ut)}, targetPrimaryRadius = {targetPrimaryRadius}");
var solver = new ReturnFromMoon();
CelestialBodyComponent moon = o.referenceBody;
CelestialBodyComponent primary = moon.referenceBody;
(V3 moonR0, V3 moonV0) = moon.Orbit.RightHandedStateVectorsAtUT(ut);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: moonR0 = [{moonR0.x:N3}, {moonR0.y:N3}, {moonR0.z:N3}] m");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: moonV0 = [{moonV0.x:N3}, {moonV0.y:N3}, {moonV0.z:N3}] = {moonV0.magnitude:N3} m/s");
double moonSOI = moon.sphereOfInfluence;
(V3 r0, V3 v0) = o.RightHandedStateVectorsAtUT(ut);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: r0 = [{r0.x:N3}, {r0.y:N3}, {r0.z:N3}] m");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: v0 = [{v0.x:N3}, {v0.y:N3}, {v0.z:N3}] = {v0.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForMoonReturnEjection: Calling ReturnFromMoon.NextManeuver");
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.
The equivalent code in MJ is like this
public static (Vector3d dv, double dt) DeltaVAndTimeForMoonReturnEjection(Orbit o, double ut, double targetPrimaryRadius)
{
Debug.Log($"DeltaVAndTimeForMoonReturnEjection: From {o.referenceBody.name} to {o.referenceBody.referenceBody.name}");
Debug.Log($"DeltaVAndTimeForMoonReturnEjection: UT = {GuiUtils.TimeToDHMS(ut)}, targetPrimaryRadius = {targetPrimaryRadius}");
var solver = new ReturnFromMoon();
CelestialBody moon = o.referenceBody;
CelestialBody primary = moon.referenceBody;
(V3 moonR0, V3 moonV0) = moon.orbit.RightHandedStateVectorsAtUT(ut);
double moonSOI = moon.sphereOfInfluence;
(V3 r0, V3 v0) = o.RightHandedStateVectorsAtUT(ut);
Debug.Log($"DeltaVAndTimeForMoonReturnEjection: Calling ReturnFromMoon.NextManeuver");
(V3 dv, double dt, double newPeR) = solver.NextManeuver(primary.gravParameter, moon.gravParameter, moonR0,
moonV0, moonSOI, r0, v0, targetPrimaryRadius, 0);
Debug.Log($"Solved PeR from calculator: {newPeR}");
return (dv.V3ToWorld(), ut + dt);
}```
So, FP calls ReturnFromMoon.NextManeuver, and that also logs the same values
public (V3 dv, double dt, double newPeR) NextManeuver(double centralMu, double moonMu, V3 moonR0, V3 moonV0, double moonSOI, V3 r0, V3 v0,
double peR, double inc, bool optguard = false)
{
FlightPlanPlugin.Logger.LogInfo(
$"ReturnFromMoon.NextManeuver: centralMu = {centralMu:N3}, moonMu = {moonMu:N3}, moonSOI = {moonSOI:N3}, peR = {peR:N3}, inc = {inc:N3}, optguard = {optguard}");
FlightPlanPlugin.Logger.LogInfo(
$"ReturnFromMoon.NextManeuver: moonR0 = {moonR0:N3} m");
FlightPlanPlugin.Logger.LogInfo(
$"ReturnFromMoon.NextManeuver: moonV0 = {moonV0:N3} = {moonV0.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogInfo(
$"ReturnFromMoon.NextManeuver: r0 = {r0:N3} m");
FlightPlanPlugin.Logger.LogInfo(
$"ReturnFromMoon.NextManeuver: v0 = {v0:N3} = {v0.magnitude:N3} m/s");```
So, you can see that moonR0, moonV0, r0, and v0, all are obtained from calls to RightHandedStateVectorsAtUT(ut)
And the code for those functions are basically the same for FP and MJ
Those vecotrs are similar but slightly different because FP backs off the node time by 1/2 the burn duration to make is so the center of the burn is at the point it's asked for. KSP1 doesn't need this, but KSP2 does. We need this because the orbital mechanics equations and methods applied by both MJ and FP assume an instantaneous impulse, so the burn vector computed has no understanding of the burn duration. It's not enough to simple move the node time back by 1/2 the duration though. Since burn vectors are in Prograde, Normal, and Radial directions, then shifting the time of the node cause a rotation of the vector in inertial space. This is why FP looks at the direction of the burn vector in an inertial frame at the requested time of the burn, then backs off the node time and rotates the burn so that it's new Prograde, Normal. and Radial components align with the original inertial vector.
What I can't explain off the top of my head is why there would be a 0.02 m/s difference between their magnitudes. I've not observed that before. The magnitudes should be the same.
Well, crap. It looks like Rendezvous is broken too. I know for sure that was working fine at one point. I'll test this out at my end as well to confirm.
Ah yes, the burn moment shift with half the burn time, this seems fine
I'm still puzzled why the orbits are so different, I'll compute both (FP and MJ) state vectors for their respective orbits with my code tonight, hopefully, they come out the same as in the log.
Did you move minimus before using MJ in your log above?
Those should not be puzzling I think but rather expected. The orbit differences are coming about due to the crazy differences in the inputs to the process which is closer to the root of the problem. I believe once we sort out why there are such differences in the inputs then the intermediate orbits will be much more similar
I’m going to catalog all the places where I use simobj position and look at how that transform is done. Maybe we’ll get lucky and find a simple fix in there. I’ve previously done tests to ensure the base functionality is returning the same values for other things, but not the right handed versions
This is involving code in Node Manager BTW as that mod also needs the functionality so I put it there
I was thinking, does the KontrolSystem (https://forum.kerbalspaceprogram.com/topic/214543-release-kontrolsystem2-042/) mod use the same codebase to make transfers? If not, maybe it can serve as a reference to test some code
This is supposed to be a scripting system (like kOS) to control kontrol everything. Obviously this quiet the task, so right now I'm looking for some very brave Kerbonauts to give an initial spin (i.e. see if it works anywhere else but on my machine) Links SpaceDock: https://spacedock.info/mod/331...
It does not use the same code base, and I have used it as a reference. In fact, when I was initially struggling to get the MJ code in FP to work, I turned to KS2 for examples and have duplicate bits of code in OrbitExtensions.cs in Node Manager such as this.
public static Vector3d WorldOrbitalVelocityAtUT(this PatchedConicsOrbit o, double UT) // KS2: OrbitalVelocity // was: SwappedOrbitalVelocityAtUT
{
// return o.getOrbitalVelocityAtUT(UT).xzy;
Vector3d thisVec = o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ; // MechJebWay
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ); // from KS2
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
// return thisVec2;
}
return mechJebWay ? thisVec : thisVec2;
}```
In all, there were 7 places I did this, and I've experimented with these confirming that the code I've got now gives the same results, and will give a warning level log in any case where it doesn't. Note that in MJ/KSP1 there is a .xzy method for Vector3d. The equivalent in KSP2 is .SwapYAndZ.
In my Dev version of Node Manager I define mechJebWay as true within the OrbitExtensions class like this
public static class OrbitExtensions
{
private static bool mechJebWay = true;```
However, regardless of how that's defined, I compute both ways and compare them so I would get a warning if they're different.
There is one exception where I deviate from the pure MechJeb approach, and that's in WorldBCIPositionAtUT.
public static Vector3d WorldBCIPositionAtUT(this PatchedConicsOrbit o, double UT) // KS2: RelativePosition // was: SwappedRelativePositionAtUT
{
// return o.getRelativePositionAtUT(UT).xzy;
Vector3d thisVec = o.GetRelativePositionAtUT(UT); // MechJebWay (sort of - without the SwapYAndZ)
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
// return thisVec2;
}
return mechJebWay ? thisVec : thisVec2;
}```
Here, you can see that in MJ, they apply the .xzy operation, but in my code we do not. This is necessary to get agreement with the KS2 result and to also get good results. If I were to apply the .SwapYAndZ operation here then all hell breaks loose and everything that depends on WorldBCIPositionAtUT would fail to produce any kind of good result.
I just pulled a fresh copy of KS2 and it looks like that mod may have changed how it computes some things since I snatched code from it. I believe the place to look is in KS2's OrbitWrapper.cs, but there are no comments at all (shame on you untoldwind!) and the names have either changed or I've lost track of what the mapping was. Probably the latter. If I look at older versions of my OrbitExtensions.cs I may find comments I used to have that noted what the corresponding KS2 method names are. With the code changed now in KS2 it will be hard to sort out just based on that.
I think a good exercise now would be to re-map the MJ OrbitExtensions methods to the corresponding KS2 methods and then update my calculations for thisVec2 so we can see if there are differences in any of these. If there are differences, then it may be a good experiment to set mechJebWay to false and see what we get.
Not too hard in some cases...
public static Vector3d WorldOrbitalVelocityAtUT(this PatchedConicsOrbit o, double UT) // KS2: OrbitalVelocity // was: SwappedOrbitalVelocityAtUT
{
// return o.getOrbitalVelocityAtUT(UT).xzy;
Vector3d thisVec = o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ; // MechJebWay
// Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ); // from KS2
Vector3d thisVec2 = o.GetOrbitalVelocityAtUTZup(UT).SwapYAndZ; // from KS2 2024.02.21
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldOrbitalVelocityAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
// return thisVec2;
}
return mechJebWay ? thisVec : thisVec2;
}```
So, KS2 uses o.OrbitalVelocity as MJ and FP use o.WorldOrbitalVelocityAtUT for example, and apparently KS2 is now using the exact same thing MJ and FP use for this. I'll keep sorting through these looking for where things get different.
public static Vector3d WorldBCIPositionAtUT(this PatchedConicsOrbit o, double UT) // KS2: RelativePosition // was: SwappedRelativePositionAtUT
{
// return o.getRelativePositionAtUT(UT).xzy;
Vector3d thisVec = o.GetRelativePositionAtUT(UT); // MechJebWay (sort of - without the SwapYAndZ)
// Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // From KS2
Vector3d thisVec2 = o.GetRelativePositionAtUTZup(UT).SwapYAndZ; // From KS2 2024.02.21
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldBCIPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
return mechJebWay ? thisVec : thisVec2;
}```
Interesting difference here perhaps.
public static Vector3d OrbitNormal(this PatchedConicsOrbit o) // KS2: OrbitNormal // was: SwappedOrbitNormal
{
// return -o.GetOrbitNormal().xzy.normalized;
Vector3d thisVec = -o.GetRelativeOrbitNormal().SwapYAndZ.normalized; // MechJebWay
// Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, -o.GetRelativeOrbitNormal().SwapYAndZ).normalized; // From KS2
Vector3d thisVec2 = -o.GetRelativeOrbitNormal().SwapYAndZ; // From KS2 2024.0220
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"OrbitNormal(1): thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"OrbitNormal(1): thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
return mechJebWay ? thisVec : thisVec2;
}```
Another one with no difference in KS2 these days.
Also this one is no longer a difference
public static Vector3d NormalPlus(this PatchedConicsOrbit o, double UT)
{
// return o.OrbitNormal();
Vector3d thisVec = o.GetRelativeOrbitNormal().SwapYAndZ.normalized; // MechJebWay
// Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativeOrbitNormal().SwapYAndZ.normalized); // From KS2
Vector3d thisVec2 = o.GetRelativeOrbitNormal().SwapYAndZ.normalized; // From KS2 2024.02.21
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"NormalPlus: thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"NormalPlus: thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
return mechJebWay ? thisVec : thisVec2;
}```
These look OK
//normalized vector along the orbital velocity
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d Prograde(this PatchedConicsOrbit o, double UT) // Agrees with KS2
{
// KS2: OrbitalVelocity(ut).normalized; // From KS2 2024.02.21
return o.WorldOrbitalVelocityAtUT(UT).normalized;
}
//normalized vector pointing radially outward from the planet
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d Up(this PatchedConicsOrbit o, double UT) // Agrees with KS2
{
//KS2: RelativePosition(ut).normalized; // From KS2 2024.02.21
return o.WorldBCIPositionAtUT(UT).normalized;
}
//normalized vector pointing radially outward and perpendicular to prograde
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3d RadialPlus(this PatchedConicsOrbit o, double UT) // Agrees with KS2
{
// KS2: Vector3d.Exclude(Prograde(ut), Up(ut)).normalized; // From KS2 2024.02.21
return Vector3d.Exclude(o.Prograde(UT), o.Up(UT)).normalized;
}```
I've been able to match up nearly all of the functions from KS2's OrbitWrapper.cs to the MJ/FP OrbitExtensions.cs. There are still a few spots where I'm uncertain though, and I suspect these include the spot(s) that matter. For example, WorldBCIPositionAtUT (#1091863665134796880 message). However, I've also found several sources that talk about swapping between right-handed and left-handed coordinates, such as here https://stackoverflow.com/questions/1263072/changing-a-matrix-from-right-handed-to-left-handed-coordinate-system
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.
It seems that all that's needed is to do a .SwapYAndZ to get from one to the other. Also, KSP2 chose to give us slightly different function names that may actually be decalring whether they're returning right-handed or left-handed coordinates. In WorldBCIPositionAtUT, the MJ approach is simply this
return o.getRelativePositionAtUT(UT).xzy;```
And the KS2 version of the same function (called RelativePosition) is this
```cs
return o.GetRelativePositionAtUTZup(UT).SwapYAndZ;```
Since Z is up in a right-handed coordinate system, then presumably GetRelativePositionAtUTZup gives us the relative position in right-handed coordinates and KS2 is transforming it to left-handed. I've seen comments in MJ that talk about KSP1 functions returning things in such a way that they need a .xzy operation, so this makes sense. KSP2 is just being honest in the method name.
So, in this case, KSP1 apparently has getRelativePositionAtUT (which returns right-handed, and so needs a .xzy), and KSP2 has both GetRelativePositionAtUT (returning left-handed) and GetRelativePositionAtUTZup (returning right-handed, and so needing a .SwapYAndZ).
This makes me wonder if there's more to the difference between these two than just the coordinate frame - or why would they have them.
Also there is this weird thing in KS2. Weird, in that it seems like it's a recursive call
public Position GlobalPosition(double ut) {
return ReferenceBody.Orbit.GlobalPosition(ut) + GlobalRelativePosition(ut);
}```
I believe this function is intended to serve the same purpose as the MJ/FP WorldPositionAtUT function, which I've got as this.
public static Vector3d WorldPositionAtUT(this PatchedConicsOrbit o, double UT) // was: SwappedAbsolutePositionAtUT
{
// return o.referenceBody.position + o.WorldBCIPositionAtUT(UT);
Vector3d thisVec = o.referenceBody.Position.localPosition + o.WorldBCIPositionAtUT(UT); // MechJebWay
Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.referenceBody.Position.localPosition + o.GetRelativePositionAtUTZup(UT).SwapYAndZ); // from KS2
// Vector3d thisVec2 = o.referenceBody.Orbit.GlobalPosition(ut) + GlobalRelativePosition(ut); // KS2: 2024.02.21 - recursive function? This is in a method called `GlobalPosition`
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"WorldPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"WorldPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
// return thisVec2;
}
return mechJebWay ? thisVec : thisVec2;
}```
There is some old KS2 code in there (marked // from KS2), and then there's the new KS2 code commented out for comparison, but what's going on here? OrbitWrapper extends Orbit objects, so it would give you an Orbit.GlobalPosition method. Calling that should then call ReferenceBody.Orbit.GlobalPosition. WTF? A ReferenceBody will have an Orbit, but since Orbit is extended, that orbit will have a GlobalPosition method and we're off to the recursive races.
In VS, when I ask it where the GlobalPosition of RefererenceBody is defined it just shows me the same function. I understand recursion, and as we all know - to understand recursion you must first understand recursion... But... WTH?
KS2, in it's current form, does not have anything equivalent to the RightHandedOrbitalVelocityAtUT method in MJ/FP, but I believe it used to - at least I've got some code and a comment that claims it did. Nevertheless, given what I beleive I know about these functions, what is in MJ and FP makes sense. MJ calls getOrbitalVelocityAtUT and doesn't do a .xzy, and FP calls GetOrbitalVelocityAtUTZup and similarly does not do a .SwapYAndZ, so that seems like it should be OK. I guess KS2 just doesn't need this function, or at least I was unable to map it to anything.
GetOrbitalVelocityAtUTZup is called in only one place in KS2, and that's in the OrbitalVelocity method in OrbitWrapper, but that applies a .SwapYAndZ to it, so it's apparelyt left-handed in it's return.
There are no places in KS2 that then turn around and call OrbitalVelocity applying another .SwapYAndZ, so it's just not got an equivalent to RightHandedOrbitalVelocityAtUT as far as I can tell.
Another similar difference is in RightHandedBCIPositionAtUT
public static V3 RightHandedBCIPositionAtUT(this PatchedConicsOrbit o, double UT)
{
// return o.getRelativePositionAtUT(UT).ToV3();
V3 thisVec = o.GetRelativePositionAtUTZup(UT).ToV3(); // MechJebWay
V3 thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, o.GetRelativePositionAtUTZup(UT)).ToV3(); // from KS2
if (thisVec != thisVec2)
{
NodeManagerPlugin.Logger.LogWarning($"RightHandedBCIPositionAtUT: at {UT} thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"RightHandedBCIPositionAtUT: at {UT} thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
// return thisVec2;
}
return mechJebWay ? thisVec : thisVec2;
}```
Where again I seem to have som older KS2 code hanging in there, but I can't find an KS2 equivalent to this what's in the current code base. There's the KS2 RelativePosition method, but that applies .SwapYAndZ to the GetRelativePositionAtUTZup - so that's not right-handed.
There's also KS2's GlobalRelativePosition which does this
public Vector GlobalRelativePosition(double ut) {
return new Vector(ReferenceFrame, orbit.GetRelativePositionAtUTZup(ut).SwapYAndZ);
}```
But the real kicker, the one I'm more concerned with for the current problem, is the MJ/FP RightHandedStateVectorsAtUT method, which is this.
public static (V3 pos, V3 vel) RightHandedStateVectorsAtUT(this PatchedConicsOrbit o, double ut)
{
o.GetOrbitalStateVectorsAtUT(ut, out Vector3d pos, out Vector3d vel);
return (pos.ToV3(), vel.ToV3());
}```
This is the one we've seen differences in, and given the KSP2 penchant for naming things that return right-handed with a ZUp, then I'm guessing that maybe this is left-handed. This is why I was expecting that possibly the difference between what MJ gives today and what FP gives would be possibly swapped in those coordinates, but they were not, and instead the observed difference was... stranger. #1091863665134796880 message
KSP2 has a GetOrbitalStateVectorsAtUT, a GetOrbitalStateVectorsAtObT, and a GetOrbitalStateVectorsAtTrueAnomaly, but no GetOrbitalStateVectorsAtUTZup or anyhting like that.
Time to go spelunking into KSP2 and see if I can learn what that function does...
LOL, GetOrbitalStateVectorsAtUT just calls GetOrbitalStateVectorsAtObT passing in this.GetObtAtUT(UT) and UT. However it does appear to return localPositionZup and relativeVelocityZup!
And guess what. GetOrbitalStateVectorsAtObT just calls GetOrbitalStateVectorsAtTrueAnomaly passing in this.TrueAnomalyAtObT(ObT) and UT!
Digging through GetOrbitalStateVectorsAtTrueAnomaly it does appear that GetOrbitalStateVectorsAtUT returns right-handed vectors.
digesting your posts
are you ever dealing with matrices? I think not right, all relevant objects are vectors in your code, right? For those you can simply swap the vector components
right handed coordinate system just means that the cross product of x and y gives you z. It doesn't imply which way is up. But I think in gaming, right handed refers to both z = cross(x,y) and z pointing up. The name "right handedness" is used a bit sloppily in gaming I think.
The recursion issue seems valid, can you add a recursion counter in there to see if it is blowing up?
man, quite the journey, I guess I have to bite the bullet and install the stuff to inspect this code in action, c# seems quite easy to read with a c++ background. However, I have a weekend trip planned this WE, so it will have to wait.
Lots and lots of vectors, but not a lot of matrices. Mostly it's Vector3d, V3. As I inherit code from MJ there are some things in Primitives which include M3.cs and V3.cs. M3 is a "3x3 Matrix with right-handed APIs that integrates with V3 and Q3" according to the comments in it. In Node Manager, where I've got that, it's used only within M3.cs and Statics.cs, where in Statics.cs it's used in the NearlyEqual method. NearlyEqual is not even used in Node Manager, but other parts of Statics are, so I included M3.cs there.
In FP there is more use of M3, in particular in Sheppard.cs in the Solve2 method, and a little bit in Statics.cs (NearlyEqual method) and in Astro.cs in the ENUToECI and ECIToENU methods.
When I look in FP, I don't see anywhere that Solve2 is used, and VS is telling me there are 0 references. I do have 16 references to Solve from Sheppard.cs, but that just uses some V3's. So, I don't think I'm really using matricies in FP and those are not likely to be the issue, but this was a good line to explore so I'm glad you asked since I hadn't gone down that line yet.
The recursion issue, if there is one, would be in KS2 and not in FP. It's quite possible it's not really an issue and there's something subtle going on there that I'm not realizing. Digging into that I see that KS2 has this in KSPOrbitModule.Orbit.cs
[KSMethod(Description = @"Get the coordinate independent position at a given universal time `ut`.
Note: This takes the motion of the parent body into account.")]
Position GlobalPosition(double ut);```
And it tells me that version of GlobalPosition has 8 references across three files in 5 specific lines - one of which is OrbitWrapper.cs line 93 - the place where I thought there may be recursion.
It's also used in OrbitWrapper's GlobalVelocity method
public VelocityAtPosition GlobalVelocity(double ut) {
return new VelocityAtPosition(
new Velocity(context.Game.UniverseModel.GalacticOrigin.celestialFrame.motionFrame,
orbit.GetFrameVelAtUTZup(ut).SwapYAndZ), GlobalPosition(ut));
}```
Which also turns up in KSPOrbitModule.Orbit.cs like this
[KSMethod(Description = @"Get the coordinate independent velocity at a given universal time `ut`.
Note: This takes the motion of the parent body into account.")]
VelocityAtPosition GlobalVelocity(double ut);```
Here are all the references to GlobalPosition from KSPOrbitModule.Orbit.cs
In MockOrbit.cs there's a GlobalPosition that does this
public Position GlobalPosition(double ut) {
var bodyPosition = body.orbit?.GlobalPosition(ut) ?? new Position(ReferenceFrame, Vector3d.zero);
return bodyPosition + new Vector(ReferenceFrame, RelativePosition(ut));
}```
That seems like it would not be recursive since if there isn't an orbit for a body (e.g. Kerbol) then it stops the recursion and just returns the position.
I think I'm getting confused with there being multiple definitions for GlobalPosition in KS2. I wonder if VS is similarly confused. When I ask it to show me all the places MockOrbit's GlobalPosition is used it points to OrbitWrapper.cs line 93 again as one of them.
Possible theories: (a) This is a subtle coding technique I'm not (yet) savvy enough to understand where things with the same name are coexisting in some harmonious and useful way. (b) VS is stupid and can't tell distinct things apart and so is reporting references that are not true. (c) I'm really not savvy and just not understanding some blindingly obvious truth.
I do find the KS2 descriptions for GlobalVelocity and GlobalPosition intriging in that they both say "Note: This takes the motion of the parent body into account", which makes me wonder if that's where FP is going wrong. This is one place where FP and KS2 are not yet aligned, so perhpas this is the clue we need to follow.
I did a quick test in my dev version with an existing save and didn't see an issue when planning a Hohmann transfer between to craft orbiting Mun. I tried both the transfer from the craft in the higher orbit to the lower one and from the lower orbit to the higher one. The lower orbit in my test case was fairly circular, but the higher one happened to be more elliptical. The process should work best when both are perfect coplanar circles. I'll download your save and see if I see this at my end.
Loading your test case save I do get this issue in my dev version. I also am getting massive log spamming from my own debugging logs for this:
The log spam happens when I'm on the Target Relative Maneuvers: Vessel tab (the one needed for this operation), so it presumably relates to the calculation of some info on that tab
Moving to the Resonant Orbit Maneuvers tab doesn't generate log spam.
OrbitNormal does get called in SynodicPeriod, so it's possible that's what's causing the log spam, however the difference is so slight that I don't think that's likely to have anything to do with the observed effect - it's just annoying in that it makes the log harder to use to diagnose this.
That's what I see in my log using your save to perform the same maneuver and with the annoying spam resolved.
Spam resolved this way:
public static Vector3d OrbitNormal(this PatchedConicsOrbit o) // KS2: OrbitNormal // was: SwappedOrbitNormal
{
// return -o.GetOrbitNormal().xzy.normalized;
Vector3d thisVec = -o.GetRelativeOrbitNormal().SwapYAndZ.normalized; // MechJebWay
// Vector3d thisVec2 = o.referenceBody.transform.celestialFrame.ToLocalPosition(o.ReferenceFrame, -o.GetRelativeOrbitNormal().SwapYAndZ).normalized; // From KS2
Vector3d thisVec2 = -o.GetRelativeOrbitNormal().SwapYAndZ; // From KS2 2024.0220
if ((thisVec - thisVec2).magnitude > 0.000001)
{
NodeManagerPlugin.Logger.LogWarning($"OrbitNormal(1): thisVec = [{thisVec.x}, {thisVec.y}, {thisVec.z}]");
NodeManagerPlugin.Logger.LogWarning($"OrbitNormal(1): thisVec2 = [{thisVec2.x}, {thisVec2.y}, {thisVec2.z}]");
}
return mechJebWay ? thisVec : thisVec2;
}```
So, it still checks to see if there's a difference, but if the difference is in any way trivial it ignors it
[Debug :Flight Plan] DeltaVAndTimeForHohmannTransfer: dv1 = [34.933, -128.408, 12.084] = 133.623 m/s, dt1 = 1:27:21.53
[Debug :Flight Plan] DeltaVAndTimeForHohmannTransfer: dv2 = [-50.525, 133.957, 14.209] = 143.872 m/s, dt2 = 1:53:28.69
here the 2nd one seems correct, but the first one doesn't
Those logs and values are coming from here:
public static ( Vector3d dV1, double UT1, Vector3d dV2, double UT2) DeltaVAndTimeForHohmannTransfer(PatchedConicsOrbit o, PatchedConicsOrbit target, double ut,
double lagTime = double.NaN, bool fixedTime = false,
bool coplanar = true, bool rendezvous = true, bool capture = true)
{
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: Making transfer at UT {FPUtility.SecondsToTimeString(ut)}");
FlightPlanPlugin.Logger.LogDebug($"lagTime = {lagTime}, fixedTime = {fixedTime}, Coplanar = {coplanar}, Rendezvous = {rendezvous}, Capture = {capture}");
(V3 r1, V3 v1) = o.RightHandedStateVectorsAtUT(ut);
(V3 r2, V3 v2) = target.RightHandedStateVectorsAtUT(ut);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: r1 = [{r1.x:N3}, {r1.y:N3}, {r1.z:N3}], v1 = [{v1.x:N3}, {v1.y:N3}, {v1.z:N3}] = {v1.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: r2 = [{r2.x:N3}, {r2.y:N3}, {r2.z:N3}], v2 = [{v2.x:N3}, {v2.y:N3}, {v2.z:N3}] = {v2.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: Calling TwoImpulseTransfer.NextManeuver");
(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);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: dv1 = [{dv1.x:N3}, {dv1.y:N3}, {dv1.z:N3}] = {dv1.magnitude:N3} m/s, dt1 = {FPUtility.SecondsToTimeString(dt1)}");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: dv2 = [{dv2.x:N3}, {dv2.y:N3}, {dv2.z:N3}] = {dv2.magnitude:N3} m/s, dt2 = {FPUtility.SecondsToTimeString(dt2)}");
return (dv1.V3ToWorld(), ut + dt1, dv2.V3ToWorld(), ut + dt2);```
So, the second dv we're seeing is actually the second impulse in a TwoImpulseTransfer, which is the burn you need at the end of the rendezvous
We're throwing that away right now and relying on the user to do a match velocity node when they get to the rendezvous point
That said, the input to TwoImpulseTransfer is coming from RightHandedStateVectorsAtUT, and so this may very well be a symptom of the same problem we're already trying to sort out for Moon Return.
Here's a minor bug in FP. IF you select a target before launching FP, or if you select the target by any means other than using FP's GUI, then the FP GUI does not display the target. Not related to our main issue, but something I probably ought to fix.
Hold on! I just got this!
The only change I made was what I thought was a trivial one to the logging, and now when I load your test case and make a node, bang it nails it.
Litterally, the only thing I changed was to simplify the logging like this
public static ( Vector3d dV1, double UT1, Vector3d dV2, double UT2) DeltaVAndTimeForHohmannTransfer(PatchedConicsOrbit o, PatchedConicsOrbit target, double ut,
double lagTime = double.NaN, bool fixedTime = false,
bool coplanar = true, bool rendezvous = true, bool capture = true)
{
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: Making transfer at UT {FPUtility.SecondsToTimeString(ut)}");
FlightPlanPlugin.Logger.LogDebug($"lagTime = {lagTime}, fixedTime = {fixedTime}, Coplanar = {coplanar}, Rendezvous = {rendezvous}, Capture = {capture}");
(V3 r1, V3 v1) = o.RightHandedStateVectorsAtUT(ut);
(V3 r2, V3 v2) = target.RightHandedStateVectorsAtUT(ut);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: r1 = {r1:N3}, v1 = {v1:N3} = {v1.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: r2 = {r2:N3}, v2 = {v2:N3} = {v2.magnitude:N3} m/s");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: Calling TwoImpulseTransfer.NextManeuver");
(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);
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: dv1 = {dv1:N3} = {dv1.magnitude:N3} m/s, dt1 = {FPUtility.SecondsToTimeString(dt1)}");
FlightPlanPlugin.Logger.LogDebug($"DeltaVAndTimeForHohmannTransfer: dv2 = {dv2:N3} = {dv2.magnitude:N3} m/s, dt2 = {FPUtility.SecondsToTimeString(dt2)}");```
Here's what's in the log now
Other than those minor changes to logging, the only difference was that I selected the target using the game's interface before launching FP.
I don't remember how I selected the target, I think I used FP
Nope... There must be some other differene...
I just tried it again and got the bad result.
OK, I know what I did differently now, but not why it made a difference. I thought I'd loaded your quicksave_2 save, but instead I'd loaded an autosave_2 that KSP2 made for me when I was previously in your quicksave_2.
When I load that save, it works fine. When I load quicksave_2 it does not.
There's my autosave_2
Interesting, maybe the bug is not with FP
That would be both a joy and a sorrow.
Though I wonder if the clue we need is buried in the difference between these saves
I'm on the road all weekend, can't test sadly
No worries... I'll keep whittling on it. There are loads of cases where MoonReturn reliably does not work.
Ill have a look thru the save in my next train
lol, I guess we are 6h appart:
"unlockedAt": "2024-02-18T11:22:23.6768437-05:00",
"unlockedAt": "2024-02-18T17:22:23.6768437+01:00",
The first "surprising" difference:
looking at: "assemblyName": "Test1-1" / "location"
autosave:
"inclination": 0.40300352700320846,
"eccentricity": 0.0001202326096178923,
"semiMajorAxis": 1118449.264075554,
"longitudeOfAscendingNode": 121.97906451938974,
"argumentOfPeriapsis": 115.90364913209123,
"meanAnomalyAtEpoch": 0.402766404669801,
"epoch": 5225.8964749889838
quicksave:
"inclination": 0.40300380668487523,
"eccentricity": 0.00011957392461973344,
"semiMajorAxis": 1118448.4274033685,
"longitudeOfAscendingNode": 121.97901579440963,
"argumentOfPeriapsis": 116.16837580409006,
"meanAnomalyAtEpoch": -0.05083948250430461,
"epoch": 4943.296481305586
The values are close, but they should be identical, right, you did not burn any engines?
Continuing my search
same for vessel Test1-3
Ok, after a long diff of both savefiles, there are lots of "innocent" differences, simply because you had another vessel active, or because you are on a later UT which changes all local coordinates. All these innocent differences make the diff a bit less efficient to scan through. The only "surprising" difference I found was the fact that the vessels have slightly different orbits in the autosave
maybe the difference is just that, the UT
Hi @wind mica ! I have my two cents here, not sure if this could be helpful but I’ll say it, feel free to ignore me: I think i’m this case the game is calculating the “final” global position by “summing” the body position relative to its parent, but if the parent body is revolving another body it needs to calculate the relative position again and so on; so in the ends it’s Position relative to Kerbol + Position relative to Kerbin + Position relative mun for example
This still makes me think the problem is in timing calculations when positions are getting updated..
Thanks! I had a similar thought myself, though it was more along the lines that perhaps KS2 approaches it this way and the recursion - if this is what's going on - is just the way it happens to arrive at the answer it needs. That said, why then would some maneuvers be consistently quite good and some so far off? I've yet to find a case where Moon Return from Mun to Kerbin doesn't give excellent results, though I've only done them from fairly low inclination, low eccentricity starting orbits. A Moon Return from Ike is the same, and at every single body orbiting Jool you can get a reasonably good result - at least not something that sends you off in some wacky direction.
That said, at Gilly or Minmus we can't get even a tolerable result - the time is way off.
So, perhaps it's about chasing the coordinate frame back to Kerbol, but why bad at Gilly and Minmus, but Great to good in other places?
If I can sort out what KS2 is doing - if it is recusrsion, then I could at least give that a shot in FP to see if it makes a difference.
Please let me know how I can help. I've installed unity, but I'm afraid I need some help getting to where I can debug the code. I did manage to find a somewhat pathological case, where asking for a moon return on Gilly takes about 1min and then borks out, maybe this case provides some info.
I've tried moon returns from many different UT's, as I'm suspecting that some of the computations may work in different "quadrants" but Gilly never seems to work.
The one thing Minimus and Gilly have in common is that they have inclined orbits, maybe some z vector is upsidedown
If you add a "return to kerbol" option to other bodies, I can test Eeloo, the "return from moon" code must work to get from a CB to kerbol, right?
Found something else, switching the "target" from Eve to Kerbin changes the retrun from moon orbit, this definately should not happen, right?
log for "return from moon" with Kerbin or Eve
This line is attracting my attention:
[Warning:Flight Plan] PlanetaryXfer: Recommend starting interplanetary transfers from Gilly from an orbit in the same plane as Gilly's orbit around Eve. Starting orbit around Gilly is inclined 12.0º with respect to Gilly's orbit around Eve (recommend < 10º). Planned transfer may not intercept target properly.
perhaps the inclination triggers a different code path, and the bug is in that codepath
I believe it should work that way. Getting FP to let you call it that way might be a bit tedious as we could need to make a custom UI bundle with a new button or something like that. Alternatively we might be able to fiddle with the Moon tab to also be available when at a planet. That would probably be easier and may work.
The inclination doesn't change the control flow - the same code is executed regardless. That warning is copied from the same warning that MJ has historically had for many years now. It's interesting that MJ gives good results at Minmus and Gilly where FP does not - despite their both having the same code for this part - or as "same" as I've been able to make it. Also, in the course of developing FP I've employed now three different versions of MJ code. There was the non-dev branch I started from more than a year ago. There was an update to align with what MJ was doing last fall (October IIRC), and then there was the most recent MJ alignment. In each of these the code for how MJ did Hohmann transfers and moon return changed in slight ways, so we've really had three separate tests of this. For sure this problem has been present since the alignment last fall. I'm unable to test the earlier versions without rolling KSP and SpaceWarp and FP all back to much earlier versions (like KSP 0.1.2 or something).
I think the poor results hinted at by MJ have to do with not necessarily getting the Pe you want at the planet you're transferring to.
Oh that's funny! So apparently FP tests to make sure you're at a moon, and that you're targeting a planet, but it's just fine with things for any moon/planet combination and will therefore allow nonsense settings like this. It should be simple enough to place a guard on this so that it doesn't allow the node to be made unless you're targeting the planet that the moon you're orbiting is in orbit about.
If you've got Unity Editor installed, then you should be able to make GUI changes to FP (which is a whole other matter), but more importantly you should also be able to set things up so that you can debug with breakpoints and all in VS.
#🔴tools-and-resources message
There's a Gist for setting up debug. It was written for KSP1, but if you're using the right version of Unity Editor then it works the same for KSP2. It's really quite awesome!
Actually, there's a KSP2 specific guide for this here: https://gist.github.com/cfloutier/f84b580d61d4eecdacd5e8e822de0871
Ill have a look at the gist, perhaps I can be of some actual help.
@grizzled vale what do I need to do to make a nuget package with FP? It doesn't seem to be making them. I found that NodeManager had a nuget folder and nuget.config and Package.nuspec files at the root level in that mod's folder, so I copied those to FP's folder and changed the Package.nuspec to reference the FlightPlan license, but other than that I don't know what to do.
It doesn't seem to bea difference in the csproj or scripts
and you're building in Release configuration?
Yep, just built Release
Do I need to make a nuget folder for it, or will it make one if there isn't one?
I didn't see any errors in the build results
oh, I see
looking at your project, you're not using the library template
so nuget building is not defined at all
Sounds like I'll need to do some more work with FP and MNC then to convert them over to the library template
mostly you need a Package.nuspec file with these contents: https://github.com/SpaceWarpDev/SpaceWarp.Template/blob/main/src/templates/SpaceWarpModLibrary/Package.nuspec.txt
and this in your Directory.Build.targets file:
https://github.com/SpaceWarpDev/SpaceWarp.Template/blob/main/src/templates/SpaceWarpModLibrary/src/SpaceWarpModLibrary/Directory.Build.targets
Then I halfway did it. I already copied and modified the Package.nuspec from nodemanager. I'll go do that with Directory.Build.targets and see if that doesn't get me on my way. Thx!
Interesting though. NodeManager has a Directory.Build.props file, but I don't see a Directory.Build.targets...
Oh, looking in the wrong place then! Thanks!
FP already has one of those, I'll compare it's content to that of NM and see what my FP version may be missing
Well, right off the top the NM version had these two lines that FP's did not
<NuGetExecutable Condition="'$(OS)' == 'Windows_NT'">nuget</NuGetExecutable>
<NuGetExecutable Condition="'$(OS)' != 'Windows_NT'">mono /usr/local/bin/nuget.exe</NuGetExecutable>
However FP's version also has a bunch of hard coded stuff where NM's has parameterized stuff like this
Makes me wonder if I shouldn't be doing more to align FP's version with NM's
yeah I think I just did FP like that at first, and then later when I was doing NM, I realized it'd be better to create properties for the stuff so it isn't hardcoded
that means you'll have to create the appropriate properties in the Directory.Build.props file most likely
I found this difference you alerted me to for nuget
<!-- Packing NuGet package -->
<Message Text="Copying plugin DLLs and XMLs to temporary folder for NuGet packing" Condition="$(ConfigurationName) == Release"/>
<MakeDir Condition="$(ConfigurationName) == Release"
Directories="$(SolutionDir)/temp_nuget"/>
<ItemGroup Label="Plugin XMLs to be copied">
<PluginXMLs Include="$(PluginBinPath)/**/*.xml"/>
</ItemGroup>
<Copy Condition="$(ConfigurationName) == Release"
SourceFiles="@(PluginDLLs)"
DestinationFolder="$(SolutionDir)/temp_nuget"/>
<Copy Condition="$(ConfigurationName) == Release"
SourceFiles="@(PluginXMLs)"
DestinationFolder="$(SolutionDir)/temp_nuget"/>
<Message Text="Packing NuGet package" Condition="$(ConfigurationName) == Release"/>
<Exec Condition="$(ConfigurationName) == Release"
Command="$(NuGetExecutable) pack "$(SolutionDir)/Package.nuspec" -OutputDirectory "$(SolutionDir)/nuget" -Properties "NoWarn=NU5125;id=$(ProjectName);version=$(Version);authors=$(Authors);description=$(Description);repositoryType=$(RepositoryType);repositoryUrl=$(RepositoryUrl)"" />
<Message Text="Removing temporary folder" Condition="$(ConfigurationName) == Release"/>
<RemoveDir Condition="$(ConfigurationName) == Release"
Directories="$(SolutionDir)/temp_nuget"/>
But also this one
<OnError ExecuteTargets="Cleanup"/>
</Target>
<!-- Clean up temporary folder if build fails -->
<Target Name="Cleanup">
<Message Text="Removing temporary folder if it exists"/>
<RemoveDir Directories="$(SolutionDir)/temp_nuget"
Condition="Exists('$(SolutionDir)/temp_nuget')"/>
Oh wait, that second one is also nuget... duh
yep, both are for nuget building/cleanup
This is the only difference I see in Directory.Build.props
Should I replace what FP (left) has or add this as a new PropertyGroup?
if you remove the stuff on the left, you'll also have to add a nuget.config file with the SpaceWarp nuget server
those two basically do the same thing
Oh, I already did that
then you can just replace it
Are things like $(AssemblyName) and $(SolutionName) already defined? Those weren't in the Directory.Build.props, but they are part of the differences in the Directory.Build.targets
yes, those are pre-defined by MSBuild
(well, AssemblyName should be defined in your Directory.Build.props)
at least it is in the template
OK, only two errors on trying to build. Apparently it's looking for the LICENSE file and I suspect I may need to pre-make an empty nuget folder
Yeah, NM has a LICENSE file where FP has a License.md file
Do I just need to change LICENSE to License.md here?
<files>
<file src="README.md" target="" />
<file src="LICENSE" target="LICENSE" />
<file src="temp_nuget\*.dll" target="lib/netstandard2.1/" />
<file src="temp_nuget\*.xml" target="lib/netstandard2.1/" />
</files>
Or is it like README.md where the target is ""?
no need to make a nuget folder
it will do it
but yes, you need to change the src to your license filename
most likely

Well, I picked up MNC from earlier work, but the differences between FP and NM are all me.
For this block, should I understand target="" to mean that it doesn't place the file there?
<files>
<file src="README.md" target="" />
<file src="LICENSE.md" target="LICENSE.md" />
<file src="temp_nuget\*.dll" target="lib/netstandard2.1/" />
<file src="temp_nuget\*.xml" target="lib/netstandard2.1/" />
</files>```
What does target="" do?
it means it won't rename the file and it will simply put it into the root folder
Should I be renameing this file? Or does it not matter much?
it doesn't
I found a possible booboo in the FP Package.nuspec where the licenseUrl was broken. I fixed that and regenerated the nuget package just to be on the safe side.
Other than an update to the licenseUrl no difference. Not sure if that will matter, but I don't want to cause cahos down the road because of it
@wind mica I've added the K2-D2 API back but I can't see the K2-D2 button in FlightPlan
in the log i've got only :
[Info :FlightPlanPlugin.OtherModsInterface] K2D2_Plugin.ModGuid = com.github.cfloutier.k2d2
[Info :FlightPlanPlugin.OtherModsInterface] _k2d2Loaded = False
as I use now the @grizzled vale template the ModGuid has a little changed
i'm trying to change it but i'm a bit lost
The assembly name is now defined with the same name as the MOD : K2D2
so changing it will lead to changing the target directory
oh right you have the same thing as schlosrat where the project name =/= the assembly name =/= the folder name =/= the mod ID
yes
perhaps I can change it by and to got back to com.github.cfloutier.k2d2 in the Directory.Build.props
if you only want to change the mod ID, that's done in swinfo
and nothing else needs to be changed
the mod ID is unchanged = K2D2
but it used to be com.github.cfloutier.k2d2
so you can go to swinfo.json and change it back to that
to have Flight Plan recognize the mod
here is the previous swininfo.json
{
"mod_id": "K2D2",
"author": "cfloutier",
"name": "K2-D2",
"description": "The KSP astromech",
"source": "https://github.com/schlosrat/k2d2",
"version": "0.12.3",
"version_check": "",
"dependencies": [{
"id": "SpaceWarp",
"version": {
"min": "1.5.2",
"max": "*"
}
}],
"ksp2_version": {
"min": "0.2.0",
"max": "*"
}
}```
the mod id was K2D2
yes, in the very early versions of SpaceWarp, you could have a different SpaceWarp mod_id and BepInEx GUID
now you can't
ok
and since Flight Plan is checking the BepInEx GUID, it makes more sense to just continue using com.github.cfloutier.k2d2
the my new mod_id should be com.github.cfloutier.k2d2... ok i change that
but isn't it also the way it is identified by... ckan or Spacedock ?
{
"spec": "2.0",
"mod_id":" com.github.cfloutier.k2d2",
"author": "Christophe Floutier",
"name": "K2-D2",
"description": "",
"source": "",
"version": "1.0.0",
"version_check": "",
"ksp2_version": {
"min": "0.2.0",
"max": "*"
},
"dependencies": [
{
"id": "com.github.x606.spacewarp",
"version": {
"min": "1.8.0",
"max": "*"
}
}
]
}
I should also add uitk as a dependency
nope, CKAN has its own identifiers for mods, and SpaceDock doesn't read any of the information in the mod at all, just the things you fill in on the website (and generates its own numerical ID for your mod)
ok then I've got progress, the butoon is visible in FlightPlan
but I've got a null pointer exception from FlightPlan
in : "FlightPlan.FpUiController.K2D2"
I think that from K2D2 side the Api have not changed. but I could have made a mistake
here is a preview version @wind mica If you have time to test what is wrong
https://github.com/schlosrat/FlightPlan/blob/5091371eade7d0efa9ac205228856183609176ce/src/FlightPlan/FPOtherModsInterface.cs#L71 here's your issue
FP expects the plugin class to be named K2D2_Plugin but it's now K2D2Plugin
I also don't see any "ToggleAppBarButton" method in the new plugin class
thanks
but I've got an appbar button
// Register Flight AppBar button
Appbar.RegisterAppButton(
ModName,
ToolbarFlightButtonID,
AssetManager.GetAsset<Texture2D>($"{ModGuid}/images/icon.png"),
isOpen => main_window.IsWindowOpen = isOpen
);
no what I mean is that schlosrat's code calls a method named "ToggleAppBarButton" that you used to have in your plugin class, now it doesn't exist
so that will cause another error
ahh nevermind, that is there for compatibility with old K2D2 versions