如何给ArduPilot写第一个Lua脚本:3个实战示例+调优避坑
2026/9/11 14:34:59 网站建设 项目流程

如何给ArduPilot写第一个Lua脚本:3个实战示例+调优避坑

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

标准模式覆盖不了的动作,正是你需要 ArduPilot Lua 脚本的时候。ArduPilot 固件内置了 Lua 5.3 解释器,源码在 libraries/AP_Scripting/lua/,它把姿态、位置、模式、电池、舵机等能力以ahrsvehiclebattery等对象暴露给脚本。你写几十行代码上传到飞控,就能实现自定义指令逻辑,不用重新编译固件。本文的 3 个示例均可直接运行,全部改写自 libraries/AP_Scripting/examples/ 里的官方样例。动手前先明确两个前提:飞控板子闪存需大于 1MB,构建系统才会自动编入脚本支持(见 libraries/AP_Scripting/README.md);所有逻辑请先在 SITL 里验证,它是基于 PC 的软件在环仿真,模拟飞控行为而不需要真机。

⚡ 先说痛点:哪些逻辑标准模式覆盖不了

我实际飞的时候,遇到三类需求是内置模式做不到的:

  • Circle(圆圈)模式下拖半径,地速会跟着变,固件没有"恒地速绕圈"
  • 电池低压靠目测 OSD,想要脚本自动向地面站推送告警
  • 想要一个单路摇杆触发的紧急返航,不依赖 GCS 连接

这三类需求的共同点是:原子能力(设置目标位置、读电压、切模式)固件都已经开放,缺的是中间的编排逻辑。Lua 脚本补的就是这段逻辑。脚本系统运行在独立线程上,核心写法固定:定义一个update函数,末尾返回update, 毫秒数,系统就会按这个间隔反复调用它。

🔧 环境准备:脚本从写好到跑起来的三步

  • SCR_ENABLE:脚本系统总开关(0=禁用,1=启用,默认 0),改为 1 后必须重启飞控才生效
  • SCR_HEAP_SIZE:分配给脚本的堆内存,单位字节(默认值随板子规模在几十 KB,内存需求大的脚本要提到 80000 以上)

上传方式按运行环境分两种:真机把.lua文件放进 SD 卡的APM/scripts/目录;SITL 则放在 ardupilot 工作目录下。启动时固件自动扫描该目录,执行其中所有脚本。注意:改错参数导致脚本加载失败时,控制台会提示 "Required SCR_HEAP_SIZE over",按提示调大堆再重启即可。

🚀 示例一与示例二:恒地速绕圈与电池电压监控

Circle 模式保持恒定 5 米每秒地速

场景:Circle 模式下半径一变地速就变,飞行测试时很干扰观察。下面的脚本读取当前半径,反算出目标转速并写回。

-- 恒速绕圈:Circle 模式自动调整转速,保持 5 m/s 地速 local target_speed = 5 -- 目标地速 (m/s) function update() if not (arming:is_armed() and vehicle:get_likely_flying() and vehicle:get_mode() == 7) then return update, 1000 -- 非目标场景,每秒检查一次 end local radius = vehicle:get_circle_radius() if radius then local rate = 360 * (target_speed / (radius * 2 * math.pi)) -- 换算转速(°/s) rate = math.max(math.min(rate, 90), -90) -- 限制在 ±90°/s vehicle:set_circle_rate(rate) end return update, 100 -- 10Hz 重新调度 end return update() -- 启动周期执行

预期效果:解锁后切到 Circle 模式,半径怎么拖地速都稳定在 5 m/s 附近,模式号 7 对应 Copter 的 Circle。

电池低于阈值自动推送告警

场景:低压是炸机主因之一,人工盯屏幕不可靠。脚本每秒读一次电压,低于阈值时向地面站推一条错误级消息。

-- 电池监控:电压低于阈值时推送一次告警 local warn_volt = 21.5 -- 告警阈值 (V),按电芯数调整 local alerted = false function battery_watch() local v = battery:voltage() -- 读取当前总电压 (V) if v and v < warn_volt and not alerted then gcs:send_text(3, "电池低压: %.1fV" % v) -- 3 为错误级别 alerted = true end if v and v > warn_volt + 0.5 then alerted = false -- 电压恢复后复位,允许再次告警 end return battery_watch, 1000 -- 每秒检查一次 end return battery_watch()

预期效果:地面站 Console 立刻收到 "电池低压" 消息,且低电压期间不会重复刷屏。gcs:send_text第一个参数是严重级别,0 最严重、6 为普通信息。

🛠️ 示例三:摇杆通道触发自动返航

场景:GCS 失联或来不及点 RTL 时,把遥控器第 7 通道拨到高位(PWM 大于 1800),脚本自动切 Guided 模式并把目标设到家点上方 10 米。

-- 摇杆触发返航:通道 7 拉高后 Guided 模式返回家点 local target_alt = 10 -- 返回高度 (米,家点上方) function update() if arming:is_armed() and rc:get_pwm(7) > 1800 then if vehicle:get_mode() ~= 4 then -- 4 为 Copter 的 Guided vehicle:set_mode(4) else local home = ahrs:get_home() if home then home:alt(home:alt() + target_alt * 100) -- 高度单位是 0.01 米 vehicle:set_target_location(home) end end end return update, 500 -- 2Hz 检查 end return update()

预期效果:拨高第 7 通道后,飞行器切到 Guided 并飞向家点正上方 10 米处悬停,不会直接落地,方便人工接管。

📊 调优避坑:参数、性能与安全

参数方面记住两条:SCR_ENABLE 是入口,不启用什么都不会发生;SCR_HEAP_SIZE 决定脚本能活多大,长表格、长字符串的脚本实测中需要 80KB 以上堆。脚本内存来自这块固定堆,堆不够时垃圾回收(解释器自动回收已释放内存的机制)也无能为力,加载会直接失败。

性能方面,实测中发现把return update, 100这类高频回调里塞复杂计算,会挤占控制线程的 CPU。建议:非实时逻辑的调度间隔不低于 100ms,重计算拆成每次一小步。

注意:脚本抛错时,错误文本会走gcs:send_text发给地面站,先看 Console 再上天,比上天后排查快得多。建议:所有脚本先在 SITL 里跑通,用Tools/autotest/sim_vehicle.py -v ArduCopter一条命令启动仿真即可。

到这里,你的飞控已经具备了不碰固件就能扩展行为的能力:从监控告警到自定义返航,都是同一套写法。想继续扩展时,直接翻官方样例库比看教程更快,下面这份清单可以按场景查找。

  • 官方示例脚本(含本文三个示例的原型):libraries/AP_Scripting/examples/
  • 可改装使用的社区 Applet 脚本:libraries/AP_Scripting/applets/
  • 构建与启用说明:libraries/AP_Scripting/README.md
  • SITL 一键启动脚本:Tools/autotest/sim_vehicle.py

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询