
ArduPilot Lua 脚本系统完整指南不改固件为飞控加装自定义能力【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilotArduPilot 内置的 Lua 脚本引擎允许你在飞控上直接运行 .lua 脚本读传感器、覆盖舵机、响应任务指令全程不需要重新编译固件。本文基于源码仓库里的 AP_Scripting 模块拆解三件事引擎如何加载和调度脚本、一套 SCR_ 参数怎么配、如何在 SITL 里跑通第一个脚本并处理生产环境的坑。读完后你能独立完成写脚本 → 本地验证 → 上车部署的完整闭环。引擎解剖一个线程、一座沙箱、一个熔断器 很多人以为脚本和飞控主循环抢 CPU实际 ArduPilot 的做法是把脚本关进一个独立空间。初始化时AP_Scripting/核心模块 会创建一个名为 Scripting 的专用线程默认栈 17KB所有 .lua 脚本共享这一个线程轮流执行。隔离由三层机制保证理解它们之后调参就不玄学了独立堆脚本拥有单独的 Lua 堆大小按平台分级——小容量平台 43KBMEM_CLASS_500 档 100KBMEM_CLASS_1000 及以上含 SITL/Linux200KB与飞控主程序内存互不侵占协作式调度脚本函数 毫秒延迟的返回值决定下次执行时间调度器按时间先后排列所有脚本谁也不阻塞谁指令计数熔断Lua 虚拟机挂了 MASKCOUNT 钩子累计执行指令数超过SCR_VM_I_COUNT默认 10000立即抛出 Exceeded CPU time防止死循环脚本烧掉整块飞控注意熔断器保护的是 CPU不是安全。一个脚本用死循环烧死自己后调度器会清理资源并每秒检查一次是否需要重启期间其他脚本照常运行。加载机制两个目录与一组 SCR_ 参数 脚本从哪来、以什么条件运行全部由参数和目录约定控制。上电后引擎扫描两个位置SD 卡的/APM/scripts/目录和编译进固件的 ROMFS 内置目录SCR_DIR_DISABLE可按位屏蔽bit 0ROMFSbit 1APM/scripts。SITL 环境下脚本直接放在仓库工作目录的scripts/文件夹即可。核心参数一览全部以 SCR_ 为前缀可在 Mission Planner 等地面站直接修改SCR_ENABLE总开关1 启用 Lua 脚本0 禁用修改后需重启飞控SCR_HEAP_SIZE脚本堆大小1KB 到 1MB默认值按平台分级改完需重启SCR_VM_I_COUNT单脚本指令熔断阈值范围 1000~1000000默认 10000SCR_THD_PRIORITY脚本线程优先级0Normal到 8Boost默认 Normal即低于 IO、存储、主循环等所有系统线程SCR_LD_CHECKSUM / SCR_RUN_CHECKSUM已加载/正在运行的脚本 CRC32 校验和不匹配则拒绝解锁-1 表示不检查SCR_DEBUG_OPTS位掩码调试选项bit 1 输出运行时内存与耗时bit 3 将运行统计写入 dataflashSCR_USER1~USER6六个 float 用户参数脚本内可读适合把半径阈值这类调试点外提参数配完下一步是让引擎真正转起来。跑通第一个脚本SITL 四步法不用真机也能完整走一遍流程SITL 下脚本放在仓库工作目录的scripts/子文件夹启动仿真脚本支持在闪存大于 1MB 的板型上自动启用Tools/autotest/sim_vehicle.py -v ArduPlane在地面站或 MAVProxy 中开启脚本引擎并重启param set SCR_ENABLE 1 reboot把你的 .lua 文件放入scripts/目录重启后自动加载地面站控制台看到 Scripting: restarted 且无 Lua 报错即成功仓库自带的 README 示例是个好起点——它展示了最小可用的周期性函数写法也解释了返回值机制function update() local pos, home ahrs:get_location(), ahrs:get_home() if pos and home then local d math.min(pos:get_distance(home), 1000) SRV_Channels:set_output_pwm(96, 1000 d) end return update, 1000 -- 1 秒后再跑一次 end return update, 1000末尾的return update, 1000就是协作调度的钩子返回的函数会被按延迟重新排队。输出写到通道 96SCRIPTING_3这是专门留给脚本的保留通道不会干扰真实舵机——验证脚本行为时这是个安全的观察出口。图运行 ArduPilot Lua 脚本的飞控真实硬件上脚本存放于 SD 卡 /APM/scripts 目录跑通之后值得看看这个引擎到底开放了哪些手脚。API 全景脚本能碰什么Lua 侧的绑定由 lua_bindings/C 函数绑定层 生成按用途可以分四类记状态读取ahrs:get_location()、battery:voltage()、esc/motors转速与温度控制输出SRV_Channels:set_output_pwm()写保留通道、vehicle:change_mode()切模式、RC 通道覆盖任务集成mission:queue_item()动态追加任务点注册mission:scripting_cmd_handler后任务里的 NAV_SCRIPT 指令cmd 18执行时飞控会把参数推给脚本处理——这是任务规划调脚本的正式通道而不是轮询硬件直连I2C 设备、CAN 传感器、独立串行口SCR_SDEV_EN、网络 socket等于把飞控当成一块可编程 IO 扩展板任务指令的例子值得看它展示了脚本如何被动响应而非主动轮询local function on_scripting_cmd(p1, p2, p3, p4) gcs:send_text(0, NAV_SCRIPT received, p1 .. p1) end mission:scripting_cmd_handler(on_scripting_cmd)注册后任务中执行 NAV_SCRIPT 指令时p1 为整数参数、p2~p4 为 float 参数回调被调度器统一触发不会和主控制循环抢时间片。图ArduPilot 飞控接线示意脚本可通过串口、I2C、CAN 等接口直接驱动扩展硬件能碰的东西越多越要懂得怎么把它管好。生产环境调优与避坑先说最常踩的三个坑内存不足控制台报 Insufficient memory loading 时加大SCR_HEAP_SIZE改完重启。堆是独立沙箱加到 100KB 也不会挤占导航滤波的内存CPU 超限报 Exceeded CPU time 说明单轮逻辑太重正确做法是拆分逻辑、拉大调度间隔直接调大 SCR_VM_I_COUNT 只是掩盖问题优先级误区SCR_THD_PRIORITY默认 Normal 是刻意压低让脚本永远排在系统线程之后。参数注释里明确警告提到 MAIN/BOOST 档前必须逐个审计所有脚本因为所有脚本共享同一优先级一个脚本失控会连坐全部另外两个容易被忽略的运维能力热重启地面站发送 MAVLink 的 SCRIPTING_CMDSTOP / STOP_AND_RESTART即可停掉或重建整个脚本环境不用断电重启飞控调试迭代时非常顺手校验和锁机脚本更新后置SCR_DEBUG_OPTSbit 5 可把当前脚本 CRC 存进 SCR_LD_CHECKSUM / SCR_RUN_CHECKSUM。之后只要有人误删或改动了脚本文件飞控拒绝解锁——对多机车队和科研外场作业来说这是必要的保险沙箱能防脚本写坏内存防不了脚本用高频 PWM 输出写坏机械结构。任何直接输出到真实通道的脚本务必先在 SITL 或地面台架上验证极限行为。小结与延伸资源本文覆盖了 AP_Scripting 的完整机制链路独立线程沙箱与指令熔断、SCR_ 参数体系、SITL 验证流程、四类 API 表面以及校验和与热重启这类生产手段。边界同样清楚脚本运行在低优先级线程里适合 IO、逻辑、数据处理类扩展不适合替代主控制环涉及解锁安全和机械输出的部分校验和与地面测试不能省。延伸入口示例脚本库libraries/AP_Scripting/examples/60 多个按场景分类的现成脚本CAN 读写、电池监测、电机矩阵、翻车保护等模块说明libraries/AP_Scripting/README.md编译开关与最小脚本速览内置 Lua 模块libraries/AP_Scripting/modules/MAVLink 消息封装、NMEA2000 等开箱即用的扩展【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考