0
点赞
收藏
分享

微信扫一扫

ROS系统实现 tf坐标系广播与监听

腊梅5朵 2022-06-01 阅读 47

安装Ros中 tf 相关功能包

sudo apt-get install ros-melodic-turtle-tf

ROS系统实现 tf坐标系广播与监听_python

启动launch文件,这个launch文件相当于一个脚本,可以一次性启动很多节点

roslaunch turtle_tf turtle_tf_demo.launch

ROS系统实现 tf坐标系广播与监听_#include_02

启动海龟控制节点

rosrun turtlesim turtle_teleop_key

ROS系统实现 tf坐标系广播与监听_python_03
能够监听当前时刻所有通过ROS广播的tf坐标系,并绘制出树状图表示坐标系之间的连接关系保存到离线文件中,监听5秒后,保存5秒内坐标系之间的关系,会生成一个pdf文件。

rosrun tf view_frames

ROS系统实现 tf坐标系广播与监听_#include_04

ROS系统实现 tf坐标系广播与监听_数据_05

使用tf_echo工具可以查看两个广播参考系之间的关系。

rosrun tf tf_echo [reference_frame] [target_frame]

例如:

rosrun tf tf_echo turtle1 turtle2

ROS系统实现 tf坐标系广播与监听_数据_06

通过rvize可视化工具更加形象的看到这三者之间的关系。

rosrun rviz rviz -d 'rospack find turtle_tf' /rviz/turtle.rviz

ROS系统实现 tf坐标系广播与监听_数据_07

ROS系统实现 tf坐标系广播与监听_python_08
ROS系统实现 tf坐标系广播与监听_数据_09

ROS系统实现 tf坐标系广播与监听_#include_10
ROS系统实现 tf坐标系广播与监听_python_11

ROS系统实现 tf坐标系广播与监听_python_12

ROS系统实现 tf坐标系广播与监听_数据_13
ROS系统实现 tf坐标系广播与监听_python_14
ROS系统实现 tf坐标系广播与监听_python_15

cd ~/catkin_ws/src

catkin_create_pkg learning_tf roscpp rospy tf turtlesim

ROS系统实现 tf坐标系广播与监听_#include_16

如何实现一个tf广播器

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

如何实现一个TF监听器

  • 定义TF监听器
  • 查找坐标变换

在创建的 learning_tf 目录中的src文件夹下创建一个 cpp文件

cd ~/catkin_ws/src/learning_tf/src

touch turtle_tf_broadcaster.cpp

在 turtle_tf_broadcaster.cpp 文件中写入以下代码。
以下代码的功能:产生tf数据,并计算、发布turtle2的速度指令

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>

std::string&nbsp;turtle_name;

void&nbsp;poseCallback(const&nbsp;turtlesim::PoseConstPtr&amp;&nbsp;msg)
{
// 创建tf的广播器
static&nbsp;tf::TransformBroadcaster&nbsp;br;

// 初始化tf数据
tf::Transform&nbsp;transform;
transform.setOrigin(&nbsp;tf::Vector3(msg-&gt;x,&nbsp;msg-&gt;y,&nbsp;0.0)&nbsp;);
tf::Quaternion&nbsp;q;
q.setRPY(0,&nbsp;0,&nbsp;msg-&gt;theta);
transform.setRotation(q);

// 广播world与海龟坐标系之间的tf数据
br.sendTransform(tf::StampedTransform(transform,&nbsp;ros::Time::now(),&nbsp;&quot;world&quot;,&nbsp;turtle_name));
}

int&nbsp;main(int&nbsp;argc,&nbsp;char**&nbsp;argv)
{
&nbsp;&nbsp;&nbsp;&nbsp;// 初始化ROS节点
ros::init(argc,&nbsp;argv,&nbsp;&quot;my_tf_broadcaster&quot;);

// 输入参数作为海龟的名字
if&nbsp;(argc&nbsp;!=&nbsp;2)
{
ROS_ERROR(&quot;need&nbsp;turtle&nbsp;name&nbsp;as&nbsp;argument&quot;);&nbsp;
return&nbsp;-1;
}

turtle_name&nbsp;=&nbsp;argv[1];

// 订阅海龟的位姿话题
ros::NodeHandle&nbsp;node;
ros::Subscriber&nbsp;sub&nbsp;=&nbsp;node.subscribe(turtle_name+&quot;/pose&quot;,&nbsp;10,&nbsp;&amp;poseCallback);

&nbsp;&nbsp;&nbsp;&nbsp;// 循环等待回调函数
ros::spin();

return&nbsp;0;
};

在创建的 learning_tf 目录中的src文件夹下创建一个 cpp文件

cd ~/catkin_ws/src/learning_tf/src

touch turtle_tf_listener.cpp

在 turtle_tf_listener.cpp 文件中写入以下代码。
以下代码的功能:监听tf数据,并计算、发布turtle2的速度指令

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>

int&nbsp;main(int&nbsp;argc,&nbsp;char**&nbsp;argv)
{
// 初始化ROS节点
ros::init(argc,&nbsp;argv,&nbsp;&quot;my_tf_listener&quot;);

&nbsp;&nbsp;&nbsp;&nbsp;// 创建节点句柄
ros::NodeHandle&nbsp;node;

// 请求产生turtle2
ros::service::waitForService(&quot;/spawn&quot;);
ros::ServiceClient&nbsp;add_turtle&nbsp;=&nbsp;node.serviceClient&lt;turtlesim::Spawn&gt;(&quot;/spawn&quot;);
turtlesim::Spawn&nbsp;srv;
add_turtle.call(srv);

// 创建发布turtle2速度控制指令的发布者
ros::Publisher&nbsp;turtle_vel&nbsp;=&nbsp;node.advertise&lt;geometry_msgs::Twist&gt;(&quot;/turtle2/cmd_vel&quot;,&nbsp;10);

// 创建tf的监听器
tf::TransformListener&nbsp;listener;

ros::Rate&nbsp;rate(10.0);
while&nbsp;(node.ok())
{
// 获取turtle1与turtle2坐标系之间的tf数据
tf::StampedTransform&nbsp;transform;
try
{
listener.waitForTransform(&quot;/turtle2&quot;,&nbsp;&quot;/turtle1&quot;,&nbsp;ros::Time(0),&nbsp;ros::Duration(3.0));
listener.lookupTransform(&quot;/turtle2&quot;,&nbsp;&quot;/turtle1&quot;,&nbsp;ros::Time(0),&nbsp;transform);
}
catch&nbsp;(tf::TransformException&nbsp;&amp;ex)&nbsp;
{
ROS_ERROR(&quot;%s&quot;,ex.what());
ros::Duration(1.0).sleep();
continue;
}

// 根据turtle1与turtle2坐标系之间的位置关系,计算turtle2需要运动的线速度和角速度
// 并发布速度控制指令,使turtle2向turtle1移动
geometry_msgs::Twist&nbsp;vel_msg;
vel_msg.angular.z&nbsp;=&nbsp;4.0&nbsp;*&nbsp;atan2(transform.getOrigin().y(),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transform.getOrigin().x());
vel_msg.linear.x&nbsp;=&nbsp;0.5&nbsp;*&nbsp;sqrt(pow(transform.getOrigin().x(),&nbsp;2)&nbsp;+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pow(transform.getOrigin().y(),&nbsp;2));
turtle_vel.publish(vel_msg);

rate.sleep();
}
return&nbsp;0;
};

在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})

ROS系统实现 tf坐标系广播与监听_数据_17

编译项目

cd ~/catkin_ws

catkin_make

设置环境变量,让系统能够找到该工作空间

source devel/setup.bash

启动ROS Master

roscore

启动小海龟仿真器

rosrun turtlesim turtlesim_node

发布/turtle1海龟坐标系关系

rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1

注:turtle_tf_broadcaster __name:=turtle1_tf_broadcaster 重新命名
ROS系统实现 tf坐标系广播与监听_数据_18

发布/turtle2海龟坐标系关系

rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2

启动自定义的节点

rosrun learning_tf turtle_tf_listener

启动海龟控制节点

rosrun turtlesim turtle_teleop_key

ROS系统实现 tf坐标系广播与监听_#include_19

用Python实现的步骤:

cd ~/catkin_ws/src/learning_tf

创建 scripts 文件夹

mkdir scripts

cd scripts

创建 turtle_tf_broadcaster.py Python文件

touch turtle_tf_broadcaster.py

用Python实现的代码:
以下代码的功能:请求/show_person服务,服务数据类型learning_service::Person

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import&nbsp;roslib
roslib.load_manifest(&#39;learning_tf')
import&nbsp;rospy

import&nbsp;tf
import&nbsp;turtlesim.msg

def&nbsp;handle_turtle_pose(msg,&nbsp;turtlename):
&nbsp;&nbsp;&nbsp;&nbsp;br&nbsp;=&nbsp;tf.TransformBroadcaster()
&nbsp;&nbsp;&nbsp;&nbsp;br.sendTransform((msg.x,&nbsp;msg.y,&nbsp;0),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf.transformations.quaternion_from_euler(0,&nbsp;0,&nbsp;msg.theta),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rospy.Time.now(),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turtlename,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;world&quot;)

if&nbsp;__name__&nbsp;==&nbsp;&#39;__main__':
&nbsp;&nbsp;&nbsp;&nbsp;rospy.init_node(&#39;turtle_tf_broadcaster')
&nbsp;&nbsp;&nbsp;&nbsp;turtlename&nbsp;=&nbsp;rospy.get_param(&#39;~turtle')
&nbsp;&nbsp;&nbsp;&nbsp;rospy.Subscriber(&#39;/%s/pose' % turtlename,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turtlesim.msg.Pose,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handle_turtle_pose,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turtlename)
&nbsp;&nbsp;&nbsp;&nbsp;rospy.spin()

创建 turtle_tf_listener.py Python文件

touch turtle_tf_listener.py

用Python实现的代码:
以下代码的功能:请求/show_person服务,服务数据类型learning_service::Person

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import&nbsp;roslib
roslib.load_manifest(&#39;learning_tf')
import&nbsp;rospy
import&nbsp;math
import&nbsp;tf
import&nbsp;geometry_msgs.msg
import&nbsp;turtlesim.srv

if&nbsp;__name__&nbsp;==&nbsp;&#39;__main__':
&nbsp;&nbsp;&nbsp;&nbsp;rospy.init_node(&#39;turtle_tf_listener')

&nbsp;&nbsp;&nbsp;&nbsp;listener&nbsp;=&nbsp;tf.TransformListener()

&nbsp;&nbsp;&nbsp;&nbsp;rospy.wait_for_service(&#39;spawn')
&nbsp;&nbsp;&nbsp;&nbsp;spawner&nbsp;=&nbsp;rospy.ServiceProxy(&#39;spawn', turtlesim.srv.Spawn)
&nbsp;&nbsp;&nbsp;&nbsp;spawner(4,&nbsp;2,&nbsp;0,&nbsp;&#39;turtle2')

&nbsp;&nbsp;&nbsp;&nbsp;turtle_vel&nbsp;=&nbsp;rospy.Publisher(&#39;turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)

&nbsp;&nbsp;&nbsp;&nbsp;rate&nbsp;=&nbsp;rospy.Rate(10.0)
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;not&nbsp;rospy.is_shutdown():
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(trans,rot)&nbsp;=&nbsp;listener.lookupTransform(&#39;/turtle2', '/turtle1', rospy.Time(0))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;(tf.LookupException,&nbsp;tf.ConnectivityException,&nbsp;tf.ExtrapolationException):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angular&nbsp;=&nbsp;4&nbsp;*&nbsp;math.atan2(trans[1],&nbsp;trans[0])
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;linear&nbsp;=&nbsp;0.5&nbsp;*&nbsp;math.sqrt(trans[0]&nbsp;**&nbsp;2&nbsp;+&nbsp;trans[1]&nbsp;**&nbsp;2)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd&nbsp;=&nbsp;geometry_msgs.msg.Twist()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.linear.x&nbsp;=&nbsp;linear
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.angular.z&nbsp;=&nbsp;angular
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turtle_vel.publish(cmd)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rate.sleep()

注意:需要将Python设置为可执行文件。

ROS系统实现 tf坐标系广播与监听_python_20
ROS系统实现 tf坐标系广播与监听_python_21

启动ROS Master

roscore

启动小海龟仿真器

rosrun turtlesim turtlesim_node

发布/turtle1海龟坐标系关系

rosrun learning_tf turtle_tf_broadcaster.py __name:=turtle1_tf_badcaster _turtle:=turtle1

发布/turtle2海龟坐标系关系

rosrun learning_tf turtle_tf_broadcaster.py __name:=turtle2_tf_badcaster _turtle:=turtle2

启动自定义的监听节点

rosrun learning_tf turtle_tf_listener.py

启动海龟控制节点

rosrun turtlesim turtle_teleop_key

ROS系统实现 tf坐标系广播与监听_#include_22

举报

相关推荐

0 条评论