Lua

Lua脚本

ArduPilot引入了对Lua脚本的支持。 脚本提供了一个安全的“沙盒”环境,可以在不修改核心飞行代码的情况下将新行为添加到自动驾驶仪中。 脚本存储在 SD 卡上,并与航班代码并行运行。

本页介绍如何在自动驾驶仪上设置脚本、脚本 API、脚本小程序以及一些有助于入门的示例。

虽然脚本通常至少需要一些 LUA 编程和编辑,但有一些可用的小程序不需要用户编辑,就可以使用。请参阅下面的链接。

注意

Lua脚本支持随Copter-4.0,Rover-4.0和Plane-3.9.11一起发布。

开始

  • 确保您的自动驾驶仪至少有 2 MB 的闪存和 70 KB 的内存。像CubePilot Cube Orange和HolyBro Durandal这样的高功率自动驾驶仪肯定会运行良好,但请检查自动驾驶的规格。

  • SCR_ENABLE 设置为 1 以启用脚本(刷新或重新启动以查看所有参数)。SCR_

  • 将脚本(扩展名为 .lua 的文件)上传到自动驾驶仪的 SD 卡文件夹。APM/scripts

    • 如果此文件夹不存在,您可以通过将SCR_ENABLE设置为 1 并重新启动来创建它。也可以在SD卡上手动创建此文件夹。

    • 如果使用任务规划器,则可以使用 MAVFTP 完成此操作。

    • 如果使用模拟器,则该文件夹位于启动模拟器的目录中。MAVFTP在这种情况下也可以工作。scripts

    ../_images/scripting-MP-mavftp.png

  • 示例/示例脚本可以在这里找到稳定的飞机直升机漫游者。最新的开发脚本可以在这里找到。

  • 小程序是使用前不需要用户编辑的脚本,可以在这里找到。其中每个都有一个同名的 .md 文件,详细说明其功能、使用和设置。例如,有一个脚本允许用户从发射机通道更改支持 SmartAudio 的视频发射器的输出功率电平,并通过参数设置其上电值。请参阅脚本小程序

  • 司机Lua脚本实际上可以为ArduPilot固件中不直接支持的新外围硬件提供硬件驱动程序,例如新的EFI或Gimbals。可以在此处找到这些示例。

注意

要从github位置下载,请先单击脚本名称,然后在右上角选择“raw”,然后单击鼠标右键以“将页面另存为”具有“.lua”文件扩展名的文本文件

  • 使用“RCX_OPTION”=“8-300”选项,最多可将 307 个 RC 通道指定为脚本输入/控制。此外,还有四个专用脚本参数可用:SCR_USER1SCR_USER4 并使用与任何其他参数相同的方法进行访问,但这些参数保留供脚本使用。

  • 当自动驾驶仪通电时,它将加载并启动所有脚本。

  • 消息和错误将发送到地面站,如果使用任务规划器,则可以在数据屏幕的“消息”选项卡中查看。

  • 可以调整SCR_HEAP_SIZE以增加或减少可用于脚本的内存量。默认值 43 kB 对于小型脚本来说已经足够了,并且适合大多数自动驾驶仪。自动驾驶仪的可用内存在很大程度上取决于启用的功能和外围设备。如果此参数设置得太低,脚本可能无法运行。如果设置得太高,其他自动导航仪功能(如地形跟随甚至 EKF)可能无法初始化。在配备STM32F4微控制器的自动驾驶仪上,智能RTL(漫游车,直升机)和地形跟踪(飞机,直升机)几乎总是需要禁用。这些功能通常默认启用,设置为 SRTL_POINTS = 0,TERRAIN_ENABLE = 0)。另请参阅 RAM 限制部分。

脚本可以做什么

  • 可以一次运行多个脚本

  • 监控车辆状态

  • 开始操纵车辆状态

Lua是一种垃圾回收的命令式编程语言。 脚本在系统上以低优先级运行,这可确保即使脚本需要很长时间来处理,核心外部测试版代码也会继续执行。 为了允许运行多个脚本,每个脚本都被分配了一个固定的时间块(以 VM 指令为单位),预计它会在其中完成其处理。 允许脚本指定新的回调函数和应调用它的时间,从而允许它连续运行。 虽然这有助于安全地绑定最坏情况的执行时间,但不能保证脚本按可靠的计划运行。

每个脚本都在自己的“沙盒”环境中运行。 这允许每个脚本操作它想要的任何全局变量,而不会导致其他脚本问题,并允许脚本在调用其回调之间保持状态。 但是,这样做的副作用是脚本中的大量内存使用可能会导致其他脚本内存不足。

示例脚本

以下脚本用于根据飞机与原位的距离更改伺服输出。

 1function update () -- periodic function that will be called
 2  local current_pos = ahrs:get_position() -- fetch the current position of the vehicle
 3  local home = ahrs:get_home()            -- fetch the home position of the vehicle
 4  if current_pos and home then            -- check that both a vehicle location, and home location are available
 5    local distance = current_pos:get_distance(home) -- calculate the distance from home in meters
 6    if distance > 1000 then -- if more then 1000 meters away
 7      distance = 1000;      -- clamp the distance to 1000 meters
 8    end
 9    servo.set_output_pwm(96, 1000 + distance) -- set the servo assigned function 96 (scripting3) to a proportional value
10  end
11
12  return update, 1000 -- request "update" to be rerun again 1000 milliseconds (1 second) from now
13end
14
15return update, 1000   -- request "update" to be the first time 1000 milliseconds (1 second) after script is loaded

此脚本首先定义更新函数,该函数将定期调用。 此函数获取车辆当前位置和起始位置,并将它们存储在局部变量 current_pos 和 home 中。 这两个变量现在要么保存位置用户数据,要么为零,如果当前无法从车辆获得信息。 然后检查变量以确保它们实际提供,然后再计算位置之间的距离。 在检查以确保测量距离永远不会超过 1 公里后,该距离用于设置伺服位置。 函数中的最后一行用于重新安排此函数,以便在当前时间的 1000 毫秒内再次运行。 脚本的最后一行还用于计划函数在加载后的 1000 毫秒内首次运行函数。

脚本崩溃和错误

如果脚本内存不足(或由于任何原因而死机),则所有当前正在运行的脚本都将终止,脚本引擎将重新启动,并从磁盘重新加载所有脚本。 这允许在所有飞行阶段发生,即使在车辆武装和飞行时也是如此。

脚本和参数

接口文档

此处描述的 API 文档不是完整列表,而是一些示例。有关当前可用方法的完整列表,LUA 自动生成的文档文件是一个完整列表,可以在此处找到它并列出所有可用的绑定及其参数。

注意

如果将 VScode 用于编辑器,则通过安装 lua 扩展(目前仅版本 2.4.1),可以将此信息作为建议集成并在编辑器中自动完成。

有关绑定如何工作的完整信息,可以在绑定生成器描述中找到源代码。

有关如何解码此处显示的方法的详细信息,请参阅绑定说明方法语法。ArduPilot 使用 Lua 版本 5.3.5。

位置

位置是一个用户数据对象,用于保存表示为纬度、经度、海拔的位置。高度可以位于几个不同的框架中,相对于家庭、高于平均海平面的绝对高度或相对于地形。要创建新的位置用户数据,您可以调用 Location() 来分配一个空的位置对象,或者调用一个返回给你的方法。

位置用户数据对象支持以下调用:

  • lat( [new_lat] )- 如果不带参数调用,则以度 * 1e7 为单位返回当前纬度作为整数。如果使用一个参数调用,它将值分配给纬度。

  • lng( [new_lng] )- 如果不带参数调用,则以度 * 1e7 为单位返回当前经度作为整数。如果使用一个参数调用,它将值分配给经度。

  • alt( [new_alt] )- 如果不带参数调用,则以整数形式返回当前高度(以 cm 为单位)。如果使用一个参数调用,它将值分配给高度。

  • relative_alt( [is_relative] )- 如果调用时不带参数,则返回 true,如果位置规划为相对于 home 的位置。如果使用布尔值调用,这将设置相对高度。

  • terrain_alt( [is_terrain] )- 如果在没有参数的情况下调用,则如果位置是相对于地形规划的,则返回 true。如果使用布尔值调用,这将标记高度是否应相对于地形。

  • origin_alt( [is_origin] )- 如果调用时不带参数,则返回 true,如果该位置规划在相对于平均海平面的绝对高度。如果使用布尔值调用,则会将高度设置为相对于平均海平面。

  • loiter_xtrack( [should_xtrack] )- 如果该位置用于悬停位置,则标记飞机是否应从中心点或从悬停器的出口位置进行跟踪。

  • get_distance( other_Location )- 给定一个位置,这将计算两个位置之间的水平距离(以米为单位)。

  • offset( offset_north , offset_east )- 按指定的米数转换此位置。

  • get_vector_from_origin_NEU()- 返回 nil 或 Vector3f,其中包含从 EKF 原点到此位置的偏移量。如果调用 EKF 源时不可用,这将返回 nil。

  • get_bearing( other_Location )- 给定一个位置,这将计算与位置的相对方位角(以弧度为单位)

  • get_distance_NED( other_Location )- 将包含 3D 矢量(以米为单位)的 nil 或 Vector3f 返回到另一个位置。

  • get_distance_NE( other_Location )- 将包含 2D 矢量(以米为单位)的 nil 或 Vector2f 返回到另一个位置。

矢量2f

Vector2f 是一个保存 2D 向量的用户数据对象。组件存储为浮点数。要创建一个新的 Vector2f,你可以调用 Vector2f() 来分配一个新的,或者调用一个返回给你的方法。

Vector2f 对象支持以下调用:

  • x( [new_x] )- 如果没有参数调用,则返回当前设置的 X 分量作为浮点数。如果使用一个参数调用,它将值分配给 X 组件。

  • y( [new_y] )- 如果没有参数调用,则返回当前设置的 Y 分量作为浮点数。如果使用一个参数调用,它将值分配给 Y 组件。

  • length()- 以浮点数的形式返回向量的长度。

  • normalize()- 将向量规范化为单位向量。

  • is_nan()- 如果向量包含任何 NaN 成员,则返回 true。

  • is_inf()- 如果向量包含任何无穷大成员,则返回 true。

  • is_zero()- 如果所有向量字段均为 0,则返回 true。

Vector2f 支持以下运算符:

  • +- 按分量添加两个向量。

  • -- 用分量减去两个向量。

矢量3f

Vector3f 是一个保存 3D 向量的用户数据对象。组件存储为浮点数。要创建一个新的 Vector3f,你可以调用 Vector3f() 来分配一个新的,或者调用一个返回给你的方法。

Vector3f 对象支持以下调用:

  • x( [new_x] )- 如果没有参数调用,则返回当前设置的 X 分量作为浮点数。如果使用一个参数调用,它将值分配给 X 组件。

  • y( [new_y] )- 如果没有参数调用,则返回当前设置的 Y 分量作为浮点数。如果使用一个参数调用,它将值分配给 Y 组件。

  • z( [new_z] )- 如果没有参数调用,则返回当前设置的 Z 分量作为浮点数。如果使用一个参数调用,它将值分配给 Z 组件。

  • length()- 以浮点数的形式返回向量的长度。

  • normalize()- 将向量规范化为单位向量。

  • is_nan()- 如果向量包含任何 NaN 成员,则返回 true。

  • is_inf()- 如果向量包含任何无穷大成员,则返回 true。

  • is_zero()- 如果所有向量字段均为 0,则返回 true。

Vector3f 支持以下运算符:

  • +- 按分量添加两个向量。

  • -- 用分量减去两个向量。

ahrs 库表示由自动驾驶仪计算的姿态航向参考系统。它提供车辆姿态和位置的估计值。

  • get_roll()- 返回当前车辆侧倾角度(以弧度为单位)。

  • get_pitch()- 返回当前车辆俯仰角(以弧度为单位)。

  • get_yaw()- 返回当前车辆偏航角(以弧度为单位)。

  • get_position()- 返回包含车辆当前位置的 nil 或位置用户数据。注意:仅当系统认为当前估计值合理时,此操作才会返回位置。

  • get_home()- 返回包含车辆当前返航点的位置。

  • get_gyro()- 返回包含当前平滑和滤波陀螺仪速率的 Vector3f(以弧度/秒为单位)

  • get_hagl()- 返回零,或地面以上的最新高度估计值(以米为单位)

  • wind_estimate()- 返回包含车辆当前风力估计值的 Vector3f。

  • groundspeed_vector()- 返回一个 Vector2f,其中包含北分量和东分量中的车辆速度(以米/秒为单位)。

  • get_velocity_NED()- 返回 nil 或包含当前 NED 车辆速度(以米/秒为单位)的 Vector3f,在北、东和下分量中。

  • get_velocity_NE()- 返回 nil,或包含当前 NE 车辆速度(以米/秒为单位)的 Vector2f,在北部和东部分量中。

  • home_is_set()- 如果已设置初始位置,则返回 true。

  • prearm_healthy()- 如果当前预扶手检查通过,则返回 true。

  • airspeed_estimate()- 返回当前空速估计值(以米/秒或零为单位)。

布防(布防:)

布防库提供对布防状态和命令的访问。

  • disarm()- 在所有情况下解除车辆的武装。仅当已解除武装时才返回 false。

  • is_armed()-如果战车当前已武装,则返回 true。

  • arm()- 试图武装车辆。如果成功,则返回 true。

电池(电池:)

电池库提供对车辆上当前连接的电池信息的访问。

  • num_instances()- 返回当前可用的电池实例数。

  • healthy( instance )- 如果请求的电池实例运行正常,则返回 true。健康被认为是ArduPilot目前能够监控电池的。

  • voltage( instance )- 返回所选电池实例的电压。

  • voltage_resting( instance )- 返回估计的电池电压(如果未处于负载下)。

  • current_amps( instance )- 返回电池当前消耗的电流(以安培为单位),如果电流监控不可用,则返回 nil。

  • consumed_mah( instance )- 返回电池使用的容量(以毫安小时为单位),如果电流监控不可用,则返回 nil。

  • consumed_wh( instance )- 返回电池的已用瓦时数,如果能量监控不可用,则返回 nil。

  • capacity_remaining_pct( instance )- 返回剩余电池百分比(从 0 到 100)

  • pack_capacity_mah( instance )- 从电池返回全部电池组容量(以毫安小时为单位)。

  • has_failsafed()- 如果被监视的任何电池触发了故障保护,则返回 true。

  • overpower_detected( instance )- 如果从被监视的电池中获取过多的电量,则返回 true。

  • get_temperature( instance )- 如果电池支持温度监控,则返回电池的温度(以摄氏度为单位)。

  • get_cycle_count( instance )- 返回电池的循环计数,如果不可用,则返回零。

全球定位系统(全球定位系统:)

GPS库提供对车辆上GPS信息的访问。

  • num_sensors()- 返回连接的 GPS 设备的数量。如果打开了 GPS 混合,它将显示为第三个传感器,并在此处报告。

  • primary_sensor()- 返回当前用作主 GPS 设备的 GPS。

  • status(instance)- 返回 GPS 定位状态。将其与 GPS 定位类型之一 (GPS.NO_GPS, GPS.GPS_OK_FIX_2D,全球定位系统。GPS_OK_FIX_3D全球定位系统。GPS_OK_FIX_3D_DGPS全球定位系统。GPS_OK_FIX_3D_RTK_FLOAT全球定位系统。GPS_OK_FIX_3D_RTK_FIXED

  • location( instance )- 返回最后一个 GPS 位置的位置用户数据。您必须检查状态以了解该位置是否仍然是最新的,如果它是NO_GPS的,或者NO_FIX那么它将返回旧数据。

  • speed_accuracy( instance )- 返回 nil,或 GPS 的速度精度(以米/秒为单位)(如果信息可用于 GPS 实例)。

  • horizontal_accuracy( instance )- 返回 nil,或 GPS 的水平精度(以米为单位)(如果信息可用于 GPS 实例)。

  • vertical_accuracy( instance )- 返回 nil,或 GPS 的垂直精度(以米为单位)(如果信息可用于 GPS 实例)。

  • velocity( instance )- 返回一个 Vector3f,其中包含 GPS 观察到的速度。您必须检查状态以了解速度是否仍然是最新的。

  • ground_speed( instance )- 返回车辆的地速(以米/秒为单位)。您必须检查状态以了解地面速度是否仍然是最新的。

  • ground_course( instance )- 以度为单位返回车辆的地面航向。您必须检查状态以了解地面路线是否仍然是当前的。

  • num_sats( instance )- 返回 GPS 当前正在跟踪的卫星数。

  • time_week( instance )- 返回 GPS 周数。

  • time_week_ms( instance )- 返回当前一周的毫秒数。

  • get_hdop( instance )- 返回 GPS 实例精度的水平稀释度。

  • get_vdop( instance )- 返回 GPS 实例精度的垂直稀释度。

  • last_fix_time_ms( instance )- 返回上次修复的时间(以系统毫秒为单位)。

  • have_vertical_velocity( instance )- 如果 GPS 实例可以报告垂直速度,则返回 true。

  • get_antenna_offset( instance )- 返回一个 Vector3f,其中包含 GPS 在正文框架中的偏移量(以米为单位)。

  • first_unconfigured_gps()- 返回 nil 或尚未完全配置的第一个 GPS 的实例编号。如果已配置所有 GPS,则返回 255(如果已配置所有 GPS)。

GCS (GCS:)

  • send_text( severity , text )- 将发送消息严重性级别的文本字符串。严重性级别为 :

严重性级别

类型

0

紧急

1

警报

2

危急

3

错误

4

警告

5

通知

6

信息

7

调试

  • set_message_interval( serial_channel , message_type , rate )- 在串行(serial_channel)上设置message_type的更新速率。例如,gcs:set_message_interval(0, 30, 500000) 将 ATTITUDE 消息流 (0) 的 SERIAL30 速率设置为 2.0 Hz(500,000 微秒)

串行指示灯(串行指示灯:)

该库允许通过保留用于脚本的输出来控制WS8212B RGB LED串,并通过SERVOx_FUNCTION = 94至109(脚本输出1至16)进行选择

  • set_num_LEDs( output_number , number_of_LEDs )- 在伺服输出上设置字符串中的number_of_LEDs。output_number是伺服输出编号 1-16,字符串连接到具有<number_of_LEDs>的字符串。

  • set_RGB( output_number , LED_number , r , g , b )- 将连接伺服output_number(1-32)输出的字符串上的LED_number(1-16)的数据设置为r,g,b值(0-255)

  • send()- 将数据发送到 LED 串

通知(通知:)

  • play_tune( tune )- 通过车辆上的蜂鸣器播放MML曲调。曲调以字符串形式提供。

可以在此处找到在线调谐测试仪

车辆(车辆:)

  • set_mode(mode_number)- 尝试将飞行器(在本例中为飞机)模式更改为mode_number。如果成功则返回 true,如果模式更改不成功,则返回 false。

  • get_mode()- 按mode_number返回当前车辆模式。

在此处找到每种车辆类型的模式编号

  • get_likely_flying()- 如果自动驾驶仪认为它正在飞行,则返回 true。不保证准确。

  • get_flying_time_ms()- 返回自自动驾驶仪认为它开始飞行以来的时间(以毫秒为单位),如果当前未飞行,则返回零。

  • start_takeoff(altitude)- 开始自动起飞到高于家乡的给定高度(以米为单位)。如果不可用,则返回 false。

  • set_target_location(Location)- 使用 Location 对象设置目标位置。如果不成功,则返回 false。

  • get_target_location()- 返回当前目标位置的位置对象。如果不可用,则返回 false。

  • set_target_velocity_NED()- 使用 Vector3f 对象设置目标速度。如果不可用,则返回 false。

地形(地形:)

地形库提供对根据地形数据库检查高度的访问。

  • enabled()- 如果启用了地形,则返回 true。

  • status()- 返回测距仪的当前状态。将其与地形状态之一(地形。地形状态已禁用,地形。地形状态不健康,地形。地形状态确定)。

  • height_amsl( Location )- 返回提供的位置用户数据处高于平均海平面的高度(以米为单位),如果不可用,则返回 nil。

  • height_terrain_difference_home( Location )- 返回提供的位置与主页之间的高度差(以米为单位),如果不可用,则返回 nil。

  • height_above_terrain()- 返回车辆当前高于地形的高度(以米为单位),如果不可用,则返回 nil。

继电器(继电器:)

继电器库提供对控制继电器输出的访问。

  • on(relay_num)- 打开请求的中继。

  • off(relay_num)- 关闭请求的中继。

  • enabled(relay_num)- 如果请求的中继已启用,则返回 true。

  • toggle(relay_num)- 打开或关闭请求的继电器。

伺服通道 (SRV_Channels:)

  • find_channel(output_function)- 返回分配output_function输出的第一个伺服输出编号 -1(请参阅参数)。如果未分配任何值,则为 false。SERVOx_FUNCTION

  • get_output_pwm(output_function)- 返回第一个伺服输出PWM值,输出分配output_function(请参阅参数)。如果未分配任何值,则为 false。SERVOx_FUNCTION

  • set_output_pwm_chan_timeout(channel, pwm, timeout)- 将伺服通道设置为指定的PWM,时间(以毫秒为单位)。这将覆盖自动驾驶仪中的任何命令,直到超时到期。

遥控通道 (RC:)

  • get_pwm()- 返回给定通道号的 RC 输入 PWM 值。请注意,此处的频道从 1 开始索引。如果通道不可用,则返回 false。

串行/UART (串行:)

  • find_serial(instance)- 返回允许来自脚本(具有 的脚本)连接的 UART 实例。对于 ,首先返回这样的 UART,第二个返回 ,依此类推。如果未找到此类实例,则返回 。SERIALx_PROTOCOL = 28instance = 0instance = 1nil

    • UART:begin(baud)- 以给定的波特率启动串行连接。

    • UART:read()- 从 UART 实例返回字节序列。

    • UART:write(number)- 将字节序列写入 UART 实例。

    • UART:available()- 返回当前可用字节的整数。

    • UART:set_flow_control(flow_control)- 设置 UART 实例的流控制。

气压计(气压:)

  • get_pressure()- 以帕斯卡为单位返回压力。

  • get_temperature()- 返回温度(以摄氏度为单位)。

  • get_external_temperature()- 返回外部温度(以摄氏度为单位)。

电调遥测 (esc_telem:)

  • get_usage_seconds(channel)- 返回单个 ESC 的使用时间(以秒为单位),如果不可用,则返回 false。

参数(参数:)

  • get(parameter_name)- 如果可用,则返回参数值,如果未找到,则返回 nil。

  • set(parameter_name)- 按名称设置参数(如果可用)。如果找到参数,则返回 true。

  • set_and_save(parameter_name)按名称设置和保存参数(如果可用)。如果找到参数,则返回 true。

转速 (转/分:)

  • get_rpm(instance)- 返回给定实例的 RPM,如果不可用,则返回 nil。

按钮(按钮:)

  • get_button_state(button_number)- 返回按钮状态(如果可用)。按钮为 1 个索引。

伺服输出

此方法是独立的,直接调用,如下所示。

  • servo.set_output (function_number, PWM)- 将 function_number 型伺服输出设置为 PWM 值(通常在 1000 到 2000 之间)

例子

请参阅代码示例文件夹

如何添加新绑定

为了让Lua脚本访问ArduPilot的更多功能,可以通过创建新的绑定来扩展API。流程如下:

  • 找到要向 Lua 公开的方法或函数。例如,如果您想公开 AHRS 的附加功能,您将首先在 libraries/AP_AHRS/AP_AHRS.h 中找到该方法。这可以是已经存在的方法(函数)或新添加到代码中的方法(函数)。

  • 编辑 libraries/AP_Scripting/generator/description/bindings.desc 并在该方法的相应部分中添加新行,或者如果应按照其他部分的示例添加新类,则添加新部分。

  • 对于 Copter/Rover/Plane 4.1 之前的版本:打开命令行提示符并 cd 到 /libraries/AP_Scripting/generator 目录并键入“make run”。

  • 对于 4.1 及更高版本,清理发行版 (./waf distclean) 并像往常一样从那里重新开始编译。

直接在固件中包含 Lua 脚本

Lua 脚本可以直接嵌入到固件二进制文件中,而不是放在外部 SD 卡上。这对于制造商为随附的外围设备或自动驾驶仪不支持 SD 卡提供脚本非常有用。有关执行此操作的说明,请在此链接上找到。

更多信息

有关在此之前做出的技术决策的更多背景信息,您可以参考2019年ArduPilot Unconference的演示文稿。

Last updated