移动机器人激光SLAM导航(三):Hector SLAM 篇

news2024/10/7 10:22:17

参考引用

  • Hector_Mapping ROS-Wiki
  • 从零开始搭二维激光SLAM
  • 机器人工匠阿杰
  • wpr_simulation

移动机器人激光SLAM导航(文章链接汇总)

1. 基于滤波器的 SLAM 问题

1.1 什么是 SLAM

  • 什么是SLAM

  • SLAM 就是为了构建地图用的,这个地图可以保存下来,用于后续的定位及导航避障中,也有一些 SLAM 作为里程计在使用,始终提供估计的位姿,目前主流 SLAM 的结构分为前端里程计,后端优化,回环检测三个大模块

    • 前端里程计:始终累加位姿,作为里程计使用
    • 后端优化:使用图的结构模型,优化整体位姿,减小前端里程计产生的累计误差
    • 回环检测:可以提供一个更强烈的图结构的约束,能够更好的减小累计误差

1.2 SLAM 问题的数学表述

  • 运动方程(提供对状态 x x x 的先验 x k − 1 x_{k-1} xk1,正向推理)
    • 其中 x x x 位姿, k − 1 / k k-1/k k1/k 时刻, u u u 控制器输入/运动测量, w w w 噪声

x k = f ( x k − 1 , u k , w k ) x_k=f(x_{k-1}, u_k, w_k) xk=f(xk1,uk,wk)

  • 观测方程(提供对状态 x x x 的后验 x k x_k xk,由果溯因)
    • 其中 z z z 传感器读数, y y y 路标, j j j 路标编号, v v v 噪声

z k , j = h ( y j , x k , v k , j ) z_{k,j}=h(y_j, x_k, v_{k,j}) zk,j=h(yj,xk,vk,j)

  • 已知量:上一时刻位姿 x k − 1 x_{k-1} xk1,控制器输入/运动测量 u k u_k uk,当前时刻对路标 j j j 的观测 z k , j z_{k,j} zk,j
  • 估计量:当前时刻机器人位姿 x k x_k xk(定位),路标 j j j 的位置 y j y_j yj(建图)

1.3 SLAM 概率模型

  • SLAM(Simultaneous Localization and Mapping):给定传感器数据情况下,同时进行机器人位姿和地图估计

    • 得到一个精确的位姿需要与地图进行匹配
    • 得到一个良好的地图需要有精确的位姿
  • SLAM 条件联合概率分布

    • 1 : t 1:t 1:t 表示从起始到 t 时刻
    • z 1 : t z_{1:t} z1:t 表示传感器观测数据(如 /scan)
    • u 1 : t u_{1:t} u1:t 表示里程计测量数据(如 /odom)
    • m m m 表示地图, x 1 : t x_{1:t} x1:t 表示机器人轨迹/位姿估计(定位)

p ( x 1 : t , m ∣ z 1 : t , u 1 : t − 1 ) p(x_{1:t},m|z_{1:t},u_{1:{t-1}}) p(x1:t,mz1:t,u1:t1)

2. Hector_Mapping

2.1 简介

  • Hector_Mapping 是一种无需里程计数据的 SLAM 方法,利用激光雷达获得二维姿态估计,虽然没有回环检测功能,但对于大多真实场景,它是较准确的,该系统已用于无人地面机器人/车辆、手持测绘设备、四旋翼无人机

  • 硬件要求

    • 需要高精度的激光扫描仪(SICK、hokuyo 等),扫描周围环境时,节点会使用 TF 变换,因此无需将雷达固定,并且不需要里程计数据

2.2 话题节点

  • 订阅的话题(Topic)
    • scan (sensor_msgs/LaserScan):订阅 2D 激光雷达扫描数据
    • syscommand (std_msgs/String):如果字符串等于 “reset”,则地图和机器人姿态将重置为初始状态
  • 发布的话题(Topic)
    • map_metadata (nav_msgs/MapMetaData):发布 Meta 地图数据(存储地图描述信息
    • map (nav_msgs/OccupancyGrid):发布占据栅格地图数据
    • slam_out_pose (geometry_msgs/PoseStamped):原始的机器人位姿(无协方差)
    • poseupdate (geometry_msgs/PoseWithCovarianceStamped):校正后的机器人位姿(具有不确定性的高斯估计)
  • Service
    • dynamic_map (nav_msgs/GetMap):获取地图数据
    • reset_map (std_srvs/Trigger):调用这个服务来重置地图,Hector_Mapping 将从头开始一张全新的地图。注意,这不会重新启动机器人的姿势,而是会从上次记录的姿势重新开始
    • pause_mapping (std_srvs/SetBool):调用此服务来停止/开始处理激光扫描
    • restart_mapping_with_new_pose (hector_mapping/ResetMapping):调用此服务来重置地图、机器人的姿势并恢复建图(如果暂停)

2.3 TF 变换

  • 必要的 TF 变换

    • <scan frame> → base_frame:通常为固定值,激光雷达坐标系 与 基坐标系 之间的变换,一般由 robot_state_publisher 或 static_transform_publisher 发布
  • 发布的 TF 变换

    • map → odom:地图坐标系 与 里程计坐标系 之间的变换,估计机器人在地图中的位姿(仅在参数 “pub_map_odom_transform” 为 true 时提供)
  • ROS 中常用坐标系

    • map:地图坐标系,也被称为世界坐标系,是静止不动的
    • odom:里程计坐标系,相对于 map 来说一般是静止的,有些情况下会变动(定位节点为了修正机器人的位姿从而改变了 map->odom 间的坐标变换)
    • base_footprint:位于机器人底盘中心在地面的投影,不提供高度信息,代表机器人的 2D 位姿
    • base_link:位于机器人几何中心,与机器人刚性连接,相对于 base_stabilized 坐标系增加了横滚角和俯仰角
    • base_stabilized:坐标系添加了机器人相对于 map/odom 层的高度信息(对于没有横滚/俯仰运动的平台,base_stabilized 等价于 base_link)
    • laser_link:激光雷达的坐标系,相对于base_link来说是静止的,因为雷达装在机器人上
      在这里插入图片描述

2.4 建图测试

在这里插入图片描述

本小节使用 移动机器人激光SLAM导航(二):运动控制与传感器篇 中安装的测试环境 wpr_simulation(hector_mapping 已在此环境中通过脚本安装)

  • 在 wpr_ws 工作空间新建功能包 slam_pkg
    $ cd ~/wpr_ws/src
    $ catkin_create_pkg slam_pkg roscpp rospy std_msgs
    $ code .      # 在 VSCode 中编辑
    
  • 在 slam_pkg 中新建 launch 文件夹,并在 launch 文件夹中新建 hector.launch 文件
    <launch>
        <!-- 载入机器人和 SLAM 仿真环境 -->
        <!-- 如果使用实体机器人,则将下行代码替换为启动激光雷达和底盘控制的 launch 文件即可 -->
        <include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch" />
    
        <!-- Hector SLAM 节点 -->
        <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping" />
    
        <!-- rviz 显示 -->
        <!-- 其中 args 是运行该 launch 文件并在 rviz 中添加相关选项后保存的配置文件 -->
        <node pkg="rviz" type="rviz" name="rviz" args="-d $(find slam_pkg)/rviz/slam.rviz" />
    
        <!-- 机器人运动控制节点 -->
        <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering" />
    </launch>
    
  • 编译并启动 hector.launch 建图
    $ cd ~/wpr_ws
    $ catkin_make
    $ source devel/setup.bash
    $ roslaunch slam_pkg hector.launch
    

在这里插入图片描述

2.5 建图参数设置 Parameters

  • ~map_update_distance_thresh (double, default: 0.4)

    • 地图更新的移动距离阈值 [单位:米],越小则更新越快
    • 每次地图更新后,机器人必须移动超过这个阈值,或满足 map_update_angle_thresh 参数描述的位移角度变化,才会再次更新地图
  • ~map_update_angle_thresh (double, default: 0.9)

    • 地图更新的旋转角度闯值 [单位:弧度],越小则更新越快
    • 每次地图更新后,机器人必须转动超过这个阈值,并产生超过 map_update_distance_thresh 阈值的位移才会再次更新地图
  • ~map_pub_period (double, default: 2.0)

    • 地图发布的周期 [单位:秒]
<launch>
    <include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch" />
    
    <!-- Hector SLAM 节点 -->
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping">
        <param name="map_update_distance_thresh" value="0.1" />
        <param name="map_update_angle_thresh" value="0.1" />
        <param name="map_pub_period" value="0.1" />
    </node>

    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find slam_pkg)/rviz/slam.rviz" />

    <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering" />

</launch>

其他参数请参考 Hector_Mapping ROS-Wiki

  • 调参效果对比 wpb_hector_comparison.launch
<launch>
  <!-- 第一个 Hector_Mapping 建图节点 -->
  <group ns="slam_1">
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping_1">

      <param name="map_update_distance_thresh" value="0.5"/>
      <param name="map_update_angle_thresh" value="0.5" />
      <param name="map_pub_period" value="0.2" />
      
      <param name="map_frame" value="slam_1/map" />
      <param name="base_frame" value="slam_1/base_footprint" />
      <param name="odom_frame" value="slam_1/odom" />
    </node>
  </group>

  <!-- 第二个 Hector_Mapping 建图节点 -->
  <group ns="slam_2">
    <node pkg="hector_mapping" type="hector_mapping" name="hector_mapping_2">

      <param name="map_update_distance_thresh" value="0.1"/>
      <param name="map_update_angle_thresh" value="0.1" />
      <param name="map_pub_period" value="0.2" />

      <param name="map_frame" value="slam_2/map" />
      <param name="base_frame" value="slam_2/base_footprint" />
      <param name="odom_frame" value="slam_2/odom" />
    </node>
  </group>

  <!-- **************************** 分割线 **************************** -->

  <!-- 载入 SLAM 的仿真场景 -->
  <include file="$(find gazebo_ros)/launch/empty_world.launch">
  <arg name="world_name" value="$(find wpr_simulation)/worlds/slam_simple.world"/>
  <arg name="paused" value="false"/>
  <arg name="use_sim_time" value="true"/>
  <arg name="gui" value="true"/>
  <arg name="recording" value="false"/>
  <arg name="debug" value="false"/>
  </include>

  <!-- 载入 1号机器人 -->
  <include file="$(find wpr_simulation)/launch/wpb_slam_template.launch">
      <arg name="robot_namespace" value="slam_1" /> 
      <arg name="local_x" value="0" /> 
      <arg name="local_y" value="-0.3" /> 
      <arg name="local_yaw" value="0" /> 
  </include>

  <!-- 载入 2号机器人 -->
  <include file="$(find wpr_simulation)/launch/wpb_slam_template.launch">
      <arg name="robot_namespace" value="slam_2" /> 
      <arg name="local_x" value="0" /> 
      <arg name="local_y" value="0.3" /> 
      <arg name="local_yaw" value="0" /> 
  </include>

  <!-- 运动控制 -->
  <node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering"/>

  <!-- 速度话题分流 -->
  <node pkg = "topic_tools" type = "relay" name = "relay_1" args="/cmd_vel /slam_1/cmd_vel" />
  <node pkg = "topic_tools" type = "relay" name = "relay_2" args="/cmd_vel /slam_2/cmd_vel" />

</launch>

3. TF 和 里程计

3.1 TF 系统

  • 地面移动机器人在地图中的位姿描述方式(x, y, yaw)
    在这里插入图片描述

  • ROS 中通过 TF(TransForm,坐标系变换) 来获取机器人具体的定位/位姿数值

    • TF 主要用于描述两个坐标系之间的空间关系
    • TF 关系由特定的 ROS 节点以消息包的形式发布到 /tf 话题中去,其他节点通过订阅这个 /tf 话题来查询坐标系
  • 案例测试

    # 利用 2.4 小节创建的 hector 建图包
    $ cd ~/wpr_ws
    $ source devel/setup.bash
    $ roslaunch slam_pkg hector.launch
    

在这里插入图片描述

  • 查看 /tf 话题类型
    $ rostopic type /tf
    tf2_msgs/TFMessage
    

在这里插入图片描述


在这里插入图片描述

  • 查看 /tf 话题数值

    $ rostopic echo /tf
    ...
    ---
    transforms: 
      - 
        header: 
          seq: 0
          stamp: 
            secs: 780
            nsecs: 481000000
          frame_id: "map"
        child_frame_id: "scanmatcher_frame"
        transform: 
          translation: 
            x: 2.27857303619
            y: 1.645611763
            z: 0.0
          rotation: 
            x: 0.0
            y: 0.0
            z: -0.352547165132
            w: 0.935794045908
    ...
    
  • 查看 TF 关系树

    $ rosrun rqt_tf_tree rqt_tf_tree
    

在这里插入图片描述

3.2 里程计

本小节使用 移动机器人激光SLAM导航(二):运动控制与传感器篇 中安装的测试环境

  • hector_mapping 在长直走廊建图
    • 由于缺少参照物特征的变化,导致机器人无法估计自己的位移,建图失败
    • 解决办法:轮子转过的圈数×轮子周长=走过的距离(轮子里程计算法
    $ cd ~/wpr_ws
    $ source devel/setup.bash
    $ roslaunch wpr_simulation wpb_corridor_hector.launch
    

在这里插入图片描述

  • GMapping 在长直走廊建图
    • 由于 GMapping 自带里程计算法,在里程计的帮助下,激光 SLAM 有效克服了建图过程中位移特征缺失的问题
    $ cd ~/wpr_ws
    $ source devel/setup.bash
    $ roslaunch wpr_simulation wpb_corridor_gmapping.launch
    

在这里插入图片描述

  • 激光雷达和里程计输出的 TF 坐标变换关系
    • 激光雷达:map --> base_footprint
    • 里程计:odom --> base_footprint
    • GMapping 的核心算法:先使用里程计推算机器人的位移,再使用激光雷达点云配准算法来修正里程计误差(如:轮子打滑) map --> odom --> base_footprint
      在这里插入图片描述

更直观化的里程计演示请查看视频 什么是里程计

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

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

相关文章

【python接口自动化】- DDT数据驱动测试

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

第一讲:入门python

第一讲&#xff1a;入门python1.安装Python1.下载2.安装3.运行4.代码 2.安装VS code 第一讲&#xff1a;入门python 本讲任务&#xff1a; 安装python安装VS code Python初学者通常首次面临的主要问题是需要在计算机上安装Python和一个适用的代码编辑器&#xff08;比如VSco…

龙芯--自主架构先驱者

&#x1f6d1; 这是ren_dong的第23篇原创 1、概述 自主可控最高的 MIPS 架构 CPU 龙芯是我国最早研制的高性能通用处理器系列&#xff0c;拥有 MIPS 指令的永久授权&#xff0c;并拓展出了自己的指令集loong ISA。龙芯采用自主 Loong ISA 指令系统&#xff0c;兼容 MIPS 指令&a…

OpenCV学习记录——形态学处理

文章目录 前言一、腐蚀和膨胀二、高级形态学运算三、具体应用代码 前言 形态学是图像处理中最常用的技术之一&#xff0c;它主要用于从图像中提取有意义的形状信息&#xff0c;例如边界和连通区域&#xff0c;以便后续的识别工作能够捕捉到目标对象最重要的形状特征。此外&…

为什么飞凌嵌入式的FET527N-C核心板更值得期待?

在高度数字化的智能时代&#xff0c;嵌入式系统在各个领域都发挥着重要作用&#xff0c;因此在项目的选型与开发中选择与需求更为匹配的核心板主控至关重要。飞凌嵌入式最新发布的FET527N-C核心板是一款值得特别关注的产品&#xff0c;具有许多令人瞩目的优势。下面小编将从四个…

arcgis自定义dem高程实现地形抬高 - 操作矢量,转tin、adf(tif),cesiumlab切高程服务

这次记录分享一下arcgis自定义高程全过程 /(ㄒoㄒ)/~~ 我的场景&#xff1a;前端实现地面抬高效果 自定义高程实现地形抬高 一、数据处理 - arcgis操作矢量1、准备工作&#xff08;可选&#xff09;2、绘制外围矢量&#xff08;可选&#xff09;3、操作矢量数据 二、创建tin - …

第8章 磁盘管理

第8章 磁盘管理 8.1 标准磁盘管理 8.1.1 两种分区格式 MBR&#xff08;Master Boot Record&#xff0c;主引导分区&#xff09;&#xff0c;支持 4 个主分区或者 3 个主分区 1 个扩展分区&#xff0c;分区的空间最大支持 2.2 TB。 GPT&#xff08;GUID Partition Table&…

IS-ISv6配置

正文共&#xff1a;1024 字 12 图&#xff0c;预估阅读时间&#xff1a;1 分钟 上篇文章中&#xff08;OSPFv6配置&#xff09;&#xff0c;我们介绍了OSPFv3的基本配置方式&#xff0c;文中提到&#xff0c;OSPFv3是基于链路运行的&#xff0c;和IS-IS协议比较像。那既然和IS-…

中二少年工具箱(PC端)简介

同学们可以私信我加入学习群&#xff01; 正文开始 简介一、功能模块1.node版本管理工具 总结 简介 中二少年开发的中二少年工具箱&#xff0c;相信博主&#xff0c;功能不孬。 辅助自己开发工作&#xff0c;帮助新人快速入门&#xff0c;提供交互式文档辅助学习……如果还不…

⑩电子产品拆解分析-家用无线遥控开关433Mhz

⑩电子产品拆解分析-家用无线遥控开关433Mhz 一、功能介绍二、电路分析以及器件作用1、433发射控制端2、433接收应答端三、Get到的点一、功能介绍 ①免布线随意贴,装上就能使用解决单线开关烦恼;②遥控配对简单,无线通讯距离长,信号可穿墙;二、电路分析以及器件作用 1、43…

Spring Bean 定义常见错误

Spring 的核心是围绕 Bean 进行的。不管是 Spring Boot 还是 Spring Cloud&#xff0c;只要名称中带有 Spring 关键字的技术都脱离不了 Bean&#xff0c;而要使用一个 Bean 少不了要先定义出来&#xff0c;所以定义一个 Bean 就变得格外重要了。 当然&#xff0c;对于这么重要…

Node.js 目录穿越漏洞(CVE-2017-14849)

文章目录 Node.js 目录穿越漏洞&#xff08;CVE-2017-14849&#xff09;1. 漏洞原理2. 漏洞复现3. 漏洞验证4. 漏洞分析 Node.js 目录穿越漏洞&#xff08;CVE-2017-14849&#xff09; 1. 漏洞原理 原因是 Node.js 8.5.0 对目录进行normalize操作时出现了逻辑错误&#xff0c…

01- k8s基础网络知识 之 underlay与overlay网络

前言&#xff1a; 我们在学习k8s网络之前&#xff0c;必须要了解k8s网络相关的一些基础知识&#xff0c;比如什么是underlay网络、overlay网络等&#xff0c;只有把基础知识掌握之后&#xff0c;后续学习k8s网络的时候&#xff0c;一些知识点就不会再云里雾里了。 1 underlay与…

架构整洁之道-组件构建原则

5 组件构建原则 大型软件系统的架构过程与建筑物修建很类似&#xff0c;都是由一个个小组件组成的。所以&#xff0c;如果说SOLID原则是用于指导我们如何将砖块砌成墙与房间的&#xff0c;那么组件构建原则就是用来指导我们如何将这些房间组合成房子的。 5.1 组件 组件是软件的…

IntelliJ创建一个springboot工程

安装jdk mac教程 windows教程 安装maven mac教程 windows教程 建议&#xff1a; 在本地磁盘新建一个文件夹叫maven&#xff0c;然后把下载的maven安装到这里。在后续的IntelliJ操作中&#xff0c;配置maven的settings.xml和repository地址为这个目录下的地址。 创建sprin…

stack和queue及优先级队列和适配器(包括deque)的介绍

stack stack的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&#xff0c;并提供一组…

【INTEL(ALTERA)】为什么 F-tile Serial Lite IV FPGA IP 设计示例会失败

说明 由于Intel Agilex 7 FPGA I 系列收发器-SoC 开发套件的时钟控制器 GUI 存在问题&#xff0c;当您需要配置芯片 Si5332 的 OUT1 时钟频率时&#xff0c;您可能会发现 F-tile Serial Lite IV 英特尔 FPGA IP设计示例失败。这是因为此 Si5332 GUI 存在问题;无法准确配置 OUT…

【算法】约数之和(数论)

题目 给定 n 个正整数 ai&#xff0c;请你输出这些数的乘积的约数之和&#xff0c;答案对 1097 取模。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含一个整数 ai。 输出格式 输出一个整数&#xff0c;表示所给正整数的乘积的约数之和&#xff0c;答案需…

CentOS 8最小安装和网络配置

文章目录 简介下载地址VMware 17创建虚拟机最小化安装拥有的外部命令yum源有问题网络配置开启SSH Server服务关闭防火墙(目前这个地方还是有问题-加上端口依然不能访问)设置host配置JDK环境完整参考 简介 CentOS 8的IOS如果下载DVD版本至少有10G 这里我们直接选择最小安装&…

当Meta转向AI并宣布为投资者分红时,其收入激增

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…