Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ardupilot/ardupilot/llms.txt

Use this file to discover all available pages before exploring further.

ArduPilot’s scripting subsystem embeds a Lua 5.3.6 interpreter directly in the autopilot firmware, giving you a sandboxed environment to customise vehicle logic, add sensors, automate missions, and prototype new features without touching C++ or reflashing the board. Scripts run on the autopilot itself alongside the core flight code.

Requirements

Scripting is automatically compiled into firmware builds for boards with more than 1 MB of flash. No special build flag is needed for supported hardware.
Scripting is not available on boards with 1 MB flash or less (for example, some older Pixhawk 1 variants). Check your board’s flash size before relying on this feature.

Enabling scripting

Set the SCR_ENABLE parameter to 1 and reboot the autopilot. Without this, the interpreter does not start and no scripts are loaded.
# In MAVProxy
param set SCR_ENABLE 1
reboot
Two additional parameters control resource allocation:
ParameterDefaultDescription
SCR_ENABLE0Set to 1 to enable the scripting engine
SCR_HEAP_SIZE43680Lua heap in bytes. Increase for complex scripts

Where to place scripts

The autopilot scans a specific directory at boot and loads every .lua file it finds there.
Place scripts in the APM/scripts/ folder on the SD card:
SD card/
└── APM/
    └── scripts/
        ├── my_script.lua
        └── another_script.lua

Script lifecycle

Every script follows the same pattern: define an update function, and return it along with the delay in milliseconds before it should be called again. The scripting engine calls this function on a cooperative schedule — it is not a real-time thread.
function update()
  -- your logic here
  return update, 1000  -- call update() again in 1000 ms
end

return update, 1000    -- first call: 1000 ms after the script loads
The return value is a (function, delay_ms) pair. Returning nil stops the script permanently.

Example: distance-from-home servo

The following script (taken from the AP_Scripting README) reads the vehicle’s current position and home location, computes the distance, and drives a servo (scripting output function 96) proportionally up to 1000 m.
function update()
  local current_pos = ahrs:get_location()   -- fetch current position
  local home = ahrs:get_home()              -- fetch home position
  if current_pos and home then              -- both must be valid
    local distance = current_pos:get_distance(home)  -- metres
    if distance > 1000 then
      distance = 1000                       -- clamp to 1000 m
    end
    -- servo function 96 = scripting3; PWM range 1000–2000
    SRV_Channels:set_output_pwm(96, 1000 + distance)
  end

  return update, 1000
end

return update, 1000

Key API bindings

Scripts access autopilot state through a set of pre-bound global objects. The bindings are generated from libraries/AP_Scripting/bindings.desc.
local pos  = ahrs:get_location()   -- returns a Location object or nil
local home = ahrs:get_home()       -- returns a Location object or nil
local dist = pos:get_distance(home) -- distance in metres (float)
local yaw  = ahrs:get_yaw()        -- yaw in radians
-- Set servo output by function number and PWM value (1000–2000 µs)
SRV_Channels:set_output_pwm(96, 1500)   -- scripting3 to mid
SRV_Channels:set_output_pwm(94, 1000)   -- scripting1 to min
Scripting servo functions start at 94 (scripting1) through 109 (scripting16).
local val = param:get("SYSID_THISMAV")  -- read a parameter
param:set("SYSID_THISMAV", 2)           -- write a parameter
gcs:send_text(6, "Hello from Lua")  -- MAV_SEVERITY_INFO = 6
local now_ms = millis()    -- milliseconds since boot
local now_us = micros()    -- microseconds since boot

Adding a new script

1

Create the script file

Write your Lua script following the update-loop pattern. Save it as my_feature.lua.
2

Copy to the scripts directory

On hardware, copy to APM/scripts/ on the SD card. In SITL, copy to scripts/ in the working directory.
3

Enable scripting and reboot

param set SCR_ENABLE 1
reboot
4

Verify loading

Check the GCS messages panel or MAVProxy output for a line like Loaded script: my_feature.lua. Errors during script load are also reported there.

Applets

The libraries/AP_Scripting/applets/ directory in the repository contains production-quality scripts maintained by the ArduPilot team. Each applet ships with a matching .md file describing parameters and usage. Examples include:
  • VTOL-quicktune.lua — automatic PID tuning for quadplanes
  • rover-quicktune.lua — automatic tuning for rovers
  • UniversalAutoLand.lua — scripted landing logic
  • copter-slung-payload.lua — slung-load compensation
  • mount-poi.lua — point-of-interest camera gimbal control
  • net_webserver.lua — embedded HTTP server via networking
Copy an applet directly to the scripts directory and configure any parameters it requires.

Example scripts

The libraries/AP_Scripting/examples/ directory contains over 150 example scripts covering topics including CAN bus access, mission editing, motor mixing, RC input overrides, rangefinder testing, LED control, and more. Browse the directory for a pattern close to your use case before writing from scratch.
The embedded Lua version is 5.3.6 — a lightly customised build of the official distribution. Standard Lua 5.3 language features are available; the standard I/O library is not (use gcs:send_text() for output).

Build docs developers (and LLMs) love