【古月居《ros入门21讲》学习笔记】16_tf坐标系广播与监听的编程实现

目录

说明:

1. 实现过程(C++)

创建功能包(C++)

创建tf广播器代码(C++)

创建tf监听器代码(C++)

配置tf监听器与广播器代码编译规则

编译并运行

编译

运行

2. 实现过程(Python)

创建tf广播器代码(Python)

创建tf监听器代码(Python)

运行效果


说明:

1. 本系列学习笔记基于B站:古月居《ROS入门21讲》课程,且使用的Ubuntu与ROS系统版本与课程完全一致;

虚拟机版本Linux系统版本ROS系统版本
VMware WorkStation Pro 16Ubuntu18.04Melodic

2. 课程中的所有示例代码均已跑通,且对Pyhon版本的代码也都做了运行验证,并附带验证过程(错误均已修正);

3. 本节是整个笔记的第16节,对应视频课程的第18节,请自行对应学习;

4. 整个系列笔记基本已经完结,但部分章节仍需润色修改 ,后面会陆续发布,请大家持续关注,      创作不易,感谢支持!


1. 实现过程(C++)

创建功能包(C++)

cd ~/catkin_ws/src
catkin_create_pkg learning_tf roscpp rospy tfturtlesim

image-20230606160521970

创建tf广播器代码(C++)

cd ~/catkin_ws/src/learning_tf/src
touch turtle_tf_broadcaster.cpp

  • 定义tf广播器(TransformBroadcaster);

  • 创建坐标变换值;

  • 发布坐标变换(sendTransform)

/*** 该例程产生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;
};
​

image-20230606161054441

创建tf监听器代码(C++)

cd ~/catkin_ws/src/learning_tf/src
touch turtle_tf_listener.cpp

  • 定义tf监听器(TransformListener);

  • 查找坐标变换(waitForTransform、lookupTransform)

/*** 该例程监听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;
​// 请求产生turtle2ros::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;
};

image-20230606162405983

配置tf监听器与广播器代码编译规则

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

image-20230606165523395

编译并运行

编译
cd ~/catkin_ws
catkin_make
source devel/setup.bash(如已配置 **.bashrc**文件,则此步不需要,配置方法在publisher的章节里)

image-20230606173417459

运行
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

上面完成后,会有一只海龟在中心点,另一只海龟在左下方,并且左下方的海龟会跑向中间的那只海龟

image-20230607105934024

打开键盘控制节点,通过键盘控制中心点那只海龟,另只海龟也会自动的跟随前面的那只海龟同步去运动

rosrun turtlesim turtle_teleop_key

image-20230607110507433

2. 实现过程(Python)

创建tf广播器代码(Python)

cd ~/catkin_ws/src/learning_tf
mkdir scripts
cd scripts
touch turtle_tf_broadcaster.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
​
import roslib
roslib.load_manifest('learning_tf')
import rospy
​
import tf
import turtlesim.msg
​
def handle_turtle_pose(msg, turtlename):br = tf.TransformBroadcaster()br.sendTransform((msg.x, msg.y, 0),tf.transformations.quaternion_from_euler(0, 0, msg.theta),rospy.Time.now(),turtlename,"world")
​
if __name__ == '__main__':rospy.init_node('turtle_tf_broadcaster')turtlename = rospy.get_param('~turtle')rospy.Subscriber('/%s/pose' % turtlename,turtlesim.msg.Pose,handle_turtle_pose,turtlename)rospy.spin()
​
​

image-20230607111815061

创建tf监听器代码(Python)

cd ~/catkin_ws/src/learning_tf/scripts
touch turtle_tf_listener.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
​
import roslib
roslib.load_manifest('learning_tf')
import rospy
import math
import tf
import geometry_msgs.msg
import turtlesim.srv
​
if __name__ == '__main__':rospy.init_node('turtle_tf_listener')
​listener = tf.TransformListener()
​rospy.wait_for_service('spawn')spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)spawner(4, 2, 0, 'turtle2')
​turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
​rate = rospy.Rate(10.0)while not rospy.is_shutdown():try:(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):continue
​angular = 4 * math.atan2(trans[1], trans[0])linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)cmd = geometry_msgs.msg.Twist()cmd.linear.x = linearcmd.angular.z = angularturtle_vel.publish(cmd)
​rate.sleep()
​
​

image-20230607112048252

注意:给turtle_tf_broadcaster.py 和 turtle_tf_listener.py文件赋予作为程序文件执行的权限,

点击turtle_tf_broadcaster.py文件,右键,属性,权限,勾选(允许作为程序文件执行),

turtle_tf_listener.py文件操作同上,在ROS-Melodic版本中,python文件不需要编译,直接运行即可。

image-20230607112635115

运行效果

roscore
rosrun turtlesim turtlesim_node
​
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
​
rosrun turtlesim turtle_teleop_key

image-20230607113817681

image-20230607113919029


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

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

相关文章

基于STC12C5A60S2系列1T 8051单片机的IIC总线器件24C02记录单片机上电次数应用

基于STC12C5A60S2系列1T 8051单片机的IIC总线器件24C02记录单片机上电次数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介…

微信小程序生成二维码并保存到本地方法

微信小程序生成二维码请保存到本地方法 官方weapp-qrcode插件 github链接 功能完成样子 wxml <view class"qrcode"><canvas style"width: 275px; height: 275px;" canvas-idmyQrcode></canvas> </view> <view class" …

使用Python类型提示保持代码整洁,提高可读性

大家好&#xff0c;虽然Python具有高可读性和简洁性的特点&#xff0c;但随着项目变得越来越大、越来越复杂&#xff0c;代码的维护可能变得困难。Python最近引入的类型提示功能可以解决这些问题。 类型提示是一种为Python添加可选静态类型的方式&#xff0c;类型提示首先在PE…

day66

今日回顾内容 web框架 django 路由控制 视图层 web框架 一、什么是web框架 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式&#xff0c;也为web行…

resty-http库爬虫程序代码示例

lua -- 导入需要的库 local http require "resty.http" local io require "io" -- 创建一个客户端 local client http.new() -- 设置HTTP客户端的 client:set_proxy(proxy_host, proxy_port) -- 执行HTTP GET请求&#xff0c;获取网页内容 local res…

力扣105. 从前序与中序遍历序列构造二叉树

栈 思路&#xff1a; 先序遍历&#xff1a;根、左子树、右子树&#xff1b;中序遍历&#xff1a;左子树、根、右子树&#xff1b;遍历先序遍历数组 prev&#xff0c;使用一个辅助栈缓存“根节点”&#xff1b;通过栈顶“根节点”与中序遍历数组 in 比较&#xff0c;确认是否到…

C语言数据结构之顺序表(上)

前言&#xff1a; ⭐️此篇博文主要分享博主在学习C语言的数据结构之顺序表的知识点时写的笔记&#xff0c;若有错误&#xff0c;还请佬指出&#xff0c;一定感谢&#xff01;制作不易&#xff0c;若觉得内容不错可以点赞&#x1f44d;收藏❤️&#xff0c;这是对博主最大的认可…

source: command not found错误的解决方法

偶遇的一个问题&#xff0c;因为在网上没有找到对应的解决办法&#xff0c;可能是属于个案&#xff0c;在此记录备忘&#xff0c;同时供大家参考。 问题现象&#xff1a; 执行命令 source /etc/profile时报错&#xff1a; bash: “source: command not found... 问题定位和…

内衣洗衣机和手洗哪个干净?小型洗衣机质量排名

这两年内衣洗衣机可以称得上较火的小电器&#xff0c;小小的身躯却有大大的能力&#xff0c;一键可以同时启动洗、漂、脱三种全自动为一体化功能&#xff0c;在多功能和性能的提升上&#xff0c;还可以解放我们双手的同时将衣物给清洗干净&#xff0c;让越来越多小伙伴选择一款…

如何恢复已删除的照片 ?适用于 Windows 的Android 数据恢复软件值得尝试

“我丢失了 Android 手机上的照片&#xff0c;有人告诉我使用恢复程序来找回所有手机数据。我使用的是 Windows 10 和华为 手机&#xff0c;对于 Windows最有效的 Android 数据恢复是什么&#xff1f;” Android 恢复程序用于检索丢失或删除的文件&#xff0c;如照片、联系人、…

算法----确定两个字符串是否接近

题目 如果可以使用以下操作从一个字符串得到另一个字符串&#xff0c;则认为两个字符串 接近 &#xff1a; 操作 1&#xff1a;交换任意两个 现有 字符。 例如&#xff0c;abcde -> aecdb 操作 2&#xff1a;将一个 现有 字符的每次出现转换为另一个 现有 字符&#xff0c…

SimpleCG小游戏开发系列(1)--扫雷

一、前言 前面我们学习了SimpleCG的游戏开发框架,从本篇开始,我们用一系列小游戏的开发来加深对框架的了解.我们先以windows的经典游戏--扫雷,作为首个例子。游戏预览如下 二、框架搭建 因为游戏程序的大体框架差不多&#xff0c;所以我们可以搭建一个通用的主程序。如下所示&a…

导致Facebook广告投放不成功的原因

Facebook是全球最大的社交媒体平台之一&#xff0c;也是众多跨境卖家选择广告投放的首选平台&#xff0c;但也还是会有很多跨境卖家在Facebook上推广效果不佳。那么本文小编讲一下导致Facebook广告投放不成功的原因以及相应解决方法。 1、受众群体太少 Facebook有个要求就是广告…

Java之顺序栈实现数制转换问题

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道中等编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我写完成功&#xff0c;会…

数字人担任展会虚拟主持人,如何释放大会新活力?

近日&#xff0c;虚拟主持人谷小雨解锁新身份&#xff0c;作为第二届全球数字贸易博览会的“数字新闻官”为大众播报展会的热门新闻话题&#xff0c;带领大众探索未来数字贸易的无限可能。 *图片源于网络 随着元宇宙的概念更多地深入各领域&#xff0c;数字人多次以虚拟主持人或…

iframe内存泄露问题

场景 左边导航栏&#xff0c;顶部tab标签&#xff0c;下面的iframe是点击导航菜单生成的&#xff0c;顶部的tab标签对应每一个打开的菜单名称&#xff0c;可以点击关闭 问题 内存泄漏 解决 const delIframeDom document.getElementById(menuId);if (delIframeDom) {delI…

apache-poi

excel类型 excel分为03版本和07版本 03版本 new HSSFWorkbook(); 优点&#xff1a;速度快 缺点&#xff1a;只能写入65536行数据 文件类型&#xff1a;.xls07版本 new XSSFWorkbook(); 优点&#xff1a;不限制写入数量 缺点&#xff1a;容易造成内存溢出(OOM)&#xff0c;速度…

程序员如何兼职?

首先&#xff0c;写博客和制作短视频是一个好方法。想象一下&#xff0c;你是一个资深的程序员&#xff0c;而你的博客就像是一个个人课堂&#xff0c;帮助那些初入编程领域的人理解各种编程概念和技巧。你可以分享你的工作经验、解决问题的过程&#xff0c;甚至可以分享一些有…

MySQL双主双从数据库集群搭建

1 引言 在之前的文章中提到过相关搭建方法&#xff0c;具体请参考《MySQL主从数据库搭建》这篇文章&#xff0c;本文主要讲述双主双从&#xff0c;双主多从集群的搭建方式。 这里要问一个问题&#xff0c;为什么MySQL要搭建数据库集群呢&#xff1f;我想应该有以下几点原因&…

面试题:Spring 中获取 Bean 的方式有哪些?

文章目录 前言1、在初始化时保存ApplicationContext对象2、通过Spring提供的工具类获取ApplicationContext对象3、实现接口ApplicationContextAware&#xff08;推荐&#xff09;4、继承自抽象类ApplicationObjectSupport5、继承自抽象类WebApplicationObjectSupport6、使用Bea…