Jump to content

Quaternions are driving me insane!


Recommended Posts

I am trying to prevent ANY roll from happening when setting up a new SAS target:

            //get target vector(navball)
Vector3 v = new Vector3(In("E/W").AsFloat(), In("U/D").AsFloat(), In("N/S").AsFloat()).normalized;
//create rotation
Quaternion rot = Quaternion.LookRotation(v, Vector3.up) * Quaternion.Euler(90, 0, 0);
Quaternion roll = Quaternion.identity;
//keep absolute roll ?
if (In("Keep Roll").AsBool())
{
//read current rotation (navball)
Quaternion relRot = Program.VesselInfo.WorldToReference(Program.VesselInfo.VesselOrientation, VesselInformation.FrameOfReference.Navball);
//calculate current roll
Vector3 absUp = (Vector3.forward * -1f);
Vector3 dir = relRot * Vector3.up;
Vector3 up = relRot * absUp;
float rollC = Mathf.Atan2(
Vector3.Dot(dir, Vector3.Cross(absUp, up)),
Vector3.Dot(absUp, up)) * Mathf.Rad2Deg;
//get navball horizontal angles
float angleC = Mathf.Atan2(dir.z, dir.x);
float angleT = Mathf.Atan2(v.z, v.x);
//delta of angles
float d = Mathf.DeltaAngle(angleC, angleT);

//add delta to current angle
roll = Quaternion.AngleAxis(rollC + d, v);
}
else
{
roll = Quaternion.AngleAxis(In("Roll").AsFloat(), v);
}
rot = roll * rot;
//apply sas target
Program.SASController.SASTarget = Program.VesselInfo.ReferenceToWorld(rot, VesselInformation.FrameOfReference.Navball);

Unfortunately this does not work, and debugging quaternions without any actual debugging is a nightmare. Could anyone provide me with a way to make a quaternion but keep the roll component of another quaternion intact? By that I don't mean that the roll value should be the same, contrary, the roll value will most likely change. I want a change of HEADING only, while preventing any roll from happening relative to the navball UP.

Link to comment
Share on other sites

Quaternions are a mess for humans to understand. Supposedly they're more resource-efficient, which is why Unity uses them, but they require years of study to understand enough to use. Quaternions are also immune to gimbal lock, which would make things very hard in KSP.

I'd recommend using Quaternion.Euler(Vector3 euler) to convert from a 3-dimensional rotation to a Quaternion and Quaternion.eulerAngles to get a 3-dimensional representation of a particular quaternion. Probably the best way to deal with Rotations in Unity is to work with Vector3s when directly changing rotations and converting to Quaternions when assigning the final rotation.

Link to comment
Share on other sites

Quaternions are a mess for humans to understand. Supposedly they're more resource-efficient, which is why Unity uses them, but they require years of study to understand enough to use. Quaternions are also immune to gimbal lock, which would make things very hard in KSP.

I'd recommend using Quaternion.Euler(Vector3 euler) to convert from a 3-dimensional rotation to a Quaternion and Quaternion.eulerAngles to get a 3-dimensional representation of a particular quaternion. Probably the best way to deal with Rotations in Unity is to work with Vector3s when directly changing rotations and converting to Quaternions when assigning the final rotation.

Yes, I have worked with Quaternions before, but still I would not know how to counter the roll of a transformation with euler-angles. Any idea? Is my question even understandable ? ;)

Link to comment
Share on other sites

Do you mean relative to the surface of a planet? That's a bit more complicated and requires getting the normal vector of the planet's surface, this UnityAnswers page might help. I'm booting up Unity on my end to see if that answer is valid.

I already convert the rotation of the vessel into the navball / surface frame of reference. Have a look at the code in my post. Also I think euler angles are not suitable to remove roll from a transformation because their values are absolute and not relative to the body. (As far as I know)

Edited by pixartist
Link to comment
Share on other sites

In that case, relative rotations are fairly easy, you should be able to subtract the rotation on the surface from the absolute rotation to get relative rotation, for example:

Quaternion relativeRotation = transform.eulerAngles - surfaceRotation

With that in mind, roll canceling should be as easy as setting the z-component of that rotation to 0.

Link to comment
Share on other sites

In that case, relative rotations are fairly easy, you should be able to subtract the rotation on the surface from the absolute rotation to get relative rotation, for example:

Quaternion relativeRotation = transform.eulerAngles - surfaceRotation

With that in mind, roll canceling should be as easy as setting the z-component of that rotation to 0.

No, that's not how euler angles work. The rotations are applied one after another. They are not simple rotations around world axis.

Link to comment
Share on other sites

Quaternions are a mess for humans to understand. Supposedly they're more resource-efficient, which is why Unity uses them, but they require years of study to understand enough to use. Quaternions are also immune to gimbal lock, which would make things very hard in KSP.

This really makes no sense. You can use quaternions just fine by thinking about them like weirdly packaged rotation matrices and using the rules of matrix algebra.

Also there is actually a way to do real debugging, but you have to use MonoDevelop.

Link to comment
Share on other sites

I FINALLY managed to tackle this ..... by drawing everything on paper and thinking for quite a while. It turns out there is a pretty simple solution:



Quaternion relRot = Program.VesselInfo.WorldToReference(Program.VesselInfo.VesselOrientation, VesselInformation.FrameOfReference.Navball);
Vector3 forward = relRot * Vector3.up;
double roll = forward.SignedAngle((Vector3.up - forward)*-1, relRot * Vector3.forward);


//the signed angle method:

public static float SignedAngle(this Vector3 normal, Vector3 a, Vector3
{
return Mathf.Atan2(
Vector3.Dot(normal, Vector3.Cross(a, ),
Vector3.Dot(a, ) * Mathf.Rad2Deg;
}

I create a vector going from UP (0,1,0) to the up vector of the vessel (which is basically the forward vector, it's the point on the navball). The I simply calculate the angle between that and the actual forward vector of the vessel along the up axis of the vessel.

Edited by pixartist
Link to comment
Share on other sites

Thanks for posting the solution, this will come in handy for something I'm working on. Who knew scalar products would be so useful?? I certainly had no idea when I was doing my maths with mechanics in college...

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...