• Ros1 学习12- tf坐标系广播与监听的编程实现


    实现步骤

    创建一程序订阅海龟的相对于world的位置,即海龟发布的/turtle_name/pose消息,接受到消息数据后,创建tf的广播器,并初始化tf数据,广播world与海龟坐标系之间的关系;

    然后,创建一程序产生第2只海龟turtle2,实时监听tf广播数据,依据turtle2与turtle1之间的坐标关系计算turtle2的速度,向turtle2发布速度控制指令,实现海龟turtle2跟踪turtle1。

    1 创建功能包

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

    cd ~/catkin_ws/src
    catkin_create_pkg learning_tf roscpp rospy tf turtlesim
    
    • 1
    • 2

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

    如何实现一个TF广播器:

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

    在learning_tf/src 新增 turtle_tf_broadcaster.cpp

    源码内容如下:

    
    
    /**
     * 该例程产生tf数据,并计算、发布turtle2的速度指令
     */
    
    #include 
    #include 
    #include 
    
    std::string turtle_name;
    //回调函数,传入参数为海归的位置
    void poseCallback(const turtlesim::PoseConstPtr& msg)
    {
    	// 创建tf的广播器,将turtle1 相对于world ,turtle2 相对于world的坐标系发出去
    	static tf::TransformBroadcaster br;
    
    	// 初始化tf数据 填充坐标系之间的关系
    	tf::Transform transform;
    	
    	transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
    	tf::Quaternion q;
    	//设置四元数(旋转矩阵),传入RPY三个角的信息。这里只有Z 方向有旋转关系
    	q.setRPY(0, 0, msg->theta);
    	transform.setRotation(q);
    
    	// 广播world与海龟坐标系之间的tf数据
    	br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
    }
    
    int main(int argc, char** argv)
    {
        // 初始化ROS节点
    	ros::init(argc, argv, "my_tf_broadcaster");
    
    	// 输入参数作为海龟的名字
    	if (argc != 2)
    	{
    		ROS_ERROR("need turtle name as argument"); 
    		return -1;
    	}
    
    	turtle_name = argv[1];
    
    	// 订阅海龟的位姿话题
    	ros::NodeHandle node;
    	ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    
        // 循环等待回调函数
    	ros::spin();
    
    	return 0;
    };
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    如何实现一个TF监听器:

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

    坐标关系插入TF tree后,树会自动运算变换矩阵,后面我们就可以用监听器调用了。
    turtle_tf_listener.cpp:根据步骤,从tf中获取任意两个坐标之间的位置关系(通过waitfor和lookup),然后命令turtle2向turtle1以定义的速度(Twist)移动。

    turtle_tf_listener.cpp 源码内容如下:

    
    /**
     * 该例程监听tf数据,并计算、发布turtle2的速度指令
     */
    
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char** argv)
    {
    	// 初始化ROS节点
    	ros::init(argc, argv, "my_tf_listener");
    
        // 创建节点句柄
    	ros::NodeHandle node;
    
    	// 请求产生turtle2
    	ros::service::waitForService("/spawn");
    	ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
    	turtlesim::Spawn srv;
    	add_turtle.call(srv);
    
    	// 创建发布turtle2速度控制指令的发布者
    	ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);
    
    	// 创建tf的监听器
    	tf::TransformListener listener;
    
    	ros::Rate rate(10.0);
    	while (node.ok())
    	{
    		// 获取turtle1与turtle2坐标系之间的tf数据
    		tf::StampedTransform transform;
    		try
    		{
    			listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
    			listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
    		}
    		catch (tf::TransformException &ex) 
    		{
    			ROS_ERROR("%s",ex.what());
    			ros::Duration(1.0).sleep();
    			continue;
    		}
    
    		// 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令
    		geometry_msgs::Twist vel_msg;
    		//定义角速度
    		vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
    				                        transform.getOrigin().x());
    		//定义角速度
    		vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
    				                      pow(transform.getOrigin().y(), 2));
    		turtle_vel.publish(vel_msg);
    
    		rate.sleep();
    	}
    	return 0;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    配置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})
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后编译

    cd ~/catkin_ws
    catkin_make
    
    • 1
    • 2

    测试:

    roscore
    
    • 1
    rosrun turtlesim turtlesim_node
    
    • 1

    注: 我们下面直接在命令行传入参数。
    第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
    
    • 1
    rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
    
    
    • 1
    • 2
    rosrun learning_tf turtle_tf_listener
    
    
    • 1
    • 2
    rosrun turtlesim turtle_teleop_key
    
    
    • 1
    • 2
  • 相关阅读:
    如何评价GPT-4o?
    PerfView专题 (第五篇):如何寻找 C# 托管内存泄漏
    Vue2 和 Vue3 响应式上有什么区别?
    内存管理(一)——内存分配
    01-为什么 switch case 语句需要加入 break
    JavaScript中的一等公民: 函数(Function)
    AE Saber插件学习笔记
    基于STC15单片机温度光照蓝牙传输-proteus仿真-源程序
    Docker下常规软件安装
    Jenkins结合Gitlab,实现镜像构建及推送
  • 原文地址:https://blog.csdn.net/hai411741962/article/details/134467888