ROS:tf坐标系广播与监听的编程实现

news2024/11/16 9:26:55

目录

  • 一、创建功能包
  • 二、创建代码并编译运行(C++)
    • 2.1创建代码
    • 2.2编译
    • 2.3运行

一、创建功能包

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

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

在这里插入图片描述

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

实现一个TF广播器:

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

实现一个TF监听器:
定义TF监听器(TransformListener)
查找坐标变换(waitForTransform、lookupTransform)

2.1创建代码

在/master/learning_tf/src文件加下创建turtle_tf_broadcaster.cpp文件和turtle_tf_listener.cpp文件
turtle_tf_broadcaster.cpp
通过TF广播任意两个坐标系之间的位置关系,需要建立一个广播器,然后创建坐标的变换值,将这个变换矩阵的信息广播出去(插入TF tree)

/**
 * 该例程产生tf数据,并计算、发布turtle2的速度指令
 */

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

std::string turtle_name;

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

	// 初始化tf数据
	tf::Transform transform;
	transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
	tf::Quaternion q;
	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;
};

turtle_tf_listener.cpp
坐标关系插入TF tree后,树会自动运算变换矩阵,后面就可以用监听器调用了

/**
 * 该例程监听tf数据,并计算、发布turtle2的速度指令
 */

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

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;
};

2.2编译

配置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

2.3运行

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只海龟。
在这里插入图片描述
用键盘控制海龟,同样可以让第2只海龟追着我们跑。

rosrun turtlesim turtle_teleop_key

在这里插入图片描述
参考视屏:古月居ROS入门21讲
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/612201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

银行业务相关

省联社&#xff0c;农商行、农村信用社之间的关系 一些知乎回答 省联社、农商行、农村信用社之间有什么联系&#xff1f; - mobye的回答 - 知乎 https://www.zhihu.com/question/24220844/answer/28276903 发源于空想社会主义&#xff0c;世界上第一个信用合作社诞生于1984年的…

第9章集 合

文章目录 9.1 Java集合框架9.1.1 集合接口与实现分离9.1.3 迭代器9.1.4 泛型实用方法 9.2 集合框架中的接口9.3.1 链表9.3.2 数组列表9.3.3散列集9.3.4 树集9.3.5 队列与双端队列9.3.6 优先队列 9.4 映射9.4.1 基本映射操作9.4.2 更新映射条目9.4.3 映射视图9.4.4 弱散列映射9.…

python数据可视化-matplotlib学习总结

目录 &#xff08;一&#xff09;常见的图形 1、趋势图&#xff08;直线图&#xff09;&#xff1a;plot&#xff08;&#xff09; 2、散点图&#xff1a;scatter(): (二&#xff09;统计图形 1、柱状图&#xff1a;bar( 2、条形图&#xff1a;barh() 3、直方图&#xff…

RSA加密算法解析

目录 RSA加密 数学原理 证明: 欧拉函数 欧拉定理 模反元素 模运算 指数运算 同余 欧几里德算法GCD 填充(padding) 对称加密的应用工作流程 非对称加密的应用工作流程 1&#xff09;加密过程 2&#xff09;解密过程 代码实现 密码学知识扩展 加密体制 如何破解…

亚马逊云科技出海日倒计时,潮向新世界,亮点抢先知

数字化浪潮之下&#xff0c;中国企业的全球化步伐明显提速。从“借帆出海”到“生而全球化”&#xff0c;中国企业实现了从传统制造业“中国产品”出口&#xff0c;向创新“中国技术”和先导“中国品牌”的逐步升级。 作为全球云计算的开创者与引领者&#xff0c;亚马逊云科技…

org.apache.commons.io.monitor+logback.xml+vue实时显示当前日志信息

使用记录&#xff1a; 第一&#xff1a; 刷新页面导致session问题 可以在java的session中记录&#xff0c;如果是同一个客户重新链接的话&#xff0c;直接返回java的session的数据ssemiter给前端&#xff0c;前端自动接着获取日志。 ssemiter&#xff1a;详情自行百度ssemit…

墨天轮专访TDengine陶建辉:坚持做难而正确的事,三次创业成就不悔人生

导读&#xff1a; 时序数据库&#xff08;Time Series Database&#xff09;在最近几年被越来越多的用户接受并使用&#xff0c;并有广泛的应用场景。云原生时序数据库 TDengine 一直稳居墨天轮时序数据库榜首&#xff0c;其近期的海外发展也初见成效。本期&#xff0c;墨天轮技…

Mybatis(黑马程序员)

1. Mybatis基础操作 1.1 需求 需求说明&#xff1a; 根据资料中提供的《tlias智能学习辅助系统》页面原型及需求&#xff0c;完成员工管理的需求开发。 通过分析以上的页面原型和需求&#xff0c;我们确定了功能列表&#xff1a; 查询 根据主键ID查询条件查询 新增 更新 …

分享几个实用又有趣的工具类网站

今天来给大家分享几个众多网友们推荐的&#xff0c;实用又有趣的工具类网站 DeepL翻译&#xff1a;免费的在线翻译网站&#xff0c;大名鼎鼎的翻译神器 DeepL&#xff0c;翻译准确、语句通顺&#xff0c;效果相当好。 https://www.deepl.com/translator BgSub 消除或者替换图…

几句话说清楚数据库的基本范式

第一范式 1NF&#xff1a;属性不能再被拆分。 人(身份证号, 姓名, 性别, 联系方式) 不满足 1NF因为联系方式包含了电话号码、电子邮箱、微信、QQ 等人(身份证号, 姓名, 性别, 电话号码) 满足 1NF 第二范式 2NF&#xff1a;不存在非主属性对主键的部分函数依赖关系。 R(A, B,…

替换jar包中的yml,class等文件的方法

文章目录 1.使用场景2.先准备好待替换的文件3.下载服务器上的jar包4.解压出来指定的文件5.将文件打入jar包6.查看是否替换成功 1.使用场景 由于线上项目中突然爆出一个bug问题&#xff0c;影响到用户使用&#xff0c;但是 线上的jar包版本&#xff0c;已经是很久的了&#xff…

rpmbuild编译安装制作rpm包

什么是rpm包? rpm 相当于windows中的安装文件,它会自动处理软件包之间的依赖关系。 rpm优点: 包管理系统简单,通过几个命令就可以实现包的安装、升级、卸载。 安装速度比源码包快的多。 缺点: 经过编译,不能看到源代码,功能选择不如源码灵活。依赖性强。 首先说一下流程…

基于RPC协议的接口自动化测试可以用Python语言实现

基于RPC协议的接口自动化测试可以用Python语言实现。下面是实现步骤&#xff1a; 1、安装依赖库&#xff0c;如protobuf、grpc。 2、编写.proto文件定义接口参数和返回值。 3、使用protoc编译.proto文件生成Python代码。 4、编写客户端代码调用远程接口进行测试。 具体实现…

C++【红黑树封装mapset】

文章目录 前言&#xff08;一&#xff09; 修改原红黑树&#xff08;1&#xff09;逐步修改并调试运行&#xff08;2&#xff09;红黑树的迭代器&#xff08;3&#xff09;最后一步最重要的 二、源代码压缩包 前言 我们在开始之前&#xff0c;首先要明白一点&#xff0c;前面我…

一文带你了解MySQL之事务隔离级别和MVCC

目录 一、数据准备二、事务隔离级别2.1 事务并发执行遇到的问题2.2 SQL标准中的四种隔离级别2.3 MySQL中支持的四种隔离级别 三、MVCC3.1 版本链3.2 ReadView3.2.1 READ COMMITTED3.2.2 REPEATABLE READ 3.3 MVCC小结 四、关于purge五、总结 一、数据准备 为了我们学习的顺利进…

一篇文章搞懂CMake(gcc、g++、cmake解释)

一篇文章搞懂CMake &#xff08;gcc、g、cmake解释&#xff09; 这里写目录标题 一篇文章搞懂CMake &#xff08;gcc、g、cmake解释&#xff09;gccgcmake1. CMake 流程如何使用cmake&#xff1f;简单的CMake.txt文件 参考 gcc gcc命令来自英文词组“GNU Compiler Collection”…

4.C++多线程-- unique_lock(类模板)

1.unique_lock 1. unique_lock<mutex> myUniLock(myMutex); 完全可以取代lock_guard 2. unique_lock 也可以使用----std::adopt_lock 3.使用adopt_lock&#xff0c;之前要先使用lock. 4.std::chrono::milliseconds my_sleepTime(20000)//20000毫秒 std::this_thread:…

运维小白必学篇之基础篇第十一集:系统进程实验

系统进程实验 实验作业&#xff1a; 1、利用top命令查看当前系统进程&#xff0c;要求没5秒刷新一次&#xff0c;分别按照CPU使用率&#xff0c;内存使用量&#xff0c;CPU使用时间&#xff0c;PID分别排序一次 每5秒刷新一次&#xff1a;top -d 5 按照CPU使用率排序&#xf…

【python】如何入门python?

文章目录 前言一、为什么学习Python&#xff1f;二、学习Python的前置条件三、入门Python的步骤3.1 安装Python3.2 安装Python开发环境3.3 学习Python基础语法3.4 编写你的第一个Python程序3.5 学习Python的高级特性3.6 使用Python库和框架 四、Python入门的资源五、常见的Pyth…

allure报告中如何让测试步骤更清晰

一、allure step测试用例步骤说明 allure step编写测试用例有两种方式 1、with allure.step()用在测试用例中 公共方法代码&#xff1a; # common_fucntion.py import allure import pytest from common.tools.log_util import LoggerrunlogLogger().get_log流程性的用例&a…