Quaternion Camera Representation in 6DOF - fending

2019-08-15 06:06发布

问题:

first question on SO although I've been here many times through Google. I have read quite a lot on the topic of using quaternions to represent rotation as well as finding people who have similar problems. I have yet to find a good solution, or one that I could understand.. so I'm giving a shot at asking a clear enough question to generate solid answers.

I am currently using a quaternion (specifically, a Qt 4.7 quaternion/C++) to represent the orientation of my camera. At each step of the program I check for mouse movement and do a fromAxisAndAngle(xaxis, x_mouse_movement) and fromAxisAndAngle(yaxis, y_mouse_movement). I take these two quaternions and multiply them (yaxis * xaxis). For the initialization I have a unit quaternion (w,x,y,z -> 1,0,0,0) to multiply with. I keep accumulating the rotation over these fromAxisAndAngle multiplications with the current orientation. This produces a roll, known as the Lie Group Problem (I think) that if you apply pitch and yaw continuously you can generate a pure roll, and this is what I have in my current implementation (which is correct for my procedure as far as I can tell).

I have implemented another method where pitch,yaw,roll are incremented and the quaternion is built fromAxisAndAngle from scratch each time from these values. This produces a correct FPS style camera, but it suffers from gimbal lock. My goal is to keep the pure quaternion representation, while eliminating (or compensating for) the rolling effect produced from only pitches and yaws so I can use this general 6DOF camera as an FPS camera or a space ship style camera. I'm looking for suggestions (specific routines) for correcting this roll, or an alternative representation that can fit my needs. Sorry for the wall of text, but I wanted to be very clear. Thanks for your time and happy hacking!

回答1:

It's not completely clear what you're trying to accomplish. Consider:

  1. Begin in the canonical orientation (+x is right, +y is up, -z is forward)
  2. Pitch down by 90°. (-z is up, -y is forward)
  3. Yaw right by 90°. (+y is right, +x is forward)
  4. Pitch up 90°. (-x is up, -z is forward)
  5. You are now facing the canonical forward again, but rolled 90° to the left.

What do you want to happen instead? This is normal behavior if you always define pitch and yaw to be with respect to the camera/body frame of reference. If, instead, you want 'yaw' to always rotate around the world's y-axis and 'pitch' to always rotate around the camera/body's x-axis (so that the camera's x-axis is always parallel to the ground plane), then, if you were pitched down by 90°, the yaw movement would visually appear to be roll (you're looking down and turning in a circle). A quaternion that maintains that property will always have a 'z' component of zero. You could simply enforce that constraint on your quaternion (being sure to always re-normalize).

However, your method of simply keeping track of pitch and yaw separately should work fine for that case. Gimbal lock isn't a problem if you're only using two axes in the first place. You just need to be sure that you apply the pitch and then the yaw.