ROS学习笔记:tf的学习与使用(一)

时间:2024-03-15 11:38:38

ROS机器人的开发过程中,经常需要用到tf坐标变换。简单来讲,tf定义了两个不同坐标系之间的旋转变换关系。

1. 一个简单的demo

$ roslaunch turtle_tf turtle_tf_demo.launch
    这时候屏幕中会出现两个turtle, 可以通过控制前面的turtle来引导后面的turtle

$ rosrun turtlesim turtle_teleop_key
$ evince frames.pdf
ROS学习笔记:tf的学习与使用(一)

从上面我们可以清楚地看到三个坐标系之间的关系。

我们还可以使用tf_echo来看两个坐标系之间是如何变换的

rosrun tf tf_echo [reference_frame] [target_frame]

ROS学习笔记:tf的学习与使用(一)

也可以通过rviz来查看坐标系的变换及移动情况。

$ rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz
ROS学习笔记:tf的学习与使用(一)

2.写一个简单的tf broadcaster程序

 $ catkin_create_pkg learning_tf tf roscpp rospy turtlesim
 $ catkin_make
 $ source ./devel/setup.bash
 $ roscd learning_tf
src/turtle_tf_broadcaster.cpp

https://raw.githubusercontent.com/ros/geometry_tutorials/hydro-devel/turtle_tf/src/turtle_tf_broadcaster.cpp

  16 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));

这里的后两个参数即为父坐标系和子坐标系。

修改CMakeLists.txt,在最后加上

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
$ catkin_make
添加start_demo.launch

  <launch>
    <!-- Turtlesim Node-->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>

    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
    <!-- Axes -->
    <param name="scale_linear" value="2" type="double"/>
    <param name="scale_angular" value="2" type="double"/>

    <node pkg="learning_tf" type="turtle_tf_broadcaster"
          args="/turtle1" name="turtle1_tf_broadcaster" />
    <node pkg="learning_tf" type="turtle_tf_broadcaster"
          args="/turtle2" name="turtle2_tf_broadcaster" />

  </launch>
$ roslaunch learning_tf start_demo.launch
 $ rosrun tf tf_echo /world /turtle1
$ rosrun turtlesim turtle_teleop_key
这时候移动turtle可以看到坐标系的变化

ROS学习笔记:tf的学习与使用(一)

3.写一个简单的tf listener

 $ roscd learning_tf
src/turtle_tf_listener.cpp

https://raw.github.com/ros/geometry_tutorials/hydro-devel/turtle_tf/src/turtle_tf_listener.cpp

  25     try{
  26       listener.lookupTransform("/turtle2", "/turtle1",
  27                                ros::Time(0), transform);
  28     }
这个代码段将坐标系由turtle1变换成turtle2。

  35     geometry_msgs::Twist vel_msg;
  36     vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
  37                                     transform.getOrigin().x());
  38     vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
根据与turtle1的距离和角度差来计算turtle2的线速度和角速度。

编写CMakeLists.txt

add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
$ catkin_make
编写launch 文件,在原launch的后面添加

<node pkg="learning_tf" type="turtle_tf_listener"
          name="listener" />
启动

 $ roslaunch learning_tf start_demo.launch
同样,通过启动键盘控制前面的turtle1可以控制后面的turtle2

在这里需要注意的是,有可能回出现如下错误

[ERROR] [1505742896.803000722]: "turtle2" passed to lookupTransform argument target_frame does not exist. 

事实上,这并不是程序的错误,只是因为通信的时延导致turtle2开始的时候无法找到turtle1,因此无法进行计算。