Author Topic: New question! Convert global vector to local vector?  (Read 1505 times)

Let's say I have a scheduled loop, and in every pass the loop makes, I want to record the total change in rotation of an object since the loop started. When the loop ends, I will have a value that equals the total number of degrees rotated. For example, if I had a cube that started at 0 degrees, rotated 1440, and then rotated -720, the final value would read 720 degrees. How do I do this? I'm having a bit of trouble with the math. And if possible, in local, not global, rotation.

EDIT: Also, would Trader's euler code be of any use in this scenario? I have a feeling it would be...


Solved the above, credit to Port for the assistance. Now I have a new problem. How do I take a vector and convert it to a local vector (the up vector of the object being the reference point, forward vector always being the Y, with X relative to it). Z can be ignored, since up/down don't change like left/right/forward/backward, and thus yaw can always be calculated globally.
« Last Edit: May 19, 2015, 01:53:31 PM by BluetoothBoy »

Keep track of the starting rotation and find the absolute value (mAbs) of the angle difference. Yes, you can use those functions to find the current angles.

Ok, that is basically what I have at the moment, it must not be working because I'm not in Euler and I that's what the math was for. Can't use mAbs though, as that will result in the cube, for example, starting at 0, rotating 1440, then rotating -720 and ending up at 2160 degrees.

Basically, my current math is as follows. %startRotationX was passed in as the current rotation when the loop started:
Code: [Select]
LOOP START
%totalAngleX = %totalAngleX + getWord(%cube.getTransform(), 3) - %startRotationX;
%startRotX = getWord(%cube.getTransform(), 3);
WAIT 50 MS & LOOP TO BEGINNING

Would this then work with Euler angles? I think it should, going through a couple simulated steps:
Starts at 10 degrees.
Total = 0 + 10 - 10; (nothing has changed since loop just began)
StartRot = 10; (Since this was taken immediately afterwards, hasn't changed)
LOOP. Rotated 20 degrees since then. Now reads 30.
Total = 0 + 30 - 10; (total now = 20)
StarRot = 30;
LOOP. Rotated -50 this time (rotation to 340). Here's where I'm running into trouble. It should read -10, but it doesn't.
Total = 20 + 340 - 30;
StartRot = 340;
Final rotation: 330 degrees when it should be -30. Easily converted at the moment, but with more loop iterations, it gets further and further from being able to do that post calculation.

I guess what I need them is to convert 0 through 360 to -360 through 0, but only when spinning in the opposite direction. Is this even possible? And will that even work?

How do you rotate more than 360 degrees in total? 450 degrees would be the same as 270 degrees.

For example, if I had a cube that started at 0 degrees, rotated 1440, and then rotated -720, the final value would read 720 degrees.

This implies you want both:

  • Effective rotation difference at the end
  • Total amount rotated

These are not the same

No, what I want is the total effective rotation (guess I didn't word it well the first time). But that also means I can't ignore negative rotation either. The way it is coded assumes that the object will not make a full rotation or more in 50ms - a reasonable assumption, I think. But the issue I have is that the angles that are being used are never negative - they only go from 0 to 360, or 360 to 0 if rotating the other way. But this causes errors because the code can't tell if it has rotated 60 degrees to the right or 300 degrees to the right. Any idea how to do this? Would this best be done by using angular velocity instead?

Also, after reading a bit more about how angles work in Torque, the x y and z rotation values don't tell what the rotation is, but rather the vector around which the object rotates. A seventh value of getTransform represents the angle. This makes my situation more complicated, as I am trying to separate x y and z local rotation values.

No, what I want is the total effective rotation (guess I didn't word it well the first time). But that also means I can't ignore negative rotation either. The way it is coded assumes that the object will not make a full rotation or more in 50ms - a reasonable assumption, I think. But the issue I have is that the angles that are being used are never negative - they only go from 0 to 360, or 360 to 0 if rotating the other way. But this causes errors because the code can't tell if it has rotated 60 degrees to the right or 300 degrees to the right. Any idea how to do this? Would this best be done by using angular velocity instead?

n = new angle at the time of checking
o = previous angle

r = n - o
if r < 0 then r = r + 360
if r > 360 then r = r - 360


Use the value of r (assuming that your values are relative to the center of the range. If not, you may want to normalize them to [-180, 180] instead (or [-pi, pi] of course)).

Also, after reading a bit more about how angles work in Torque, the x y and z rotation values don't tell what the rotation is, but rather the vector around which the object rotates. A seventh value of getTransform represents the angle. This makes my situation more complicated, as I am trying to separate x y and z local rotation values.

As you said yourself, use the Euler angle conversion functions that Trader posted with the last 4 words of getTransform.

Alright, I will try this. Didn't even think about adding/subtracting a constant. One more thing - does the axisToEuler code convert to local or global rotation? I'm assuming the latter. If so, and I need local, should I stick with rotation matrices and use  %obj.getForwardVector(); to calculate local rotation? This has to work in local rotation, unfortunately (which I know is generally more complex than global).

I just did a few rough console tests and have found that the axisToEuler code does in fact go from 180 to -180. Yay, more changing around math...

But now I'm starting to wonder - should I even be using this? If I'm trying to get local rotation (the up vector of the object being the reference point), I have a feeling I'm going about this all wrong.

Alright, got it working. The final code:

n = new angle at the time of checking
o = previous angle
a = total angle

r = n - o
if r < -180 then r = r + 360
if r > 180 then r = r - 360

a = a + r


Another thing that threw my calculations is that I only just realized I wasn't passing a back as an argument when I looped, and thus caused a to reset ever iteration. Silly me...

Now I only have one more issue to solve. Before converting the axis to Euler, I need to convert global axis to local axis around the object's up vector. Anyone know enough vector math to help me do this?

wouldn't you just subtract the X and Y values so that the vector is relative to the object

or more specifically vecXY - posXY

wouldn't you just subtract the X and Y values so that the vector is relative to the object

or more specifically vecXY - posXY
Um... Just to clarify what you are saying, subtract the x and y values of the object's vector from the x and y values of the object's up vector?

there's the slight possibility that i've misunderstood what you're actually asking

Here's a more detailed explanation of what I'm asking.

I have an object that has a global rotation (as do all things, of course). This is relative to a fixed set of axes. Now, the values I need are not these. I'm trying to get pitch, roll, and yaw for this object - but not global pitch, roll, and yaw. It needs to be relative to the forward vector of the object. So, if the object is tilted back 10 degrees and rotated 10 degrees around an axis going through the object from its front to its back (local Y), the pitch would read 10 degrees and the roll would read 10 degrees. If I were aligned perfectly along the global axes, there would be no issue. BUT, as soon as there is any yaw (which will be staying global, as up and down never change), the pitch and roll get messed up. So I guess the big question here is: how do I make the front of the object ALWAYS be the forward vector?

EDIT: Updated the OP as well, might help with the explanation a bit.
« Last Edit: May 19, 2015, 01:54:09 PM by BluetoothBoy »

Pitch and roll are not relative to an object.  What is the pitch and roll of an aircraft in flight, relative to that aircraft?

Zero and zero, respectively. The question barely even makes sense.


Now, the answer to the question you MEANT to ask ("how do I get the pitch and roll of a vehicle") can be fulfilled with these two pieces of code.

Code: [Select]
function WheeledVehicle::getPitch(%plane)
{
    return mAsin(vectorDot(%plane.getForwardVector(), "0 0 1"));
}

function FlyingVehicle::getPitch(%plane)
{
    return mAsin(vectorDot(%plane.getForwardVector(), "0 0 1"));
}

function WheeledVehicle::getRoll(%plane)
{
    %right = vectorCross(%plane.getUpVector(), %plane.getForwardVector());
    return mAsin(vectorDot(%right, "0 0 1"));
}

function FlyingVehicle::getRoll(%plane)
{
    %right = vectorCross(%plane.getUpVector(), %plane.getForwardVector());
    return mAsin(vectorDot(%right, "0 0 1"));
}
« Last Edit: May 19, 2015, 03:56:18 PM by Xalos »

I'm not entirely sure what you're asking either, however I have a resource of some advanced vector math, including rotating, that you might find useful, here.