Jump to content

Vessel Rotations and Planetary Location


Recommended Posts

Hello everyone!

Whitecat again and I am having some small issues with my new 'sea launch' system part of the BoatNavigation plugin here.

The system its self works fine, teleporting a vessel to a water based location upon launch (with a momentary pause at the KSC Runway) based on a UI from the SPH, derived from Hyperedit code, the only issue is that a teleported vessel retains its original rotation relative to Kerbins surface..

For instance, a vessel launched from the Runway with an upward (vertical) facing command pod would spawn upside-down/ at a different angle when teleported to a latitude and longitude say on the other side of Kerbin.

My question is, how would one go about determining a necessary rotation transformation to correct this and how would I go about doing so? or even better, how could one set the rotation to the original (Runway/SPH) orientation whilst still being at a different point on the body?

I am sure the answer lies within Quaternions but this is a very new area for me so I have no idea what I am doing!

Thanks in advance for any help! :)

Link to comment
Share on other sites

Thanks for the replies, I have the following code at the moment:

Vector3 oldVect = vessel.mainBody.GetSurfaceNVector(vessel.latitude, vessel.longitude);

Vector3 newVect = vessel.mainBody.GetSurfaceNVector(newLatitude, newLongitude);

Quaternion correctionRotation = Quaternion.FromToRotation(oldVect, newVect);

vessel.SetRotation(correctionRotation);

I might be being really dumb, but the SetRotation is only giving the vessel a fixed rotation (regardless of the position on the surface) of around 60 degrees from the horizontal plane... :huh: Oh by the way the vessel is set OnRails() just in case that messes with any rotation setting stuff...

Link to comment
Share on other sites

I apologize but I still do not quite understand, how would I go about applying this rotation to the vessel? Quaternions are confusing :( As for euler angles.... I understand these just as little :huh: I have looked through the source code of PersistentRotation as I thought this might help but honestly I am lost...

Link to comment
Share on other sites

The nice thing about quaternions is that you can just multiply them together. So rotation A combined with rotation B is just A*B. So to apply the new rotation on top of the existing vessel orientation, you can do vessel.transform.rotation = vessel.transform.rotation * newRotation.

Link to comment
Share on other sites

Oh I see, thanks! So something like this?

Vector3 oldVect = vessel.mainBody.GetSurfaceNVector(vessel.latitude, vessel.longitude);

Vector3 newVect = vessel.mainBody.GetSurfaceNVector(Latitude, Longitude);

Quaternion correctionRotation = Quaternion.FromToRotation(vessel.transform.rotation.eulerAngles, newVect);

vessel.transform.rotation = vessel.transform.rotation * correctionRotation;

EDIT 17:41

Okay actually this causes the vessel to separate into parts and break apart when it is teleported....

<a  href=%7Boption%7Dhttp://i.imgur.com/5nYWRhh.png' alt='5nYWRhh.png'>

Its a neat effect... but to quote Galaxy Quest... "Its inside out... and then it exploded"...

Edited by Whitecat106
Link to comment
Share on other sites

Uh, yeah, that's what I meant...certainly didn't expect that outcome though. :]

Sorry, that's the limit of my theoretical knowledge here, maybe someone else knows better?

Haha! Thanks for your help anyway! It looks like some parts of the vessel rotated correctly and some did not... The Flaps (used as pretty guard rails) on the left side of the ship seem to have been rotated to the same point but the same flaps on the other side seem not rotated and staggered even though they were originally placed with symmetry... everything is just a bit off... This disturbs me... I don't even know how to debug this!

Its bizarre that this turned out like that... I was expecting either upside-down or no change... not inverted and Picasso-esque... :confused: Actually looking closer it looks as though the root part (the hull next to the paddlewheels) has been rotated to around 90 degrees from the x, and ..most.. of the rest of the ship has not... Weird!

Well I'm open to any other suggestions! Preferably a Van-Gogh effect this time.. :sticktongue:

EDIT 21:43

Wait! I have an idea, Kerbin Side creates new launchsites and vessels are spawned at these with 'normal' normal vectors, maybe the ship is rotated upon transfer from the VAB to the other site? - I am going to look into this now and I will post my results here! :)

EDIT 21:55

Nope no clues here, the closest thing was using the PQS of a static object being re-orientated - Sadly; incredibly unhelpful. I have tested out the Picasso Code again and with the camera rotated to face the front, the vessel looks more like a cross section with each part at a different altitude but will relatively consistent rotations.... I'm stumped.

EDIT 14:52

Okay so I also tried this method but with rotating every part of the vessel rather than the vessel its self.. - The same explosive results, it looks like x.transform.rotation or x.transform.rotate just causes issues with part attachment rules? This is frustrating...

Edited by Whitecat106
Link to comment
Share on other sites

vessel.transform is referencing current "control from" part transform. If you're rotating each part, you should also move it. Choose some vessel-local point, for example CoM of the vessel, and think about your teleportation as moving this point. For each part you need to rotate it's transform.rotation and apply also the same rotation to it's position vector around chosen reference point (CoM). Vector rotation is also done by * operator. Quaternion * vector.

Edited by Boris-Barboris
grammar
Link to comment
Share on other sites

I would just do this after the ship gets teleported, you may need to use the FlightGlobals.getUpAxis() function though, I'm not sure:


//get the up axis
var upAxis = FlightGlobals.upAxis;

//set the vessel's up vector
vessel.rootPart.partTransform.up = upAxis;

//get the rotation that resulted from setting the up vector
var newRot = vessel.rootPart.partTransform.rotation;

//set the rotation
vessel.SetRotation(newRot);

Link to comment
Share on other sites

  • 3 weeks later...

Hello everyone, thank you for your replies but I still have had no luck, if I try to rotate the ship after teleportation the vessel is already positioned and loaded in the scene (as an active vessel) and will not rotate with SetRotation, attempts to rotate the vessel using the above methods before teleportation either have no effect or rotate certain parts individually causing the vessel to be destroyed. I see it that since the teleport itself occours with only one function there is no way to adjust a rotation while the vessel is 'in transit'.

Boris-Barboris, could you explain further how I could impliment your suggestion? Would this surely not be what KSP already does 'behind the scenes' when rotating a vessel?

Link to comment
Share on other sites

Hello everyone, thank you for your replies but I still have had no luck, if I try to rotate the ship after teleportation the vessel is already positioned and loaded in the scene (as an active vessel) and will not rotate with SetRotation

You seem to pack (rails) and hold unpack in your TeleportToLocation method so it should work.

private void DoTeleport()
{
var vessel = FlightGlobals.ActiveVessel;

var originalUp = FlightGlobals.getUpAxis();

ActiveSeaLaunch.TeleportToLocation(89f, 0f, vessel);

var newUp = FlightGlobals.getUpAxis();

// adjust vessel rotation based on how much the up direction changed
var diff = Quaternion.FromToRotation(originalUp, newUp);

vessel.SetRotation(diff * vessel.transform.rotation);
}

I don't know if you're using a different teleport method for this. You could write an equivalent method (of Vessel.SetRotation) that manipulates the part rigidbody locations as Boris suggested if packing the vessel isn't feasible for some reason

Link to comment
Share on other sites

  • 5 months later...
On 10/9/2015 at 3:31 PM, xEvilReeperx said:

You seem to pack (rails) and hold unpack in your TeleportToLocation method so it should work.

 

 

private void DoTeleport()
{
    var vessel = FlightGlobals.ActiveVessel;

    var originalUp = FlightGlobals.getUpAxis();

    ActiveSeaLaunch.TeleportToLocation(89f, 0f, vessel);

    var newUp = FlightGlobals.getUpAxis();

    // adjust vessel rotation based on how much the up direction changed
    var diff = Quaternion.FromToRotation(originalUp, newUp);

    vessel.SetRotation(diff * vessel.transform.rotation);
}

 

I don't know if you're using a different teleport method for this. You could write an equivalent method (of Vessel.SetRotation) that manipulates the part rigidbody locations as Boris suggested if packing the vessel isn't feasible for some reason

@xEvilReeperx I'm trying to use this code in KRASH, but it's not working.

I set originalUp at the launchpad:

originalUp: [0, 0, 0]

newUp after the teleport:

newUp: [-0.988477635301813, -5.83846358332169E-09, -0.151366986189645]

and diff is:

diff: (0.0, 0.0, 0.0, 1.0)

 I even added an additional HoldVesselunpack (what does it do?) before the setrotation (although the SetOrbit function already had it):

                vessel.SetOrbit(orbit);
                try
                {
                    Log.Info ("FixedUpdate HoldVesselUnpack");
                    OrbitPhysicsManager.HoldVesselUnpack(60);
                }
                catch (NullReferenceException)
                {
                    Log.Info("OrbitPhysicsManager.HoldVesselUnpack threw NullReferenceException");
                }
                // rotation code
                var newUp = FlightGlobals.getUpAxis();
                // adjust vessel rotation based on how much the up direction changed
                var diff = Quaternion.FromToRotation(KRASHShelter.originalUp, newUp);
                vessel.SetRotation(diff * vessel.transform.rotation);
                // rotation code
                Log.Info("originalUp: " + KRASHShelter.originalUp.ToString());
                Log.Info ("newUp: " + newUp.ToString ());
                Log.Info ("diff: " + diff.ToString ());

and this is the setOrbit function:

        public static void SetOrbit(this Vessel vessel, Orbit newOrbit)
        {
            Log.Info ("vessel.SetOrbit");

            //var originalUp = FlightGlobals.getUpAxis ();
            //Log.Info ("originalUp: " + originalUp.ToString ());
                
            var destinationMagnitude = newOrbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()).magnitude;
            if (destinationMagnitude > newOrbit.referenceBody.sphereOfInfluence)
            {
                Extensions.ErrorPopup("Destination position was above the sphere of influence");
                return;
            }
            if (destinationMagnitude < newOrbit.referenceBody.Radius)
            {
                Extensions.ErrorPopup("Destination position was below the surface");
                return;
            }

            vessel.PrepVesselTeleport();

            try
            {
                Log.Info ("vessel.SetOrbit 2");
                OrbitPhysicsManager.HoldVesselUnpack(60);
            }
            catch (NullReferenceException)
            {
                Log.Info("OrbitPhysicsManager.HoldVesselUnpack threw NullReferenceException");
            }

            var allVessels = FlightGlobals.fetch == null ? (IEnumerable<Vessel>)new[] { vessel } : FlightGlobals.Vessels;
            foreach (var v in allVessels.Where(v => v.packed == false))
                v.GoOnRails();

            var oldBody = vessel.orbitDriver.orbit.referenceBody;
            Log.Info ("oldBody: " + oldBody.ToString ());
            HardsetOrbit(vessel.orbitDriver, newOrbit);

            vessel.orbitDriver.pos = vessel.orbit.pos.xzy;
            vessel.orbitDriver.vel = vessel.orbit.vel;

            var newBody = vessel.orbitDriver.orbit.referenceBody;
            Log.Info ("newBody: " + newBody.ToString ());


            if (newBody != oldBody)
            {
                var evnt = new GameEvents.HostedFromToAction<Vessel, CelestialBody>(vessel, oldBody, newBody);
                GameEvents.onVesselSOIChanged.Fire(evnt);
            }
        }


So I was wondering if you would have any idea why the vessel isn't rotating?

Thanks in advance

 

 

LGG

 

 

Link to comment
Share on other sites

5 minutes ago, linuxgurugamer said:

I set originalUp at the launchpad:

originalUp: [0, 0, 0]

 

Is that the actual vector you supplied? You should be getting a unit length vector, either using the up axis from FlightGlobals if you're only teleporting the active vessel, or else by calculating the normal at the departure/arrival locations yourself

Link to comment
Share on other sites

52 minutes ago, xEvilReeperx said:

Is that the actual vector you supplied? You should be getting a unit length vector, either using the up axis from FlightGlobals if you're only teleporting the active vessel, or else by calculating the normal at the departure/arrival locations yourself

I got that from FlightGlobals.getUpAxis right after the vessel isvstable at the launchpad.  Regardless, even if it was wrong, I would expect the ship to rotate in some manner, but is doesn't

Link to comment
Share on other sites

1 hour ago, sarbian said:

How do you expect the call to return the rotation between a point ([0,0,0]) and a vector ?

Ummm, I have no idea?   I was copying code as listed above, and obviously am not doing it right.

public static Vector3d originalUp;

Log.Info("originalUp: " + originalUp.ToString());

was returning:

originalUp: [0, 0, 0]

The original code earlier had:

var originalUp = FlightGlobals.getUpAxis();

    ActiveSeaLaunch.TeleportToLocation(89f, 0f, vessel);

    var newUp = FlightGlobals.getUpAxis();

Maybe I'm totally wrong (has happened before).  Which is why I'm asking for help.

 

 

Link to comment
Share on other sites

40 minutes ago, xEvilReeperx said:

Uh ... you're assigning something to originalUp right? Maybe you forgot to put a 'originalUp = FlightGlobals.getUpAxis()' in your method somewhere?

Blast!

No, it wasn't, it was in the wrong location.

So I fixed it, now originalup seems to be correct:


KRASH: originalUp: [-0.823562378226326, -0.00169659515293149, 0.567223175421355]
KRASH: newUp: [-0.975128585895769, -5.87685244420722E-09, -0.221639890292606]
KRASH: diff: (0.0, -0.4, 0.0, 0.9)

but it still isn't working.

============================================================================================

Well, I've made some progress.  The following code:

 Quaternion normal = Quaternion.LookRotation (vessel.GetWorldPos3D ());

 vessel.SetRotation (normal);

seems to always make the vessel arrive horizontal on the equator.  Interestingly enough, the further away from the equator, the more towards vertical, but it isn't the same everywhere.

So, I'm wondering if I need something like the following logic (in pseudocode):

At launch:

curWorldPos = Quaternion.LookRotation (vessel.GetWorldPos3D ());
heading = angle ship is pointing (at launchpad, should be 90 degrees)

After teleport:

newWorldPos = Quaternion.LookRotation (vessel.GetWorldPos3D ());

Quaternion normal = Quaternion.LookRotation (vessel.GetWorldPos3D ());


Adjust normal by heading

vessel.SetRotation (normal);


I have no idea what a Quaternion is, other than a point in space and a direction.

Edited by linuxgurugamer
Link to comment
Share on other sites

30 minutes ago, linuxgurugamer said:

I have no idea what a Quaternion is, other than a point in space and a direction.

That isn't what a quaternion is, you can't specify both a point and a direction with only 4 numbers.  A quaternion is a 4d analogue of a complex number that just happens to be very useful when dealing with rotations.  It basically specifies an axis about which the rotation happens and the angle of the rotation about that axis though there isn't a direct correspondence with the w, x, y and z component values.

You may be confusing it with a Unity Transform which is a point in space and a rotation (specified by a Vector3 and a Quaternion).

Link to comment
Share on other sites

30 minutes ago, xEvilReeperx said:

Can you be more specific when you say "not working"? The orientation doesn't change at all? Does it work teleporting around Kerbin? What are you expecting and what are you seeing?

Sure.  Using the original code I posted:

             vessel.SetOrbit(orbit);
                try
                {
                    Log.Info ("FixedUpdate HoldVesselUnpack");
                    OrbitPhysicsManager.HoldVesselUnpack(60);
                }
                catch (NullReferenceException)
                {
                    Log.Info("OrbitPhysicsManager.HoldVesselUnpack threw NullReferenceException");
                }
                // rotation code
                var newUp = FlightGlobals.getUpAxis();
                // adjust vessel rotation based on how much the up direction changed
                var diff = Quaternion.FromToRotation(KRASHShelter.originalUp, newUp);
                vessel.SetRotation(diff * vessel.transform.rotation);
                // rotation code
                Log.Info("originalUp: " + KRASHShelter.originalUp.ToString());
                Log.Info ("newUp: " + newUp.ToString ());
                Log.Info ("diff: " + diff.ToString ());

Latitude: 0
Longitude: 0
After teleport: about 7 degrees from horizontal, nose up

Latitude: 0
Longitude: 30
After Teleport:  25 degrees from horizontal, nose down

Latitude 0
Longitude: 60
After teleport: 55 degrees from horizontal, nose down

And I also tried at KSP itself:

Latitude: -0.1
Longitude: -74.56
After teleport: 85 degrees from horizontal, nose up

 

So it looks like it isn't doing anything, from what I can tell, the craft is always pointing in the same direction.

Link to comment
Share on other sites

You may want to check that the order of quaternion multiplication is the one you actually want. I remember having a difficult to identify issue that came down to having the order wrong.
What does your Quaternion "diff" look like in Euler coordinates (log: Quat.eulerAngles)? Which axes is it trying to rotate on (from memory, x is pitch, y is roll, z is yaw wrt to your reference frame)?

What is the vessel rotation prior to using vessel.SetRotation vs. after (logging, not visual)? Is there any change there? Is there a change at the part level (since vessel transform is just the root part it should be, but...)?

Does the ship rotate at all during the teleport relative to the planety? Does the reference frame rotate at all during the teleport relative to the planet? It may be more reliable to try and match up the difference between the rotations from the normal vector, instead of a vector that is quite possibly no longer accurate.

// rotation relative to the upVec
Quaternion originalRot = Quaternion.FromToRotation(upVec, vessel.up);
// teleport stuff...

// new rotation relative to the upVec
Quaternion newRot = Quaternion.FromToRotation(newUpVec, vessel.up);
// B - A...
Quaternion diff = newRot * originalRot.Inverse();
// rotate vessel by the difference
vessel.SetRotation(vessel.transform.rotation * diff);

 

Edited by Crzyrndm
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...