上一节介绍了激光雷达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. python 安装各种库的镜像

    让python pip使用国内镜像#国内源:#清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:https://mirrors.aliyun.com/py ...

  2. Day 006:PAT练习--1005 Spell It Right (20 分)

    上星期一直在写报告乱七八糟的,从今天开始不刷乙级的了,还是多刷甲级进步来得快一点! 显而易见,该题的关键在于将输入之和的每一位从高到低输出,这里我们发现题意中的输入数的范围为0-10^100,显然我们 ...

  3. 灵感乍现!造了个与众不同的Dubbo注册中心扩展轮子

    hello大家好呀,我是小楼. 作为一名基础组件开发,服务好每一位业务开发同学是我们的义务(KPI). 客服群里经常有业务开发同学丢来一段代码.一个报错,而我们,当然要微笑服务,耐心解答. 有的问题, ...

  4. Java Web实现用户登录功能

    java web 学习记录一下 mvc结构实现mysql 连接 什么是mvc MVC是模型(model).视图(view).控制(controller)这三个单词上的首字母组成.它是一种应用模型,它的 ...

  5. python3 Softmax函数

    Softmax函数公式 Softmax的作用简单的说就计算一组数值中每个值的占比 import torch import torch.nn.functional as F # 原始数据tensor y ...

  6. 团队Beta5

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 无 接下来的计划 无 **还剩下哪些任务 ...

  7. 详解:什么是VXLAN?

    点击上方"开源Linux",选择"设为星标"回复"学习"获取独家整理的学习资料! 本文介绍了什么是VXLAN,以及VXLAN的基本概念和工作 ...

  8. C#/VB.NET 在Excel单元格中应用多种字体格式

    在Excel中,可对单元格中的字符串设置多种不同样式,通常只需要获取到单元格直接设置样式即可,该方法设置的样式会应用于该单元格中的所有字符.如果需要对单元格中某些字符设置样式,则可以参考本文中的方法. ...

  9. 如何使用Python实现图像融合及加法运算?

    摘要:本篇文章主要讲解Python调用OpenCV实现图像融合及加法运算,包括三部分知识:图像融合.图像加法运算.图像类型转换. 本文分享自华为云社区<[Python图像处理] 五.图像融合.加 ...

  10. 透过实例demo带你认识gRPC

    摘要:gRPC是基于定义一个服务,指定一个可以远程调用的带有参数和返回类型的的方法.在服务端,服务实现这个接口并且运行gRPC服务处理客户端调用. 本文分享自华为云社区<gRPC介绍以及spri ...