机器人导航入门指南(从 0 到 1)
机器人导航入门指南(从 0 到 1)
机器人导航入门指南(从 0 到 1)
本文档基于
D:\pan\桌面\导航下的全部资料(资料.txt、1.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(线速度 + 角速度)驱动电机。传感器层:激光雷达发布
/scan(sensor_msgs/LaserScan),IMU 发布姿态,相机发布图像/点云。建图层(SLAM):吃
/scan+/odom+tf,吐出/map(nav_msgs/OccupancyGrid,栅格地图)和位姿估计。定位层:在已有地图上,用粒子滤波(AMCL)估计"我现在在地图的哪个点"。
导航层:吃地图 + 定位 + 目标点,吐出
/cmd_vel。0.4 SLAM 与导航配合的两种典型场景
场景 A:先建图,再导航(最常见)
跑 SLAM 建图,遥控小车走满区域;
保存地图(
.pgm+.yaml);关掉 SLAM,用静态地图 + AMCL 定位 + move_base 导航长期运行。
场景 B:边 SLAM 边导航(探索未知环境)
SLAM 实时更新
/map和定位;导航实时用这份地图做规划 + 避障(如
rrt_exploration自动探索建图)。仍是两个系统并行协作,不是谁包含谁。
第 1 章 必备前置知识
在动手之前,先建立这些"共同语言",否则后面的命令和参数都看不懂。
1.1 ROS 基础概念(最小必要集)
概念 一句话解释 在导航里的例子 节点 (node) 一个可执行进程,做一件事 move_base、amcl、slam_gmapping话题 (topic) 节点间异步广播数据的"总线" /scan、/map、/cmd_vel、/odom消息 (msg) 话题上数据的格式 geometry_msgs/Twist、sensor_msgs/LaserScan服务 (service) 同步的"请求-响应" ~dynamic_map获取地图动作 (action) 带反馈的可取消长任务 move_base/goal(导航到目标点)launch 文件 一键启动多个节点 + 配参 yahboomcar_navigation.launch参数 (param/yaml) 节点的可配置项 max_vel_x、inflation_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 → odomodom里程计连续坐标系(短时光滑、长时漂移) 底盘驱动发布 odom → base_linkbase_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/GlobalPlannerNavfn 的改进重写版,资料默认用它 carrot_planner/CarrotPlanner简单规划器,目标不可达时退到最近可行点 切换方法(
move_base_params.yaml):base_global_planner: "global_planner/GlobalPlanner" # 默认 # base_global_planner: "navfn/NavfnROS"2.4 局部规划器:DWA vs TEB(重点)
这是资料里着墨最多的部分(
12.txt、14.txt)。DWA(动态窗口法,
dwa_local_planner)
在速度空间
(vx, vy, vθ)里离散采样;对每个采样速度做前向仿真,预测短时间内的轨迹;
给每条轨迹打分:靠近全局路径、靠近目标、远离障碍、速度代价;
选最高分轨迹,把对应速度发给底盘;
循环。
特点:模型简单,适合差速/全向机器人;先到目标坐标点,再原地旋转到目标朝向。
TEB(Timed-Elastic-Band,时间弹性带,
teb_local_planner)
把轨迹看作一串带时间信息的位姿,用 g2o 图优化求解,目标 = 时间最短 + 路径最短 + 远离障碍 + 满足运动学。
运动中边走边调朝向,到终点时朝向通常已对齐,不需要原地旋转。
支持阿克曼(car-like)模型(有最小转弯半径),R2 阿克曼车必须用 TEB,DWA 不适用。
缺点:两轮差速车上可能出现不必要的后退(启动/到点时),需要调参抑制。
选择建议:
差速/麦轮车(X3):默认 DWA,路径流畅、行为可预期;
阿克曼车(R2):必须 TEB;
想要平滑且能处理动态障碍、并支持多拓扑并行规划:用 TEB。
2.5 算法的四条主流技术流派(回扣总览)
基于图搜索的传统算法:Dijkstra、A* —— 核心是设计合理的代价函数 (Cost),非常依赖对业务场景的理解。
基于优化的现代算法:TEB、MPC —— 构造数学模型求最优解,离线计算 + 在线选择。
组合导航算法:SINS/GNSS 等 —— 融合多传感器(自动驾驶、航空航天),核心是姿态算法(欧拉角、方向余弦矩阵、四元数)。
群体智能/采样类: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_frame、use_odometry、provide_odom_frame、num_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_linkmap → odom(修正量)4.2 AMCL 自适应蒙特卡洛定位(
11.txt)蒙特卡洛思想(豆子比喻):矩形里有个不规则形状怎么算面积?均匀撒一把豆子,统计形状内/外的豆子比例 × 矩形面积 ≈ 形状面积。机器人定位同理:用一堆粒子表示"机器人可能在哪",粒子越密的地方,可能性越高。
粒子滤波流程:
初始化:在地图上撒一把粒子(位姿假设);
运动预测:机器人动,粒子跟着动(用里程计);
观测更新:每个粒子位姿模拟一次激光观测,和真实激光比,给每个粒子打分(权重);
重采样:高分粒子附近多生粒子,低分粒子被淘汰;
多轮迭代后,粒子收敛到真实位置。
"自适应"解决了两个问题:
机器人绑架问题:发现粒子平均分突降(正确粒子被误丢)时,在全局重新撒粒子;
粒子数自适应:粒子已收敛时减少粒子数,省算力。
rviz 里的可视化:启动后能看到机器人周围撒一把绿色粒子,移动机器人时粒子跟随并逐步收敛成一小团 → 定位完成。
4.3 AMCL 关键参数(三类)
整体过滤器
参数 含义 min_particles/max_particles粒子数上下限(100 / 5000) update_min_d/update_min_a平移/旋转多少才更新一次滤波器 transform_tolerancetf 容忍延迟(秒) initial_pose_x/y/a初始位姿(用于缩小初始搜索范围) 激光模型:
laser_model_type(beam/likelihood_field/likelihood_field_prob,默认likelihood_field)、laser_max_beams(每次用多少光束)等。里程计模型:
odom_model_type(diff差速 /omni全向 /diff-corrected/omni-corrected),odom_alpha1~5是各种噪声参数。X3 麦轮用omni或diff,根据实测选。4.4 实操:建图后用 AMCL 跑导航
# 加载静态地图 + AMCL + move_base roslaunch yahboomcar_nav yahboomcar_navigation.launch use_rviz:=false map:=house在 rviz 中:
用 2D Pose Estimate 设置初始位姿(让小车在仿真和现实的位置一致);
用 2D Nav Goal 给目标点,开始导航。
第 5 章 导航(move_base / Nav2 全景)
本章对应
12.txt、14.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的通信机制:
Action:
move_base/goal(目标)、/feedback(当前位置)、/status(状态)、/result(结果)—— 适合关心执行状态的场景;Topic:
move_base_simple/goal(简单目标,不追踪状态)、cmd_vel(速度);Service:
make_plan(只规划不执行)、clear_costmaps(清代价地图)、clear_unknown_space。5.2 代价地图 costmap(避障的数据基础)
costmap_2d用传感器数据构建代价地图,并按膨胀半径计算每个格子的代价。导航用两张代价地图:
global_costmap local_costmap 用途 全局规划 局部规划/避障 坐标系 mapodom范围 整张静态地图 滚动小窗口(如 6×6m) static_maptrue(基于 map_server) false rolling_windowfalse 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_tolerance、yaw_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.yaml,14.txt)TEB 参数分 6 组:
Trajectory(轨迹):
dt_ref(时间分辨率)、max_global_plan_lookahead_dist(前瞻距离)、feasibility_check_no_poses(碰撞检查点数);Robot(机器人):
max_vel_x、max_vel_x_backwards(倒车速度,不想让它倒车就调小)、min_turning_radius(阿克曼用,差速设 0)、wheelbase(轴距);GoalTolerance(目标容差):
xy_goal_tolerance、yaw_goal_tolerance;Obstacles(障碍):
min_obstacle_dist(与障碍最小距离,要包含机器人膨胀)、inflation_dist、include_dynamic_obstacles(预测动态障碍);Optimization(优化权重):
weight_kinematics_forward_drive:迫使前进不倒车(经验:调到最大也不能完全禁止倒车,要配合其他参数);
weight_obstacle:躲障碍权重;
weight_optimaltime:时间最优权重;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_recovery、rotate_recovery、move_slow_and_clear。12.txt给出了move_base_params.yaml里恢复行为、controller_frequency、planner_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 echo、rqt_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.pgm和my_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 三步调参法
先用
rqt_reconfigure动态调,实时看效果:rosrun rqt_reconfigure rqt_reconfigure # ROS1 ros2 run rqt_reconfigure rqt_reconfigure # ROS2调到最优后,把数值写回 yaml(否则重启失效);
改完 yaml 必须重新编译(ROS1):
cd ~/yahboomcar_ws && catkin_make && source devel/setup.bash7.2 分模块调参顺序(推荐)
按"从粗到细"的顺序,一次只动一组:
底盘/里程计:先确保
/odom准(不打滑、不走偏),这是所有上层算法的基础;建图:慢速走,地图闭合、无错位;
AMCL 定位:粒子收敛快、不漂;
代价地图:
inflation_radius(别撞墙也别太保守)、obstacle_range;全局规划:先确认能规划出路径(无
NO PATH);局部规划:最后调速度/加速度/采样/评分权重,追求流畅。
7.3 关键参数直觉
现象 可能原因 调整方向 撞墙 膨胀不够 / 速度太快 ↑ inflation_radius,↓max_vel_x绕远路、不敢走 膨胀过大 / 代价过高 ↓ inflation_radius,↓cost_factor抖动、来回摆 振荡 / 采样不足 oscillation_reset_dist,↑vth_samples规划不出路径 朝向 / 未知区 试 navfn,检查allow_unknownTEB 老倒车 前进权重不够 ↑ weight_kinematics_forward_drive,↓max_vel_x_backwards定位漂移 初始位姿不准 / 粒子少 重设 2D Pose Estimate,↑min_particles7.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_make(8.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 必须用 TEB(
14.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:
roslaunch→ros2 launch;rosrun→ros2 run;catkin_make→colcon build;move_base→Nav2(nav2_planner+nav2_controller);gmapping/cartographer→SLAM Toolbox(ROS2 推荐)。
第 9 章 进阶方向与学习资源
9.1 学完本文后的进阶路线
算法深入:啃 A/D、RRT*、MPC 的数学;读 TEB 论文(Timed-Elastic-Band)和 Cartographer 论文。
3D / 视觉 SLAM:LIO-SAM(激光+IMU 紧耦合)、ORB-SLAM(纯视觉)、VINS-Fusion(VIO)。
多机/编队:多机器人协同建图与探索(rrt_exploration 的多机版)。
学习类方法:强化学习导航、端到端导航(从感知直接到速度)。
真实产品化:Nav2 行为树(BT)、生命周期节点、量产级定位融合(GNSS+IMU+LiDAR)。
组合导航:SINS/GNSS 融合、姿态表示(欧拉角/方向余弦矩阵/四元数)—— 自动驾驶/无人机方向。
9.2 资料内的官方文档链接(按主题)
SLAM 建图
gmapping: Making sure you're not a bot!
hector_slam: Making sure you're not a bot!
Cartographer: Cartographer ROS Integration — Cartographer ROS documentation
rrt_exploration: http://wiki.ros.org/rrt_exploration
导航
navigation: Making sure you're not a bot!
move_base: Making sure you're not a bot!
costmap_2d: http://wiki.ros.org/costmap_2d
global_planner: http://wiki.ros.org/global_planner
dwa_local_planner: Making sure you're not a bot!
teb_local_planner: Making sure you're not a bot!
map_server: Making sure you're not a bot!
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_velOccupancyGrid 占据栅格地图(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)思想,能够实现动态环境下的实时全局路径规划。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)