本文将给出一个示例说明如何给导航功能包集发布odometry信息, 其中主要包括发布消息nav_msgs/Odometry以及通过tf广播"odom"坐标系到"base_link"坐标系的转换信息。

1 发布Odometry信息

导航功能包集需要依靠tf 来确定机器人在物理世界中的位置以及传感器数据和静态地图的关系。但受限于tf自身并不能提供任何有关机器人移动速度的信息,所以导航功能包集需要里程源能够同时发布坐标变换和携带速度信息的nav_msgs/Odometry类型消息。

2 nav_msgs/Odometry消息

nav_msgs/Odometry消息中存储了自由空间中机器人的位姿估计和速度信息:

# This represents an estimate of a position and velocity in free space.
# The pose in this message should be specified in the coordinate frame given by header.frame_id.
# The twist in this message should be specified in the coordinate frame given by the child_frame_id
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist

该消息中的“pose”对应于机器人在odometric坐标系下估计的位置以及一个可选的位姿估计协方差,“twist”对应于机器人子坐标系(通常是移动基座坐标系)下的速度以及一个可选的速度估计协方差。

3 利用tf发布里程转换

如在TF配置 Transform Configuration 指导中阐述, "tf"软件库利用transform树来管理机器人上各个坐标系之间的转换。同理里程源也必须发布其坐标系的信息以供统一管理。

4 代码实现

在本节中,我们将使用伪造的机器人给出可以发布nav_msgs/Odometry消息,以及利用tf发布里程转换的示例代码。

添加如下依赖到包的manifest.xml文件,

<depend package="tf"/>
<depend package="nav_msgs"/>

以下是示例代码:

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>int main(int argc, char** argv){ros::init(argc, argv, "odometry_publisher");ros::NodeHandle n;ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);tf::TransformBroadcaster odom_broadcaster;double x = 0.0;double y = 0.0;double th = 0.0;double vx = 0.1;double vy = -0.1;double vth = 0.1;ros::Time current_time, last_time;current_time = ros::Time::now();last_time = ros::Time::now();ros::Rate r(1.0);while(n.ok()){ros::spinOnce();               // check for incoming messagescurrent_time = ros::Time::now();//compute odometry in a typical way given the velocities of the robotdouble dt = (current_time - last_time).toSec();double delta_x = (vx * cos(th) - vy * sin(th)) * dt;double delta_y = (vx * sin(th) + vy * cos(th)) * dt;double delta_th = vth * dt;x += delta_x;y += delta_y;th += delta_th;//since all odometry is 6DOF we'll need a quaternion created from yawgeometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);//first, we'll publish the transform over tfgeometry_msgs::TransformStamped odom_trans;odom_trans.header.stamp = current_time;odom_trans.header.frame_id = "odom";odom_trans.child_frame_id = "base_link";odom_trans.transform.translation.x = x;odom_trans.transform.translation.y = y;odom_trans.transform.translation.z = 0.0;odom_trans.transform.rotation = odom_quat;//send the transformodom_broadcaster.sendTransform(odom_trans);//next, we'll publish the odometry message over ROSnav_msgs::Odometry odom;odom.header.stamp = current_time;odom.header.frame_id = "odom";//set the positionodom.pose.pose.position.x = x;odom.pose.pose.position.y = y;odom.pose.pose.position.z = 0.0;odom.pose.pose.orientation = odom_quat;//set the velocityodom.child_frame_id = "base_link";odom.twist.twist.linear.x = vx;odom.twist.twist.linear.y = vy;odom.twist.twist.angular.z = vth;//publish the messageodom_pub.publish(odom);last_time = current_time;r.sleep();}
}

以下是代码解读,
1)由于我们需要发布里程坐标系到基座坐标系的转换,以及里程消息nav_msgs/Odometry,所以我们需要包含相应头文件,

#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>

2)我们需要一个ROS消息发布器发布消息和一个tf transform广播器,因此有如下代码,

ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);
tf::TransformBroadcaster odom_broadcaster;

3)假定机器人初始位置在里程坐标系原点,

double x = 0.0;
double y = 0.0;
double th = 0.0;

4)我们预设置几个速度值,让"base_link"坐标系在"odom" 坐标系移动,

double vx = 0.1;
double vy = -0.1;
double vth = 0.1;

5)使用我们预先设定的常量速度更新里程信息,当然现实世界中速度是算出来的不是常量,

double dt = (current_time - last_time).toSec();
double delta_x = (vx * cos(th) - vy * sin(th)) * dt;
double delta_y = (vx * sin(th) + vy * cos(th)) * dt;
double delta_th = vth * dt;

x += delta_x;
y += delta_y;
th += delta_th;

6)通常在系统中我们尽量使用3D版本的消息,这样方便适当时候2D和3D部件一起工作。 因此,有必要将里程的yaw值转换成四元数来发布。非常幸运的是,tf提供了很容易用yaw创建四元数或者从四元数得到yaw值的函数接口。

geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);

7)我们将创建一个TransformStamped消息然后通过tf发送它。 我们要在当前时刻发送"odom"坐标系到"base_link"坐标系的转换,因此我们需要设置消息header和子坐标系,并确保"odom"是父坐标系而"base_link"是子坐标系。

geometry_msgs::TransformStamped odom_trans;
odom_trans.header.stamp = current_time;
odom_trans.header.frame_id = "odom";
odom_trans.child_frame_id = "base_link";

8)用来自里程计的数据填充transform消息,并稍后用TransformBroadcaster发送出去,

odom_trans.transform.translation.x = x;
odom_trans.transform.translation.y = y;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = odom_quat;

9)此外,我们也需要发布nav_msgs/Odometry消息,以便导航功能包集能获得速度信息。 message so that the navigation stack can get velocity information from it. We'll set the header of the message to the current_time and the "odom" coordinate frame.

nav_msgs::Odometry odom;
odom.header.stamp = current_time;

10)使用里程计数据填充nav_msgs/Odometry消息并发送出去。 我们将该消息子坐标系为"base_link",因为我们发布的速度信息要给到该坐标系。

    //set the position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.position.z = 0.0;
    odom.pose.pose.orientation = odom_quat;

    //set the velocity
    odom.child_frame_id = "base_link";
    odom.twist.twist.linear.x = vx;
    odom.twist.twist.linear.y = vy;
    odom.twist.twist.angular.z = vth;

11)发布里程消息

//publish the message
odom_pub.publish(odom);

总结:基于里程计要发送东西主要包括,

1)"odom"坐标系到"base_link"坐标系里程变换(线位移和角位移的转换)

2)消息nav_msgs/Odometry(线位移和角位移 + 线速度和角速度)

ROS Navigation-----发布Odometry信息相关推荐

  1. 译:在ROS上发布Odometry信息

    在ROS上发布Odometry信息 描述: 这一教程提供了一个为Navigation Stack发布Odometry消息的例子,不仅包含了如何发布nav_msgs/Odometry消息,还包括一个&q ...

  2. 理解ROS Navigation Stack,看完这篇你就知道啦!

    前言 ROS Navigation Stack是ROS提供的一个二维的导航功能包集合,通过输入里程计.传感器信息和目标位姿,输出控制机器人到达目标状态的安全速度指令.ROS Navigation St ...

  3. ROS Navigation导航包介绍

    Navigation功能包集概述 这是2D的导航功能包集,通过接收里程计数据.tf坐标变换树以及传感器数据,为移动机器人输出目标位置以及安全速度.概念层面上讲,导航功能包集是相当简单的. 它从里程计和 ...

  4. ROS : Navigation 基于碰撞传感器、悬崖传感器的实时避障 [kobuki]

    ROS : Navigation 基于碰撞传感器.悬崖传感器的实时避障 [kobuki] 话题消息 碰撞传感器 悬崖传感器 点云数据 传感器详细信息 基于碰撞传感器.悬崖传感器的实时避障 转点云数据源 ...

  5. ROS Navigation Tuning Guide(导航调试指南)

    ROS Navigation Tuning Guide 导航调试指南 准备工作 距离传感器 里程计 定位 速度与加速度的设置 获得最大速度 获得最大加速度 设置最小值 XY方向的速度 Global P ...

  6. 使用键盘发布手柄控制信息

    最近在看CMU的ShuoYang开源的自己写的MIT cheetah3的控制代码,在经过了漫长的docker环境安装后,发现因为自己没有xbox手柄,因此无法直接控制gazebo中的机器狗,因此准备使 ...

  7. 【硬核】 ROS Navigation 局部路径规划常见算法

    简介 ​ 最近,作者参加了关于RMUS 高校 SimReal挑战赛,首次接触到了机器人导航领域,这里记录一下这段时间的收货.sim2real的全称是simulation to reality,是强化学 ...

  8. Flask项目实战——10—(前台板块页面搭建、文本编辑页面搭建、发布帖子信息前验证权限、帖子模型搭建、发布帖子功能、帖子信息渲染到前后台页面)

    1.前台板块页面搭建 视图文件查询数据传输到前台界面:前台蓝图文件:apps/front/views.py 注意数据的收集方法和数据传输的类型. # -*- encoding: utf-8 -*- & ...

  9. ROS Navigation插件注册自定义导航避障算法

    前言 最近开组会的时候,导师催促我寻找创新点,着实让我头疼.因为说实话,我真的不想找什么创新点,我只想学习一些招聘简历上的技能类的东西,比如熟悉A*.Dijkstra和DWA导航避障算法,熟悉ROS, ...

  10. 我看了下GAAS里ROS里发布的pose 的 topic包含position和orientation,我觉得position是实际位置,orientation是期望位置。错了,是标准的里程计消息。

    我看了下GAAS里ROS里发布的pose 的 topic包含position和orientation,我觉得position是实际位置,orientation是期望位置. 错了,我后来看到ROS机器人 ...

最新文章

  1. ADF12C 在线预览PDF文件 afinlineFrame
  2. redhat7操作系统安装
  3. Nacos 1.0.0 GA,架构、功能与 API 设计全面重构
  4. “12306” 的架构到底有多牛逼?
  5. Linux 源代码阅读知识点及要求
  6. 重构代码 —— 提取出类
  7. 浅谈御剑web指纹识别-CMS指纹识别
  8. [NLP]论文笔记-A SIMPLE BUT TOUGH-TO-BEAT BASELINE FOR SENTENCE EMBEDDINGS
  9. linux数组fortran,Fortran77-90-95入门(十)--数组
  10. 用202种编程语言输出hello world,你会几种?(3)
  11. 清华大学学术答辩通用PPT模板
  12. shader 重建世界坐标
  13. 企业私有云规划资源设计
  14. C语言 商业贷款计算器 等额本金 等额本息
  15. 编写一个求x的n次方的函数
  16. kodi android 目录,如何在xbmc / kodi插件中创建多个目录?
  17. Access端口和Trunk端口
  18. 世界上最远的距离——泰戈尔
  19. 【离散数学】数理逻辑 第一章 命题逻辑(4) 联结词的完备集
  20. 推荐一款免费的带有坐标系的在线绘图web应用(汇报神器)

热门文章

  1. 计算机键盘芯片,电脑键盘芯片详解中文.pdf
  2. html控制手机回退键,向日葵手机控制手机全程指导
  3. st语言 数组的常用方法_三菱ST语言编程中常用的函数/功能块使用方法
  4. AndroidStudio NDK开发环境配置及示例
  5. 编写USB鼠标驱动程序,并测试
  6. 惠普打印机故障代码_惠普打印机出现故障怎么办
  7. 布料仿真中常用积分方法
  8. emd经验模态分解 matlab,经验模态分解(EMD)在地球物理资料中的应用(附MATLAB程序)...
  9. java-合并两个有序链表
  10. 《论文排版札记》part1 论文公式编号—WPS版