ROS中的tf(transform)的理解 ,你追我小乌龟的深入剖析

2023-05-16

对于ros中的tf其实一直理解不是很深,最近工作上一直在用,就很懵逼,出来混果然是要还的~于是这两天把ros官方提供的小乌龟版的你追我,如果你追到我,我就让你xxx,一个一个命令跑了一下,现在有了一个较深的理解,如果哪里说的不对,还请指正。

首先看launch文件内容

 <launch>
    <!-- 海龟仿真器 -->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>

    <!-- 键盘控制 -->
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>

    <!-- 两只海龟的tf广播 -->
    <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" />

    <!-- 监听tf广播,并且控制turtle2移动 -->
    <node pkg="learning_tf" type="turtle_tf_listener"
          name="listener" />

 </launch>

分析一下,首先启动了turtlesim的节点,然后是键盘控制,这里有一点需要注意一下,至少我是一直没搞得很清楚

<node pkg="turtlesim" type="turtlesim_node" name="sim"/>

转化为命令行即为:

rosrun turtlesim turtlesim_node __name:=sim

最后那个 __name:=sim 即给节点起名为sim,如果不改名的话,就是你代码里起的名字了,但是需要注意的是因为在例程中因为要启动 /turtle1/turtle2,如果不起名的话,第二只就把第一只干掉了,所以起名还是很重要的~

然后就是启动两只乌龟的learning_tf_broadcaster,注意这里启动完之后,就会有第一只和第二只和世界坐标系之间的关系,当然我们也可以定义第三只第四只乌龟。启动三只乌龟后的tf图如下所示:

在这里插入图片描述
这时候,其实,三只乌龟以及世界坐标系的关系就都可以相互转换了,比如第二只要去追第一只,得到第二只相对第一只的transform就可以求啦~同理,第三只追第二只,第三只追第一只,以及第n只追第k只都可以定义啦~

            listener.waitForTransform("/turtle3", "/turtle2", ros::Time(0), ros::Duration(3.0));
            listener.lookupTransform("/turtle3", "/turtle2", ros::Time(0), transform3);
	   		listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
            listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform2);

然后分别发布到 “turtle2/cmd_vel” “turtle3/cmd_vel” 再加上键盘发布 “turtle1/cmd_vel” 的消息,于是三只乌龟就开始了愉快的,你追我的小游戏。乌龟的世界太疯狂,而且追上了还在上面扭来扭去的,咳咳咳…

在这里插入图片描述

对了,记得也要调用服务生成乌龟3,原来代码里只生成了乌龟2。

补充一些关于广播tf和接收tf的内容

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

    // 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
    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);

    // 发布坐标变换
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}

对于广播tf的话,回调函数传入的是turtle1/pose,会发现只调用了一次这个回调函数,也即为了初始化。

    tf::Transform transform;
    transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );

首先setOrigin为turtle1当前的x,y坐标,也即把自己当前的坐标认为自己在全局坐标系下的坐标,以此来确定父坐标系的原点。同理,设定父坐标系的方向,自己当前的方向认为是自己相对于父坐标系的方向。然后发布出去。

对于接收者,只需要

listener.waitForTransform("/turtle3", "/turtle2", ros::Time(0), ros::Duration(3.0));
listener.lookupTransform("/turtle3", "/turtle2", ros::Time(0), transform3);

就可以得到转换以后的关系啦~

突然奇想,如果两个乌龟定义的世界坐标系不一样会怎么样呢,于是改了改试了一下~

transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );

所有的乌龟setOrigin都是这么设置的,那么如果第二个乌龟的世界坐标系改一下呢,于是改成了

transform.setOrigin( tf::Vector3(msg->x + 1, msg->y + 1, 0.0) );

即第二个乌龟的世界原点是(1,1),不是(0,0),也即第二个乌龟应该都会滞后第一个乌龟(1,1),第一个乌龟在(5,5)的话,在第二个乌龟看来,就是在(4,4),跑一下看看效果~

在这里插入图片描述
果然是这样子的~

然后官网上有一个添加一个carrot框架到现有的坐标系下的例子,代码是酱紫的~

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

int main(int argc, char** argv){
  ros::init(argc, argv, "my_tf_broadcaster");
  ros::NodeHandle node;

  tf::TransformBroadcaster br;
  tf::Transform transform;

  ros::Rate rate(10.0);
  while (node.ok()){
    transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) );
    transform.setRotation( tf::Quaternion(0, 0, 0, 1) );
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "turtle1", "carrot1"));
    rate.sleep();
  }
  return 0;
};

跟broadcaster很像是不是,这里的话,尤其要注意一下

    transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) );
    transform.setRotation( tf::Quaternion(0, 0, 0, 1) );

相当于设置turtle1这个动坐标系认为是父坐标系,然后以父坐标系向右偏移两个单位为carrot坐标系的原点,然后carrot坐标系就要以这个动坐标系为基准。所以listen里面把

  listener.lookupTransform("/turtle2", "/carrot1", ros::Time(0), transform);

此时小乌龟实际上就会以一个2的偏移开始运动~

还有个小疑问,关于ros::Time::now() 和 ros::Time(0),晚点把时间这块琢磨一下,一起补充。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS中的tf(transform)的理解 ,你追我小乌龟的深入剖析 的相关文章

随机推荐

  • python实现smote处理正负样本失衡问题

    机器学习中难免遇到正负样本不平衡问题 xff0c 处理办法通常有梁总 xff0c 一 xff1a 过采样 xff0c 增加正样本数据 xff1b 二 xff1a 欠采样 xff0c 减少负样本数据 xff0c 缺点是会丢失一些重要信息 sm
  • echarts 饼图hover效果,饼图中间显示自定义信息

    option 61 tooltip show true trigger 39 item 39 position 39 35 39 39 32 39 backgroundColor 39 implements 39 textStyle col
  • MATLAB在线工具

    在线Matlab工具 xff0c 不用安装matlab了 xff0c 里面的语法几乎和matlab相同 matlab网页版 xff1a 1 octave online http octave online net 2 matlab onli
  • Apache IoTDB下载与安装

    1 中文官方文档 xff1a https iotdb apache org zh 2 下载地址 xff1a https iotdb apache org zh Download 发行版本踩了个小坑 xff1a 1 0 0版本启动时如果作为单
  • 【游戏开发】游戏开发书籍汇总

    1 游戏设计的艺术 2 游戏设计的100个原理 3 我在美国学游戏设计 4 游戏新手村 xff1a 从零开始做游戏 5 Directx游戏开发终极指南 6 Windows游戏编程大师技巧 7 快乐之道 xff1a 游戏设计的黄金法则 人类的
  • 【获奖公布】“我的2016”主题征文活动

    还记得2015的年末 xff0c 2016的新年伊始 xff0c 你给自己定下的目标 xff0c 对自己许下的诺言么 xff1f 时光荏苒 xff0c 一年又在指缝间溜走了 xff0c 离2016的结束还剩十多天 xff0c 在接下来的这十
  • Dockerfile介绍与指令解析

    一 Dockerfile介绍 镜像是容器的基础 xff0c 每次执行docker run的时候都会指定哪个镜像作为容器运行的基础 我们之前的例子都是使用来自docker hub的镜像 xff0c 直接使用这些镜像只能满足一定的需求 xff0
  • Kubernetes快速上手指南,让你所见即所得

    版权声明 xff1a 本文为 ABC实验室 原创文章 xff0c 版权所有 xff0c 侵权必究 xff01 编者语 Kubernetes作为新一代云计算平台 xff0c 自2014年开源以来得到快速发展 xff08 2016年 xff09
  • 使用github管理科研文献

    使用github管理科研文献 一 准备工作 xff1a 二 建立远程科研文献库三 远程科研文献数据库的维护四 其他PC客户端的访问 每个科研工作者都需要建立自己的科研文献库 以楼主本人为例 xff0c 我通常在实验室的台式机上完成科研文献的
  • RBF神经网络逼近在线自适应控制(MATLAB实现之S函数模块分析)

    上次用了参考模型的方法用RBF神经网络试了一下放到自适应控制模型上 xff0c 其实跟踪效果还可以 xff0c 放大了有点不舒服就是了 xff0c 差了一点点 xff0c 然后看了看书的第四章 xff0c 知道采用梯度下降法调整神经网络权值
  • 基于RBF神经网络的Flexible Robot自适应控制(论文笔记)

    上一篇笔记 https blog csdn net qq 24182661 记录的是第一篇论文2015 Continuum Robots for Medical Applications A survey的论文笔记 xff0c 主要做的笔记
  • Golang 解析xml文件标签带冒号( : )解决方案

    背景 xff1a 我们有项目需要使用golang语言解析rabbitmq xml 并把里面的内容解析出来 xff0c 但是在解析的时候遇到了问题 xff0c 最后通过google搜索 xff0c 在stackoverflow上找到了解决方案
  • 【Python】Python中 在函数内部对函数外的变量进行操作

    在Python中 xff0c 如果想函数内部对函数外的变量进行操作 xff0c 有一些问题 xff08 一些在Java xff0c C中再正常不过的操作这里就不行 xff09 正常情况下 xff0c 在函数外定义的变量是可以直接在函数体内部
  • 关于proteus中串口发送数据与实际不符的问题(如发00h,收80h)

    工程实训要用到串口 xff0c 51单片机 xff0c 串口工作方式一 xff0c 只发不接受 在proteus中用VIRTUAL TERMINAL xff08 虚拟终端 xff09 监视串口发送数据 现象 xff1a 不论是用虚拟终端还是
  • Jetson TX2的各种坑.md

    最近在使用Jetson TX2 在跑实验 xff0c 然后遇到下面问题 xff0c 做笔记 xff0c 记录一下 内存出错无法 xff0c 中断 出现下面那种错误 2019 01 11 19 41 46 959970 E tensorflo
  • 基于STM32的FreeRTOS开发(1)----FreeRTOS简介

    为什么使用freertos FreeRTOS 是一个免费和开源的实时操作系统 xff0c 它主要用于嵌入式系统 它非常轻量级 xff0c 可以在很小的硬件资源上运行 xff0c 因此非常适合在限制硬件资源的嵌入式系统中使用 FreeRTOS
  • 获奖公布 | 征文——从高考到程序员

    每年的这几天 xff0c 空气中总会弥漫着紧张的味道 xff0c 2017 全国统一高考如期而至 朋友圈里的各种高考热文如流水般 xff0c 不停歇地出现在眼前 xff0c 难免会勾起自己曾经的青涩时光 还记得 xff0c 考试前 xff0
  • STM32驱动ESP8266连接阿里云(2)----接入阿里IoT Studio实现Web可视化

    烧录MQTT固件 概述 阿里IoT Studio是一个物联网开发平台 xff0c 可用于快速构建基于云端的物联网应用 它提供了丰富的物联网组件和工具 xff0c 使得开发者可以轻松地进行设备接入 数据存储 数据分析等操作 要实现Web可视化
  • ‘gbk‘ codec can‘t encode character解决方法

    一 问题 xff1a 在将网络数据流导入文件时 xff0c 有可能遇到 39 gbk 39 codec can 39 t encode characte 错误 二 分析 xff1a 1 在windows下面 xff0c 新文件 xff08
  • ROS中的tf(transform)的理解 ,你追我小乌龟的深入剖析

    对于ros中的tf其实一直理解不是很深 xff0c 最近工作上一直在用 xff0c 就很懵逼 xff0c 出来混果然是要还的 xff5e 于是这两天把ros官方提供的小乌龟版的你追我 xff0c 如果你追到我 xff0c 我就让你xxx x