机器人--里程计

教程

轮式里程计视频讲解

里程计分类

ros--odometry

什么是里程计

里程计是一种利用从移动传感器获得的数据来估计物体位置随时间的变化而改变的方法。该方法被用在许多机器人系统来估计机器人相对于初始位置移动的距离

注意:里程计是一套算法,不是物理硬件。

作用

机器人相对于初始位置移动的位姿信息。

在ros中,通过发布里程计话题odom,其他模块可以订阅这个话题的数据,获取机器人实时的位姿信息。

里程计和TF

既然里程计话题发布机器人的位姿信息,TF也是发布机器人位姿信息,为什么不发布里程计话题就可以了,还要计算出里程之后再发布tf?

特性里程计话题TF(Transform)
数据内容包含位姿(pose)和速度(twist),通常带协方差仅包含坐标系间的刚性变换(平移+旋转)
主要用途提供里程计的完整运动状态(供算法使用)提供坐标系间的空间关系(供可视化、传感器融合等使用)
消费者导航算法(如EKF、路径规划)RViz、传感器数据处理节点、多坐标系协作模块
更新频率通常较低(10-50Hz,取决于传感器)通常较高(与TF广播频率一致,可能100Hz+)
话题名称

不固定,不同的机器人可以使用不同的里程计话题名称,创建话题时需要质地的那个话题名称。

订阅的时候也通过话题名称订阅。

固定话题名称,/tf和/tf_static。所有的TF变化都通过这两个话题发布,再通过looup_transform订阅指定两个坐标系的TF。
RVIZ插件Odometry插件TF插件

RVIZ对TF的依赖要更强些。

里程计在ros中的作用

ros2中的里程计odometry:

# 包含父ID
std_msgs/Header header# 子ID,即姿势所在的坐标系
string child_frame_id# 通常相对于父坐标的估计姿态.
geometry_msgs/PoseWithCovariance pose# 在子坐标系中的线速度和角速度.
geometry_msgs/TwistWithCovariance twist

ros2中的里程计是需要通过传感器比如编码器,IMU等获取机器人的线速度,角速度,加速度等信息来完成填充odometry接口中的数据,之后再以话题的方式发布出去

可见ros2中的里程计不仅可以发布机器人的当前位姿,还包括机器人的线速度和角速度等信息。

里程计的分类

轮式里程计

轮式里程计是通过电机编码器反馈电机转速,再利用电机转速和减速比等物理参数计算出小车轮子的转速,再通过运动学正解计算小车整体的线速度和角速度,也就是里程计需要发布的参数的。

角度累计

不断累计机器人绕Y轴转动的角度yam,其实根据三角函数计算式可知,超过180度就是计算-180度内的角度,超过-180度就是计算180度内的角度,所以,机器人转一圈的范围也就是0~180或者0~-180之间,为了防止角度溢出,我们只需要控制角度累计的角度再-180~180之间即可。

两轮差速位置累计

delta_th = vth * dt;
odom_th_ += delta_th; // 角度累计--姿态累计
delta_x = vx * cos(odom_th_) * dt; // 位姿累计
delta_y = vx * sin(odom_th_) * dt;

适用对象: 专为 两轮差分驱动机器人 设计(如TurtleBot),假设机器人 只有X方向线速度(vx)和Z轴角速度(vth,Y方向速度始终为0。

对于差分驱动机器人:

  1. Y方向速度恒为0(不能横向移动),因此 Y * sin(pZ)Y * cos(pZ) 项为0。

  2. dt 很小,角度变化 delta_th 对位移的影响可忽略,此时方法1是方法2的近似。

通用2D位置累计

pZ += Z * Sampling_Time; // 角度累计
pX += (X * cos(pZ) - Y * sin(pZ)) * Sampling_Time; // 位置累计
pY += (X * sin(pZ) + Y * cos(pZ)) * Sampling_Time;

适用对象: 适用于 任何2D平面运动的机器人(如全向轮、麦克纳姆轮机器人),支持 X/Y方向线速度(X, Y)和Z轴角速度(Z

哪种更准确?

  • 如果机器人 严格两轮差分驱动,且 dt 足够小: 两种方法等效(因为 Y=0,方法2退化为方法1)。

  • 如果机器人 有Y方向速度dt 较大: 必须用方法2,否则会忽略旋转对位移的耦合影响。

  • 如果机器人 快速旋转vth较大): 方法2更准确,方法1会引入误差。

里程累计

里程累计包括位置,即X轴位置和Y轴位置累计和角度累计,三者共同表示机器人的位姿。

注意:一定要线角度累计,再利用累计的角度计算位置累计。

惯性里程计

视觉里程计

激光里程计

ros中的实现--odometry

odometry:

# 包含父ID
std_msgs/Header header# 子ID,即姿势所在的坐标系
string child_frame_id# 通常相对于父坐标的估计姿态.
geometry_msgs/PoseWithCovariance pose# 在子坐标系中的线速度和角速度.
geometry_msgs/TwistWithCovariance twist
odom.child_frame_id = robot_frame_id; 	#里程计TF子坐标
odom.twist.twist.linear.x =  X; # X方向速度
odom.twist.twist.linear.y =  Y; # Y方向速度
odom.twist.twist.angular.z = Z; # 绕Z轴角速度

角速度可以通过IMU获取,或者通过编码器和运动学正解获取机器人整体角速度和线速度,那么XY方向的线速度怎么获取呢?

在轮式里程计中,计算出机器人整体的角速度和线速度之后,可以利用角速度计算出这段时间内的总的旋转角度,再通过总的旋转角度计算出线速度再XY轴上各自的分量,各自分速度再和时间积分就是位置里程。

delta_th = vth * dt;
odom_th_ += delta_th; // 角度累计--姿态累计
delta_x = vx * cos(odom_th_) * dt; // 位姿累计
delta_y = vx * sin(odom_th_) * dt;

里程计和TF广播

里程计是如何完成TF广播的?

里程计代表机器人的位置相对于初始位置的累加变化,即机器人当前位姿。

TF(动态)广播器记录和发布的是两个坐标系之间的实时平移和旋转的坐标系变换关系。

  tf2::Quaternion q;q.setRPY(0, 0, odom_th_); // odom_th_是yam旋转角累计// 发布里程计话题,用于算法odom_publisher_->publish(odom_msg);// 之后发布TF,用于RVIZ坐标变换geometry_msgs::msg::TransformStamped t;t.header.stamp = this->get_clock()->now();t.header.frame_id = "odom";t.child_frame_id = "base_footprint";t.transform.translation.x = odom_x_;t.transform.translation.y = odom_y_;t.transform.translation.z = 0.0;t.transform.rotation.x = q[0];t.transform.rotation.y = q[1];t.transform.rotation.z = q[2];t.transform.rotation.w = q[3];if (pub_odom_) {// 广播里程计TFtf_broadcaster_->sendTransform(t);}

里程计话题发布

1,创建话题

2,创建话题消息

消息类型:

nav_msgs/msg/Odometry

# 消息中的 pose(位姿) 应该由 header.frame_id 给出的坐标系指定。 
# 消息中的 twist(速度信息) 应该由 child_frame_id 给定的坐标系来指定。# 包含位姿的父坐标系的 frame_id。
- 这是一个标准的 ROS 2 消息头(Header),包含时间戳和父坐标系 ID。
- `header.frame_id` 表示 **位姿(pose)所在的参考系**,也就是“父坐标系”。
std_msgs/Header headerbuiltin_interfaces/Time stampint32 secuint32 nanosecstring frame_idstring child_frame_id# 估计的位姿,通常是相对于一个固定的全局世界坐标系。
geometry_msgs/PoseWithCovariance posePose posePoint positionfloat64 xfloat64 yfloat64 zQuaternion orientationfloat64 x 0float64 y 0float64 z 0float64 w 1float64[36] covariance# 估计的线速度和角速度是相对于子坐标系的。
geometry_msgs/TwistWithCovariance twistTwist twistVector3  linearfloat64 xfloat64 yfloat64 zVector3  angularfloat64 xfloat64 yfloat64 zfloat64[36] covariance

1. std_msgs/Header header

  • 作用:消息的头部信息,包含时间戳和参考坐标系。

    • stamp (builtin_interfaces/Time):

      • sec:时间戳的秒部分(Unix时间)。

      • nanosec:时间戳的纳秒部分(0~999,999,999)。

      • 用途:标识里程计数据的时间点,用于与其他传感器数据同步。

    • frame_id (string):

      • 值示例"odom"

      • 用途:既是里程计的父坐标系,也是pose的参考坐标系,也就是pose的父坐标系,也就是pose是child_frame_id这个坐标系相对于frame_id这个坐标系的pose。

2. string child_frame_id

  • 作用:指定机器人本体的坐标系。

    • 值示例"base_footprint""base_link"

    • 用途:里程计子坐标系,也就是机器人本体坐标系,也是pose和速度信息所在坐标系。

3. geometry_msgs/PoseWithCovariance pose

  • 作用:机器人相对于全局坐标系的位姿(位置+朝向)及其不确定性。

    • pose (geometry_msgs/Pose):

      • position (Point):

        • x, y, z:3D位置坐标(单位:米)。

        • 注意:对于地面机器人,z 通常为0(除非有高度变化)。

      • orientation (Quaternion):

        • x, y, z, w:四元数表示朝向(需归一化)。

        • 默认值(0, 0, 0, 1) 表示无旋转(朝向与父坐标系一致)。

    • covariance (float64[36]):

      • 位姿的6x6协方差矩阵(按行优先排列),表示不确定性:

[x_var, xy, xz, x_roll, x_pitch, x_yaw,xy, y_var, yz, y_roll, y_pitch, y_yaw,...]

4. geometry_msgs/TwistWithCovariance twist

  • 作用:机器人本体的线速度和角速度及其不确定性。

    • twist (geometry_msgs/Twist):

      • linear (Vector3):

        • x:前进速度(单位:米/秒,正值为前进)。

        • y:横向速度(正值为左移,差分驱动机器人通常为0)。

        • z:垂直速度(地面机器人通常为0)。

      • angular (Vector3):

        • x:横滚角速度(绕X轴旋转,地面机器人通常为0)。

        • y:俯仰角速度(绕Y轴旋转,地面机器人通常为0)。

        • z:偏航角速度(绕Z轴旋转,单位:弧度/秒,正值为逆时针)。

    • covariance (float64[36]):

      • 速度的6x6协方差矩阵(排列方式同 pose.covariance)。

      • 用途:描述速度测量的噪声特性(如IMU误差)。

协方差的选择

const double odom_pose_covariance[36]   = {1e-3,    0,    0,   0,   0,    0, 0, 1e-3,    0,   0,   0,    0,0,    0,  1e6,   0,   0,    0,0,    0,    0, 1e6,   0,    0,0,    0,    0,   0, 1e6,    0,0,    0,    0,   0,   0,  1e3 };const double odom_pose_covariance2[36]  = {1e-9,    0,    0,   0,   0,    0, 0, 1e-3, 1e-9,   0,   0,    0,0,    0,  1e6,   0,   0,    0,0,    0,    0, 1e6,   0,    0,0,    0,    0,   0, 1e6,    0,0,    0,    0,   0,   0, 1e-9 };const double odom_twist_covariance[36]  = {1e-3,    0,    0,   0,   0,    0, 0, 1e-3,    0,   0,   0,    0,0,    0,  1e6,   0,   0,    0,0,    0,    0, 1e6,   0,    0,0,    0,    0,   0, 1e6,    0,0,    0,    0,   0,   0,  1e3 };const double odom_twist_covariance2[36] = {1e-9,    0,    0,   0,   0,    0, 0, 1e-3, 1e-9,   0,   0,    0,0,    0,  1e6,   0,   0,    0,0,    0,    0, 1e6,   0,    0,0,    0,    0,   0, 1e6,    0,0,    0,    0,   0,   0, 1e-9} ;
什么是协方差矩阵?

在概率机器人学中,协方差矩阵用来表示某个状态变量的不确定性。数值越大,说明该维度上的测量或估计越不可靠。

位姿协方差结构:

[ x_x, x_y, x_z, x_roll, x_pitch, x_yaw,  // x可靠性y_x, y_y, y_z, y_roll, y_pitch, y_yaw, // y可靠性z_x, z_y, z_z, z_roll, z_pitch, z_yaw, // z可靠性roll_x, roll_y, roll_z, roll_roll, roll_pitch, roll_yaw, // roll可靠性pitch_x, pitch_y, pitch_z, pitch_roll, pitch_pitch, pitch_yaw, // pitch可靠性yaw_x, yaw_y, yaw_z, yaw_roll, yaw_pitch, yaw_yaw ] // yaw可靠性

{1e-3,   0,   0,    0,    0,    0, 0, 1e-3,   0,    0,    0,    0,0,   0, 1e6,    0,    0,    0,0,   0,   0,  1e6,    0,    0,0,   0,   0,    0,  1e6,    0,0,   0,   0,    0,    0,  1e3}
维度含义说明
xy1e-3X、Y 位置估计较准确
z1e6Z 轴方向不关心或不可靠(如地面机器人)
rollpitch1e6不依赖或无法测量
yaw1e3偏航角有一定误差
  • xy方向:高精度(方差=0.001,置信度高)。

  • z方向:极低精度(方差=1e6,表示忽略此方向,适用于地面机器人)。

  • 旋转(rollpitch):极低精度(方差=1e6,通常地面机器人不关心俯仰/横滚)。

  • yaw方向:中等精度(方差=1000,适用于航向角估计)。

这是一个典型的 2D 地面机器人位姿协方差矩阵

{1e-9,   0,   0,    0,    0,    0, 0, 1e-3,1e-9,    0,    0,    0,0,   0, 1e6,    0,    0,    0,0,   0,   0,  1e6,    0,    0,0,   0,   0,    0,  1e6,    0,0,   0,   0,    0,    0, 1e-9}
  • 移动的x和旋转的yaw方向:极高精度(方差=1e-9,几乎完全信任)。

位姿协方差结构类似,但表示速度的不确定性(数据可靠性)。

-- 机器人禁止使用高可靠性协方差;运动姿态使用低可靠性协方差。

3,发布

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

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

相关文章

云原生时代 Kafka 深度实践:02快速上手与环境搭建

2.1 本地开发环境搭建 单机模式安装 下载与解压:前往Apache Kafka 官网,下载最新稳定版本的 Kafka 二进制包(如kafka_2.13-3.6.0.tgz,其中2.13为 Scala 版本)。解压到本地目录,例如/opt/kafka&#xff1a…

Vue Hook Store 设计模式最佳实践指南

Vue Hook Store 设计模式最佳实践指南 一、引言 在 Vue 3 组合式 API 与 TypeScript 普及的背景下,Hook Store 设计模式应运而生,它结合了 Vue 组合式 API 的灵活性与状态管理的最佳实践,为开发者提供了一种轻量级、可测试且易于维护的状态…

无人机多人协同控制技术解析

一、运行方式 无人机多人点对点控制通常采用以下两种模式: 1. 主从控制模式 指定一个主控用户拥有最高优先级,负责飞行路径规划、紧急操作等关键指令;其他用户作为观察者,仅能查看实时画面或提交辅助指令,需经主…

树型表查询方法 —— SQL递归

目录 引言: 自链接查询: 递归查询: 编写service接口实现: 引言: 看下图,这是 course_category 课程分类表的结构: 这张表是一个树型结构,通过父结点id将各元素组成一个树。 我…

微服务难题?Nacos服务发现来救场

文章目录 前言1.什么是服务发现2.Nacos 闪亮登场2.1 服务注册2.2 服务发现 3.Nacos 的优势3.1 简单易用3.2 高可用3.3 动态配置 4.实战演练4.1安装 Nacos4.2 服务注册与发现示例代码(以 Spring Boot 为例) 总结 前言 大家好,我是沛哥儿。今天…

AStar低代码平台-脚本调用C#方法

修改报工表表单&#xff0c;右键定义弹出菜单&#xff0c;新增一个菜单项&#xff0c;并在点击事件脚本中编写调用脚本。 编译脚本&#xff0c;然后在模块代码里面定义这个方法&#xff1a; public async Task<int> on_call_import(DataRow curRow) {PrintDataRow(cur…

python调用langchain实现RAG

一、安装langchain 安装依赖 python -m venv env.\env\Scripts\activatepip3 install langchainpip3 install langchain-corepip3 install langchain-openaipip3 install langchain-communitypip3 install dashscopepip3 install langchain_postgrespip3 install "psyc…

大学大模型教学:基于NC数据的全球气象可视化解决方案

引言 气象数据通常以NetCDF(Network Common Data Form)格式存储,这是一种广泛应用于科学数据存储的二进制文件格式。在大学气象学及相关专业的教学中,掌握如何读取、处理和可视化NC数据是一项重要技能。本文将详细介绍基于Python的NC数据处理与可视化解决方案,包含完整的代…

ORB-SLAM2学习笔记:ComputeKeyPointsOctTree分析过程记录

ComputeKeyPointsOctTree是ORB特征提取器中计算关键点的部分&#xff0c;特别是使用八叉树&#xff08;OctTree&#xff09;方法进行关键点分布。 首先&#xff0c;函数参数是vector<vector的引用allKeypoints&#xff0c;用来存储各层的关键点。代码开头调整了allKeypoint…

LeetCode Hot100(多维动态规划)

62. 不同路径 比较板子的dp&#xff0c;实际上就是到达一个点有两种方式&#xff0c;从上面来或者是左边&#xff0c;加起来就可以了 class Solution {public int uniquePaths(int m, int n) {int [][]arr new int[m2][n2];arr[1][1]1;for(int i1;i<m;i){for(int j1;j<…

Oracle MOVE ONLINE 实现原理

Oracle MOVE ONLINE 实现原理 Oracle 的 MOVE ONLINE 操作是一种在线重组表的技术&#xff0c;允许在不中断业务的情况下重新组织表数据。以下是其实现原理的详细分析&#xff1a; 基本概念 MOVE ONLINE 是 Oracle 12c 引入的特性&#xff0c;用于替代传统的 ALTER TABLE ..…

工作流长任务处置方案

以下是前后端协作处理长任务工作流的完整实现方案&#xff0c;结合技术选型与设计要点&#xff0c;以清晰结构呈现&#xff1a; 一、后端实现方案 异步任务队列架构 • 技术选型&#xff1a; ◦ 消息队列&#xff1a;NATS&#xff08;轻量级&#xff09;或 RabbitMQ&#xf…

RabbitMQ仲裁队列高可用架构解析

#作者&#xff1a;闫乾苓 文章目录 概述工作原理1.节点之间的交互2.消息复制3.共识机制4.选举领导者5.消息持久化6.自动故障转移 集群环境节点管理仲裁队列增加集群节点重新平衡仲裁队列leader所在节点仲裁队列减少集群节点 副本管理add_member 在给定节点上添加仲裁队列成员&…

fingerprint2浏览器指纹使用记录

我在uniapp-vue3-H5端使用的&#xff0c;记录一下 抄的这里前端使用fingerprintjs2获取浏览器指纹fingerprintjs2是通过设备浏览器信息获取浏览器指纹的插件&#xff08; - 掘金 1、安装依赖 npm i fingerprintjs2 -S2、抽成模块文件&#xff0c;/utils/Fingerprint2.js 生成指…

深度学习面试八股简略速览

在准备深度学习面试时&#xff0c;你可能会感到有些不知所措。毕竟&#xff0c;深度学习是一个庞大且不断发展的领域&#xff0c;涉及众多复杂的技术和概念。但别担心&#xff0c;本文将为你提供一份全面的指南&#xff0c;从基础理论到实际应用&#xff0c;帮助你在面试中脱颖…

使用 Redis 作为向量数据库

一、什么是向量数据库&#xff1f; 向量&#xff08;Vector&#xff09;&#xff1a;在机器学习和 AI 中&#xff0c;向量是由一系列数字组成的序列&#xff0c;用于数值化地描述数据的特征或语义。文本、图像、音频等非结构化数据可以通过模型转换成固定长度的向量。 向量数据…

变量的计算

不同类型变量之间的计算 数字型变量可以直接计算 在python中&#xff0c;数字型变量可以直接通过算术运算符计算bool型变量&#xff1a;True 对应数字1 &#xff1b;False 对应数字0、 字符串变量 使用 拼接字符串 使用 * 拼接指定倍数的相同字符串 变量的输入&#xff1a;&…

PostgreSQL学会如何建表

开始使用PostgreSQL之前&#xff0c; 上一节我们说了怎样安装它。 PostgreSQL可能已经安装到你的电脑上了,安装后postgre服务默认在电脑开机时运行启动。 一.了解PostgreSQL的运行 PostgreSQL使用一种客户端/服务器&#xff08;C/S&#xff09;模型。 和其他典型的客户端/服务…

Linux驱动学习笔记(十)

热插拔 1.热插拔&#xff1a;就是带电插拔&#xff0c;即允许用户在不关闭系统&#xff0c;不切断电源的情况下拆卸或安装硬盘&#xff0c;板卡等设备。热插拔是内核和用户空间之间&#xff0c;通过调用用户空间程序实现交互来实现的&#xff0c;当内核发生了某种热拔插事件时…

大模型应用开发第五讲:成熟度模型:从ChatGPT(L2)到未来自主Agent(L4)

大模型应用开发第五讲&#xff1a;成熟度模型&#xff1a;从ChatGPT&#xff08;L2&#xff09;到未来自主Agent&#xff08;L4&#xff09; 资料取自《大模型应用开发&#xff1a;动手做AI Agent 》。 查看总目录&#xff1a;学习大纲 关于DeepSeek本地部署指南可以看下我之…