上一节介绍了激光雷达Scan传感数据的订阅和发布。

本节会介绍里程计Odom数据的发布和订阅。里程计在cartographer中主要用于前端位置预估和后端优化。

官方文档:

http://wiki.ros.org/navigation/Tutorials/RobotSetup/Odom


目录

1:nav_msgs/Odometry消息类型

2:发布Odometry消息

3:订阅Odometry消息


1:nav_msgs/Odometry消息类型

在终端查看消息数据结构:

rosmsg show nav_msgs/Odometry

Odometry消息类型数据结构如下:

Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist

其中pose是位置数据,twist是速度数据。

因为还有其他的数据结构,这里展开一下,更加清晰一点:


2:发布Odometry消息

定义了在一个圆圈中行驶的假机器人的里程计数据用来进行发布

#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::Publisher和一个tf::TransformBroadcaster以便能够分别使用 ROS 和 tf 发送消息。
  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();            
    current_time = ros::Time::now();     //根据设置的速度更新里程信息
    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;     geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);     //创建一个TransformStamped消息,通过 tf发布从“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";     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;     odom_broadcaster.sendTransform(odom_trans);     //填充Odometry消息
    nav_msgs::Odometry odom;
    odom.header.stamp = current_time;
    odom.header.frame_id = "odom";     //设置位置
    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;     //设置速度
    odom.child_frame_id = "base_link";
    odom.twist.twist.linear.x = vx;
    odom.twist.twist.linear.y = vy;
    odom.twist.twist.angular.z = vth;     //发布Odometry消息
    odom_pub.publish(odom);     last_time = current_time;
    r.sleep();
  }
}

3:订阅Odometry消息

(1) 通过rosbag订阅

rostopic echo /odom

(2) 通过rviz查看

打开rviz

rosrun rviz rviz

Fixed Frame修改为base_link,添加Odometry并将Topic设为/odom(3) 编写程序打印

#include "ros/ros.h"
#include "nav_msgs/Odometry.h"
#include "tf/transform_listener.h" void OdomCallback(const nav_msgs::Odometry::ConstPtr &msg)
{     double x, y, z;
    double roll, pitch, yaw;
    x = msg->pose.pose.position.x;
    y = msg->pose.pose.position.y;
    z = msg->pose.pose.position.z;
    tf::Quaternion quat;                                     //定义一个四元数
    tf::quaternionMsgToTF(msg->pose.pose.orientation, quat); //取出方向存储于四元数
    tf::Matrix3x3(quat).getRPY(roll, pitch, yaw);     ROS_INFO("Odom: %f, %f, %f, %f, %f, %f", x, y, z, roll, pitch, yaw);
} int main(int argc, char **argv)
{
    ros::init(argc, argv, "listener");
    ros::NodeHandle node;
    ros::Subscriber subOdom = node.subscribe("odom", 1000, OdomCallback);
    ros::spin();
    return 0;
}

【完】


下一节会介绍陀螺仪Imu数据的发布和订阅

【cartographer_ros】四: 发布和订阅里程计odom信息的更多相关文章

  1. 【cartogarpher_ros】三: 发布和订阅雷达scan信息

    上一节介绍和测试了cartographer的官方demo. 本节会编写ros系统中,最常用的激光雷达LaserScan传感数据的订阅和发布,方便在cartographer中加入自己的数据进行建图与定位 ...

  2. SLAM+语音机器人DIY系列:(四)差分底盘设计——6.底盘里程计标

    摘要 运动底盘是移动机器人的重要组成部分,不像激光雷达.IMU.麦克风.音响.摄像头这些通用部件可以直接买到,很难买到通用的底盘.一方面是因为底盘的尺寸结构和参数是要与具体机器人匹配的:另一方面是因为 ...

  3. 【cartographer_ros】五: 发布和订阅陀螺仪Imu信息

    上一节介绍了里程计Odometry传感数据的订阅和发布. 本节会介绍陀螺仪Imu数据的发布和订阅.陀螺仪在cartographer中主要用于前端位置预估和后端优化. 目录 1:sensor_msgs/ ...

  4. 【cartographer_ros】六: 发布和订阅路标landmark信息

    上一节介绍了陀螺仪Imu传感数据的订阅和发布. 本节会介绍路标Landmark数据的发布和订阅.Landmark在cartographer中作为定位的修正补充,避免定位丢失. 这里着重解释一下Land ...

  5. 视觉slam十四讲个人理解(ch7视觉里程计1)

    参考博文::https://blog.csdn.net/david_han008/article/details/53560736 https://blog.csdn.net/n66040927/ar ...

  6. ROS中测试机器人里程计信息

    在移动机器人建图和导航过程中,提供相对准确的里程计信息非常关键,是后续很多工作的基础,因此需要对其进行测试保证没有严重的错误或偏差.实际中最可能发生错误的地方在于机器人运动学公式有误,或者正负号不对, ...

  7. SLAM+语音机器人DIY系列:(三)感知与大脑——3.轮式里程计与运动控制

    摘要 在我的想象中机器人首先应该能自由的走来走去,然后应该能流利的与主人对话.朝着这个理想,我准备设计一个能自由行走,并且可以与人语音对话的机器人.实现的关键是让机器人能通过传感器感知周围环境,并通过 ...

  8. 知方可补不足~SQL2008中的发布与订阅模式

    回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...

  9. redis 笔记06 发布与订阅、事务、慢查询日志、监视器

    发布与订阅 1. 服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责 解除客 ...

随机推荐

  1. 面渣逆袭:Spring三十五问,四万字+五十图详解

    大家好,我是老三啊,面渣逆袭 继续,这节我们来搞定另一个面试必问知识点--Spring. 有人说,"Java程序员都是Spring程序员",老三不太赞成这个观点,但是这也可以看出S ...

  2. 论文解读(Graphormer)《Do Transformers Really Perform Bad for Graph Representation?》

    论文信息 论文标题:Do Transformers Really Perform Bad for Graph Representation?论文作者:Chengxuan Ying, Tianle Ca ...

  3. 一文彻底搞懂MySQL分区

    一个执着于技术的公众号 一.InnoDB逻辑存储结构 首先要先介绍一下InnoDB逻辑存储结构和区的概念,它的所有数据都被逻辑地存放在表空间,表空间又由段,区,页组成. 段 段就是上图的segment ...

  4. ThreadLocal夺命11连问

    前言 前一段时间,有同事使用ThreadLocal踩坑了,正好引起了我的兴趣. 所以近期,我抽空把ThreadLocal的源码再研究了一下,越看越有意思,发现里面的东西还真不少. 我把精华浓缩了一下, ...

  5. for循环+数字类型补充

    一.for循环 1.循环取值 1.1列表类型:  定义l=['a','b','c'],要提取列表中的值  如果采用while循环的话:   print(len(l))   i=0   while i& ...

  6. 929. Unique Email Address - LeetCode

    Question 929. Unique Email Address Solution 题目大意: 给你一个邮箱地址的数组,求出有多少个不同的地址,其中localName有如下规则 加号(+)后面的字 ...

  7. arts-week14

    Algorithm 923. 3Sum With Multiplicity - LeetCode Review Building a network attached storage device w ...

  8. 136. Single Number - LeetCode

    Question 136. Single Number Solution 思路:构造一个map,遍历数组记录每个数出现的次数,再遍历map,取出出现次数为1的num public int single ...

  9. vision transformer

    VIT 总览 Step1 Step2

  10. Vue自定义组件之v-model的使用

    自定义组件之v-model的使用 v-model的语法糖可以为下面v-bind && @input联合完成: <input v-model="text"> ...