2
$\begingroup$

I am making a GPS for vehicles in a game and I need them to turn accordingly to the rotation between the ending point and starting point. I have calculated the rotation, and before I can apply the rotation I found out I need to edit the values a bit. Not knowing how to do it but observing the roll/pitch has to be changed somewhere I have come up with the following formula, in which I input the Pitch and Yaw and I get back the almost correct pitch and roll output, but not perfect.

This is the formula:

//values are normalised in range [0,360]
Pair CorrectValues(float Pitch, float Yaw)
{
    float 
        Roll_out = 0.0, 
        Pitch_out = 0.0;

    //if Yaw is bigger than 315 OR Yaw is smaller than 45
    if(Yaw > 315.0 || Yaw < 45.0)
        Roll_out = -Pitch;

    //if YAW is between 45 and 135
    if(Yaw > 45.0 && Yaw < 135.0)
        Pitch_out = -Pitch;

    //if YAW is between 135 and 225
    if(Yaw > 135.0 && Yaw < 225.0)
        Roll_out = Pitch;

    //if YAW is between 225 and 315
    if(Yaw > 225.0 && Yaw < 315.0)
        Pitch_out = Pitch;

    return Pair(Roll_out,Pitch_out);
}

I think I need to do somthing with cos/sin, I have tried many combinations but all of them just make the rotation weird (which mean I just randomly tried applying sin/cos in many combinations to the out values in the form of X_out = sin or cos (Pitch) * Pitch).

Can anyone give me a push in the good direction to solve this? The main issue is that it "yaggy" / "laggy"


Edit: As for request for more detail I'm putting it here:

I Need to set the vehicle's quaternion orientation to the one which you can calculate between two positions, which means there is one rotation we will not calculate = roll.

So I did calculate the Pitch and Yaw between two 3D points (XYZ) with this formula:

const float MATH_PI = 3.14159265359;
const float RAD_TO_DEG = 180.0/MATH_PI;
void GetPitchYawBetweenCoords(point3D source, point3D target, point2D &output)
{
    point delta3D = target-source;//X2-X1, Y2-Y1, Z2-Z1
    output.x = atan2( delta3D.y, delta3D.x ) * RAD_TO_DEG;//yaw
    output.y = atan2( delta3D.z, sqrt( delta3D.x * delta3D.x + delta3D.y * delta3D.y ) ) * RAD_TO_DEG;//pitch
}

Then I did use a programming library called OpenGL Mathematics to convert these rotations to a Quaternion, and apply it to the vehicle, but this wasn't working all the time so I did the above modifications which approaches the "correct rotations".

But I'm wondering if there is any correct or better way to do this?

Ad an update to my comment:

glm::eulerAngles assumes the input of Pitch,Roll,Yaw in radians which I do, It's weird how this works if the Yaw angle is 0 and the Pitch is set correctly, and if the Yaw angle is 180 degrees then the pitch is reversed.. and at other angles.. well it looks like it's being interpolated? I will upload a screenshot.

a.k.a. : When I ONLY set the Pitch and Yaw without ANY calculations/modifications and calculate it into a quaternion, the vehicle rotation is like being "interpolated" / slowly inversed, look here:

Click to enlarge enter image description here

The center of All cars equals (0.0,0.0,0.0) and ALL the cars have the pitch set to a value which equals (XY In front of Car at distance 10.0, CurrentCarZ-10.0). (they all should point DOWN)

Yet you can see this is somehow producing interesting results.

Why is this "interpolating" like this?

Only the car (the closest one to me - ID 495 - pink) which is totally facing UP by some amount of degrees has actually the inverted rotation, all other not what I expected (you can see they are a bit rolled, and the one at heading 0 is totally perfect - ID 499 - green).

(Note: North is 180 degrees)

The "formula" you can see in the picture equals then to this (this is a function which just uses the GLM library):

EulerToQuat(Pitch, 0.0, Yaw, Qw, Qx, Qy, Qz);
//{Qw,Qx,Qy,Qz} = glm::quat(glm::vec3(Pitch,0.0,Yaw)*vector_to_radians)//constructs a quaternion form XYZ euler angles
$\endgroup$
  • $\begingroup$ This sort of correction shouldn't be necessary. Could you please describe in a little more detail how the pitch and yaw angles are calculated, and how they're applied? I wonder if there's an error in that code. Maybe the rotations are being applied in the wrong order, or something like that. $\endgroup$ – Chris Culter Jul 31 '13 at 17:41
  • $\begingroup$ I'm having a hard time understanding what your question is. Are you saying that you want a more accurate function than the one you gave? $\endgroup$ – rschwieb Jul 31 '13 at 17:41
  • $\begingroup$ I just randomly tried applying sin/cos in many combinations... Usually people put the "flail about wildly with nonsense" problem solving strategy after the "try to reason carefully" strategy :) THis sort of problem should develop a fairly concrete picture which you can start reasoning from. $\endgroup$ – rschwieb Jul 31 '13 at 18:23
  • $\begingroup$ @Chris Updated the question $\endgroup$ – Gizmo Jul 31 '13 at 18:43
  • $\begingroup$ @Gizmo Okay, you're effectively applying pitch first, then yaw. That makes sense. Which OpenGL function are you calling? Does it assume the same order? $\endgroup$ – Chris Culter Jul 31 '13 at 18:51
1
$\begingroup$

I have figured out that:

1) The cos/sin functions accept RADIANS, not Degrees :(

2) That this code snippet WORKS perfectly:

//pitch,roll,yaw = all are degrees
EulerToQuat(-Pitch*cos(Yaw*degrees_to_radians), -Pitch*sin(-Yaw*degrees_to_radians), Yaw, Qw, Qx, Qy, Qz);
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.