ROS 2边学边练(33)-- 写一个静态广播(C++)

news2024/12/29 11:06:30

前言

        通过这一篇我们将了解并学习到如何广播静态坐标变换到tf2(由tf2来转换这些坐标系)。

        发布静态变换对于定义机器人底座与其传感器或非移动部件之间的关系非常有用。例如,在以激光扫描仪中心的坐标系中推理激光扫描测量数据是最简单的。

        这是一个独立的教程,涵盖了静态变换的基础知识,包含两个部分。在第一部分,我们将编写代码以将静态变换发布到tf2。在第二部分,我们将说明如何在tf2_ros中使用命令行工具static_transform_publisher

        后面的接着两篇博文中(下一篇可能会穿插一篇有关ROS世界坐标系的博文),我们将重新学习下上一篇博文(《初识tf2》)的一些知识,在后面的其他博文将会涉及到tf2的更多高级功能。

动动手

创建功能包

        我们在之前创建的某个工作空间(比如ros2_ws)或新建一个工作空间内创建一个learning_tf2_cpp包(工作空间的src路径下):

$ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies geometry_msgs rclcpp tf2 tf2_ros turtlesim -- learning_tf2_cpp

写个静态广播节点

        在learning_tf2_cpp/src下,执行如下命令下载官方为我们准备好的源文件:

$wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp

        下载下来的static_turtle_tf2_broadcaster.cpp内容如下:

#include <memory>

#include "geometry_msgs/msg/transform_stamped.hpp"
#include "rclcpp/rclcpp.hpp"
#include "tf2/LinearMath/Quaternion.h"
#include "tf2_ros/static_transform_broadcaster.h"

class StaticFramePublisher : public rclcpp::Node
{
public:
  explicit StaticFramePublisher(char * transformation[])
  : Node("static_turtle_tf2_broadcaster")
  {
    tf_static_broadcaster_ = std::make_shared<tf2_ros::StaticTransformBroadcaster>(this);

    // Publish static transforms once at startup
    this->make_transforms(transformation);
  }

private:
  void make_transforms(char * transformation[])
  {
    geometry_msgs::msg::TransformStamped t;

    t.header.stamp = this->get_clock()->now();
    t.header.frame_id = "world";
    t.child_frame_id = transformation[1];//命令行传入的第二个参数,第一个参数为可执行文件的名称

    t.transform.translation.x = atof(transformation[2]);
    t.transform.translation.y = atof(transformation[3]);
    t.transform.translation.z = atof(transformation[4]);
    tf2::Quaternion q;
    q.setRPY(
      atof(transformation[5]),
      atof(transformation[6]),
      atof(transformation[7]));
    t.transform.rotation.x = q.x();
    t.transform.rotation.y = q.y();
    t.transform.rotation.z = q.z();
    t.transform.rotation.w = q.w();

    tf_static_broadcaster_->sendTransform(t);
  }

  std::shared_ptr<tf2_ros::StaticTransformBroadcaster> tf_static_broadcaster_;
};

int main(int argc, char * argv[])
{
  auto logger = rclcpp::get_logger("logger");

  // Obtain parameters from command line arguments
  if (argc != 8) {
    RCLCPP_INFO(
      logger, "Invalid number of parameters\nusage: "
      "$ ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster "
      "child_frame_name x y z roll pitch yaw");
    return 1;
  }

  // As the parent frame of the transform is `world`, it is
  // necessary to check that the frame name passed is different
  if (strcmp(argv[1], "world") == 0) {
    RCLCPP_INFO(logger, "Your static turtle name cannot be 'world'");
    return 1;
  }

  // Pass parameters and initialize node
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<StaticFramePublisher>(argv));
  rclcpp::shutdown();
  return 0;
}
代码分析
#include "geometry_msgs/msg/transform_stamped.hpp"

        包含transform_stamped.hpp头文件是为了能访问TransformStamped消息类型,并将其发布到转换树当中去。

#include "rclcpp/rclcpp.hpp"

        包含rclcpp.hpp头文件,是为了使用rcl::Node类。

#include "tf2/LinearMath/Quaternion.h"
#include "tf2_ros/static_transform_broadcaster.h"

        包含Quaternion.h是为了利用四元数类中提供的方便转换欧拉角为四元数(或四元数转换为欧拉角)的功能,包含static_transform_broadcaster.h是为了使用TransformBroadcaster从而使得发布静态转换变得简单。

tf_static_broadcaster_ = std::make_shared<tf2_ros::StaticTransformBroadcaster>(this);

this->make_transforms(transformation);

        StaticFramePublisher类的构造函数中初始化名称为static_turtle_tf2_broadcaster的节点。然后,创建StaticTransformBroadcaster,它将在启动时发送一个静态转换。 

geometry_msgs::msg::TransformStamped t;

t.header.stamp = this->get_clock()->now();
t.header.frame_id = "world";
t.child_frame_id = transformation[1];

        在这里,我们创建一个TransformStamped对象,它将是我们在填充后发送的消息载体。在传递实际的转换值之前,我们需要为其提供适当的元数据初始化一下。 

  1.         t.header.stamp,这个好理解,将当前时间作为时间戳填充上;
  2.         t.hear.frame_id,我们创建连接(link)的父坐标系名称,我们取名“world”;
  3.         t.child_frame_id, 我们创建连接(link)的子坐标系名称;
t.transform.translation.x = atof(transformation[2]);
t.transform.translation.y = atof(transformation[3]);
t.transform.translation.z = atof(transformation[4]);
tf2::Quaternion q;
q.setRPY(
  atof(transformation[5]),
  atof(transformation[6]),
  atof(transformation[7]));
t.transform.rotation.x = q.x();
t.transform.rotation.y = q.y();
t.transform.rotation.z = q.z();
t.transform.rotation.w = q.w();

        这里是填充关于小海龟的6D(六个自由度)位姿数据(偏移及旋转)。

tf_static_broadcaster_->sendTransform(t);

         数据都准备好了之后,我们调用sendTransform函数将消息t(静态转换)发布广播出去。

更新package.xml和CMakeLists.txt

package.xml

<description>Learning tf2 with rclcpp</description>
<maintainer email="mike@qq.com">mike</maintainer>
<license>Apache License 2.0</license>

        根据实际情况手动修改。

CMakeLists.txt

add_executable(static_turtle_tf2_broadcaster src/static_turtle_tf2_broadcaster.cpp)
ament_target_dependencies(
   static_turtle_tf2_broadcaster
   geometry_msgs
   rclcpp
   tf2
   tf2_ros
)

        添加可执行程序,名字为static_turtle_tf2_broadcaster,我们在使用ros2 run命令时会使用到此生成的可执行程序。

install(TARGETS
   static_turtle_tf2_broadcaster
   DESTINATION lib/${PROJECT_NAME})

        指定构建安装的路径(可执行程序生成的路径),方便调用程序按图索骥。

构建

        都搞定之后,我们就可以构建这个包了,但,养成好习惯,先检查依赖再构建。

$rosdep install -i --from-path src --rosdistro iron -y
$colcon build --packages-select learning_tf2_cpp

运行

        我们新开一个终端,先进入工作空间根路径然后source下环境:

$source install/setup.bash

        现在我们终于可以运行了,但我们需要在调用可执行文件时还需将位姿数据传进去,方便该节点填充消息(x,y,z,r,p,y->0,0,1,0,0,0):

$ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0

上面的参数z为1,代表给mystaticturtle坐标系广播了一个离地1米高度的海龟位姿信息(让mystaticturtle坐标系朝着这个小目标前进)。

补充一点机器人学背景专业知识。

在ROS(Robot Operating System)中,6自由度(6DOF,即6 Degrees of Freedom)通常指的是一个刚体在空间中的完全定位所需的参数。这些参数描述了刚体在三维空间中的位置和姿态。具体来说,6自由度包括:

    三个位置参数(Position):
        X轴位移(X-axis translation)
        Y轴位移(Y-axis translation)
        Z轴位移(Z-axis translation)

这三个参数描述了刚体在三维空间中的位置。

    三个姿态参数(Attitude)或方向参数(Orientation):
        横滚角(Roll)
        俯仰角(Pitch)
        偏航角(Yaw)

这三个参数描述了刚体在三维空间中的方向或姿态。这些角度通常使用欧拉角、四元数或其他方式来表示。

在ROS中,这些参数经常用于描述传感器数据(如IMU、激光雷达等)、机器人末端执行器的位置、机器人的自身姿态等。例如,tf2库就用于处理这些变换,允许用户在不同坐标系之间转换点、向量和姿态。

当处理机器人学中的运动时,了解这些参数和它们如何影响机器人在空间中的位置和姿态是非常重要的。

位置参数(Position)

    X轴位移(X-axis translation):
        这个参数描述了刚体在X轴方向上的位置。正值通常表示向右移动,负值表示向左移动。它决定了刚体在三维空间中的水平位置。
    Y轴位移(Y-axis translation):
        这个参数描述了刚体在Y轴方向上的位置。正值通常表示向前移动,负值表示向后移动。它决定了刚体在三维空间中的前后位置。
    Z轴位移(Z-axis translation):
        这个参数描述了刚体在Z轴方向上的位置。正值通常表示向上移动,负值表示向下移动。它决定了刚体在三维空间中的垂直位置。

姿态参数(Attitude)或方向参数(Orientation)

姿态参数通常用来描述刚体在三维空间中的方向或朝向。有多种方式可以表示姿态,但最常见的包括欧拉角和四元数。这里,我们简单解释欧拉角:

    横滚角(Roll):
        这个参数描述了刚体绕其X轴的旋转。正值通常表示顺时针旋转,负值表示逆时针旋转。它描述了刚体在水平面上的旋转。
    俯仰角(Pitch):
        这个参数描述了刚体绕其Y轴的旋转。正值通常表示向上抬头,负值表示向下低头。它描述了刚体在垂直平面内的旋转。
    偏航角(Yaw):
        这个参数描述了刚体绕其Z轴的旋转。正值通常表示向右转动,负值表示向左转动。它描述了刚体在水平面上的方向改变。

需要注意的是,欧拉角存在万向锁问题,即在某些特定姿态下,横滚角和俯仰角会变得不确定,影响姿态描述的准确性。因此,在实际应用中,有时会更倾向于使用四元数或其他方法来表示姿态。

         我们再来检查一下主题/tf_static发布的静态转换消息(不知道是哪个主题可以ros2 topic list确认一下)。

$ros2 topic echo /tf_static

 如果一切顺利,我们将会看到下面的内容。

发布静态转换的正确方式

        除了我们上面编写构建的StaticTransformBroadcaster可以发布静态转换外,我们还可以利用tf2_ros工具(名字为static_transform_publisher)来实现同样的目的(实际情况就是直接使用现成的工具而不是自己去实现,上面的代码实现是为了让我们了解到其内部的实现,知己知彼嘛),我们可以直接在命令行调用此工具或者在launch文件里添加使用。

        使用以米为单位的x/y/z偏移和以弧度为单位的滚转/俯仰/偏航,将静态坐标变换发布到tf2。我们来看看怎么调用:

$ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id

        可以看出,除了6D参数外还有我们在自己编写的代码里面的父子坐标系名称。我们执行一下,效果与上面的是一样的。

 

 

        使用以米和四元数为单位的x/y/z偏移将静态坐标变换发布到tf2。

$ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id

补充四元数知识点:

四元素(Quaternion)是一种用于表示旋转的数学工具,在机器人学和计算机图形学等领域有广泛应用。它由一个实部和三个虚部组成,可以表示为(w, x, y, z)或(w, V),其中V是虚部,表示为向量(x, y, z)。四元素满足特定的数学规则,包括虚部的乘法规则,如i^2 = j^2 = k^2 = ijk = −1等。

在ROS(Robot Operating System)中,四元素常用于表示机器人的姿态。姿态描述了机器人在三维空间中的位置和朝向,而四元素是描述这种姿态的一种常用方式。ROS提供了处理四元素的库和工具,使得机器人软件能够方便地处理与姿态相关的任务。

在使用四元素时,需要注意其标准化问题。标准化四元素意味着将其长度(模长)调整为1,以确保其正确表示旋转。未标准化的四元素可能会导致错误的结果。

此外,ROS中的tf2系统也涉及到四元素的使用。tf2用于进行坐标旋转以及tf、msg两种四元素数据结构的变换,它使得在不同坐标系之间转换姿态变得简单高效。

综上所述,四元素是机器人学和计算机图形学中的重要工具,尤其在ROS中,它扮演着描述机器人姿态的关键角色。

  static_transform_publisher既可以直接在命令行使用又可以在launch文件里面使用,我们来看看它在launch文件里面是怎么用的。

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
             package='tf2_ros',
             executable='static_transform_publisher',
             arguments = ['--x', '0', '--y', '0', '--z', '1', '--yaw', '0', '--pitch', '0', '--roll', '0', '--frame-id', 'world', '--child-frame-id', 'mystaticturtle']
        ),
    ])

        看起来是不是比较容易接受,但需要注意的是,除了参数--frame-id 和参数 --child-frame-id外的其他参数都是可选的,如果未指定某个特定选项,则会假定使用恒等变换(默认值)。

本篇完。

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

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

相关文章

Ventus(承影):基于RISC V的开源GPGPU

Ventus&#xff08;承影&#xff09;&#xff1a;基于RVV的开源GPGPU 清华大学集成电路学院dsp-lab的承影RVV GPGPU设计文档。 整体目标 提供一个开源的基于RVV的GPGPU实现方案&#xff0c;并给出软件映射方案、指令集&#xff08;支持的指令及特性、添加的自定义指令&#xf…

15.接口自动化学习-Mock(挡板/测试桩)

场景&#xff1a; 新需求还未开发时&#xff0c;使用mock提早介入测试&#xff0c;等后边开发后&#xff0c;进行调试 三方接口返回效率低&#xff0c;使用mock技术走通流程 1.mock方式 &#xff08;1&#xff09;如果会写django或flask,可以写简单对应的代码 &#xff08;…

小米一面:说说MVC与设计模式的关系

前言 大家好&#xff0c;我叫阿杆&#xff0c;不叫阿轩。 先来看看面试环节吧。 面试官&#xff1a;请说说MVC模式是基于哪种设计模式的&#xff1f; 求职者&#xff1a;MVC本身不就是一种设计模式吗&#xff1f; 面试官&#xff1a;我的意思是&#xff0c;MVC是基于23中设计…

【04-提升模型性能:集成学习与超参数优化】

文章目录 前言集成学习BaggingBoosting超参数优化随机搜索贝叶斯优化总结前言 在前几篇博文中,我们已经介绍了一些机器学习的基础知识、Scikit-learn的核心工具与技巧,以及如何评估模型性能。本篇博文将重点讲解两个可以显著提升机器学习模型性能的高级策略:集成学习和超参数…

python企业员工培训考试系统django+vue

这次开发的供电公司安全生产考试系统管理员&#xff0c;教师&#xff0c;学生。管理员功能有个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;主观题信息管理&#xff0c;主观题回答管理&#xff0c;主观题评分管理&#xff0c;成绩信息管理&#xff0c;试卷管理…

命名空间:namespace

对于无名命名空间 &#xff1a;但是不能再次定义相同名称的变量 在同一文件中

Linux程序调试优化(2)—— 一次学会嵌入式Linux下程序崩溃定位

文章目录 1.gdb调试1.1 gcc 编译时不带-g1.2 gcc 编译时带-g 2.coredump栈回溯2.1 使能core文件生成2.1 借助core文件回溯堆栈 3.backtrace捕捉SIGSEGV信号4.其他工具5.总结 写程序时&#xff0c;难免碰到程序崩溃的现象&#xff0c;而如何排查这些内存崩溃问题&#xff0c;例如…

Pulsar Meetup 深圳 2024 会务介绍

“ Hi&#xff0c;各位热爱 Pulsar 的小伙伴们&#xff0c;Pulsar Meetup 深圳 2024 报名倒计时啦&#xff0c;快来报名。这里汇集了腾讯、华为和谙流科技等大量 Pulsar 大咖&#xff0c;干货多多&#xff0c;礼品多多&#xff0c;不容错过啊。 ” 活动介绍 图片 由 AscentStre…

巧用波卡生态优势,Mythical Games 引领 Web3 游戏新航向

Polkadot 对创新、安全和治理的承诺为 Mythical Games 提供了极大的发展价值。这个链上生态不仅将支持 Mythical Games 成长发展&#xff0c;还将帮助其他 Mythos 合作伙伴来壮大建设项目。 —— Mythical Games 创始人兼首席执行官 John Linden 近期 Web3 游戏行业又有新动向&…

【管理咨询宝藏86】MBB物流公司营销项目价值定位与目标客户规划报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏86】MBB物流公司营销项目价值定位与目标客户规划报告 【格式】PDF版本 【关键词】战略规划、MBB、麦肯锡 【核心观点】 - 价值定位是企业希望深…

HORROR SYSTEM

HORROR SYSTEM是一个创新的工具包,允许开发者在Unity3D中创建独特的原创恐怖游戏。 HORROR SYSTEM是一款强大而灵活的工具,旨在基于Unity3D引擎创建沉浸式第三人称恐怖游戏。 这项资产易于使用且直观,可以让任何经验水平的开发人员将他们的想法付诸实践,创造出高质量、充满…

飞行汽车飞行控制系统功能详解

飞行汽车是一种创新的交通工具&#xff0c;结合了汽车和飞机的特点。它可以在陆地上行驶&#xff0c;同时也具备在空中飞行的能力。飞行汽车的概念已经存在多年&#xff0c;并且近年来随着技术的进步和研发的深入&#xff0c;这种交通工具正在逐渐从概念走向现实。 飞行汽车的…

NLP方面知识

NLP方面知识 一 基础1.Tokenizer1.1 分词粒度&#xff1a;1.2 大模型的分词粒度1.3 各路语言模型中的tokenizer 2.Embedding layer2.1 理解Embedding矩阵 一 基础 1.Tokenizer tokenizer总体上做三件事情&#xff1a; 分词。tokenizer将字符串分为一些sub-word token string&…

学习Rust的第10天:枚举和模式匹配

今天我们来看看一个类似的概念 enums 。 Enums: We saw that in Rust, enums are data types that list possible values, giving a simple and type-safe mechanism to describe alternatives. We looked at how to create enums and use them to represent similar possibili…

MT8788智能模块简介_MTK联发科安卓核心板方案厂商

MT8788安卓核心板是一款具备超高性能和低功耗的4G全网通安卓智能模块。该模块采用联发科AIOT芯片平台&#xff0c;供货周期长。 MT8788核心板搭载了12nm制程的四个Cortex-A73处理器核心和四个Cortex-A53处理器核心&#xff0c;最高主频可达2.0GHz。板载内存容量可选为4GB64GB(也…

【Win】怎么下载m3u8视频\怎么通过F12开发人员工具获取视频地址\怎么下载完整的.ts格式视频

怎么下载m3u8视频&#xff1f;首先通过浏览器本地的开发人员工具&#xff0c;获取m3u8的地址&#xff0c;然后再通过第三方下载工具下载&#xff0c;此处以N_m3u8DL-CLI_v3.0.2为例 如下图的步骤&#xff0c;即可获取到视频的m3u8地址 打开N_m3u8DL-CLI_v3.0.2&#xff0c;粘贴…

生成式AI在B端产品的应用分析

AI产品发展到现在&#xff0c;消费端的产品应用还受到比较大的限制&#xff1b;但是在B端&#xff0c;已经有了不错的表现。作者总结了AI产品在B端的几款应用&#xff0c;一起来看看表现如何。 生成式AI在B端产品的应用分析© 由 ZAKER 提供 随着今年生成式AI应用的大范围…

ROS1快速入门学习笔记 - 04创建工作环境与功能包

一、定义 工作空间(workspace)是一个存放工程开发相关文件的文件夹。 src:代码空间&#xff08;Source Space&#xff09;build: 编辑空间&#xff08;Build Space&#xff09;devel:开发空间&#xff08;Development Space&#xff09;install:安装空间&#xff08;Install …

【网络安全】HTTP协议 — 基础

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 学习目标​ 一、万维网的诞生与发展​编辑 1.万维网的诞生与发展 2.HTTP协议诞生与发展 二、网络基础 1.TCP/IP分层传输 1&#xff09;TCP/IP协议 2&#xff09;封装与拆封 …

【linux】匿名管道|进程池

1.进程为什么要通信&#xff1f; 进程也是需要某种协同的&#xff0c;所以如何协同的前提条件(通信) 通信数据的类别&#xff1a; 1.通知就绪的 2.单纯的数据 3.控制相关的信息 2.进程如何通信&#xff1f; 进程间通信&#xff0c;成本会高一点 进程间通信的前提&#xff0c;先…