机器人导航入门指南(从 0 到 1)

机器人导航入门指南(从 0 到 1)

本文档基于 D:\pan\桌面\导航 下的全部资料(资料.txt1.txt ~ 14.txt)整理而成,配套硬件为 Yahboom X3 麦轮车 + 激光雷达(A1/S2/RPLIDAR),软件栈以 ROS1 (move_base) 为主线,并在关键处标注 ROS2 (Nav2) 的对应关系。

阅读建议:第 0~2 章建立认知,第 3~5 章是核心原理,第 6~8 章是动手实操与调参,第 9 章是进阶路线。可以边读边在车上跑。


目录


第 0 章 认知地图:先搞清楚"导航"到底是什么

0.1 一句话区分 SLAM 与导航

SLAM 负责"知道环境长什么样 + 自己在哪";导航负责"根据这个信息,自己走到某个地方去"。 SLAM 不包含导航,导航通常依赖 SLAM(或等价的定位/建图方案)作为底层支撑。

这是贯穿全文的最重要一句话。很多人把两者混为一谈,是因为它们在演示里常常一起开,看起来像"一套东西"。但软件架构上它们是解耦的两个模块。

0.2 职责边界(务必记住这张表)

能力 SLAM 导航
建图(生成 /map) ❌(只读地图)
定位("我在哪") ❌(依赖定位结果)
全局路径规划
局部避障
发布速度指令 /cmd_vel
目标点管理

0.3 一个自主移动机器人由哪些"层"组成

从下往上理解(这是全文的骨架):

┌─────────────────────────────────────────┐
│  任务层:要去哪?(目标点 /goal_pose)        │
├─────────────────────────────────────────┤
│  导航层:全局规划 + 局部规划 + 避障 + 恢复   │  ← move_base / Nav2
├─────────────────────────────────────────┤
│  定位层:我在哪?(AMCL / SLAM 位姿)         │
├─────────────────────────────────────────┤
│  建图层:地图长啥样?(/map 栅格地图)         │  ← SLAM
├─────────────────────────────────────────┤
│  传感器层:雷达 / IMU / 里程计 / 相机        │
├─────────────────────────────────────────┤
│  底盘层:电机驱动,发布 /odom,接收 /cmd_vel │
└─────────────────────────────────────────┘
  • 底盘层:电机编码器 → 算出轮速 → 正运动学 → 机器人整体速度 → 时间积分 → 里程计 /odom。同时接收 /cmd_vel(线速度 + 角速度)驱动电机。

  • 传感器层:激光雷达发布 /scansensor_msgs/LaserScan),IMU 发布姿态,相机发布图像/点云。

  • 建图层(SLAM):吃 /scan + /odom + tf,吐出 /mapnav_msgs/OccupancyGrid,栅格地图)和位姿估计。

  • 定位层:在已有地图上,用粒子滤波(AMCL)估计"我现在在地图的哪个点"。

  • 导航层:吃地图 + 定位 + 目标点,吐出 /cmd_vel

0.4 SLAM 与导航配合的两种典型场景

场景 A:先建图,再导航(最常见)

  1. 跑 SLAM 建图,遥控小车走满区域;

  2. 保存地图(.pgm + .yaml);

  3. 关掉 SLAM,用静态地图 + AMCL 定位 + move_base 导航长期运行。

场景 B:边 SLAM 边导航(探索未知环境)

  • SLAM 实时更新 /map 和定位;

  • 导航实时用这份地图做规划 + 避障(如 rrt_exploration 自动探索建图)。

  • 仍是两个系统并行协作,不是谁包含谁


第 1 章 必备前置知识

在动手之前,先建立这些"共同语言",否则后面的命令和参数都看不懂。

1.1 ROS 基础概念(最小必要集)

概念 一句话解释 在导航里的例子
节点 (node) 一个可执行进程,做一件事 move_baseamclslam_gmapping
话题 (topic) 节点间异步广播数据的"总线" /scan/map/cmd_vel/odom
消息 (msg) 话题上数据的格式 geometry_msgs/Twistsensor_msgs/LaserScan
服务 (service) 同步的"请求-响应" ~dynamic_map 获取地图
动作 (action) 带反馈的可取消长任务 move_base/goal(导航到目标点)
launch 文件 一键启动多个节点 + 配参 yahboomcar_navigation.launch
参数 (param/yaml) 节点的可配置项 max_vel_xinflation_radius

常用调试工具:

rosrun rqt_graph rqt_graph          # 看节点-话题连接图
rosrun rqt_tf_tree rqt_tf_tree      # 看坐标变换树
rosrun rqt_reconfigure rqt_reconfigure   # 运行时动态改参数(调参神器)
rviz                               # 2D/3D 可视化

1.2 坐标变换 (tf) —— 导航的"骨架"

导航强依赖一组坐标系之间的变换关系,称为 tf 树。典型的室内移动机器人 tf 链是:

map → odom → base_link → (laser_link / imu_link / ...)
坐标系 含义 谁发布
map 全局地图坐标系(固定不动) SLAM / AMCL 发布 map → odom
odom 里程计连续坐标系(短时光滑、长时漂移) 底盘驱动发布 odom → base_link
base_link 机器人本体中心 底盘驱动
laser_link 雷达安装位置 robot_state_publisher / 静态 tf

关键点base_link 只能有一个父节点,所以 AMCL 不直接发布 map → base_link,而是发布 map → odom 的修正量。这样既维护了 tf 树,又能暴露出里程计的累计误差(被 AMCL 修正掉)。

直观例子:轮子打滑时,里程计以为走了 1 米,但 AMCL 用雷达观测发现其实没动 → 它调整 map → odom 把这 1 米误差"吃掉"。

1.3 地图的表示:占据栅格地图 (Occupancy Grid)

SLAM 输出的 /map 是一张栅格图,每个像素取值:

  • 0 = 自由空间(free)

  • 100 = 被占用(occupied,障碍物)

  • -1 = 未知(unknown)

保存为两个文件:

  • map.pgm:图片(黑白灰,肉眼可看);

  • map.yaml:元数据。

map.yaml 关键字段(建图保存后必看):

image: map.pgm              # 图片路径
resolution: 0.05            # 分辨率:米/像素(一格 5cm)
origin: [-15.4, -12.2, 0.0] # 地图左下角在 map 坐标系下的 (x,y,yaw)
negate: 0                   # 是否黑白颠倒
occupied_thresh: 0.65       # 占用概率 > 0.65 视为障碍
free_thresh: 0.196          # 占用概率 < 0.196 视为自由

1.4 传感器与里程计

传感器 输出 在导航中的作用
激光雷达 (2D LiDAR) /scan 建图、定位(AMCL)、避障(局部代价地图)
IMU 姿态/角速度 提供朝向 yaw,融合进里程计
轮式里程计 /odom 短时位姿估计,是 SLAM/AMCL 的运动预测来源
深度相机 (Astra/Realsense) 点云 补充 3D 障碍信息

注意:轮式里程计有累计误差(打滑、轮子磨损)。纯里程计定位叫 Odometry Localization;融合地图观测后叫 AMCL Map Localization,后者能消除累计误差。

1.5 硬件 & 环境准备(Yahboom X3)

# 树莓派 PI5 主控:先进 docker
~/run_docker.sh
​
# 设置车型(在 .bashrc 里,影响很多 launch 文件)
sudo vim .bashrc
export ROBOT_TYPE=X3   # 可选: X1(四驱) X3(麦轮) X3plus(麦轮机械臂) R2(阿克曼) X7

常用启动组合:

roslaunch yahboomcar_nav laser_bringup.launch          # laser + 底盘
roslaunch yahboomcar_nav laser_usb_bringup.launch      # mono相机 + laser + 底盘
roslaunch yahboomcar_nav laser_astrapro_bringup.launch # Astra + laser + 底盘

第 2 章 导航算法的核心思想

万变不离其宗:导航 = 在图(栅格地图)上搜索一条从起点到终点的路径,并实时躲开障碍。

2.1 两层规划结构

实际机器人导航几乎都是两层结构

层次 任务 频率 典型算法
全局规划 (Global Planner) 在已知地图上规划一条"宏观路径" 低频(几 Hz) Dijkstra、A*、RRT
局部规划 (Local Planner) 实时跟随全局路径,躲避动态障碍,输出 /cmd_vel 高频(10~20 Hz) DWA、TEB、Trajectory Rollout

为什么要分两层?

  • 全局规划重(搜整张图),不能每帧都跑;

  • 局部规划轻(只在窗口内采样),但要快、要躲人。

  • 代价地图也分两层与之对应:global_costmap(静态、大范围)和 local_costmap(滚动、小窗口、含动态障碍)。

2.2 经典图搜索算法(全局规划基础)

Dijkstra(迪杰斯特拉)

  • 思想:从起点向所有方向均匀扩展,直到找到终点。

  • 优点:保证最短路径;缺点:慢,漫无目的。

A*(A-star,带启发式的 Dijkstra)

  • 思想:f(n) = g(n) + h(n),其中 g(n) 是已走代价,h(n) 是到终点的估计距离(启发函数,如欧氏距离)。

  • h(n) 把搜索"拉向"目标方向,效率远高于 Dijkstra。

  • 风险:启发函数设计不好可能走入死胡同。

D*

  • A* 的升级,支持环境变化时增量重规划(用于未知/动态环境)。

RRT(快速探索随机树)

  • 用随机采样"长"出一棵树,倾向于探索未知区域。

  • rrt_exploration 里用于自动找边界点(已探索与未知的交界),实现自主探索建图。

2.3 ROS 中的全局规划器插件

资料里(12.txt)提到的全局规划插件:

插件 说明
navfn/NavfnROS 老牌栅格规划器,实现了 Dijkstra 和 A*
global_planner/GlobalPlanner Navfn 的改进重写版,资料默认用它
carrot_planner/CarrotPlanner 简单规划器,目标不可达时退到最近可行点

切换方法(move_base_params.yaml):

base_global_planner: "global_planner/GlobalPlanner"   # 默认
# base_global_planner: "navfn/NavfnROS"

2.4 局部规划器:DWA vs TEB(重点)

这是资料里着墨最多的部分(12.txt14.txt)。

DWA(动态窗口法,dwa_local_planner

  1. 在速度空间 (vx, vy, vθ) 里离散采样;

  2. 对每个采样速度做前向仿真,预测短时间内的轨迹;

  3. 给每条轨迹打分:靠近全局路径、靠近目标、远离障碍、速度代价;

  4. 选最高分轨迹,把对应速度发给底盘;

  5. 循环。

特点:模型简单,适合差速/全向机器人;先到目标坐标点,再原地旋转到目标朝向。

TEB(Timed-Elastic-Band,时间弹性带,teb_local_planner

  • 把轨迹看作一串带时间信息的位姿,用 g2o 图优化求解,目标 = 时间最短 + 路径最短 + 远离障碍 + 满足运动学。

  • 运动中边走边调朝向,到终点时朝向通常已对齐,不需要原地旋转。

  • 支持阿克曼(car-like)模型(有最小转弯半径),R2 阿克曼车必须用 TEB,DWA 不适用。

  • 缺点:两轮差速车上可能出现不必要的后退(启动/到点时),需要调参抑制。

选择建议

  • 差速/麦轮车(X3):默认 DWA,路径流畅、行为可预期;

  • 阿克曼车(R2):必须 TEB

  • 想要平滑且能处理动态障碍、并支持多拓扑并行规划:用 TEB

2.5 算法的四条主流技术流派(回扣总览)

  1. 基于图搜索的传统算法:Dijkstra、A* —— 核心是设计合理的代价函数 (Cost),非常依赖对业务场景的理解。

  2. 基于优化的现代算法:TEB、MPC —— 构造数学模型求最优解,离线计算 + 在线选择。

  3. 组合导航算法:SINS/GNSS 等 —— 融合多传感器(自动驾驶、航空航天),核心是姿态算法(欧拉角、方向余弦矩阵、四元数)。

  4. 群体智能/采样类:RRT、PSO(如 OkayPlan)—— 适合动态环境下的实时全局规划。


第 3 章 建图(SLAM)—— 导航的前提

本章对应资料 5~10.txt。所有建图算法的操作流程几乎一致,只是 map_type 参数不同:

# 1. 启动底盘 + 雷达
roslaunch yahboomcar_nav laser_usb_bringup.launch
​
# 2. 启动建图(改 map_type 即可切换算法)
roslaunch yahboomcar_nav yahboomcar_map.launch use_rviz:=false map_type:=gmapping
#                                                    map_type:=hector / karto / cartographer
​
# 3. 遥控走满区域,地图尽量闭合
roslaunch yahboomcar_ctrl yahboom_keyboard.launch
​
# 4. 保存地图
rosrun map_server map_saver -f ~/yahboomcar_ws/src/yahboomcar_nav/maps/my_map
# 或
bash ~/yahboomcar_ws/src/yahboomcar_nav/maps/map.sh

通用注意事项(每种算法都适用)

  • 建图时速度要慢,特别是旋转速度要慢,否则打滑导致地图错位;

  • 让小车走满要建图的区域,地图尽量闭合;

  • 环境越规则、闭合越好,散射点越少,地图质量越高;

  • 雷达被显示屏遮挡会产生"缺口",可在雷达配置里调整屏蔽范围。

3.1 Gmapping(5.txt

  • 原理:基于 RBpf 粒子滤波,定位与建图分离(先定位再建图)。改进点:改进提议分布 + 选择性重采样。

  • 优点:小场景实时性好,精度高,计算量小。

  • 缺点:每个粒子都带一张地图,大场景内存/计算暴涨无回环检测,回环处可能错位。

  • 限制:单帧激光点数 < 1440,否则会报 [mapping-4] process has died

  • 适用:室内小场景、快速原型。

关键参数速记:

参数 含义
particles 粒子数(默认 30),大场景要加
linearUpdate / angularUpdate 每平移/旋转多少处理一次扫描
maxUrange / maxRange 激光可用最大范围
delta 地图分辨率(默认 0.05m)
xmin/ymin/xmax/ymax 地图初始尺寸

3.2 Hector(7.txt

  • 原理不需要里程计,用高斯牛顿直接从激光数据估算位姿。

  • 优点:无里程计也能跑。

  • 缺点:对传感器要求高;机器人速度快时打滑严重,建图偏差大;没有回环检测

  • 适用:没有可靠里程计的平台,但要慢速运动。

3.3 Karto(8.txt

  • 原理:基于稀疏图优化的 2D 激光 SLAM,带闭环检测。前端扫描匹配 + 后端图优化(SPA / g2o),单线程。

  • 优点:有大环境制图优势(只存位姿图,不存多张地图),有回环检测。

  • 注意:4ROS 雷达与 A1 雷达需改 Karto.h 第 4165 行源码(去掉 +1)并重新 catkin_make

3.4 Cartographer(9.txt,Google 开源,最主流)

  • 原理:主流 SLAM 三段式 —— 特征提取 + 闭环检测 + 后端优化(多线程后端,用 ceres-solver 建优化问题)。

  • 由若干 LaserScan 组成一个 submap 子图,一系列 submap 组成全局地图;闭环检测以 submap 为基本单元,用 scan_match 策略。

  • 核心亮点多传感器融合(odometry / IMU / LaserScan / 点云 / GPS / landmark)。

  • 源码三部分:cartographer(核心)+ cartographer_ros(ROS 接口)+ ceres-solver(后端优化)。

  • 配置在 .lua 文件(不是 yaml),关键参数:tracking_frameuse_odometryprovide_odom_framenum_laser_scans 等。

  • 推荐场景:质量要求高、环境复杂、需要回环修正的场景。ROS2 首选 SLAM Toolbox,思路与之同源。

3.5 rrt_exploration(10.txt,自主探索建图)

不是传统 SLAM,而是让机器人自动探索未知区域,边走边建图。

  • 基于 RRT 找"边界点"(frontier:已探索 free 区与未知区的交界)。

  • 由 5 类节点组成:

    • global_rrt_frontier_detector:全局边界检测(多机只跑一个);

    • local_rrt_frontier_detector:局部边界检测(每机一个,树会重置);

    • frontier_opencv_detector:用 OpenCV 找边界(非 RRT);

    • filter:过滤旧点、无效点、冗余点;

    • assigner:把边界点作为目标派给机器人(依赖 move_base,所以要先开导航)。

  • 用法:rviz 里用 Publish Point 顺时针/逆时针点 4 个点框定探索区域,第 5 个点点在小车附近 → 开始自动探索。

  • 建完自动保存地图(rrt_map)并回零点。

3.6 五种建图算法对比(选型表)

算法 方法 需里程计 回环检测 大场景 多传感器 适用场景
gmapping 粒子滤波 RBpf 室内小场景、快速上手
hector 高斯牛顿扫描匹配 一般 无里程计平台
karto 图优化 + SPA 中大场景、需要回环
cartographer 子图 + ceres 优化 高质量、复杂环境、多传感器
rrt_exploration RRT 自主探索 自动探索建图(需配合导航)

入门建议路线:gmapping 入门 → cartographer 进阶。先用 gmapping 跑通"建图→保存→加载→导航"全流程,再用 cartographer 追求质量。


第 4 章 定位 —— "我在哪"

导航前必须知道自己在地图上的位置。建图阶段由 SLAM 顺便给出;建图完成后,长期运行用 AMCL

4.1 两种定位方式对比

Odometry Localization(纯里程计) AMCL Map Localization(地图定位)
来源 电机编码器 + 正运动学 + 积分 里程计 + 地图 + 激光观测(粒子滤波)
误差 累计漂移(打滑越走越偏) 会被地图观测修正
发布的 tf odom → base_link map → odom(修正量)

4.2 AMCL 自适应蒙特卡洛定位(11.txt

蒙特卡洛思想(豆子比喻):矩形里有个不规则形状怎么算面积?均匀撒一把豆子,统计形状内/外的豆子比例 × 矩形面积 ≈ 形状面积。机器人定位同理:用一堆粒子表示"机器人可能在哪",粒子越密的地方,可能性越高。

粒子滤波流程

  1. 初始化:在地图上撒一把粒子(位姿假设);

  2. 运动预测:机器人动,粒子跟着动(用里程计);

  3. 观测更新:每个粒子位姿模拟一次激光观测,和真实激光比,给每个粒子打分(权重);

  4. 重采样:高分粒子附近多生粒子,低分粒子被淘汰;

  5. 多轮迭代后,粒子收敛到真实位置。

"自适应"解决了两个问题

  • 机器人绑架问题:发现粒子平均分突降(正确粒子被误丢)时,在全局重新撒粒子;

  • 粒子数自适应:粒子已收敛时减少粒子数,省算力。

rviz 里的可视化:启动后能看到机器人周围撒一把绿色粒子,移动机器人时粒子跟随并逐步收敛成一小团 → 定位完成。

4.3 AMCL 关键参数(三类)

整体过滤器

参数 含义
min_particles / max_particles 粒子数上下限(100 / 5000)
update_min_d / update_min_a 平移/旋转多少才更新一次滤波器
transform_tolerance tf 容忍延迟(秒)
initial_pose_x/y/a 初始位姿(用于缩小初始搜索范围)

激光模型laser_model_typebeam / likelihood_field / likelihood_field_prob,默认 likelihood_field)、laser_max_beams(每次用多少光束)等。

里程计模型odom_model_typediff 差速 / omni 全向 / diff-corrected / omni-corrected),odom_alpha1~5 是各种噪声参数。X3 麦轮用 omnidiff,根据实测选。

4.4 实操:建图后用 AMCL 跑导航

# 加载静态地图 + AMCL + move_base
roslaunch yahboomcar_nav yahboomcar_navigation.launch use_rviz:=false map:=house

在 rviz 中:

  1. 2D Pose Estimate 设置初始位姿(让小车在仿真和现实的位置一致);

  2. 2D Nav Goal 给目标点,开始导航。


第 5 章 导航(move_base / Nav2 全景)

本章对应 12.txt14.txt,是导航的核心

5.1 navigation / move_base 是什么

navigation 是 ROS 的 2D 导航避障功能包:输入里程计 + 全局位姿,输出安全的 /cmd_vel

核心节点 move_base 是导航的"总调度",它以插件形式调用各模块:

                ┌─────────────── move_base ───────────────┐
目标点 ───────► │                                          │ ────► /cmd_vel
move_base_simple│  Global Planner  →  Local Planner        │  (线速度+角速度)
   /goal        │       ▲                  ▲               │
                │  global_costmap     local_costmap        │
                │       ▲                  ▲               │
                │     /map + AMCL     /scan + /odom        │
                │                                          │
                │  Recovery Behaviors(恢复行为)           │
                └──────────────────────────────────────────┘

move_base 的通信机制:

  • Actionmove_base/goal(目标)、/feedback(当前位置)、/status(状态)、/result(结果)—— 适合关心执行状态的场景;

  • Topicmove_base_simple/goal(简单目标,不追踪状态)、cmd_vel(速度);

  • Servicemake_plan(只规划不执行)、clear_costmaps(清代价地图)、clear_unknown_space

5.2 代价地图 costmap(避障的数据基础)

costmap_2d 用传感器数据构建代价地图,并按膨胀半径计算每个格子的代价。导航用两张代价地图:

global_costmap local_costmap
用途 全局规划 局部规划/避障
坐标系 map odom
范围 整张静态地图 滚动小窗口(如 6×6m)
static_map true(基于 map_server) false
rolling_window false true(跟随机器人)
动态障碍 一般不加 (来自实时 /scan)

图层结构(plugin 机制):

  • static_layer:静态层(来自地图,基本不变);

  • obstacle_layer:障碍层(来自传感器,2D 标记 + 光线追踪清除);

  • inflation_layer:膨胀层(在致命障碍周围加代价,表示"配置空间")。

膨胀层的 5 个代价符号(重要概念):

  • Lethal(致命):真有障碍,机器人中心在此必撞;

  • Inscribed(内切):距障碍 < 机器人内切圆半径,中心在此必撞;

  • Possibly circumscribed(可能外切):距障碍 < 外切圆半径但 > 内切半径,撞不撞看朝向;

  • Freespace(自由):随便走;

  • Unknown(未知):未知。

可视化里:红色 = 障碍,蓝色 = 内切膨胀,红色多边形 = 机器人 footprint。规则:footprint 不能碰红格,机器人中心不能碰蓝格。

costmap_common_params.yaml 关键项

obstacle_range: 2.5        # 只更新 2.5m 内的障碍
raytrace_range: 3.0        # 清理前方 3m 外的空间
footprint: [[x0,y0],...]   # 机器人多边形(与 robot_radius 二选一)
inflation_radius: 0.55     # 膨胀半径
observation_sources: laser_scan_sensor
laser_scan_sensor: {sensor_frame: ..., data_type: LaserScan, topic: /scan, marking: true, clearing: true}

5.3 全局规划参数(global_planner_params.yaml

GlobalPlanner:
  use_dijkstra: true       # true=Dijkstra, false=A*
  allow_unknown: false     # 是否探索未知区(需 costmap 也开 track_unknown_space)
  default_tolerance: 0.2   # 目标被占时,以它为半径找最近可达点
  lethal_cost: 253         # 致命区代价
  neutral_cost: 50         # 中等代价
  cost_factor: 3.0         # 代价缩放系数
  use_grid_path: false     # true=沿栅格边走,false=梯度下降更光滑

如果启动时报 NO PATH!,多半是方向/朝向问题,可试试默认的 navfn 插件。

5.4 局部规划:DWA 参数详解(dwa_local_planner_params.yaml

机器人配置(差速车把 y 速度设 0):

max_vel_x: 0.6      min_vel_x: -0.6   # 负=可后退
max_vel_y: 0.3      min_vel_y: -0.3   # 差速车设 0
acc_lim_x: 10.0     acc_lim_y: 10.0   # 差速车 y 设 0
acc_lim_th: ...                       # 角加速度

目标容差xy_goal_toleranceyaw_goal_tolerance

前向仿真

sim_time: 2.0          # 仿真时长(秒)
vx_samples: 6          # x 速度采样数
vth_samples: 20        # 角速度采样数
controller_frequency: 5.0

轨迹评分(打分公式各项权重):

path_distance_bias: 90.0   # 贴近全局路径的权重
goal_distance_bias: 24.0   # 贴近目标的权重
occdist_scale: 0.3         # 躲障碍的权重

调参直觉:想让它更"贴路径"就加大 path_distance_bias,想更"躲障碍"就加大 occdist_scale

5.5 局部规划:TEB 参数详解(teb_local_planner_params.yaml14.txt

TEB 参数分 6 组:

  1. Trajectory(轨迹)dt_ref(时间分辨率)、max_global_plan_lookahead_dist(前瞻距离)、feasibility_check_no_poses(碰撞检查点数);

  2. Robot(机器人)max_vel_xmax_vel_x_backwards(倒车速度,不想让它倒车就调小)、min_turning_radius(阿克曼用,差速设 0)、wheelbase(轴距);

  3. GoalTolerance(目标容差)xy_goal_toleranceyaw_goal_tolerance

  4. Obstacles(障碍)min_obstacle_dist(与障碍最小距离,要包含机器人膨胀)、inflation_distinclude_dynamic_obstacles(预测动态障碍);

  5. Optimization(优化权重)

    • weight_kinematics_forward_drive:迫使前进不倒车(经验:调到最大也不能完全禁止倒车,要配合其他参数);

    • weight_obstacle:躲障碍权重;

    • weight_optimaltime:时间最优权重;

  6. Homotopy Class Planner(并行规划)enable_homotopy_class_planning: true(同时在多个拓扑路径上规划,挑最优)。

TEB 关键经验

  • min_turning_radius 经验值 = 车长的 2.4 倍

  • wheelbase 需实测标定(驱动轴到转向轴距离);

  • 倒车问题:调 weight_kinematics_forward_drive + max_vel_x_backwards + penalty_epsilon

5.6 恢复行为(Recovery Behaviors)

全局规划失败 / 机器人震荡 / 局部规划失败时,move_base 进入恢复流程(可配置、可禁用):

conservative_reset(保守清障) → clearing_rotation(原地旋转清空间)
   → aggressive_reset(激进清障) → clearing_rotation → 仍失败 → aborted(中止)

相关包:clear_costmap_recoveryrotate_recoverymove_slow_and_clear12.txt 给出了 move_base_params.yaml 里恢复行为、controller_frequencyplanner_patience 等完整配置。


第 6 章 从 0 到 1 实操路线

跟着下面 7 步走,第一次就能跑通"建图 → 导航"全流程。每一步都先理解再做。

Step 1:环境 & 底盘就绪

~/run_docker.sh                      # PI5 进 docker
export ROBOT_TYPE=X3                 # .bashrc 里设好车型
roslaunch yahboomcar_nav laser_usb_bringup.launch   # 底盘+雷达+相机

确认 /scan/odom/tf 都有数据(用 rostopic echorqt_graph 检查)。

Step 2:用最简单的"雷达避障"感性认识(2.txt,不用建图)

ros2 run yahboomcar_bringup Mcnamu_driver_X3   # ROS2 风格;ROS1 对应 bringup launch
ros2 run yahboomcar_laser laser_Avoidance_a1_X3

理解:雷达回调里把每个角度的 ranges[i] 分到 左/右/前三组计数,谁触发阈值就往反方向打角速度。这是最原始的"反应式避障",连 SLAM 都不用。

资料里的雷达玩法梯度(2~4.txt):避障 → 警卫(对准最近目标,近了报警)→ 跟随(追最近目标保持距离)→ 巡逻(走固定轨迹)。它们都用 rqt_reconfigure 动态调 PID 和阈值,是理解"传感器→决策→速度"闭环的好起点。

Step 3:用 gmapping 建第一张地图(5.txt

roslaunch yahboomcar_nav yahboomcar_map.launch use_rviz:=false map_type:=gmapping
roslaunch yahboomcar_ctrl yahboom_keyboard.launch        # 慢慢走满区域
rosrun map_server map_saver -f ~/yahboomcar_ws/src/yahboomcar_nav/maps/my_map

检查 maps/my_map.pgmmy_map.yaml 都生成了。

Step 4:加载地图 + AMCL 定位(11.txt

roslaunch yahboomcar_nav yahboomcar_navigation.launch use_rviz:=false map:=my_map
roslaunch yahboomcar_nav view_navigate.launch            # 虚拟机端开 rviz

在 rviz 用 2D Pose Estimate 把小车定位准(看绿色粒子收敛)。

Step 5:单点 / 多点导航(12.txt

  • 2D Nav Goal:点一个目标,到达即停;

  • Publish Point:连续点多个目标,机器人巡航。

  • 手柄 R2 可随时取消目标点。

Step 6:换 cartographer 提升地图质量(9.txt

sudo bash ~/yahboomcar_ws/src/yahboomcar_nav/scripts/copy_carto.sh   # 首次配置
roslaunch yahboomcar_nav yahboomcar_map.launch map_type:=cartographer

对比和 gmapping 的地图差异(尤其是大场景和回环处)。

Step 7:进阶玩法

  • 自动探索建图10.txt):rrt_exploration.launch + rviz 点 5 个点;

  • APP 建图/导航13.txt):手机连机器人 IP,rosbridge 通信,摇杆遥控 + 触屏设点;

  • 阿克曼车 R2:换 TEB 局部规划器,调 min_turning_radius


第 7 章 调参方法论

调参是导航工程化的核心能力。资料里反复出现的通用方法论

7.1 三步调参法

  1. 先用 rqt_reconfigure 动态调,实时看效果:

    rosrun rqt_reconfigure rqt_reconfigure   # ROS1
    ros2 run rqt_reconfigure rqt_reconfigure # ROS2
  2. 调到最优后,把数值写回 yaml(否则重启失效);

  3. 改完 yaml 必须重新编译(ROS1):

    cd ~/yahboomcar_ws && catkin_make && source devel/setup.bash

7.2 分模块调参顺序(推荐)

按"从粗到细"的顺序,一次只动一组

  1. 底盘/里程计:先确保 /odom 准(不打滑、不走偏),这是所有上层算法的基础;

  2. 建图:慢速走,地图闭合、无错位;

  3. AMCL 定位:粒子收敛快、不漂;

  4. 代价地图inflation_radius(别撞墙也别太保守)、obstacle_range

  5. 全局规划:先确认能规划出路径(无 NO PATH);

  6. 局部规划:最后调速度/加速度/采样/评分权重,追求流畅。

7.3 关键参数直觉

现象 可能原因 调整方向
撞墙 膨胀不够 / 速度太快 inflation_radius,↓ max_vel_x
绕远路、不敢走 膨胀过大 / 代价过高 inflation_radius,↓ cost_factor
抖动、来回摆 振荡 / 采样不足 oscillation_reset_dist,↑ vth_samples
规划不出路径 朝向 / 未知区 navfn,检查 allow_unknown
TEB 老倒车 前进权重不够 weight_kinematics_forward_drive,↓ max_vel_x_backwards
定位漂移 初始位姿不准 / 粒子少 重设 2D Pose Estimate,↑ min_particles

7.4 调试工具清单

rosrun rqt_graph rqt_graph              # 节点拓扑
rosrun rqt_tf_tree rqt_tf_tree          # tf 树
rosrun rqt_reconfigure rqt_reconfigure  # 动态参数
rviz                                   # 2D 可视化(地图/路径/代价地图/粒子全在这看)
rostopic echo /cmd_vel                  # 看实际下发速度
rostopic echo /amcl_pose                # 看定位输出

第 8 章 常见问题与避坑

Q1:gmapping 报 [mapping-4] process has died A:单帧激光点数超过 1440。换 cartographer,或降低雷达分辨率/采样。

Q2:karto 用 A1/4ROS 雷达跑不起来? A:要改 Karto.h 第 4165 行(Update() 里去掉 +1)并 catkin_make8.txt)。

Q3:地图有缺口/散射点? A:减速(尤其旋转);改善环境闭合度;调整雷达屏蔽角度(显示屏遮挡)。

Q4:rviz 里小车位置和实际不一致? A:先用 2D Pose Estimate 设准初始位姿,让 AMCL 粒子收敛。定位丢失("机器人绑架")也要重新设。

Q5:导航时撞障碍? A:检查 inflation_radius 是否够大、footprint 是否正确、obstacle_range 是否覆盖动态障碍。差速车别忘了把 DWA 的 max_vel_y/acc_lim_y 设 0。

Q6:阿克曼 R2 用 DWA 不行? A:DWA 不支持最小转弯半径,R2 必须用 TEB14.txt)。

Q7:TEB 老是倒车/路径奇怪? A:调 weight_kinematics_forward_drive(加大)、max_vel_x_backwards(减小)、penalty_epsilon;确认 min_turning_radius(≈ 2.4×车长)和 wheelbase 实测值。

Q8:NO PATH! 报错? A:朝向/方向问题,先试默认 navfn/NavfnROS;检查目标点是否落在障碍或未知区。

Q9:改了参数没生效? A:catkin_make + source devel/setup.bash;或确认是用 rqt_reconfigure 改的(运行时)还是 yaml(启动时)。

Q10:ROS1 vs ROS2 命令怎么对应? A:roslaunchros2 launchrosrunros2 runcatkin_makecolcon build;move_base→Nav2nav2_planner + nav2_controller);gmapping/cartographer→SLAM Toolbox(ROS2 推荐)。


第 9 章 进阶方向与学习资源

9.1 学完本文后的进阶路线

  1. 算法深入:啃 A/D、RRT*、MPC 的数学;读 TEB 论文(Timed-Elastic-Band)和 Cartographer 论文。

  2. 3D / 视觉 SLAM:LIO-SAM(激光+IMU 紧耦合)、ORB-SLAM(纯视觉)、VINS-Fusion(VIO)。

  3. 多机/编队:多机器人协同建图与探索(rrt_exploration 的多机版)。

  4. 学习类方法:强化学习导航、端到端导航(从感知直接到速度)。

  5. 真实产品化:Nav2 行为树(BT)、生命周期节点、量产级定位融合(GNSS+IMU+LiDAR)。

  6. 组合导航:SINS/GNSS 融合、姿态表示(欧拉角/方向余弦矩阵/四元数)—— 自动驾驶/无人机方向。

9.2 资料内的官方文档链接(按主题)

SLAM 建图

导航

9.3 推荐学习节奏(4 周计划)

目标 产出
W1 ROS 基础 + tf + 里程计;跑通底盘和雷达 能用键盘遥控小车,rqt_graph 看懂拓扑
W2 gmapping 建图 + 地图保存加载;AMCL 定位 得到一张像样的 .pgm,rviz 里能定位
W3 move_base 全流程;DWA 单点/多点导航 给目标点能自主到达、避障
W4 cartographer / TEB / rrt_exploration 进阶;系统调参 高质量地图 + 流畅导航 + 自动探索

附录:核心概念速查表

术语 含义
SLAM 同步定位与建图,输出 /map + 位姿
AMCL 自适应蒙特卡洛定位(粒子滤波),输出 map→odom 修正
move_base / Nav2 导航总调度,整合规划+代价地图+恢复
global_costmap / local_costmap 全局/局部代价地图
Global Planner 全局路径规划(Dijkstra/A*)
Local Planner 局部规划(DWA/TEB),输出 /cmd_vel
OccupancyGrid 占据栅格地图(0 自由 / 100 占用 / -1 未知)
tf 坐标变换树(map→odom→base_link→...)
Recovery Behavior 失败后的恢复行为(清障/旋转)
footprint 机器人外轮廓多边形
inflation_radius 障碍膨胀半径(配置空间)
submap Cartographer 的子图,闭环检测基本单元

最后一句:导航不是玄学,是"地图 + 定位 + 规划 + 控制"四件套的工程组合。先把全流程跑通(哪怕效果一般),再逐模块打磨参数,是最稳的从 0 到 1 路径。祝玩得开心。

导航算法是一个涵盖路径规划、自主导航和组合导航等多个子领域的综合性技术体系。针对你提到的“导航算法”,我将从核心算法体系、主流技术流派和职业发展三个维度进行梳理。
一、核心算法体系
导航算法的核心思想,万变不离其宗的是基于图的最短路径搜索算法
其中,最基础的算法是 Dijkstra 算法,但它存在效率低下的问题,因为它会向所有方向进行漫无目的的探索
为了提升效率,引入了启发式搜索的 A* 算法​,它通过估计目标方向来指导搜索
不过,A* 算法也可能走入“死胡同”,因此衍生出了 D* 等其他升级方案
在实际应用中,算法的选择取决于具体的任务场景。例如,在机器人领域,导航算法通常被分为两个层次:
全局路径规划​:负责在已知地图上规划出一条从起点到终点的宏观路径,常用算法包括 Dijkstra、A\​* 和 动态规划 等
局部路径规划​:负责在机器人行驶过程中,实时规避动态障碍物,保证行驶安全。常用算法包括 自适应动态窗法 等。例如,CMU团队开发的避障算法通过离线生成庞大的轨迹库,能在几毫秒内规划出一条无碰撞路径
此外,针对大规模路网(如地图导航),经典的 Dijkstra 算法效率较低,此时会采用更高级的加速算法,例如 CH算法​。其核心思路是通过预处理阶段创建“shortcuts”来跳过不重要的顶点,从而大幅提升查询速度
二、主流技术流派
导航算法的实现方式多样,主要可以分为以下几类:
基于图搜索的传统算法​:这是最经典的方法,以 Dijkstra 和 A\​* 为代表,其核心是设计合理的 代价函数(Cost)​​,这非常依赖工程师对业务场景的深入理解
基于优化的现代算法​:这类算法通过构建数学模型来求解最优路径。例如,CMU团队开发的自主导航算法,其障碍物规避和可行驶区域分析模块,通过离线计算和在线实时选择相结合的方式,实现了高效且鲁棒的导航


组合导航算法​:在自动驾驶和航空航天等领域,单一的传感器(如GPS)往往不可靠,因此需要融合多种传感器数据。​SINS/GNSS组合导航 是其中的典型代表,它融合了惯性导航系统(SINS)和全球导航卫星系统(GNSS)的数据。这类算法的核心在于姿态算法​,常用数学工具包括欧拉角、方向余弦矩阵和四元数来描述载体的姿态变化。
新兴的粒子群优化算法​:例如 OkayPlan 算法,它基于粒子群优化(PSO)思想,能够实现动态环境下的实时全局路径规划。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐