Mike Taylor
Mike Taylor

Reputation: 13

Calculating facing arc between two 3d rotational matrixes

I am working on a space-ship simulator, and having trouble with facing arcs between two space objects. Each object has a rotation matrix defined as follows:

//Top row
rotation[0][0] = cos(pitch)*cos(yaw);
rotation[0][1] = -sin(yaw)*cos(pitch);
rotation[0][2] = sin(pitch);
//Middle row
rotation[1][0] = cos(yaw)*sin(pitch)*sin(roll) + sin(yaw)*cos(roll);
rotation[1][1] = -sin(yaw)*sin(pitch)*sin(roll) + cos(yaw)*cos(roll);
rotation[1][2] = -cos(pitch)*sin(roll);
//Bottom row
rotation[2][0] = -cos(yaw)*sin(pitch)*cos(roll) + sin(yaw)*sin(roll);
rotation[2][1] = sin(yaw)*sin(pitch)*cos(roll) + cos(yaw)*sin(roll);
rotation[2][2] = cos(pitch)*cos(roll);

As well as having XYZ coordinates.

Using this information, I need to be able to decide what 90 degree arc is facing between object1 and object1: Forward, Starboard, Port, Aft, Dorsal (upper) and Ventral (lower) I was trying to use the following formula:

arc = acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )

Where |a| is the vector direction of |object2| - |object1| and |b| is row1 (forward arc), row2 (starboard arc) or row3 (up arc). I am doing something wrong because it's not behaving as expected. So I am asking for help to find where I am making a mistake.

P.S. yaw, pitch and roll are stored in degrees (0-360), and converted to rads by multiplying it by PI / 180.0.

Upvotes: 1

Views: 106

Answers (1)

M Oehm
M Oehm

Reputation: 29126

I think you're approaching the problem wrongly by describing the bearing in terms of roll, pitch and yaw. These are Euler angles that describe the movement of a spaceship in terms of the ship's current coordinate system itself. These angles are not independent and will cause problems when one of them is ±90°. Roll, pitch and yaw are useful if you want to describe the movement of the ship.

I would model your case differently: Each ship has a position {P}, which is given in the global Cartesian x, y, z system. It also has a bearing, which is given as three orthonormal vectors u, v, w in the global space. You'll then also have a rotation matrix:

      | ux   vx   wx |
[R] = | uy   vy   wy |
      | uz   vz   wz |

You can then describe the position of any other object with position S in the local coordinate system of the ship:

{s} = [R] · {S - P}

Notes:

  • You can determine which way to look from your ship to see the other object best by determining the maximum absolute component of {s} = {su, sv, sw}. For example, if s = {-12, 8, 10}, the object is behind you. (Or, perhaps more precisely, it is more behind you than it is in any of the other five directions; aft is the principal direction) If s = {2, -5, 8}, the object is below you.

  • You use u for forward, y for starboard and z for up. That describes a left-hand system. I recommend using a right-hand system, because that's what nearly all Cartesian systems conform to. For eaxample, you could use u for forwards, y for starboard and w for down.

  • You can express the Cartesian vector {s} in spherical coordinates with the zenith in the w direction. This will give you the distance of the object r and two independent angles, the azimuth in the ship's (u, v) plane and the zenith which describes the elevation of the object from this plane.

  • When your ship moves, you can update the global bearing by means of roll, pitch and yaw.

  • You can still calculate the arcs that you want with your formula above. Use {s} = {su, sv, sw} in the ship's coordinates and your reference axes are u = {1, 0, 0}, v = {0, 1, 0} and w = {0, 0, 1}:

    uarc = acos(su / r)
    varc = acos(sv / r)
    warc = acos(sw / r)
    

    Here, r is the distance, r² = {s}·{s}. The arcs you calculate are not very useful. They tell you the angle between an axis and the object, but these angles are ambiguous. It is probably better to calculate angles in planes, e.g.

    uvarc = atan2(sv, su)
    vwarc = atan2(sw, sv)
    wuarc = atan2(su, sw)
    

    The zero-degree reference is the second axis in the expression, i.e. u for uvarc. This gives you the angle of the distance vector projected onto that plane.

Upvotes: 1

Related Questions