1. 课程导论与系统架构
大家好,欢迎来到《从零搭建无人机航线规划系统》的第一章。
说实话,我入行做无人机飞控那会儿,市面上还没有什么成熟的航线规划开源方案。那时候我们团队接了个农业植保的项目,需要无人机按照地块边界自动生成喷洒路径。我拿着遥控器在地里手动打点,打了整整两天……后来我就在想,能不能自己写一套规划系统?
嗯,这个想法最终变成了这门课。今天我们先从全局视角,看看整个系统长什么样。
1.1 什么是无人机航线规划系统?
说白了,航线规划就是让无人机知道「从哪起飞、经过哪些点、最后落在哪」。但实际远不止这么简单。
一个完整的航线规划系统,需要解决三个核心问题:
- 飞哪里 —— 航点坐标、高度、速度
- 怎么飞 —— 转弯半径、爬升率、避障策略
- 飞得稳 —— 风场补偿、电池余量、应急返航
我在项目中遇到过最头疼的事:规划出来的航线在仿真里跑得完美,一到真机测试就撞树。后来发现是没考虑无人机的最小转弯半径。你想想看,固定翼和四旋翼的转弯能力完全不一样,规划算法必须知道底层飞控的约束。
核心认知:航线规划不是「画一条线」,而是「在约束条件下找一条可飞路径」。约束包括:无人机动力学、空域规则、传感器视野、电池续航。
1.2 核心功能模块
我把整个系统拆成了 6 个模块。每个模块单独开发、单独测试,最后拼在一起。我个人习惯用这种「微服务」的思路做嵌入式系统,虽然 ROS2 本身不是微服务,但模块化设计能让调试效率翻倍。
| 模块名称 | 职责 | 输入 | 输出 |
|---|---|---|---|
| 任务管理器 | 解析用户任务(航拍/巡检/测绘) | JSON 任务文件 | 任务队列 |
| 路径规划器 | 生成全局路径(A* / RRT*) | 地图、起终点 | 航点列表 |
| 轨迹优化器 | 平滑路径、满足动力学约束 | 原始航点 | 时间-位置曲线 |
| 状态估计器 | 融合 GPS/IMU/视觉 | 传感器数据 | 位姿 + 速度 |
| 控制接口 | 将轨迹转为 PX4 的 MAVLink 指令 | 期望轨迹 | uORB 消息 |
| 监控与日志 | 记录飞行数据、异常告警 | 系统状态 | CSV / ROS bag |
注意看,路径规划和轨迹优化是分开的。为什么?因为路径规划只管「走哪条路」,轨迹优化管「怎么走」。我在早期项目里把两者混在一起,结果每次改动力学参数都要重跑整个规划器,太痛苦了。
1.3 技术栈选型:Python + ROS2 + PX4
选技术栈的时候,我其实纠结过要不要用 C++ 全栈。后来决定用 Python 做上层规划,ROS2 做中间件,PX4 做底层飞控。理由有三:
- Python 快速迭代 —— 规划算法经常要调参、换策略,Python 改完就能跑。我习惯先用 Python 验证算法,再考虑是否用 C++ 重写性能瓶颈部分。
- ROS2 的分布式通信 —— 规划节点、状态估计节点、监控节点可以跑在不同机器上。调试的时候我在笔记本上跑规划器,树莓派上跑飞控桥接,方便得很。
- PX4 的成熟生态 —— 不想从零写底层控制。PX4 的 EKF 和 PID 已经经过大量验证,我们只需要把规划好的航线通过 MAVLink 喂给它就行。
我的建议:如果你刚接触 ROS2,可以先从 rclpy 入手。Python 版的 ROS2 客户端虽然性能不如 C++,但做原型验证足够了。等系统稳定了,再把高频节点(比如控制接口)换成 C++。
这里有个坑,我曾经踩过:ROS2 的 DDS 发现机制在 Wi-Fi 环境下偶尔会丢节点。解决办法是把 ROS_DOMAIN_ID 设成固定值,别用默认的 0。嗯,这个小细节能省你半天调试时间。
1.4 系统整体架构图
下面这张图是我画的第一版架构。每次做新系统,我都习惯先画一张「盒子加箭头」的图,把数据流理清楚再写代码。
从图里你能看到,数据流是单向的:用户任务 → 任务管理器 → 路径规划器 → 轨迹优化器 → 控制接口 → PX4。但状态估计器和监控模块是「旁路」的,它们不参与主流程,却决定了飞行质量。
注意:千万不要把状态估计器放在主流程里做串行处理。我曾经试过让轨迹优化器等待状态估计器返回结果再计算下一步,结果导致控制频率从 50Hz 掉到 10Hz,飞机直接抖起来了。状态估计应该异步运行,用最新的一帧数据就好。
1.5 为什么选这个架构?
你可能想问:市面上有那么多航线规划方案,为什么非要自己搭一套?
我的回答是:为了「可控」。商业飞控的航线规划往往是黑盒,你没法改里面的转弯逻辑,也没法加自定义的避障策略。而我们从零搭建的系统,每一行代码都看得见、改得动。
举个例子:有一次客户要求无人机在输电塔周围做「螺旋上升」的巡检路径。市面上的规划工具根本画不出这种轨迹。我们自己在轨迹优化器里加了一段螺旋线生成逻辑,两天就搞定了。这就是自己搭系统的底气。
小技巧:架构设计时,多想想「如果我要换掉其中一个模块,需要改多少代码?」好的架构,换一个模块只需要改接口适配层,核心逻辑不动。我习惯在模块之间用抽象接口类(Python 的 ABC)做隔离,这样后期重构成本极低。