【ROS仿真实战】获取机器人在gazebo位置真值的三种方法(三)
文章目录
- 前言
- 一. 使用ROS tf库
- 二、 使用Gazebo Model Plugin
- 三、 使用libgazebo_ros_p3d插件
- 四、总结
前言
在ROS和Gazebo中,获取机器人的位置信息通常通过ROS消息传递进行。在这篇文章中,我们将介绍三种获取机器人在Gazebo中位置真值的方法:使用ROS tf库、使用自己编写Gazebo Model Plugin以及libgazebo_ros_p3d Plugin。
一. 使用ROS tf库
ROS tf库是ROS中用于管理坐标变换的库,它可以通过ROS消息传递来管理不同坐标系之间的关系。在Gazebo中,每个模型都有一个本地坐标系(local coordinate system),这个坐标系的原点通常位于模型的重心。模型的本地坐标系可以通过SDF文件或URDF文件定义。在Gazebo中,机器人也是一个模型,因此可以通过ROS tf库来获取机器人的位置信息。
以下是获取机器人在Gazebo中位置信息的步骤:
- 在机器人控制程序中,通过tf监听器(tf listener)订阅tf变换消息(tf transform message)。
#include <ros/ros.h>
#include <tf/transform_listener.h>int main(int argc, char** argv) {ros::init(argc, argv, "robot_position");ros::NodeHandle nh;tf::TransformListener listener;while (ros::ok()) {tf::StampedTransform transform;try {listener.lookupTransform("world", "base_link", ros::Time(0), transform);} catch (tf::TransformException& ex) {ROS_ERROR("%s", ex.what());ros::Duration(1.0).sleep();continue;}double x = transform.getOrigin().x();double y = transform.getOrigin().y();double z = transform.getOrigin().z();ROS_INFO("Robot position: x=%f, y=%f, z=%f", x, y, z);ros::spinOnce();}return 0;
}
-
在lookupTransform函数中指定目标坐标系和源坐标系。在这个例子中,目标坐标系是"world",表示机器人在地图坐标系中的位置。源坐标系是"base_link",表示机器人本身的坐标系。
-
通过调用getOrigin函数获取机器人在目标坐标系中的位置。
需要注意的是,机器人控制程序中必须先启动tf监听器,否则程序会无法订阅到tf变换消息。
二、 使用Gazebo Model Plugin
另一种获取机器人在Gazebo中位置信息的方法是使用Gazebo Model Plugin。Gazebo Model Plugin是一种可以附加到Gazebo模型上的插件,可以在模拟过程中对模型进行控制和监测。
以下是使用Gazebo Model Plugin获取机器人在Gazebo中位置信息的步骤:
- 编写Gazebo Model Plugin
首先,我们需要编写一个Gazebo Model Plugin,用于订阅机器人在Gazebo中的位姿信息,并将其发布到ROS话题中。在这个例子中,我们使用的是Gazebo提供的ModelPlugin。
下面是一个简单的例子,演示如何获取机器人在Gazebo中的位置信息,并将其发布到ROS话题中:
#include <gazebo/common/Plugin.hh>
#include <gazebo/physics/physics.hh>
#include <ros/ros.h>
#include <geometry_msgs/PoseStamped.h>namespace gazebo {class RobotPlugin : public ModelPlugin {public:RobotPlugin() {}void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf) override {// 获取机器人模型model_ = _parent;// 初始化ROS节点ros::NodeHandle nh;// 创建一个ROS发布器,发布机器人的位置信息pose_pub_ = nh.advertise<geometry_msgs::PoseStamped>("/robot_pose", 10);// 创建一个Gazebo回调函数,用于在每个仿真步骤中获取机器人的位姿信息update_connection_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&RobotPlugin::OnUpdate, this));}private:void OnUpdate() {// 获取机器人的位姿信息auto pose = model_->WorldPose();// 将位姿信息转换为ROS消息类型geometry_msgs::PoseStamped pose_msg;pose_msg.header.frame_id = "world";pose_msg.header.stamp = ros::Time::now();pose_msg.pose.position.x = pose.Pos().X();pose_msg.pose.position.y = pose.Pos().Y();pose_msg.pose.position.z = pose.Pos().Z();pose_msg.pose.orientation.x = pose.Rot().X();pose_msg.pose.orientation.y = pose.Rot().Y();pose_msg.pose.orientation.z = pose.Rot().Z();pose_msg.pose.orientation.w = pose.Rot().W();// 发布机器人的位姿信息pose_pub_.publish(pose_msg);}// 机器人模型physics::ModelPtr model_;// ROS发布器,用于发布机器人的位置信息ros::Publisher pose_pub_;// Gazebo回调函数,用于在每个仿真步骤中获取机器人的位姿信息gazebo::event::ConnectionPtr update_connection_;
};GZ_REGISTER_MODEL_PLUGIN(RobotPlugin)} // namespace gazebo
- 编译和运行
编译上述代码,可以使用Catkin工作空间进行编译。在Catkin工作空间的根目录下,创建一个名为“src”的目录,然后将上述代码复制到“src”目录下。接下来,使用以下命令编译代码:
catkin_make
接下来,可以在.launch文件中添加gazebo_ros包,并启动Gazebo仿真环境,启动ROS节点:
<launch><arg name="model" default="robot"/><include file="$(find gazebo_ros)/launch/empty_world.launch"><arg name="world_name" value="$(find my_robot)/worlds/my_world.world"/><arg name="paused" value="false"/><arg name="use_sim_time" value="true"/><arg name="gui" value="true"/><arg name="headless" value="false"/><arg name="debug" value="false"/></include><node name="gazebo_model_publisher" pkg="my_robot" type="gazebo_model_publisher" output="screen"><param name="model" value="$(arg model)"/><param name="topic" value="/robot_pose"/></node>
</launch>
在上面的.launch文件中,首先包含了gazebo_ros包的empty_world.launch文件,并传递了相关参数,启动Gazebo仿真环境。然后,启动一个节点gazebo_model_publisher,这个节点是我们自己编写的Gazebo Model Plugin,通过订阅机器人的位置信息并将其发送到ROS话题中。
运行.launch文件:
roslaunch my_robot gazebo_model_publisher.launch
此时,机器人在Gazebo中的位置信息将会以ROS话题的形式发布,可以使用rostopic命令查看:
rostopic echo /robot_pose
这样,我们就可以通过Gazebo Model Plugin获取机器人在Gazebo中的位置信息了。
三、 使用libgazebo_ros_p3d插件
libgazebo_ros_p3d
是一个用于在Gazebo仿真环境中发布三维位置和速度信息的ROS插件库。该插件可以使ROS节点通过ROS话题订阅机器人的三维位置和速度信息,并将其发布到Gazebo仿真环境中,使得机器人的运动可以在仿真环境中被准确地模拟和显示。
该插件通过Gazebo中的物理引擎模拟机器人的运动,并将模拟结果转换成ROS消息发布到ROS话题中。该插件可以很方便地与其他ROS节点和包进行集成,实现对机器人运动的控制和监控。
使用libgazebo_ros_p3d
插件需要在Gazebo模型文件中添加插件的配置,并在ROS节点中订阅插件发布的ROS话题。插件配置中需要指定插件的名称、参考框架、更新频率等参数,以及要发布的三维位置和速度信息的名称和单位。
<!-- Fake localization plugin --><plugin name="ground_truth_odometry" filename="libgazebo_ros_p3d.so"><alwaysOn>true</alwaysOn><updateRate>100.0</updateRate><bodyName>base_link</bodyName><topicName>base_pose_ground_truth</topicName><gaussianNoise>0.01</gaussianNoise><frameName>map</frameName>--><!-- initialize odometry for fake localization--><xyzOffsets>0 0 0</xyzOffsets><rpyOffsets>0 0 0</rpyOffsets></plugin>
编写节点订阅话题/gazebo/model_states,找到对应模型的名称即可,例如机器人名称为turtlebot3。
void _modelStatesCallback(const gazebo_msgs::ModelStatesConstPtr &msg)
{int modelCount = msg->name.size();for(int modelInd = 0; modelInd < modelCount; ++modelInd){if(msg->name[modelInd] == "turtlebot3"){_current_pose.pose = msg->pose[modelInd];_current_velocity.twist = msg->twist[modelInd];break;}}
}
在ROS机器人算法开发和测试过程中,libgazebo_ros_p3d
插件可以帮助开发人员在仿真环境中快速、准确地获取机器人的位置和速度信息,方便进行算法开发和测试。
四、总结
总的来说,在进行ROS机器人算法开发和测试时,获取机器人在Gazebo中位置信息的基本步骤是通过订阅ROS话题或使用插件提供的接口来获取机器人位置信息,并将其发送到ROS话题中。选择适合自己的方法,根据实际需求和问题进行调试和优化是非常重要的。无论使用哪种方法,这个基本步骤都是相同的,只是具体实现方式会有所不同。因此,在使用Gazebo进行ROS机器人算法开发和测试时,需要根据实际情况选择合适的方法来获取机器人的位置信息。
相关文章:

【ROS仿真实战】获取机器人在gazebo位置真值的三种方法(三)
文章目录 前言一. 使用ROS tf库二、 使用Gazebo Model Plugin三、 使用libgazebo_ros_p3d插件四、总结 前言 在ROS和Gazebo中,获取机器人的位置信息通常通过ROS消息传递进行。在这篇文章中,我们将介绍三种获取机器人在Gazebo中位置真值的方法࿱…...
Winform从入门到精通(35)——FontDialog(史上最全)
文章目录 前言一、属性1、Name2、AllowScriptChange3、AllowSimulations4、AllowVectorFonts5、AllowVerticalFonts6、Color7、FixedPitchOnly8、Font9、FontMustExist10、MaxSize11、MinSize12、 ScriptsOnly13、ShowApply14、ShowColor15、ShowEffects16、ShowHelp...
AcWing 854. Floyd求最短路Floyd模板
Floyd算法: 标准弗洛伊德算法,三重循环,基于动态规划。 循环结束之后 d[i][j]存储的就是点 i 到点 j 的最短距离。 需要注意循环顺序不能变:第一层枚举中间点,第二层和第三层枚举起点和终点。 特点: 1.复杂…...

Graph Theory(图论)
一、图的定义 图是通过一组边相互连接的顶点的集合。 In this graph, V { A , B , C , D , E } E { AB , AC , BD , CD , DE } 二、图的类型 2.1 Finite Graph A graph consisting of finite number of vertices and edges is called as a finite graph. Null Graph Tri…...
[Python]生成 txt 文件
前段时间有位客户问: 你们的程序能不能给我们生成个 txt 文件,把新增的员工都放进来,字段也不需要太多,就要 员工姓名/卡号/员工编号/员工职位/公司 这些字段就行了,然后我们的程序会去读取这个 txt 文件,拿里面的内容,读完之后会这个文件删掉 我: 可以接受延迟吗?可能没办法实…...
GeoTools实战指南: 自定义矢量样式并生成截图
GeoTools实战指南: 自定义矢量样式并生成截图 介绍 本段代码的主要功能是将矢量数据(Shapefile)渲染成一张图片。 准备环境 首先,您需要将GeoTools库添加到您的项目中。使用Maven或Gradle添加依赖项,或者直接下载GeoTools的jar文件并添加到您的类路径中。 Maven <…...
深度学习超参数调整介绍
文章目录 深度学习超参数调整介绍1. 学习率2. 批大小3. 迭代次数4. 正则化5. 网络结构总结 深度学习超参数调整介绍 深度学习模型的性能很大程度上取决于超参数的选择。超参数是指在训练过程中需要手动设置的参数,例如学习率、批大小、迭代次数、网络结构等等。选择…...

Bootloader
本篇不作太过的技术了解,仅可作为初学者的参考。用嘴简单的语言讲清楚一件事。 项目中遇到Bootloader升级MCU,我很好这是什么软件,逻辑是什么,怎么升级的。 术语及定义 指纹信息fingerprint诊断仪用于标识特定的下载尝试的信息 …...
安卓开发_广播机制_广播的最佳实践:实现强制下线功能
安卓开发_广播机制_广播的最佳实践:实现强制下线功能 ActivityCollector类用于管理所有的ActivityBaseActivity类作为所有Activity的父类创建一个LoginActivity来作为登录界面布局LoginActivity 在MainActivity中加入强制下线功能布局MainActivity在BaseActivity中注…...

国民技术N32G430开发笔记(10)- IAP升级 Application 的制作
IAP升级 Application 的制作 1、App程序跟Bootloader程序最大的区别就是, 程序的执行地址变成了之前flash设定的0x08006000处, 大小限制为20KB 所以修改Application工程的ld文件 origin 改成 0x08006000 length 改成0x5000 烧录是起始地址也要改为x0x…...

[计算机图形学]材质与外观(前瞻预习/复习回顾)
一、图形学中的材质 不同的物体表面有着不同的材质,而不同的材质意味着它们与光线的作用不同。那么我们之前在介绍辐射度量学和渲染方程提到过其中一个函数,叫做BRDF,而在实际上,也就是BRDF定义了不同的材质。BRDF决定了光如何被反…...

Java 的简要介绍及开发环境的搭建(超级详细)
图片来源于互联网 目录 | CONTENT Java 简介 一、什么是 Java 二、认识 Java 版本 三、选择哪个版本比较好 搭建 Java 开发环境 一、下载 Java 软件开发工具包 JDK 二、配置环境变量 自动配置 手动配置 三、下载合适的 IDE IntelliJ IDEA Visual Studio Code Eclip…...

每天一道算法练习题--Day15 第一章 --算法专题 --- -----------二叉树的遍历
概述 二叉树作为一个基础的数据结构,遍历算法作为一个基础的算法,两者结合当然是经典的组合了。很多题目都会有 ta 的身影,有直接问二叉树的遍历的,有间接问的。比如要你找到树中满足条件的节点,就是间接考察树的遍历…...

golang - 函数的使用
核心化编程 为什么需要函数? 代码冗余问题不利于代码维护函数可以解决这个问题 函数 函数:为完成某一功能的程序指令(语句)的集合,称为函数 在 Go 中,函数分为:自定义函数(自己写…...

真题详解(极限编程)-软件设计(六十一)
真题详解(二分查找平均值)-软件设计(六十)https://blog.csdn.net/ke1ying/article/details/130417464 VLANtag属于 数据链路层实现。 数据链路层:网桥交换机。 网络层:路由器。 物理层:中继器。 Telent…...
计算机网络笔记:TCP粘包
默认情况下, TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到⼀起作⼀次发送 , 这样可以减少 IO 消耗提⾼性能。 如果是传输⽂件的话, 那么根本不⽤处理粘包的问题, 来⼀个包拼⼀个包就好了。但是如果是多条消息, 或者…...

Vue(标签属性:ref、配置项:props、混入mixin、插件、样式属性:scroped)
一、ref(打标识) 前面提及到了标签属性:keys 这里将了解ref:打标识 正常布置脚手架并创建入口文件main.js,引入组件 1. 可以给元素注册引用信息(获取真实DOM) 给一个按钮获取上方的dom的方法,方…...

数仓建设规划核心问题!
小A进入一家网约车出现服务公司,负责公司数仓建设,试用期主要一项 OKR是制定数据仓库建设规划;因此小 A 本着从问题出发为原点,先对公司数仓现状进行一轮深入了解,理清存在问题,然后在以不忘初心原则提出解…...
容器镜像的导入导出
容器镜像的导入导出 第1关:导入导出容器 任务描述 本关任务是学习导入导出容器,要求学习者参照示例完成将busyboxContainer容器的文件系统保存为一个tar包,通过该tar包导入一个busybox:v1.0镜像。 相关知识 将 "容器的文件系统&…...

Java每日一练(20230502)
目录 1. 二叉搜索树的最近公共祖先 🌟🌟 2. 随机分组问题 🌟 3. K 个一组翻转链表 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...