【ROS学习笔记】14.tf坐标系广播与监听的编程实现

基于B站ROS公开课:【古月居】古月·ROS入门21讲
基于Ubuntu 20.04.1、Noetic版本
修正错误,并详述Python版本部署


上节学习了坐标管理系统tf的简介和理论,这节讲解TF坐标变换的实现机制 广播监听的编程实现。
(部分图摘自:b站【古月居】古月·ROS入门21讲)

1 创建功能包

创建的 learning_tf 包来进行代码存放和编译。

cd ~/catkin_ws/src
catkin_create_pkg learning_tf roscpp rospy tf turtlesim

2 创建代码并编译运行(C++)

如何实现一个TF广播器

  • 定义TF广播器(TransformBroadcaster)
  • 创建坐标变换值
  • 发布坐标变换(sendTransform)

如何实现一个TF监听器

  • 定义TF监听器(TransformListener)
  • 查找坐标变换(waitForTransform、lookupTransform)

创建代码

(源码:https://github.com/guyuehome/ros_21_tutorials/tree/master/learning_tf/src)
用红字标示了自己的注解笔记。

turtle_tf_broadcaster.cpp :根据实现的步骤,我们想要通过TF广播任意两个坐标系之间的位置关系,需要建立一个广播器,然后创建坐标的变换值,将这个变换矩阵的信息广播出去(插入TF tree)。
注意下面main函数时我们需要传入参数,参数从终端命令行输入(输入的参数包括节点名称 和 turtle_name),下面运行部分会解释一下传入的参数的方法。这样我们从终端传参可以重复跑两遍这个C++程序分别对应turtle1和turtle2的广播器。
在这里插入图片描述
坐标关系插入TF tree后,树会自动运算变换矩阵,后面我们就可以用监听器调用了。
turtle_tf_listener.cpp:根据步骤,从tf中获取任意两个坐标之间的位置关系(通过waitfor和lookup),然后命令turtle2向turtle1以定义的速度(Twist)移动。
在这里插入图片描述
将代码拷贝到src文件夹下。

编译

先配置CMakeLists.txt编译规则:

  • 设置需要编译的代码和生成的可执行文件;
  • 设置链接库;

将下面代码拷贝到指定位置:

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})

add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

在这里插入图片描述
然后编译:

cd ~/catkin_ws
catkin_make

运行

默认已经source,接着分别在每个终端运行。

roscore
rosrun turtlesim turtlesim_node

注:
我们下面直接在命令行传入参数。
第1个参数:我们在turtle_tf_broadcaster.cpp定义节点时使用了"my_tf_broadcaster"的名字,我们使用__name:=传入新的名字取代"my_tf_broadcaster",这样避免名字重复(因为ROS中节点名字不能重复),这样就可以重复跑程序了。
第2个参数是turtle名称 turtle1 和 turtle2。

rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1
rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
rosrun learning_tf turtle_tf_listener

上面完成后就会有一个海龟生成并跑向中间的第1只海龟。
在这里插入图片描述

rosrun turtlesim turtle_teleop_key

我们用键盘控制海龟,同样可以让第2只海龟追着我们跑。
在这里插入图片描述

2 创建代码并编译运行(Python)

如何实现一个TF广播器

  • 定义TF广播器(TransformBroadcaster)
  • 创建坐标变换值
  • 发布坐标变换(sendTransform)

如何实现一个TF监听器

  • 定义TF监听器(TransformListener)
  • 查找坐标变换(lookupTransform)

创建代码

(源码:https://github.com/guyuehome/ros_21_tutorials/tree/master/learning_tf/scripts)
用红字标示了自己的注解笔记。

turtle_tf_broadcaster.py :根据实现的步骤,我们想要通过TF广播任意两个坐标系之间的位置关系,需要建立一个广播器,然后创建坐标的变换值,将这个变换矩阵的信息广播出去(插入TF tree)。
注意下面main函数中,我们的turtlename是一个通过终端传入的参数,下面运行部分会解释一下传入的参数的方法。这样我们从终端传参可以重复跑两遍这个python程序分别对应turtle1和turtle2的广播器。
在这里插入图片描述
坐标关系插入TF tree后,树会自动运算变换矩阵,后面我们就可以用监听器调用了。
turtle_tf_listener.py:根据步骤,从tf中获取任意两个坐标之间的位置关系,然后命令turtle2向turtle1以定义的速度(Twist)移动。
在这里插入图片描述
将代码拷贝到新建的scripts文件夹下。
右击py文件→属性,打开执行权限。

编译

先配置CMakeLists.txt编译规则:
加上一个关于turtle_tf_broadcaster.py和turtle_tf_listener.py的catkin_install_python方法:
将下面代码写到指定位置:

在这里插入图片描述
然后编译

cd ~/catkin_ws
catkin_make

运行

默认已经source,接着运行。

roscore
rosrun turtlesim turtlesim_node

注:
我们下面直接在命令行传入参数。
第1个参数:我们在turtle_tf_broadcaster.py定义节点时使用了"turtle_tf_broadcaster"的名字,我们使用__name:=传入新的名字取代"my_tf_broadcaster",这样避免名字重复(因为ROS中节点名字不能重复),这样就可以重复跑程序了。
第2个参数是turtle名称 turtle1 和 turtle2。

rosrun learning_tf turtle_tf_broadcaster.py __name:=turtle1_tf_broadcaster _turtle:=turtle1
rosrun learning_tf turtle_tf_broadcaster.py __name:=turtle2_tf_broadcaster _turtle:=turtle2
rosrun learning_tf turtle_tf_listener.py

注:显示“ the rosdep view is empty: call ‘sudo rosdep init’ and ‘rosdep update’ ”的话不用介意。
上面完成后就会有一个海龟生成并跑向中间的第1只海龟。

rosrun turtlesim turtle_teleop_key

我们用键盘控制海龟,同样可以让第2只海龟追着我们跑。
在这里插入图片描述

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS中,坐标系坐标系之间的变换是通过tf(transform)包来实现的。tf包提供了一种方便的方式来管理坐标系之间的关系,并且能够自动地计算出不同坐标系之间的变换。下面是一个简单的例子,演示如何通过tf实现坐标系之间的变换。 假设我们有两个坐标系,分别为`/world`和`/robot_base`,我们想要将`/robot_base`坐标系中的一个点`(x, y, z)`变换到`/world`坐标系中。我们可以按照以下步骤进行: 1. 创建一个`tf::Transform`对象,表示`/robot_base`坐标系相对于`/world`坐标系的变换。 ```cpp tf::Transform transform; transform.setOrigin(tf::Vector3(x, y, z)); // 设置变换的平移部分 transform.setRotation(tf::Quaternion(0, 0, 0, 1)); // 设置变换的旋转部分 ``` 2. 发布`/robot_base`坐标系相对于`/world`坐标系的变换。 ```cpp static tf::TransformBroadcaster br; br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "/world", "/robot_base")); ``` 3. 在需要使用变换后的点的节点中,通过tf监听器(tf listener)获取变换后的点。 ```cpp tf::TransformListener listener; tf::StampedTransform transform; listener.waitForTransform("/world", "/robot_base", ros::Time(0), ros::Duration(1.0)); // 等待获取变换信息 listener.lookupTransform("/world", "/robot_base", ros::Time(0), transform); // 获取变换信息 tf::Vector3 point(x, y, z); tf::Vector3 transformed_point = transform * point; // 计算变换后的点 ``` 通过以上步骤,我们就可以将`/robot_base`坐标系中的点`(x, y, z)`变换到`/world`坐标系中了。需要注意的是,tf的变换是从目标坐标系到源坐标系的变换,因此在发布变换信息时,需要指定目标坐标系和源坐标系的名称。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值