ArduPilot 自定义指令指南:3 段 Lua 脚本,给飞控装上自己的工具箱
【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot
ArduPilot 自定义指令基于 Lua 脚本实现,不用改核心固件,就能给多旋翼、固定翼、直升机加一套私有逻辑。读完这篇,你可以独立完成从环境配置到脚本部署的全流程,并写出第一个可上机的脚本。
场景先行:哪些飞控难题该交给脚本 🎯
先别急着看参数,对照一下这三个日常痛点:
模式不够用。内置飞行模式是固定的一套。你想让它按特定半径盘旋、或者跑一套私有机动规则,固件里没有现成入口,硬改源码又代价太大。
电池盯法太粗。默认低压逻辑是"一刀切"的。而你的航线可能想:降到 11.8V 先提醒,跌破 10.5V 再强制动作。这种分段策略,只有自己的判断代码才给得了。
任务里想塞私有逻辑。任务文件执行到某一步,你希望触发只有你自己懂的动作,而不是通用指令。飞控其实早就给脚本留了通道,任务指令可以派发到脚本侧处理。
三件事的共同点是:几行 Lua 就能解决,不必动固件、不必重新烧录。这个能力由 AP_Scripting 模块 承载,相当于在飞控里常驻了一位"翻译官"——你把 Lua 说给它听,它转译成飞控能执行的动作。
三步跑起 ArduPilot 脚本系统 🔧
硬件门槛先过一遍
脚本引擎自带虚拟机,比较吃资源。建议飞控至少是 STM32F7/H7 级别,Pixhawk 4、CubeBlack 这类都可以,板端还要留约 1MB 空间存脚本文件。低于这个档位,堆内存和存储都会捉襟见肘,先别急着往下走。
四个参数决定脚本的"性格"
以下参数都能在地面站(Mission Planner 等)里直接配置,注意部分参数要重启飞控才生效:
| 参数 | 作用 | 取值提示 |
|---|---|---|
| SCR_ENABLE | 脚本系统总开关 | 0 关闭,1 启用 Lua |
| SCR_HEAP_SIZE | 脚本堆内存 | 默认约 43–200KB,随硬件浮动 |
| SCR_VM_I_COUNT | 虚拟机指令执行上限 | 防止脚本霸占 CPU |
| SCR_THD_PRIORITY | 脚本线程优先级 | 按实时性需求微调 |
环境搭建三步走
- 装开发环境,命令如下:
git clone https://gitcode.com/GitHub_Trending/ar/ardupilot cd ardupilot Tools/environment_install/install-prereqs-ubuntu.sh -y- 确认编译宏:在 ArduCopter 配置 里检查 AP_SCRIPTING_ENABLED 是否已定义。这个宏没打开,整个脚本模块根本不会进固件,后面全是白忙;
- 部署脚本:把 .lua 文件通过 SD 卡或地面站放入 /APM/scripts/ 目录。上电后系统按扩展名自动加载,不需要你手动点名。
上手写:3 个高频脚本示例 ✏️
圆形轨迹跟随怎么写
场景一句话:让飞机绕悬停点画一个固定半径的圆。
-- 圆形轨迹跟随:每 100ms 推进一个相位角 local radius = 10 -- 半径(米) local angle = 0 function circle_tick() angle = angle + 0.05 vehicle:set_target_position(radius * math.cos(angle), radius * math.sin(angle), 5, 0, 0, 0) return circle_tick, 100 -- 第二个参数是调度间隔 end return circle_tick()把 radius 和步长 0.05 换一换,就能得到不同圈径和圈速的效果。
电池低压报警怎么写
场景一句话:自定义电压红线,分级提示,不依赖默认低压逻辑。
-- 电压低于 10.5V 时经 GCS 发警告,30 秒内不刷屏 local last_warn = 0 function battery_monitor() local v = battery:voltage() if v < 10.5 and os.time() - last_warn > 30 then gcs:send_text(0, "低压预警: " .. v .. " V") last_warn = os.time() end return battery_monitor, 1000 -- 每秒查一次 end return battery_monitor()阈值 10.5 改成你电池组的实际红线;要更狠一点,就在 if 里追加一个自动返航调用。
任务指令扩展怎么写
任务指令如何派到脚本侧,飞控在 AP_Mission_Commands.cpp 的 start_command_do_scripting 函数里已经铺好了路,脚本只需拦截自定义指令 ID 就能接手后续动作。
-- 拦截私有任务指令(ID 需与任务文件中一致) local CMD_USER = 31000 mavlink:register_handler(CMD_USER, function(cmd) gcs:send_text(0, "私有指令, param1=" .. cmd.param1) return 0 -- 返回 0 表示接受 end) return function() return nil, 5000 end把 handler 里的动作换成真正的业务逻辑,param1 就是任务规划端传给脚本的参数,两边约定好即可。
稳定运行的老兵经验 🛡️
性能线
- 堆内存别给满:它就像工作台面,够用就行,余量要留给飞行关键任务。
- 重计算挪到低频定时器里做,高频回调只取数、做轻量判断。
- 长驻脚本记得适时调 collectgarbage() 手动回收,别让垃圾占着堆不放。
调试线
- gcs:send_text() 把关键状态直接打到地面站,比事后翻日志快得多。
- SCR_DEBUG_OPTS 打开详细日志,再配合 Mission Planner 的脚本控制台,输出实时可见。
安全线
- 打开 SCR_LD_CHECKSUM,校验和不过的脚本拒绝加载,防住被动手脚的文件。
- 任何新脚本先跑一遍 SITL,把异常路径在模拟器里走通,再谈实飞。
收个尾
脚本系统本质是把二次开发权限下放给你的接口:固件守安全底线,脚本装个性化玩法。从官方示例里挑一个先跑通,再按自己的航线需求逐步改造,是最快的上手路径。
- 官方示例库:libraries/AP_Scripting/examples/,几十个现成脚本可以直接抄作业;
- 社区脚本与自测:Tools/autotest/pysim/ 及周边自动测试,看看别人怎么写、怎么测脚本;
- 讨论区:ArduPilot Discourse 论坛的脚本板块,卡住先搜再问,效率更高。
【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考