Apollo详解之transform模块
前言
坐标变换在机器人系统中十分重要,有关坐标变换,可参考ROS官方文档tf2。
广播静态坐标变换
静态坐标变换是指两坐标系之间的变换关系是固定的一种坐标变换,常用于表示汽车上两位置固定坐标系之间的变换关系,例如各个传感器之间的坐标变换。
坐标变换使用的是一种树型的数据结构,即对于一个子坐标系来说,其只能存在唯一一个父坐标系的坐标变换关系。
静态坐标变换广播方法
运行modules/transform/dag/static_transform.dag
文件,就会将配置文件中指定的所有静态坐标变换发布至/tf_static
话题
StaticTransformComponent
Apollo通过StaticTransformComponent
来发布静态坐标变换,其作用是读取modules/transform/conf
目录下的配置参数文件,其中包含所有需要发布的静态变换数据,经解析后,发布至/tf_static
话题。
TransformStampeds
StaticTransformComponent
组件发布的是TransformStampeds
类型的消息,其定义可参考modules/transform/proto/transform.proto
。TransformStampeds
定义了所需要所有的静态坐标变换,包括父坐标系、子坐标系、变换关系等。
配置文件
Apollo的transform模块是读取transform配置文件发布静态变换关系的,通过定义不同的配置,可以发布不同的静态坐标变换,该配置文件在modules/transform/conf
文件夹下,该配置文件的定义可参考modules/transform/proto/static_transform_conf.proto
。
// 描述静态变换的外参文件
message ExtrinsicFile {
optional string frame_id = 1;
optional string child_frame_id = 2;
optional string file_path = 3;
optional bool enable = 4;
}
// 所有的静态变换
message Conf {
repeated ExtrinsicFile extrinsic_file = 1;
}
该配置文件中每一个坐标变换是通过指定外参YAML配置文件定义的,例如modules/drivers/lidar/velodyne/params/velodyne128_novatel_extrinsics_example.yaml
,该外参配置文件描述的是GNSS和lidar坐标系之间的静态坐标变换关系。
推荐将该外参YAML配置文件以*_extrinsics.yaml
的格式进行命名,外参YAML配置文件格式:
header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: front_6mm
child_frame_id: front_12mm
transform:
translation:
x: 0.0
y: 0.0
z: 0.0
rotation:
x: 0.0
y: 0.0
z: 0.0
w: 0.0
``
注意`StaticTransformComponent`组件只会读取文件中的`transform`、`child_frame_id`和`frame_id`,并且**一定要满足树型数据结构**。
在定义好各个YAML外参文件之后,在transform配置文件中指定好各个YAML外参文件路径,运行该组件后,即可将所有指定的静态变换发布至`/tf_static`。
#### 标定与transform
通过对transform模块中静态变换的分析,可以看出,该模块将车上所有传感器之间的静态变换进行发布,各个激光雷达和摄像头坐标系都以GNSS坐标系`novatel`以父坐标系进行坐标变换,而坐标系`novatel`以`localization`坐标系为父坐标系进行变换,可参考[Apollo 5.5 源码学习笔记(五) | transform模块 | Apollo中的坐标系统详解](https://blog.csdn.net/zhanghm1995/article/details/106151288?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162674923916780366571985%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162674923916780366571985&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-1-106151288.pc_search_result_control_group&utm_term=Apollo%20transform&spm=1018.2226.3001.4187)中的一幅图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210720112355117.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80OTAyNDczMg==,size_16,color_FFFFFF,t_70)
因此,传感器标定工作的目的就是找到上图各个静态坐标变换之间精确的变换关系。
## 广播动态坐标变换
除了静态坐标变换,机器人系统也需要动态坐标变换描述之间可能发生相对运动的坐标系之间的变换,例如车辆坐标系和全局坐标系之间的动态坐标变换。
#### 动态坐标变换广播方法
在需要的组件中创建`TransformBroadcaster`对象,定义好动态坐标变换,调用方法`SendTransform`方法将该变换发布至`/tf`话题。
#### TransformBroadcaster
Apollo中各个组件通过`TransformBroadcaster`对象来广播该组件的动态坐标变换`TransformStamped`,通过调用`SendTransform`方法将该变换发布至`/tf`话题。
###### 疑问
1. 如果存在多个组件发布动态坐标变换消息,产生多个节点向同一个话题发布消息的情况时,如何保证消息被正确订阅?
## 监听坐标变换
Apollo中监听坐标变换是通过`Buffer`对象来完成的,其是一个单例类,完成初始化后会订阅静态变换`/tf_static`和动态变换`/tf`话题的消息,将其转换为ROS的消息类型并保存至tf2的数据结构当中。当需要获取两坐标之间的变换关系时,即可调用`Buffer`对象的方法来获得变换关系。
#### 坐标变换监听方法
创建`Buffer`对象,调用`lookupTransform`、`canTransform`和`GetLatestStaticTF`等方法获取坐标变换
#### Buffer
`Buffer`继承于`BufferInterface`和`tf2::BufferCore`,前者定义了该类所有的接口,后者是坐标变换监听的具体实现,来自于ROS的tf2库。具体的方法有`lookupTransform`、`canTransform`和`GetLatestStaticTF`,具体可参考`modules/transform/buffer.h`
下一篇: 关于jstree的一些应用记录