Search code examples
3dgeometryrotation

3D Rotation Logic Gives Wrong Value for Y After Rotation


I have the following method in a Point class for rotating a point in a 3D space.

public void rotate3d(double pitch, double roll, double yaw) {
  pitch *= RADIANS_PER_DEGREE; // 0.01745
  roll *= RADIANS_PER_DEGREE;
  yaw *= RADIANS_PER_DEGREE;

  // pitch - rotate around x-axis
  y = y * Math.cos(pitch) - z * Math.sin(pitch);
  z = y * Math.sin(pitch) + z * Math.cos(pitch);

  // yaw - rotate around y-axis
  x = x * Math.cos(yaw) + z * Math.sin(yaw);
  z = z * Math.cos(yaw) - x * Math.sin(yaw);

  // roll - rotate around z-axis
  x = x * Math.cos(roll) - y * Math.sin(roll);
  y = x * Math.sin(roll) + y * Math.cos(roll);
}

Rotating point(10d, 10d, 0d) by 30d degrees around the z axis gives x= 3.660 & y= 10.490. However, the expected is x= 3.660 & y= 13.6602. What's causing the difference in y values?

I referred to https://www.mathworks.com/matlabcentral/answers/123763-how-to-rotate-entire-3d-data-with-x-y-z-values-along-a-particular-axis-say-x-axis and https://danceswithcode.net/engineeringnotes/rotations_in_3d/rotations_in_3d_part1.html to implement.

I did this for a number of rotation angles and see a pattern (wrong one), as shown in the attached image. enter image description here


Solution

  • You overwrite the variables in all rotations !!!

    for example:

    // pitch - rotate around x-axis
    y = y * Math.cos(pitch) - z * Math.sin(pitch);
    z = y * Math.sin(pitch) + z * Math.cos(pitch); // here y is already changed !!!
    

    You should use temp variables to remedy the code for example like this:

    // pitch - rotate around x-axis
    t = y * Math.cos(pitch) - z * Math.sin(pitch);
    z = y * Math.sin(pitch) + z * Math.cos(pitch);
    y = t;
    
    // yaw - rotate around y-axis
    t = z * Math.cos(yaw) - x * Math.sin(yaw);
    x = z * Math.sin(yaw) + x * Math.cos(yaw);
    z = t;
    
    // roll - rotate around z-axis
    t = x * Math.cos(roll) - y * Math.sin(roll);
    y = x * Math.sin(roll) + y * Math.cos(roll);
    x = t;