• ROS2中如何从欧拉角转换成四元素


    ROS1中使用from tf.transformations import quaternion_from_euler导入quaternion_from_euler()即可调用。而ROS2中默认没有安装,需要单独安装一下ros-galactic-tf-transformations(我使用的ROS2是galactic,根据版本名不同做相应修改即可):

    1. sudo apt-get update
    2. sudo apt-get install ros-galactic-tf-transformations

    然后导入包,不过包名改成了tf_transformations

    1. import tf_transformations
    2. # 将欧拉角转换为四元数(roll, pitch, yaw)
    3. q = tf_transformations.quaternion_from_euler(roll, pitch, yaw)
    4. # 将四元素转换成欧拉角
    5. euler = tf_transformations.euler_from_quaternion([x, y, z, w])

    不安装tf_transformations的话,还可以安装其它工具包来替代,例如python的第三方quaternions包:

    pip install quaternions  -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
    1. from quaternions import Quaternion as Quaternion
    2. euler = [0.98012,0.5232,0.2105] # ROLL PITCH HEADING
    3. q = Quaternion.from_euler(euler, axes = ['y', 'y', 'x']) # a= (w, x, y, z)
    4. e = Quaternion.get_euler(q) # e = (Heading, Pitch, Roll)

    需要注意的是ROS在gemetry_msgs包里已定义有Quaternion类,另外ROS1里tf2里也定义有Quaternion,同时使用时注意用别名或包名区分。

    另外,也可以安装trimesh工具包后使用里面的quaternion_from_euler

    pip3.8 install trimesh -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
    1. from trimesh.transformations import quaternion_from_euler
    2. from geometry_msgs.msg import Quaternion as GeoQuaternion
    3. def createQuaternionFromYaw(yaw):
    4. q = quaternion_from_euler(0, 0, yaw)
    5. return GeoQuaternion(x=q[0],y=q[1],z=q[2],w=q[3])

    看一下trimesh里/usr/local/lib/python3.8/dist-packages/trimesh/transformations.py里的quaternion_from_euler()的源码和/opt/ros/galactic/lib/python3.8/site-packages/tf_transformations/__init__.py里的quaternion_from_euler()代码,发现功能实现基本一致:

    1. # axis sequences for Euler angles
    2. _NEXT_AXIS = [1, 2, 0, 1]
    3. # map axes strings to/from tuples of inner axis, parity, repetition, frame
    4. _AXES2TUPLE = {
    5. 'sxyz': (0, 0, 0, 0), 'sxyx': (0, 0, 1, 0), 'sxzy': (0, 1, 0, 0),
    6. 'sxzx': (0, 1, 1, 0), 'syzx': (1, 0, 0, 0), 'syzy': (1, 0, 1, 0),
    7. 'syxz': (1, 1, 0, 0), 'syxy': (1, 1, 1, 0), 'szxy': (2, 0, 0, 0),
    8. 'szxz': (2, 0, 1, 0), 'szyx': (2, 1, 0, 0), 'szyz': (2, 1, 1, 0),
    9. 'rzyx': (0, 0, 0, 1), 'rxyx': (0, 0, 1, 1), 'ryzx': (0, 1, 0, 1),
    10. 'rxzx': (0, 1, 1, 1), 'rxzy': (1, 0, 0, 1), 'ryzy': (1, 0, 1, 1),
    11. 'rzxy': (1, 1, 0, 1), 'ryxy': (1, 1, 1, 1), 'ryxz': (2, 0, 0, 1),
    12. 'rzxz': (2, 0, 1, 1), 'rxyz': (2, 1, 0, 1), 'rzyz': (2, 1, 1, 1)}
    13. _TUPLE2AXES = dict((v, k) for k, v in _AXES2TUPLE.items())
    14. ...
    15. def quaternion_from_euler(ai, aj, ak, axes='sxyz'):
    16. """Return quaternion from Euler angles and axis sequence.
    17. ai, aj, ak : Euler's roll, pitch and yaw angles
    18. axes : One of 24 axis sequences as string or encoded tuple
    19. >>> q = quaternion_from_euler(1, 2, 3, 'ryxz')
    20. >>> np.allclose(q, [0.435953, 0.310622, -0.718287, 0.444435])
    21. True
    22. """
    23. try:
    24. firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()]
    25. except (AttributeError, KeyError):
    26. _TUPLE2AXES[axes] # validation
    27. firstaxis, parity, repetition, frame = axes
    28. i = firstaxis + 1
    29. j = _NEXT_AXIS[i + parity - 1] + 1
    30. k = _NEXT_AXIS[i - parity] + 1
    31. if frame:
    32. ai, ak = ak, ai
    33. if parity:
    34. aj = -aj
    35. ai /= 2.0
    36. aj /= 2.0
    37. ak /= 2.0
    38. ci = math.cos(ai)
    39. si = math.sin(ai)
    40. cj = math.cos(aj)
    41. sj = math.sin(aj)
    42. ck = math.cos(ak)
    43. sk = math.sin(ak)
    44. cc = ci * ck
    45. cs = ci * sk
    46. sc = si * ck
    47. ss = si * sk
    48. q = np.empty((4, ))
    49. if repetition:
    50. q[0] = cj * (cc - ss)
    51. q[i] = cj * (cs + sc)
    52. q[j] = sj * (cc + ss)
    53. q[k] = sj * (cs - sc)
    54. else:
    55. q[0] = cj * cc + sj * ss
    56. q[i] = cj * sc - sj * cs
    57. q[j] = cj * ss + sj * cc
    58. q[k] = cj * cs - sj * sc
    59. if parity:
    60. q[j] *= -1.0
    61. return q
    62. def euler_from_quaternion(quaternion, axes='sxyz'):
    63. """Return Euler angles from quaternion for specified axis sequence.
    64. >>> angles = euler_from_quaternion([0.99810947, 0.06146124, 0, 0])
    65. >>> np.allclose(angles, [0.123, 0, 0])
    66. True
    67. """
    68. return euler_from_matrix(quaternion_matrix(quaternion), axes)
    1. def quaternion_from_euler(ai, aj, ak, axes='sxyz'):
    2. """
    3. Return quaternion from Euler angles and axis sequence.
    4. ai, aj, ak : Euler's roll, pitch and yaw angles
    5. axes : One of 24 axis sequences as string or encoded tuple
    6. >>> q = quaternion_from_euler(1, 2, 3, 'ryxz')
    7. >>> numpy.allclose(q, [0.310622, -0.718287, 0.444435, 0.435953])
    8. True
    9. """
    10. return _reorder_output_quaternion(
    11. transforms3d.euler.euler2quat(ai, aj, ak, axes=axes)
    12. )
    13. ...
    14. def euler_from_quaternion(quaternion, axes='sxyz'):
    15. """
    16. Return Euler angles from quaternion for specified axis sequence.
    17. >>> angles = euler_from_quaternion([0.06146124, 0, 0, 0.99810947])
    18. >>> numpy.allclose(angles, [0.123, 0, 0])
    19. True
    20. """
    21. return euler_from_matrix(quaternion_matrix(quaternion), axes)

    另外,ros2默认安装的spawn_entity代码/opt/ros/galactic/lib/python3.8/site-packages/scripts/spawn_entity.py里的提供了一个简单实现:

    1. def quaternion_from_euler(roll, pitch, yaw):
    2. cy = math.cos(yaw * 0.5)
    3. sy = math.sin(yaw * 0.5)
    4. cp = math.cos(pitch * 0.5)
    5. sp = math.sin(pitch * 0.5)
    6. cr = math.cos(roll * 0.5)
    7. sr = math.sin(roll * 0.5)
    8. q = [0] * 4
    9. q[0] = cy * cp * cr + sy * sp * sr #w
    10. q[1] = cy * cp * sr - sy * sp * cr #x
    11. q[2] = sy * cp * sr + cy * sp * cr #y
    12. q[3] = sy * cp * cr - cy * sp * sr #z
    13. return q

    可以看到这个实现没有提供坐标轴顺序参数axes,按默认的sxyz来的。

    pyquaternion包里的Quaternion只提供了使用q[w,x,y,z]创建实例以及使用matrix创建实例或使用由3维向量指定的旋转轴和旋转角度(弧度)创建实例,当使用nuScenes数据集时,里面涉及的3Dbox的roation都是pyquaternion.Quaternion类型的(标注文件sample_annotations.json的rotation的值就是[w,x,y,z]形式),需要把3D检测模型输出的yaw角的弧度值转换成Quaternion后计算nuScenes指标时就需要使用上面的转换获得q[w,x,y,z]后,再直接使用Quaternion(q)创建实例即可。

    那么axes参数值都有哪些呢?意思是什么,查了一下资料这里汇总一下:

    根据三次基本转动选取的坐标轴的不同,欧拉角共有12种组合,再考虑到可选取原始坐标系的坐标轴,也可选取“新”坐标系的坐标轴,则共有24种欧拉角表示。一般规定原始坐标系为静坐标系(static),每个基本转动后形成的新坐标系为动坐标系(rotating)。

    24 种欧拉角表示列举如下:

    • 静轴(即转轴选静坐标系的坐标轴):

    sXYZ,sXZY,sXYX,sXYZ,sXZY,sXYX,sXYZ,sXZY,sXYX,
    sXZX,sYXZ,sYZX,sXZX,sYXZ,sYZX,sXZX,sYXZ,sYZX,
    sYXY,sYZY,sZXY,sYXY,sYZY,sZXY,sYXY,sYZY,sZXY,
    sZYX,sZXZ,sZYZsZYX,sZXZ,sZYZsZYX,sZXZ,sZYZ

    • 动轴(即转轴选动坐标系的坐标轴):

    rZYX,rYZX,rXYX,rZYX,rYZX,rXYX,rZYX,rYZX,rXYX,
    rXZX,rZXY,rXZY,rXZX,rZXY,rXZY,rXZX,rZXY,rXZY,
    rYXY,rYZY,rYXZ,rYXY,rYZY,rYXZ,rYXY,rYZY,rYXZ,
    rXYZ,rZXZ,rZYZrXYZ,rZXZ,rZYZrXYZ,rZXZ,rZYZ

    静轴欧拉角和动轴欧拉角有如下规律:
         绕静轴 XYZXYZXYZ 分别 转 α,β,γα,β,γα,β,γ 角度的转动与绕动轴 ZYXZYXZYX分别转 γ,β,αγ,β,αγ,β,α 角度的转动等价,其他形式的欧拉角亦有此类似规律。

    axes的值和firstaxis, parity, repetition, frame的含义解释:

  • 相关阅读:
    《代码大全2》第7章 高质量的子程序
    Python 操作redisearch
    计算机毕业设计之java+springboot基于vue的校园台球厅人员与设备管理系统
    渗透测试-应急响应思路分享
    SAP PO接口日志 集成引擎的归档对象
    6.10.多段线图层(Polyline)
    【国庆头像】来一波美女国庆头像 超好看
    OpenHarmony网络协议通信—kcp
    C# HTML
    最新AI智能创作系统ChatGPT商业源码+详细图文搭建部署教程+AI绘画系统
  • 原文地址:https://blog.csdn.net/XCCCCZ/article/details/132657227