#Rotating vessel during warp

1 messages · Page 1 of 1 (latest)

formal quail
#

So, burning while warping. KSP2 devs made a point on this being the norm now.

With this in mind, I built a 100k dv Xenon probe. Barely got it to LKO after a few tries.
Then found out that even with K2D2 and ManeuverNodeController, trying to get out of LKO is a chore.
And I'm planning to get into 750km (very low) polar Jool orbit later (completionist reflex after reading the OrbitalSurvey changelog), so the current approach is not feasible.

Ofc, building a more reasonable spacecraft is not an option.

So instead I've decided to make a mod that auto-rotates the craft during warp to the currently selected SAS mode (like prograde/retrograde),
In other words, I want to warp-burn my Xenon continuously, without stopping warp to correct the course.

But after messing around for a bit I found out I don't know what I'm doing.
Here is the latest attempt. Mostly pieces of code stolen from various parts of K2D2... But rewritten the way I like.
https://pastebin.com/U6PENXGf
And here is a demonstration of how it currently works.
https://youtu.be/-vf6K0Bf0AY
At the end I also opened the console to view debug output, tho I don't see anything useful in it rn...

Now, the problems:

  1. vessel.transform.UpdateRotation only works during warp. I mean, that itself is fine, but makes me think vessel.transform isn't supposed to be used this way;
  2. Vector3d Vector.vector property (like vessel.transform.forward.vector) is in local coordinates, so outputting it isn't very useful. While a regular Vector doesn't override .ToString();
  3. For some reason I need vessel up instead of forward (as a base vector for rotation). Why? Counterintuitive to me;
  4. This way of rotating the vessel is inaccurate, it eases rotation to prograde slowly instead of teleporting it. And then it glitches out after ~90 degrees of orbit.

At this point it's past midnight, so explanation might be a bit scuffed, please ask if something doesn't make sense.

Any tips from some more experienced people?

slate flare
#

This is a bug that is being worked on by the devs according to the last KERB

#

But if you make an early fix for it maybe it could go in Community Fixes?

formal quail
#

Ah, ok... Should I post in issues there?

#

Also is any of my code workable?

#

I mean there isn't much...

rose geyser
#

but they do put stuff like that into KERB

slate flare
rose geyser
#

(see wobbly rockets - that never was a "bug")

slate flare
#

They set it as a regular bug

rose geyser
#

yeah, but they also did that for resource processing in the background

#

which was definitely intended

#

but people didn't like the performance cost so they listed it as a bug

#

lmao

slate flare
#

Tbh this seems more to me like

#

They just kinda forgot

#

That they would need to do this

rose geyser
#

I don't think forgot is the right word, more like, just postponed it

#

until interstellar

slate flare
#

Mmm yeah

rose geyser
#

until people started complaining

slate flare
#

thats probably more accurate

rose geyser
slate flare
#

its a pretty serious issue though, hope its actually addressed soon

#

Or maybe this mod shall

rose geyser
#

yeah I've been complaining about time warp thrusting for a long time

#

the current implementation as a whole is just whacky

slate flare
#

Yeahhh

#

Its really buggy as well unfortunately

#

I try to avoid doing it unless I have to

rose geyser
#

I basically only use it when impatient to circularize

#

and that's mostly when testing some other mod or bug fix lol

rose geyser
#

it almost seems to me like it was used for the testing of a feature like the one you're trying to implement

#

from some of the uses in code

formal quail
#

Really? I thought game just overrides the transform while not warping

rose geyser
#

there's this

#

which looks very similar to what you're doing

#

it's in the class TriggerTools

#

which controls a debug window that we don't have access to

#

at least I don't think so, but I can quickly test

formal quail
rose geyser
#

the prefab file for the window is missing from the game assets (as is the case with most of their debug tools)

#

that's what I meant by that

#

they probably only include them in debug builds

#

but the code that controls them is still in the game

formal quail
#

I see...

rose geyser
#

there's all of these actually

#

but when I was trying them all at some point, I was only able to get the FX tools one I think

#

and it didn't have anything too interesting

#

I kinda wish they included them with the game, it's not like anyone other than modders would really want to use them anyway

#

and it's not like they have to worry about "cheating" when you can just edit save files to do anything you want

formal quail
#

... or alt+F8

rose geyser
#

right

formal quail
#

well anyway, I guess I will have to decompile in the end, at least to figure out wth Rotation.FromTo actually computes... tomorrow, if you don't beat me to it

#

... and this LookRotation too

formal quail
#

So, I've dug through some implementations, found math that doesn't make sense no matter how I look at it

Then decided to just try all the combinations of vessel.transform directions and Rotation.FromTo vs Rotation.LookRotation
And found that:

  1. vessel.transform.left, of all things, somehow spin-stabilizes the direction during warp;
  2. Using Rotation.LookRotation somehow prevents camera from being wonky.
    https://youtu.be/-9DohaLUHOc

I hate this working code, but trying to make my code any less speculative and junky somehow causes me even more pain:
https://pastebin.com/wThXKBb2
I think I'll just submit it to CKAN as-is and try to never touch it again...
Also gonna post whole repo to GitHub under Unlicense, in case anyone wants to continue in my stead

formal quail
rose geyser
#

it's #6 on the list

formal quail
#

thx

rose geyser
#

the spin stabilization is hilarious

formal quail
#

aaaand it doesn't work on trust. I mean it changes vehicle direction, but not trust direction

rose geyser
#

ahh

formal quail
rose geyser
#

yeah, seems like it

formal quail
#

ahahaha I wasn't crazy or bad at math, they really do swap Y and Z in different places, among other absolutely stupid things

#

and the better hanling of this fact is (pretty sure, but not 100%) why Rotation.LookRotation doesn't mess up camera, unlike Rotation.FromTo

formal quail
#

Well, I still don't have a solution though... Lemmi at least lay it out:
So, the problem is that trust direction during warp is handled separately from the main craft direction (VesselComponent.transform)
In that case, to track down what field/property is used a trust direction - I tried to find related code

The best clue I found is FlightCtrlState, in particular mainThrottle and pitch fields. Surely, if I look at how those fields are used - I'll find where they are contribute to some kind of trust vector, that gets added to the current orbit parameters
Except I didn't. I went over all of the related code in dnSpy twice (electricity turned off at one point, while I was stepping back, erasing all the progress I haven't held directly in my head). I see a lot of shuffling information back and forth, but not much of actually using it for physics calculations

Well, I've entirely skipped VFX classes. But there is no way VFX somehow affects physics calculations, right? RIGHT???
Maybe it's somehow not in Assembly-CSharp.dll and so the code isn't getting found?
Maybe there are some reflection shenanigans? Well, it sure seems like that, given how, for instance KSP.Sim.IDynamicOrbit.UpdateFromStateVectors isn't called from anywhere, even tho I presume it's the main way to change the orbit? But how do I even deal with that???

I'm going crazy, @rose geyser, any tips?

untold kestrel
#

Bear in mind I haven't looked in any depth at the implementation details, and that my memory on this is quite fuzzy.
But if I remember right thrust under warp is a completely separate simulation from normal thrust, where the vessel is basically treated as a single point, without any relation whatsoever to its constituent parts, their rigidbodies, etc. This presumably means that any notion of torque or rotational force/velocity is nonexistent in this simulation.
I don't think there is any bidirectional, automatic synchronization of the orientation between the trust simulation and the physical, visually shown vessel.
So to achieve an orientation change (ie, locking on a SAS target), you primarily need to alter the direction vector used in that separate simulation. Then ideally, you also have to separately update the physical representation of the vessel (which I guess is what you were trying to do until now) so things are aligned visually, but this is probably not required for things to work as you intend.

formal quail
untold kestrel
#

Again I don't remember things very well, but isn't the thrust under warp simulation handled by the same code as the maneuver planner integrator, and is a burst/jobs implementation ?

formal quail
#

I just realized I was writing thrust as trust... actually searching for thrust has given me a bunch of new things to sift through

untold kestrel
#

Looks up KSP.Sim.impl.VesselComponent.HandleOrbitalPhysicsUnderThrustStart()
This is where the magic happens.
Basically, this create one or more OdeSolverStageComponent solver instance, which is the burst/job orbit integrator shared with the maneuver tool planner.
The thrust direction is set here (see Vector3 vector = subStage.VectoredDirectionThrustActual.normalized * (float)(subStage.IspActual * 9.80665);, then manipulated further, then passed to the job implementation, which basically precompute the resulting orbital path.
Implementing what you want will likely be quite problematic, as this doesn't seem designed to be altered once computed.
If you want to change any parameter (such as the orientation), you will likely need to recompute everything every frame, which is likely to be an issue.

formal quail
#

yeah lol

#

I just got to this

#

I guess then the best option is to IL-inject new math somewhere here...

rose geyser
#

depending on what all happens in the method, you might even get away with just a postfix

untold kestrel
#

This is the same reason you can't change throttle when burning under warp. Basically, everything is on rails

#

This will require a much more complicated solution than just a postfix.

#

You basically need to reimplement the whole thing...

formal quail
untold kestrel
#

To say it otherwise, when thrusting under warp, the vessel is following a precomputed path and course of actions. The inputs are fixed and as this is designed, it's not possible to change mid course without re-running the whole precomputed path every frame. Which will very likely be a very large perf issue.

formal quail
#

yeah, i've got that, I'm talking about the option of pre-computing it differently in the first place

rose geyser
#

that will be quite difficult

untold kestrel
#

That would mean reimplementing the whole solver/integrator to account for that extra variable.

rose geyser
#

it could be doable for something like K2-D2 executing a specific maneuver node burn

#

but not for an indeterminate burn

#

I feel like the least they could do is allow you to use low physical time warp in space, like in KSP1

#

maybe like up to 8x or 10x

#

that works just fine with Better Time Warp

untold kestrel
#

lol "just fine"

rose geyser
#

idk, I use 8x all the time, and there aren't that many issues with it

#

unless your thrust is way off center or something

#

for ion engines it's basically necessary in KSP1

formal quail
untold kestrel
#

Well, my experience greatly differ. Any vessel that has some vague chance of being physically (I mean joint stability) unstable will 100% explode at 6-8 phys warp.

formal quail
#

not enough for my ion probe tho lol

rose geyser
#

8x is usually the most I can deal with

#

(though this is all from KSP1 experience)

formal quail
#

I also first though about adding K2D2 module that basically automatically starts and stops warp (when craft rotated too far from target direction)

#

the current idea is actually second one

rose geyser
#

theoretically you might be able to do something like that with this physics under thrust method, too

#

don't reset the solver every frame, but just in some longer intervals

#

based on the angle difference, or something like that

formal quail
#

hmmm yeah, maybe

rose geyser
#

it won't be amazingly accurate, but still better than just being stuck in one direction

formal quail
#

Finally got time to implement this. Spent a lot of time trying to get any kind of patching to work, only to find out I was missing Harmony.CreateAndPatchAll (didn't need it the last time I was modding)

Anyway, after I checked that HandleOrbitalPhysicsUnderThrustStart is only called for the current vessel, only when thrusting under warp, I decided to try calling it on every update, how bad can it be... And it isn't actually. It just works.

#

Since I'm at it:


    [HarmonyPatch(typeof(VesselComponent), "HandleOrbitalPhysicsUnderThrustStart", MethodType.Normal)]
    public class VesselComponent_HandleOrbitalPhysicsUnderThrustStart_Patch
    {
        //private static readonly ConcurrentDictionary<VesselComponent, byte> all_instances = new ConcurrentDictionary<VesselComponent, byte>();
        public static BepInEx.Logging.ManualLogSource log = null!; // set in SASedWarpPlugin.OnInitialized

        public static void Prefix(
            //VesselComponent __instance
        ) {
            //var added = all_instances.TryAdd(__instance, 0);
            //log.LogDebug($"HandleOrbitalPhysicsUnderThrustStart: new_inst={added}, total_inst={all_instances.Count}");
        }

    }

Can someone tell me why this works:

            Harmony.CreateAndPatchAll(typeof(VesselComponent_HandleOrbitalPhysicsUnderThrustStart_Patch));

But this doesn't:

            Harmony.CreateAndPatchAll(Assembly.GetCallingAssembly());
rose geyser
#

I wouldn't use GetCallingAssembly, I think it might return the main KSP2 assembly instead of yours, since that's where the code actually gets called from

#

try typeof(YourPluginClass).Assembly instead

formal quail
rose geyser
formal quail
#

also measured HandleOrbitalPhysicsUnderThrustStart using Stopwatch - it's usually ~0.8 milliseconds. I'd say acceptable

rose geyser
#

indeed, that doesn't sound too bad

#

how does it do under high timewarp?

formal quail
#

the same

#

but after I got escape trajectory from kerbin, it started saying in console that there is too large of a delta error, and so thrust under warp is canceled

#

basically burning propelant without changing the orbit

rose geyser
#

oh yeah I've seen that issue before

formal quail
#

it should probably at least turn off thrust when it does that...

rose geyser
#

it probably isn't related to your mod

#

it tends to happen when you do really long burns with an ion engine

#

not sure where the bug comes from exactly

formal quail
#
            if (vector3d3.sqrMagnitude < 0.010000000000000002 && vector3d4.sqrMagnitude < 0.010000000000000002)
            {
                base.SimulationObject.Orbiter.PatchedOrbit = base.SimulationObject.Orbiter.PatchedNBodyOrbits[0];
                return;
            }
            GlobalLog.Error(LogFilter.Flight, "Delta error between patched orbit and NBody orbit too large. Cancelling Thrust under TimeWarp.");
            this.HandleOrbitalPhysicsUnderThrustEnd();
#

hmmm... how can I make KSP display yellow message at the top?

#

I might as well handle this

rose geyser
#

Like this: #🔴mod-dev message

formal quail
#

basically, if I use NotificationTier.Passive - it starts displaying a bunch of random game messages. but if I use NotificationTier.Alert - it's all white boxes

#

I hope I don't need to do localization to make this work...

#

ok, added localization, but it's still broken

#

maybe it's collision with some other mod...

#

like "Toggle Notifications"

rose geyser
#

Yeah localization shouldn't be needed

#

Could you show exactly how you were calling it with the passive type?

#

Some of the types don't work/aren't implemented, I think Alert is one of them

#

No I'm wrong

#

Alert should definitely work

#

Strange

formal quail
#
            GameManager.Instance.Game.Notifications.ProcessNotification(new NotificationData
            {
                Tier = NotificationTier.Alert,
                Primary = new NotificationLineItemData { LocKey = "SASedWarp/MathBug" }
            });
#

This is what's currently

#

And this is the locale csv:

Key,Type,Desc,English
SASedWarp/MathBug,Text,,<color=red>KSP math bug prevented thrust under warp\nCanceling throttle to not waste fuel</color>
formal quail
#

btw, I finished setting up github workflow to make .zip automatically. is there a way to also automatically upload it to spacedock?

rose geyser
#

yep! I will be adding it to the template shortly, it already has all the other actions prepared (automatic building, zipping, and uploading releases), so this is the next step

#

for now you can look at Patch Manager's release action, it has all of them

formal quail
rose geyser
#

you can see them set at the top of the file:

env:
  MOD_ID: 3482
  KSP2_ID: 22407
#

MOD_ID is the ID of the mod on SpaceDock, and KSP2_ID is the ID of the game on SpaceDock

formal quail
#

thx

#

didn't think it'd be numeric

formal quail
#

YES, IT LIVES!

#

would've like to do everything in github script, but after 54 workflow runs, I'm done for now

formal quail
#

yet, I still can't just sit and play, that delta error is gonna be the end of me...

#

it seems once it shows up, it doesn't matter how much I wait/reload, it'll still continue to show up in the save

rose geyser
#

yeah, that's also been my experience...

formal quail
#

is there an existing bug report?

rose geyser
#

I am not sure

formal quail
#

Was thinking about debugging HandleOrbitalPhysicsUnderThrustStart, but today suddenly unlocked memory with PTSD after the last time I tried to debug a unity game

iirc, regular vs can already attach to a running process, but it refuses decompile it to C# code, only showing 64-bit assembly instructions (not even IL-code)
meanwhile dnSpy is a decompiler and also has attachable debugger, but to make it work with unity game I needed some files which are stored in very obscure places on github, and to build one thing I need another... I think I ended up having to download shady versions of Unity toolkits and QT, and still couldn't make it work. this time I don't even have the disk space for all that...

did maybe someone here have a better experience?

untold kestrel
# formal quail Was thinking about debugging `HandleOrbitalPhysicsUnderThrustStart`, but today s...

dnSpyEx (https://github.com/dnSpyEx/dnSpy) works fine for debugging by following those steps : https://github.com/dnSpyEx/dnSpy/wiki/Debugging-Unity-Games#turning-a-release-build-into-a-debug-build
Note that those steps are the exact same required to debug your own code from within visual studio, exporting portable debug symbols and using the unity VS extension. Some details here based on my steps for KSP 1 : https://gist.github.com/cfloutier/f84b580d61d4eecdacd5e8e822de0871
Debugging the stock code in visual studio is a lot more involving. It require exporting the decompiled Assembly-CSharp.dll as a VS project with IlSpy (which is the only decompiler that will produce mostly correct code), fixing any remaining compilation errors in the exported source code, recompiling it and using that recompiled dll instead of the original.

rose geyser
#

I will say that I've been having issues getting dnSpy debugging to work in the latest KSP2 versions. The game is in debug mode and I can attach to it with Rider just fine and step through both my code and the game code, however, dnSpy just never finds any Unity process to attach to

#

the same process worked just fine pre-0.1.5 as far as I know

untold kestrel
#

Ha, I don't think I tried dnSpyEx since they updated the unity version, yeah.

lethal helm
#

wait, there is a dnspy fork

#

?

formal quail
#

a bunch of them I think? like, the whole forest to get lost in...

#

(iirc)

rose geyser
#

I just tried that fork and no luck, doesn't find KSP2 either