【自动驾驶】ROS中的TF坐标变换(一):静态坐标变换

目录

  • 引子
    • ros中的右手坐标系
    • 补充:
      • 欧拉角及四元数理解
      • 旋转
      • 平移操作
      • 复合操作
    • 运行坐标变换的例子
    • 坐标转换
  • 静态坐标变换-发布坐标系信息
    • 创建功能包
  • 静态坐标变换-订阅坐标系信息
    • 添加cpp订阅者主文件
    • 修改cmakelist
    • 文件编译报错的解决方案
    • 运行程序进行测试

引子

机器人系统上,有多个传感器,如激光雷达、摄像头等,有的传感器是可以感知机器人周边的物体方位(或者称之为:坐标,横向、纵向、高度的距离信息)的,以协助机器人定位障碍物,可以直接将物体相对该传感器的方位信息,等价于物体相对于机器人系统或机器人其它组件的方位信息吗?显示是不行的,这中间需要一个转换过程。

ros中的右手坐标系

tf:TransForm Frame,坐标变换
在这里插入图片描述
坐标系:ROS 中是通过坐标系统开标定物体的,确切的将是通过右手坐标系来标定的。

补充:

欧拉角及四元数理解

欧拉角:
对于在三维空间里的一个参考系,任何坐标系的取向,都可以用三个欧拉角来表现。参考系又称为实验室参考系,是静止不动的。而坐标系则固定于刚体,随着刚体的旋转而旋转。
在这里插入图片描述
在这里插入图片描述

在空间中会有n+1个坐标系,其中只有一个坐标系起到标定作用,也就是说“其他n个坐标系全都是基于该坐标系找到自己在空间中的位置的”。只有大家都知道了自己在空间中的具体位置,坐标转换才可以顺利进行下去。

在描述机器人运动时,我们常常提及“位姿”,其实位姿是一个合成词,我们可以将其拆解为“位置+姿态”。位置就是指“机器人某个运动关节/测量传感器在世界坐标系中的具体位置,姿态就是”基于该点的坐标系相较于世界坐标系所进行的旋转“。
四元数就比较复杂了,可以参考:
解析四元数
四元数的应用
四元数。就是通过四元数连乘的形式表达机器人末端相对于基坐标系的关系,或者先有关系,再通过求逆的运算求解每个关节应页的位置关系。四元数只能表示旋转,不能表示平移。

旋转

坐标变换,当没有平移,只有旋转操作时,可以理解为一个向量在原坐标系中的投影,又在另一个坐标系中的投影:
其中:

在这里插入图片描述
是坐标变换的旋转矩阵,将向量P在原B坐标系变换至A坐标系中。其组成是【X Y Z】即单位化的B坐标系的轴在A坐标系中的投影。
在这里插入图片描述

平移操作

在这里插入图片描述

复合操作

在这里插入图片描述

运行坐标变换的例子

roslaunch turtle_tf2 turtle_tf2_demo_cpp.launch

启动乌龟跟随例子窗口。

坐标转换

ros中封装了现成的坐标变换模块。
在坐标转换实现中常用的 msg:

(1)geometry_msgs/TransformStamped:
用于传输坐标系相对位置信息

  std_msgs/Header header                     #头信息uint32 seq                                #|-- 序列号time stamp                                #|-- 时间戳string frame_id                            #|-- 坐标 ID
string child_frame_id                    #子坐标系的 id
geometry_msgs/Transform transform        #坐标信息geometry_msgs/Vector3 translation        #偏移量float64 x                                #|-- X 方向的偏移量float64 y                                #|-- Y 方向的偏移量float64 z                                #|-- Z 方向上的偏移量geometry_msgs/Quaternion rotation        #四元数float64 x                                float64 y                                float64 z                                float64 w

translation指child_frame_id 相对于frame_id 的变化

(2)geometry_msgs/PointStamped
用于传输某个坐标系内坐标点的信息

std_msgs/Header header                    #头uint32 seq                                #|-- 序号time stamp                                #|-- 时间戳string frame_id                            #|-- 所属坐标系的 id
geometry_msgs/Point point                #点坐标float64 x                                    #|-- x y z 坐标float64 yfloat64 z

x,y,z是坐标点的具体坐标值。
具体结构都可以用rosmsg info查看

静态坐标变换-发布坐标系信息

静态坐标变换
所谓静态坐标变换,是指两个坐标系之间的相对位置是固定的。
坐标系相对关系,可以通过发布方发布
订阅方,订阅到发布的坐标系相对关系,再传入坐标点信息(可以写死),然后借助于 tf 实现坐标变换,并将结果输出。
场景:
现有一机器人模型,核心构成包含主体与雷达,各对应一坐标系,坐标系的原点分别位于主体与雷达的物理中心,已知雷达原点相对于主体原点位移关系如下: x 0.2 y0.0 z0.5。当前雷达检测到一障碍物,在雷达坐标系中障碍物的坐标为 (2.0 3.0 5.0),请问,该障碍物相对于主体的坐标是多少?

创建功能包

 catkin_create_pkg tfdemo_publisher std_msgs rospy roscpp tf2 tf2_ros tf2_geometry_msgs geometry_msgs

除了基本依赖以外,新增了若干坐标系相关的依赖。
编写c++文件

// 1.包含头文件
// 2.设置编码,节点初始化
//主要是发布两个坐标系间的相对关系
#include "ros/ros.h"
#include "tf2_ros/static_transform_broadcaster.h"
#include "geometry_msgs/TransformStamped.h"
//引入四元数包
#include "tf2/LinearMath/Quaternion.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,"");// 2.初始化 ROS 节点ros::init(argc,argv,"static_brocast");// 3.创建静态坐标转换广播器,专用于发布静态坐标tf2_ros::StaticTransformBroadcaster broadcaster;// 4.创建坐标系信息geometry_msgs::TransformStamped ts;//----设置头信息ts.header.seq = 100;ts.header.stamp = ros::Time::now();ts.header.frame_id = "base_link";//相对坐标系关系中被参考的那一个//----设置子级坐标系ts.child_frame_id = "laser";//就是另一个坐标系,子集//----设置子级相对于父级的偏移量ts.transform.translation.x = 0.2;ts.transform.translation.y = 0.0;ts.transform.translation.z = 0.5;//----设置四元数:将 欧拉角数据转换成四元数tf2::Quaternion qtn;//使用该对象设置欧拉角,然后调用函数将欧拉角转换为四元数,这里欧拉角刚好都是0,这里的单位都是弧度qtn.setRPY(0,0,0);ts.transform.rotation.x = qtn.getX();ts.transform.rotation.y = qtn.getY();ts.transform.rotation.z = qtn.getZ();ts.transform.rotation.w = qtn.getW();// 5.广播器发布坐标系信息broadcaster.sendTransform(ts);//静态的发布一次即可,当ROS节点调用ros::spin()时,它会一直等待直到有消息到达该节点。当节点接收到消息时,//它将调用与该消息相关联的回调函数进行处理。这使得ROS节点能够响应其他节点的请求,同时保持事件循环处于活动状态。//也就是维持一个事件循环ros::spin();return 0;
}

还有cmakelist文件:

add_executable(${PROJECT_NAME}_node src/demo01.cpp)
target_link_libraries(${PROJECT_NAME}_node${catkin_LIBRARIES}
)

编译并运行工程:

source /root/work/ws/devel/setup.bash
roscore
rosrun tfdemo_publisher tfdemo_publisher_node

如果roscore提示已启动,可使用killall -9 rosmaster杀掉重启。
查询当前话题:

rostopic list

得到:

/rosout
/rosout_agg
/tf_static

查看:

rostopic echo  /tf_static

得到:

transforms: - header: seq: 100stamp: secs: 1723624279nsecs: 917443332frame_id: "base_link"child_frame_id: "laser"transform: translation: x: 0.2y: 0.0z: 0.5rotation: x: 0.0y: 0.0z: 0.0w: 1.0
---

或者在rviz里也可以查看。

静态坐标变换-订阅坐标系信息

订阅demo01内的坐标系相对关系,传入坐标点,再进行转换。

添加cpp订阅者主文件

为了简便,该订阅者cpp文件与发布者在同一个包的同一个src下,在这里插入图片描述


//1.包含头文件
#include "ros/ros.h"
#include "tf2_ros/transform_listener.h"
#include "tf2_ros/buffer.h"
#include "geometry_msgs/PointStamped.h"
#include "tf2_geometry_msgs/tf2_geometry_msgs.h" //注意: 调用 transform 必须包含该头文件int main(int argc, char *argv[])
{setlocale(LC_ALL,"");// 2.初始化 ROS 节点ros::init(argc,argv,"tf_sub");ros::NodeHandle nh;// 3.创建 TF 订阅节点,listener订阅数据,并缓存至Buffer当中tf2_ros::Buffer buffer;tf2_ros::TransformListener listener(buffer);ros::Rate r(1);while (ros::ok()){// 4.生成一个坐标点(相对于子级坐标系)geometry_msgs::PointStamped point_laser;point_laser.header.frame_id = "laser";point_laser.header.stamp = ros::Time::now();point_laser.point.x = 1;point_laser.point.y = 2;point_laser.point.z = 7.3;// 5.转换坐标点(相对于父级坐标系)//新建一个坐标点,用于接收转换结果  //--------------使用 try 语句或休眠,否则可能由于缓存接收延迟而导致坐标转换失败------------------------try{geometry_msgs::PointStamped point_base;point_base = buffer.transform(point_laser,"base_link");ROS_INFO("转换后的数据:(%.2f,%.2f,%.2f),参考的坐标系是:",point_base.point.x,point_base.point.y,point_base.point.z,point_base.header.frame_id.c_str());}catch(const std::exception& e){// std::cerr << e.what() << '\n';ROS_INFO("程序异常.....");}r.sleep();  ros::spinOnce();}return 0;
}

修改cmakelist

新增节点2即可:

add_executable(${PROJECT_NAME}_node src/demo01.cpp)
add_executable(${PROJECT_NAME}_node2 src/demo02.cpp)target_link_libraries(${PROJECT_NAME}_node${catkin_LIBRARIES}
)
target_link_libraries(${PROJECT_NAME}_node2${catkin_LIBRARIES}
)

文件编译报错的解决方案

如果碰到:./boost/thread/pthread/thread_data.hpp:60:5: error: missing binary operator before token “(“报错
在这里插入图片描述
即可编译通过。

运行程序进行测试

source /root/work/ws/devel/setup.bash
roscore
rosrun tfdemo_publisher tfdemo_publisher_node
rosrun tfdemo_publisher tfdemo_publisher_node2

在这里插入图片描述

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

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

相关文章

【MySQL数据库】单机、集群、分布式的区别

单机、集群和分布式是计算机系统中三种不同的架构模型,它们在资源管理、任务执行和性能优化方面有显著区别。 图片来源 1. 单机(Standalone) 单机指的是单一计算机系统,即所有的计算任务和数据都在一台计算机上处理。单机系统的特点包括: 硬件限制:受限于单台机器的计…

Visual Studio 2022 无法打开源文件atlimage.h

最近在搞tcp socket 通信demo&#xff0c;网上抄了一下源码&#xff08;代码参考&#xff1a;C中的Socket编程使用协议发送图片_快速传输 照片 c-CSDN博客&#xff09;&#xff0c;还没开始编译就提示 无法打开源文件atlimage.h&#xff0c;全局搜了一下没有这个文件&#xff0…

JSON Web Token (JWT): 理解与应用

JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间以JSON对象的形式安全地传输信息。JWT通常用于身份验证和授权目的&#xff0c;因为它可以使用JSON对象在各方…

Unity开发抖音小游戏广告部分接入

Unity开发抖音小游戏广告部分接入 介绍环境确保开通流量主获取广告位广告部分代码测试如下总结 介绍 最近在使用Unity做抖音小游戏这块的内容&#xff0c;因为要接入广告&#xff0c;所以这里我把我接入广告的部分代码和经验分享一下。 环境确保 根据抖音官方的文档我们是先…

Linux网络编程—socket、bind

一、socket创建套接字 socket是用来创建网络通信或本地通信的套接字&#xff0c;跟文件有关&#xff1a;告诉系统&#xff0c;PCB&#xff08;进程控制块&#xff09;控制的数据应该向哪个套接字写入、或读取&#xff1b;这个套接字是在TCP/IP协议下运行的 #include <sys/t…

选择排序(附动图)

1.思路 基本思想&#xff1a; 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完 。 1.1双向选择排序&#xff08;升序&#xff09; 头尾指针&#xff08;索引&#xf…

初识C++

一、C的由来 C的起源可以追溯到1979年&#xff0c;当时Bjarne Stroustrup(本贾尼斯特劳斯特卢普&#xff0c;这个翻译的名字不同的地方可能有差异)在贝尔实验室从事计算机科学和软件工程的研究工作。面对项目中复杂的软件开发任务&#xff0c;特别是模拟和操作系统的开发⼯作&…

涉案财物管理系统DW-S405|实现人员随身物品智能化管理

涉案财物管理系统DW-S405系统基于物联网技术规范涉案财物管理流程&#xff0c;确保涉案财物的安全性、完整性和合法性&#xff1b;可以提高办案效率&#xff0c;减少办案成本&#xff0c;实现资源共享。 财物管理 管理员可通过个人账号和指纹验证两种登录方式进入财物管理系统…

1. 数据结构——顺序表的主要操作

1. 内容 顺序表的初始化、插入、删除、按值查找、输出以及其时间复杂度的计算。 2.代码 #include<stdio.h> #include<stdlib.h> //函数结果状态代码 #define OK 1 #define OVERFLOW -2 #define ERROR 0 #define MAXSIZE 100typedef int ElemType; //顺序表每个…

使用Nexus搭建Maven私服仓库

一、私服仓库简介 在Java的世界中&#xff0c;我们通常使用Maven的依赖体系来管理构件&#xff08;artifact&#xff0c;又称为二方库或三方库&#xff09;的依赖&#xff0c;Maven仓库用于存储这些构件。一般的远程仓库&#xff08;比如Maven Central&#xff09;只提供下载功…

OpenCV Python 图像处理入门

OpenCV入门 OpenCV&#xff1a;轻量、高效、开源。最广泛使用的计算机视觉工具。 下面涉及图片的读取&#xff0c;RGB彩色通道&#xff0c;区域裁剪&#xff0c;绘制图形和文字&#xff0c;均值滤波&#xff0c;特征提取&#xff0c;模板匹配&#xff0c;梯度算法&#xff0c…

获奖方案|趋动科技:资源池化释放AI算力价值

“据统计&#xff0c;GPU的平均利用率不超过30%&#xff0c;会产生巨大的算力资源浪费。我们用软件定义的方式通常可以把用户GPU的利用率提升3-8倍&#xff0c;甚至可以到10倍。” 这是算力池化软件公司趋动科技援引行业报告数据并结合自身企业最佳实践经验给出的最新数据。通…

在 SOCKS 和 HTTP 代理之间如何选择?

在 SOCKS 和 HTTP 代理之间进行选择需要彻底了解每种代理的工作原理以及它们传达的配置。只有这样&#xff0c;您才能轻松地在不同类型的代理之间进行选择。 本文概述了 HTTP 和 SOCKS 代理是什么、它们如何运作以及它们各自带来的好处。此外&#xff0c;我们将比较这两种代理类…

Java算法解析一:二分算法及其衍生出来的问题

这个算法的前提是&#xff0c;数组是升序排列的 算法描述&#xff1a; i和j是指针可以表示查找范围 m为中间值 当目标值targat比m大时&#xff0c;设置查找范围在m右边&#xff1a;i m-1 当目标值targat比m小时&#xff0c;设置查找范围在m左边&#xff1a;j m1 当targat的…

数据结构第一天

数据结构基础知识 1.1 什么是数据结构 数据结构就是数据的逻辑结构以及存储操作 (类似数据的运算) 数据结构就教会你一件事&#xff1a;如何更有效的存储数据 1.2 数据 数据&#xff1a;不再是单纯的数字&#xff0c;而是类似于集合的概念。 数据元素&#xff1a;是数据的基本单…

使用 Python 进行 PDF 文件加密

使用 Python 解密加密的 PDF 文件-CSDN博客定义一个名为的函数&#xff0c;该函数接受三个参数&#xff1a;输入的加密 PDF 文件路径input_pdf、输出的解密 PDF 文件路径output_pdf和密码password。https://blog.csdn.net/qq_45519030/article/details/141256661 在数字化时代…

优先级队列的实现

什么是优先级队列 优先级队列是一种特殊的数据结构&#xff0c;它类似于队列或栈&#xff0c;但是每个元素都关联有一个优先级或权重。在优先级队列中&#xff0c;元素的出队顺序不是简单地按照它们进入队列的先后顺序&#xff08;先进先出&#xff0c;FIFO&#xff09;&#…

虚幻5|角色武器装备的数据库学习(不只是用来装备武器,甚至是角色切换也很可能用到)

虚幻5|在连招基础上&#xff0c;给角色添加武器并添加刀光|在攻击的时候添加武器并返回背后&#xff08;第一部分&#xff0c;下一部分讲刀光&#xff09;_unreal 如何给角色添加攻击-CSDN博客 目的&#xff1a;捡起各种不同的武器&#xff0c;捡起的武器跟装备的武器相匹配 …

练习:python条件语句、循环语句和函数的综合运用

需求描述&#xff1a; 期望输出效果&#xff1a; 练习成果&#xff1a; #简单的银行业务流程 many 50000 def main_menu():print("----------主菜单----------"f"\n{name}您好&#xff0c;欢迎来到ATM&#xff0c;请选择操作&#xff1a;""\n查询余…

挑战同档位最强护眼性能,书客L2 Pro革新护眼台灯全新体验!

2024年8月17日&#xff0c;SUKER书客在今日宣布&#xff1a;书客护眼台灯L2 PRO正式发售。书客作为专业护眼台灯实力老牌&#xff0c;主打“医学养护眼”的特性&#xff0c;是唯一做到降低96%近视风险的同时&#xff0c;缓解88%用眼疲劳&#xff0c;光源99.8%高度还原自然光&am…