tf:TransForm Frame,坐标变换
坐标系:ROS 中是通过坐标系统开标定物体的,确切的将是通过右手坐标系来标定的。
作用:在 ROS 中用于实现不同坐标系之间的点或向量的转换。
说明:在ROS中坐标变换最初对应的是tf,不过在 hydro 版本开始, tf 被弃用,迁移到 tf2,后者更为简洁高效,tf2对应的常用功能包有:
tf2_geometry_msgs:可以将ROS消息转换成tf2消息。
tf2:封装了坐标变换的常用消息。
tf2_ros:为tf2提供了roscpp和rospy绑定,封装了坐标变换常用的API。
详细内容可参考资料:http://wiki.ros.org/tf2
1.1 坐标msg消息
geometry_msgs/TransformStamped:传输坐标系相关位置信息
命令行键入:rosmsg info geometry_msgs/TransformStamped
geometry_msgs/PointStamped:传输某个坐标系内坐标点的信息
命令行键入:rosmsg info geometry_msgs/PointStamped
1.2 静态坐标变换
两个坐标系之间的相对位置是固定的。
需求描述:现有一机器人模型,核心构成包含主体与雷达,各对应一坐标系,坐标系的原点分别位于主体与雷达的物理中心,已知雷达原点相对于主体原点位移关系如下: x=0.2、y=0.0、z=0.5。当前雷达检测到一障碍物,在雷达坐标系中障碍物的坐标为 (2.0 3.0 5.0),请问,该障碍物相对于主体的坐标是多少?
实现分析:
(1)坐标系相对关系,可以通过发布方发布
(2)订阅方,订阅到发布的坐标系相对关系,再传入坐标点信息(可以写死),然后借助于 tf 实现坐标变换,并将结果输出
实现流程:C++ 与 Python 实现流程一致
C++ 实现
(1)新建功能包,添加依赖
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs
(2)编写发布方实现
(3)编写订阅方实现
python实现
(1)新建功能包,添加依赖
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs
(2)编写发布方实现
(3)编写订阅方实现
补充:当坐标系之间的相对位置固定时,那么所需参数也是固定的: 父系坐标名称、子级坐标系名称、x偏移量、y偏移量、z偏移量、x 翻滚角度、y俯仰角度、z偏航角度,实现逻辑相同,参数不同,那么 ROS 系统就已经封装好了专门的节点,使用方式如下:
rosrun tf2_ros static_transform_publisher x偏移量 y偏移量 z偏移量 z偏航角度 y俯仰角度 x翻滚角度 父级坐标系 子级坐标系 实现流程:
1.3 动态坐标变换
两个坐标系之间的相对位置是变化的。
需求描述:启动 turtlesim_node,该节点中窗体有一个世界坐标系(左下角为坐标系原点),乌龟是另一个坐标系,键盘控制乌龟运动,将两个坐标系的相对位置动态发布。
实现分析:
(1)乌龟本身不但可以看作坐标系,也是世界坐标系中的一个坐标点
(2)订阅 turtle1/pose,可以获取乌龟在世界坐标系的 x坐标、y坐标、偏移量以及线速度和角速度
(3)将 pose 信息转换成 坐标系相对信息并发布
实现流程:C++ 与 Python 实现流程一致
(1)新建功能包,添加依赖
(2)创建坐标相对关系发布方(同时需要订阅乌龟位姿信息)
(3)创建坐标相对关系订阅方
(4)执行
C++实现
(1)新建功能包,添加依赖
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)编写发布方实现
(3)编写订阅方实现
python实现
(1)新建功能包,添加依赖
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)编写发布方实现
(3)编写订阅方实现
1.4 多坐标变换
需求描述:现有坐标系统,父级坐标系统 world,下有两子级系统 son1,son2,son1 相对于 world,以及 son2 相对于 world 的关系是已知的,求 son1原点在 son2中的坐标,又已知在 son1中一点的坐标,要求求出该点在 son2 中的坐标
实现分析:
(1)发布 son1 相对于 world,以及 son2 相对于 world 的坐标消息
(2)订阅坐标发布消息,并取出订阅的消息,借助于 tf2 实现 son1 和 son2 的转换
(3)还要实现坐标点的转换
实现流程:C++ 与 Python 实现流程一致
(1)新建功能包,添加依赖
(2)创建坐标相对关系发布方(需要发布两个坐标相对关系)
(3)创建坐标相对关系订阅方
(4)执行
C++实现
(1)创建功能包
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)发布方
(3)订阅方
python实现
(1)创建功能包
创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)发布方---订阅方
1.5 坐标系关系查看
查看是否安装:rospack find tf2_tools
安装:sudo apt install ros-noetic-tf2-tools
1.6 TF坐标变换实践
需求描述:程序启动之初产生两只乌龟,中间的乌龟(A) 和 左下乌龟(B), B 会自动运行至A的位置,并且键盘控制时,只是控制 A 的运动,但是 B 可以跟随 A 运行龟跟随实现的核心,是乌龟A和B都要发布相对世界坐标系的坐标信息,然后,订阅到该信息需要转换获取A相对于B坐标系的信息,最后,再生成速度信息,并控制B运动。
(1)启动乌龟显示节点
(2)在乌龟显示窗体中生成一只新的乌龟(需要使用服务)
(3)编写两只乌龟发布坐标信息的节点
(4)编写订阅节点订阅坐标信息并生成新的相对关系生成速度信息
C++实现
(1)创建项目功能包:依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)服务客户端(生成乌龟)
(3)发布方(发布两只乌龟的坐标信息)
(4)订阅方(解析坐标信息并生成速度信息)---运行
python实现
(1)创建项目功能包:依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim
(2)服务客户端(生成乌龟)
(3)发布方(发布两只乌龟的坐标信息)
(4)订阅方(解析坐标信息并生成速度信息)---运行