AP_Scripting: add MAVLink command long and ack examples

This commit is contained in:
Iampete1 2023-06-18 14:00:58 +01:00 committed by Andrew Tridgell
parent 352f721626
commit ceca374f23
5 changed files with 188 additions and 1 deletions

View File

@ -0,0 +1,65 @@
-- Example of receiving MAVLink commands
local mavlink_msgs = require("MAVLink/mavlink_msgs")
local COMMAND_ACK_ID = mavlink_msgs.get_msgid("COMMAND_ACK")
local COMMAND_LONG_ID = mavlink_msgs.get_msgid("COMMAND_LONG")
local msg_map = {}
msg_map[COMMAND_ACK_ID] = "COMMAND_ACK"
msg_map[COMMAND_LONG_ID] = "COMMAND_LONG"
-- initialize MAVLink rx with number of messages, and buffer depth
mavlink:init(1, 10)
-- register message id to receive
mavlink:register_rx_msgid(COMMAND_LONG_ID)
local MAV_CMD_DO_SET_MODE = 176
local MAV_CMD_WAYPOINT_USER_1 = 31000
-- Block AP parsing user1 so we can deal with it in the script
-- Prevents "unsupported" ack
mavlink:block_command(MAV_CMD_WAYPOINT_USER_1)
function handle_command_long(cmd)
if (cmd.command == MAV_CMD_DO_SET_MODE) then
gcs:send_text(0, "Got mode change")
elseif (cmd.command == MAV_CMD_WAYPOINT_USER_1) then
-- return ack from command param value
return math.min(math.max(math.floor(cmd.param1), 0), 5)
end
return nil
end
function update()
local msg, chan = mavlink:receive_chan()
if (msg ~= nil) then
local parsed_msg = mavlink_msgs.decode(msg, msg_map)
if (parsed_msg ~= nil) then
local result
if parsed_msg.msgid == COMMAND_LONG_ID then
result = handle_command_long(parsed_msg)
end
if (result ~= nil) then
-- Send ack if the command is one were intrested in
local ack = {}
ack.command = parsed_msg.command
ack.result = result
ack.progress = 0
ack.result_param2 = 0
ack.target_system = parsed_msg.sysid
ack.target_component = parsed_msg.compid
mavlink:send_chan(chan, mavlink_msgs.encode("COMMAND_ACK", ack))
end
end
end
return update, 1000
end
return update()

View File

@ -183,7 +183,7 @@ int lua_mavlink_send_chan(lua_State *L) {
int lua_mavlink_block_command(lua_State *L) {
// Allow : and . access
const int arg_offset = (luaL_testudata(L, 1, "mavlnk") != NULL) ? 1 : 0;
const int arg_offset = (luaL_testudata(L, 1, "mavlink") != NULL) ? 1 : 0;
binding_argcheck(L, 1+arg_offset);

View File

@ -0,0 +1,11 @@
local COMMAND_ACK = {}
COMMAND_ACK.id = 77
COMMAND_ACK.fields = {
{ "command", "<I2" },
{ "result", "<B" },
{ "progress", "<B" },
{ "result_param2", "<i4" },
{ "target_system", "<B" },
{ "target_component", "<B" },
}
return COMMAND_ACK

View File

@ -0,0 +1,16 @@
local COMMAND_LONG = {}
COMMAND_LONG.id = 76
COMMAND_LONG.fields = {
{ "param1", "<f" },
{ "param2", "<f" },
{ "param3", "<f" },
{ "param4", "<f" },
{ "param5", "<f" },
{ "param6", "<f" },
{ "param7", "<f" },
{ "command", "<I2" },
{ "target_system", "<B" },
{ "target_component", "<B" },
{ "confirmation", "<B" },
}
return COMMAND_LONG

View File

@ -0,0 +1,95 @@
local mavlink_msgs = {}
function mavlink_msgs.get_msgid(msgname)
local message_map = require("MAVLink/mavlink_msg_" .. msgname)
if not message_map then
error("Unknown MAVLink message " .. msgname)
end
return message_map.id
end
function mavlink_msgs.decode_header(message)
-- build up a map of the result
local result = {}
local read_marker = 3
-- id the MAVLink version
result.protocol_version, read_marker = string.unpack("<B", message, read_marker)
if (result.protocol_version == 0xFE) then -- mavlink 1
result.protocol_version = 1
elseif (result.protocol_version == 0XFD) then --mavlink 2
result.protocol_version = 2
else
error("Invalid magic byte")
end
_, read_marker = string.unpack("<B", message, read_marker) -- payload is always the second byte
-- strip the incompat/compat flags
result.incompat_flags, result.compat_flags, read_marker = string.unpack("<BB", message, read_marker)
-- fetch seq/sysid/compid
result.seq, result.sysid, result.compid, read_marker = string.unpack("<BBB", message, read_marker)
-- fetch the message id
result.msgid, read_marker = string.unpack("<I3", message, read_marker)
return result, read_marker
end
function mavlink_msgs.decode(message, msg_map)
local result, offset = mavlink_msgs.decode_header(message)
local message_map = require("MAVLink/mavlink_msg_" .. msg_map[result.msgid])
if not message_map then
-- we don't know how to decode this message, bail on it
return nil
end
-- map all the fields out
for _,v in ipairs(message_map.fields) do
if v[3] then
result[v[1]] = {}
for j=1,v[3] do
result[v[1]][j], offset = string.unpack(v[2], message, offset)
end
else
result[v[1]], offset = string.unpack(v[2], message, offset)
end
end
-- ignore the idea of a checksum
return result;
end
function mavlink_msgs.encode(msgname, message)
local message_map = require("MAVLink/mavlink_msg_" .. msgname)
if not message_map then
-- we don't know how to encode this message, bail on it
error("Unknown MAVLink message " .. msgname)
end
local packString = "<"
local packedTable = {}
local packedIndex = 1
for i,v in ipairs(message_map.fields) do
if v[3] then
packString = (packString .. string.rep(string.sub(v[2], 2), v[3]))
for j = 1, v[3] do
packedTable[packedIndex] = message[message_map.fields[i][1]][j]
if packedTable[packedIndex] == nil then
packedTable[packedIndex] = 0
end
packedIndex = packedIndex + 1
end
else
packString = (packString .. string.sub(v[2], 2))
packedTable[packedIndex] = message[message_map.fields[i][1]]
packedIndex = packedIndex + 1
end
end
return message_map.id, string.pack(packString, table.unpack(packedTable))
end
return mavlink_msgs