Я пытаюсь преобразовать кватернионы в углы эйлерового тангажа. У меня проблемы с карданным замком. Первая странная вещь, которая возникает, это то, что ошибки уже начинают появляться, когда угол наклона находится в окрестности + -pi / 2. Я думал, что проблемы должны возникать только в точности пи / 2.
Во-вторых, мой код показывает неправильный угол поворота 180 градусов с шагом -90 градусов.
Я пробовал код на этом посте и на этом сайте , но ни один из них не работал. Я также попробовал библиотеку pyquaternion , но эта даже не пытается компенсировать блокировку карданного подвеса. В конце концов я сделал Python-эквивалент этого раздела руководства.
Это сработало лучше, но все же дает вышеуказанные проблемы. Это похоже на проблему, которая должна быть решена 1000 раз, но я не могу точно определить проблему.
Для кватерниона: [0.86169383 0.02081877 -0.5058515 0.03412598] код возвращает правильные углы шага крена рыскания: [0.15911653941132517, -60.832556785346696, -9.335093630495875]
Для кватерниона: [0,81154224 0,01913839 -0,58165337 0,05207959] код возвращает неправильные углы шага поворота рыскания: [-173.53260107524108, -71.09657335881491, 0,0]
Вот мой код:
def yaw_pitch_roll(self):
"""Get the equivalent yaw-pitch-roll angles aka. intrinsic Tait-Bryan angles following the z-y'-x'' convention
Returns:
yaw: rotation angle around the z-axis in radians, in the range `[-pi, pi]`
pitch: rotation angle around the y'-axis in radians, in the range `[-pi/2, pi/2]`
roll: rotation angle around the x''-axis in radians, in the range `[-pi, pi]`
The resulting rotation_matrix would be R = R_x(roll) R_y(pitch) R_z(yaw)
Note:
This feature only makes sense when referring to a unit quaternion. Calling this method will implicitly normalise the Quaternion object to a unit quaternion if it is not already one.
"""
self._normalise()
qw = self.q[0]
qx = self.q[1]
qy = self.q[2]
qz = self.q[3]
print(2*(qx*qz-qw*qy), self.q)
if 2*(qx*qz-qw*qy)>=0.94: #Preventing gimbal lock for north pole
yaw = np.arctan2(qx*qy-qw*qz,qx*qz+qw*qy)
roll = 0
elif 2*(qx*qz-qw*qy)<=-0.94: #Preventing gimbal lock for south pole
yaw = -np.arctan2(qx*qy-qw*qz,qx*qz+qw*qy)
roll = 0
else:
yaw = np.arctan2(qy*qz + qw*qx,
1/2 - (qx**2 + qy**2))
roll = np.arctan2(qx*qy - qw*qz,
1/2 - (qy**2 + qz**2))
pitch = np.arcsin(-2*(qx * qz - qw * qy))
return yaw, pitch, roll