机器人软件系统

SLAM定位建图、路径规划(A*/RRT*)、运动规划(MoveIt2)、行为树任务编排、LLM任务规划——完整的机器人软件栈。

5-6周
7 个章节
代码示例
5 个实验

本阶段目录

  1. SLAM定位与建图
  2. 路径规划:A*到RRT*
  3. 运动规划:MoveIt2
  4. 行为树
  5. LLM任务规划
  6. ROS通信拓扑实验

1. SLAM:同时定位与建图

问题:$$p(x_{1:T}, m | z_{1:T}, u_{1:T})$$——未知环境中同时定位和建图

类型传感器代表
激光SLAM2D/3D LiDARCartographer
视觉SLAMRGB-DORB-SLAM3

图优化SLAM:节点=位姿,边=约束,最小化$$\min_x \sum \|e_{ij}(x_i, x_j)\|^2_{\Sigma_{ij}}$$

2. 路径规划

A*:$$f(n)=g(n)+h(n)$$,保证最优但高维困难

RRT*:采样基+局部重连,适合6DOF+的高维空间

# A* 核心循环
while open_set:
    _, _, current = heapq.heappop(open_set)
    if current == goal: return reconstruct_path(came_from, current)
    for neighbor in neighbors(current):
        tentative_g = g_score[current] + 1
        if tentative_g < g_score.get(neighbor, inf):
            came_from[neighbor] = current
            g_score[neighbor] = tentative_g
            heapq.heappush(open_set, (tentative_g + h(neighbor), -tentative_g, neighbor))

3. 运动规划:MoveIt2

架构:规划请求→规划管道→OMPL运动规划器→轨迹

约束规划:笛卡尔路径+定向约束(工具保持竖直)+关节限位

4. 行为树

节点符号作用
Sequence顺序执行,一个失败整体失败
Fallback尝试子节点直到一个成功
bt = Sequence("抓取任务", [
    Condition("检测物体", obj_detected),
    Action("接近", approach),
    Action("抓取", grasp),
    Fallback("验证重试", [
        Sequence("验证-提起", [
            Condition("验证成功", verify_grasp),
            Action("提起", lift),
        ]),
        Action("重新抓取", grasp),
    ]),
])

5. LLM任务规划

自然语言→LLM→JSON技能序列→行为树执行→运动规划→轨迹执行

6. ROS通信节点/拓扑图网页实验

真实机器人软件栈不是单个脚本,而是一张持续流动的通信网络。感知节点发布图像和点云,融合节点生成目标,规划器输出路径,控制节点发送关节或底盘命令;任何一个节点频率、QoS、CPU负载或桥接延迟异常,都会变成“机器人反应慢、TF不同步、控制发抖”。

站内实验:ROS 通信拓扑可视化

打开实验后拖动相机频率、点云频率、QoS可靠度、桥接延迟和CPU负载。画布会实时展示节点、Topic、消息脉冲、端到端延迟和丢包率,帮助你建立“系统不是黑盒,而是一张可诊断的图”的直觉。

观察对象节点 · Topic · 消息脉冲
核心指标延迟 · 丢包 · 融合健康度
工程连接rqt_graph · Foxglove · ros2 topic hz

实验前置问题

  1. 相机从30Hz升到60Hz时,哪个节点最可能先变成瓶颈?
  2. QoS可靠度提高以后,为什么延迟有时会变大?
  3. 如果控制节点收到旧消息,真实机器人会出现什么症状?

完成标准

阶段总结

SLAM是机器人的"眼睛+记忆",运动规划是从可行到最优的桥梁,行为树比状态机更适合复杂任务的反应式执行。

知识地图

系统模块输入输出典型工具
SLAMLiDAR/RGB-D/IMU/里程计地图+机器人位姿Cartographer、ORB-SLAM3、Nav2
任务规划自然语言目标、场景约束可执行技能序列PDDL、LLM planner、行为树
运动规划起点、目标、障碍物、约束无碰撞轨迹MoveIt2、OMPL、TrajOpt
行为执行技能序列、反馈状态成功/失败/重试BehaviorTree.CPP、ROS2 action
系统监控日志、TF、topic、诊断信息健康状态和故障定位ros2 doctor、rqt、Foxglove

任务规划到行为树

现代具身智能常用“LLM负责高层语义,行为树负责可控执行”的分层结构。LLM不直接控制电机,而是输出技能调用计划;行为树负责检查前置条件、失败恢复、超时和安全中断。

{
  "goal": "把红色积木放入左侧盒子",
  "plan": [
    {"skill": "detect", "object": "red_block"},
    {"skill": "pick", "object": "red_block"},
    {"skill": "place", "target": "left_box"},
    {"skill": "verify", "condition": "object_in_box"}
  ]
}

MoveIt2工程工作流

  1. 建模:准备URDF/Xacro、关节限位、惯量、碰撞几何和末端执行器。
  2. 配置:用MoveIt Setup Assistant生成SRDF、规划组、Kinematics、OMPL参数。
  3. 规划:设置目标位姿、姿态约束、路径约束和规划时间,比较RRTConnect、RRT*、PRM。
  4. 执行:把轨迹发送给ros2_control,监控joint trajectory controller状态。
  5. 诊断:用RViz、TF tree、PlanningScene、ros2 topic echo检查碰撞体和坐标系。

实验任务

  1. A*导航:在栅格地图上实现A*,比较曼哈顿、欧氏、对角线启发函数的路径质量。
  2. RRT*机械臂规划:在2D/3D关节空间中规划避障路径,报告采样次数、路径长度和平滑后长度。
  3. 行为树抓取:实现检测-接近-抓取-验证-重试流程,模拟检测失败和抓取失败。
  4. MoveIt2 Pick&Place:在仿真中完成一套pick/place demo,并保存RViz截图和轨迹耗时。
  5. ROS拓扑诊断:完成网页端ROS通信拓扑实验,记录延迟、丢包率、瓶颈节点和你的调参策略。

常见问题排查

能力清单与下一阶段前置要求

完成本阶段后,应能画出机器人软件栈数据流,独立解释SLAM、任务规划、行为树、MoveIt2之间的接口边界。进入机器人控制前,需要掌握坐标系、状态反馈、轨迹、误差和控制频率这些概念。

教材式自测与学习进度

概念自测

  1. 解释SLAM中定位和建图为什么互相依赖。
  2. 说明A*启发函数需要满足什么条件才能保证最优。
  3. 比较A*、RRT、RRT*、PRM的适用场景。
  4. 解释MoveIt2中的PlanningScene有什么作用。
  5. 说明IK失败、碰撞失败、控制失败分别应该在哪里排查。
  6. 比较行为树和有限状态机在失败恢复上的差异。
  7. 解释LLM任务规划为什么不能直接绕过行为树和安全检查。
  8. 说明ROS2 action为什么适合长时间机器人技能。

操作练习

  1. 画出一个移动机械臂系统的topic、service、action数据流。
  2. 实现A*并把搜索过程可视化。
  3. 实现简化RRT并统计不同步长下的成功率。
  4. 用XML写一个BehaviorTree.CPP风格的抓取行为树。
  5. 在RViz中检查TF tree和PlanningScene碰撞体。

进度追踪

里程碑验收标准完成
SLAM理解能解释前端里程计和后端图优化
路径规划能实现A*和RRT基础版本
MoveIt2能在仿真中完成一次无碰撞规划
行为树能设计含重试和恢复的任务树
任务规划能把自然语言目标拆成可执行技能序列

扩展挑战

  1. 把LLM输出计划自动转换为行为树XML。
  2. 为MoveIt2规划失败设计fallback策略。
  3. 把SLAM地图用于导航,再把导航结果交给机械臂抓取。
  4. 用Foxglove录制一次完整任务并做故障复盘。

阶段复盘问题

  1. 一个机器人任务失败时,如何区分感知失败、规划失败、控制失败和执行器故障?
  2. 如果行为树频繁进入重试分支,应该优先看日志、传感器还是规划参数?
  3. 为什么复杂任务最好拆成可复用技能,而不是写一个巨大的端到端脚本?