You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
10 KiB
379 lines
10 KiB
#include <AP_Common/AP_Common.h> |
|
#include <GCS_MAVLink/GCS.h> |
|
#include <SRV_Channel/SRV_Channel.h> |
|
|
|
#include "lua_bindings.h" |
|
|
|
int check_arguments(lua_State *L, int expected_arguments, const char *fn_name); |
|
int check_arguments(lua_State *L, int expected_arguments, const char *fn_name) { |
|
#if defined(AP_SCRIPTING_CHECKS) && AP_SCRIPTING_CHECKS >= 1 |
|
if (expected_arguments < 0) { |
|
AP_HAL::panic("Lua: Attempted to check for negative arguments"); |
|
} |
|
#endif |
|
|
|
const int args = lua_gettop(L); |
|
if (args != expected_arguments) { |
|
return luaL_error(L, "%s expected %d arguments got %d", fn_name, expected_arguments, args); |
|
} |
|
return 0; |
|
} |
|
|
|
// GCS binding |
|
|
|
int lua_gcs_send_text(lua_State *L); |
|
int lua_gcs_send_text(lua_State *L) { |
|
check_arguments(L, 1, "send_text"); |
|
|
|
const char* str = lua_tostring(L, -1); |
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, str); |
|
return 0; |
|
} |
|
|
|
static const luaL_Reg gcs_functions[] = |
|
{ |
|
{"send_text", lua_gcs_send_text}, |
|
{NULL, NULL} |
|
}; |
|
|
|
// servo binding |
|
|
|
int lua_servo_set_output_pwm(lua_State *L); |
|
int lua_servo_set_output_pwm(lua_State *L) { |
|
check_arguments(L, 2, "set_output_pwm"); |
|
|
|
const SRV_Channel::Aux_servo_function_t servo_function = (SRV_Channel::Aux_servo_function_t)luaL_checkinteger(L, -2); |
|
luaL_argcheck(L, ((servo_function >= SRV_Channel::Aux_servo_function_t::k_scripting1) && |
|
(servo_function <= SRV_Channel::Aux_servo_function_t::k_scripting16)), |
|
2, "function out of range"); |
|
|
|
const int output = luaL_checknumber(L, -1); |
|
luaL_argcheck(L, ((output >= 0) && (output <= UINT16_MAX)), 2, "output out of range"); |
|
|
|
SRV_Channels::set_output_pwm((SRV_Channel::Aux_servo_function_t)servo_function, output); |
|
|
|
return 0; |
|
} |
|
|
|
static const luaL_Reg servo_functions[] = |
|
{ |
|
{"set_output_pwm", lua_servo_set_output_pwm}, |
|
{NULL, NULL} |
|
}; |
|
|
|
// location stuff |
|
static int new_location(lua_State *L) { |
|
Location *loc = (Location *)lua_newuserdata(L, sizeof(Location)); |
|
luaL_getmetatable(L, "location"); |
|
lua_setmetatable(L, -2); |
|
memset((void *)loc, 0, sizeof(Location)); |
|
return 1; |
|
} |
|
|
|
static Location *check_location(lua_State *L, int arg) { |
|
void *data = luaL_checkudata(L, arg, "location"); |
|
luaL_argcheck(L, data != NULL, arg, "`location` expected"); |
|
return (Location *)data; |
|
} |
|
|
|
static int location_lat(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushinteger(L, loc->lat); |
|
return 1; |
|
case 2: // set |
|
{ |
|
const int32_t lat = luaL_checkinteger(L, 2); |
|
luaL_argcheck(L, ((lat >= -900000000) && (lat <= 900000000)), 2, "invalid latitude out of range"); |
|
loc->lat = lat; |
|
return 0; |
|
} |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_long(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushinteger(L, loc->lng); |
|
return 1; |
|
case 2: // set |
|
{ |
|
const int32_t lng = luaL_checkinteger(L, 2); |
|
luaL_argcheck(L, ((lng >= -1800000000) && (lng <= 1800000000)), 2, "invalid longitude out of range"); |
|
loc->lng = lng; |
|
return 0; |
|
} |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_alt(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushinteger(L, loc->alt); |
|
return 1; |
|
case 2: // set |
|
loc->alt = luaL_checknumber(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_relative_alt(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushboolean(L, loc->relative_alt); |
|
return 1; |
|
case 2: // set |
|
loc->relative_alt = lua_toboolean(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_loiter_ccw(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushboolean(L, loc->loiter_ccw); |
|
return 1; |
|
case 2: // set |
|
loc->loiter_ccw = lua_toboolean(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_terrain_alt(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushboolean(L, loc->terrain_alt); |
|
return 1; |
|
case 2: // set |
|
loc->terrain_alt = lua_toboolean(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_origin_alt(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushboolean(L, loc->origin_alt); |
|
return 1; |
|
case 2: // set |
|
loc->origin_alt = lua_toboolean(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_loiter_xtrack(lua_State *L) { |
|
Location *loc = check_location(L, 1); |
|
switch(lua_gettop(L)) { |
|
case 1: // access |
|
lua_pushboolean(L, loc->loiter_xtrack); |
|
return 1; |
|
case 2: // set |
|
loc->loiter_xtrack = lua_toboolean(L, 2); |
|
return 0; |
|
default: |
|
return luaL_argerror(L, lua_gettop(L), "too many arguments"); |
|
} |
|
} |
|
|
|
static int location_tostring(lua_State *L) { |
|
Location *loc = check_location(L, -1); |
|
char buf[64] = {}; |
|
snprintf(buf, sizeof(buf), |
|
"Loc(%ld.%07ld %c, %ld.%07ld %c, %.02f)", |
|
labs(loc->lat / 10000000), |
|
labs(loc->lat % 10000000), |
|
loc->lat > 0 ? 'N' : 'S', |
|
labs(loc->lng / 10000000), |
|
labs(loc->lng % 10000000), |
|
loc->lng > 0 ? 'E' : 'W', |
|
loc->alt * 1e-2); |
|
lua_pushstring(L, buf); |
|
return 1; |
|
} |
|
|
|
static int location_distance(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 2) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
lua_pushnumber(L, check_location(L, -2)->get_distance(*check_location(L, -1))); |
|
|
|
return 1; |
|
} |
|
|
|
static int location_project(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 3) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
location_update(*check_location(L, -3), |
|
luaL_checknumber(L, -2), |
|
luaL_checknumber(L, -1)); |
|
|
|
lua_pop(L, 2); |
|
|
|
return 1; |
|
} |
|
|
|
static int location_passed_point(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 3) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
lua_pushboolean(L, location_passed_point(*check_location(L, -3), |
|
*check_location(L, -2), |
|
*check_location(L, -1))); |
|
|
|
return 1; |
|
} |
|
|
|
static int location_path_proportion(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 3) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
lua_pushnumber(L, location_path_proportion(*check_location(L, -3), |
|
*check_location(L, -2), |
|
*check_location(L, -1))); |
|
|
|
return 1; |
|
} |
|
|
|
static int location_offset(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 3) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
check_location(L, -3)->offset(luaL_checknumber(L, -2), |
|
luaL_checknumber(L, -1)); |
|
|
|
lua_pop(L, 2); |
|
|
|
return 1; |
|
} |
|
|
|
static int location_equal(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 2) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
Location *l2 = check_location(L, -2); |
|
Location *l1 = check_location(L, -1); |
|
|
|
lua_pushboolean(L, locations_are_same(*l1, *l2)); |
|
|
|
return 1; |
|
} |
|
|
|
static const luaL_Reg locLib[] = { |
|
{"new", new_location}, |
|
{NULL, NULL} |
|
}; |
|
|
|
static const luaL_Reg locationMeta[] = { |
|
{"lat", location_lat}, |
|
{"long", location_long}, |
|
{"alt", location_alt}, |
|
{"relative_alt", location_relative_alt}, |
|
{"loiter_ccw", location_loiter_ccw}, |
|
{"terrain_alt", location_terrain_alt}, |
|
{"origin_alt", location_origin_alt}, |
|
{"loiter_xtrack", location_loiter_xtrack}, |
|
{"distance", location_distance}, |
|
{"project", location_project}, |
|
{"passed_point", location_passed_point}, |
|
{"path_proportion", location_path_proportion}, |
|
{"offset", location_offset}, |
|
{"__tostring", location_tostring}, |
|
{"__eq", location_equal}, |
|
{NULL, NULL} |
|
}; |
|
|
|
static int ahrs_position(lua_State *L) { |
|
check_arguments(L, 1, "ahrs:position"); |
|
|
|
new_location(L); |
|
Location *loc = check_location(L, -1); |
|
AP::ahrs().get_position(*loc); |
|
|
|
return 1; |
|
} |
|
|
|
static int ahrs_get_home(lua_State *L) { |
|
check_arguments(L, 1, "ahrs:home"); |
|
|
|
new_location(L); |
|
Location *loc = check_location(L, -1); |
|
*loc = AP::ahrs().get_home(); |
|
|
|
return 1; |
|
} |
|
|
|
static const luaL_Reg ahrsMeta[] = { |
|
{"position", ahrs_position}, |
|
{"home", ahrs_get_home}, |
|
{NULL, NULL} |
|
}; |
|
|
|
// all bindings |
|
|
|
void load_lua_bindings(lua_State *L) { |
|
luaL_newlib(L, gcs_functions); |
|
lua_setglobal(L, "gcs"); |
|
|
|
luaL_newlib(L, servo_functions); |
|
lua_setglobal(L, "servo"); |
|
|
|
// location metatable |
|
luaL_newmetatable(L, "location"); |
|
luaL_setfuncs(L, locationMeta, 0); |
|
lua_pushstring(L, "__index"); |
|
lua_pushvalue(L, -2); |
|
lua_settable(L, -3); |
|
lua_pop(L, 1); |
|
luaL_newlib(L, locLib); |
|
lua_setglobal(L, "loc"); |
|
|
|
// ahrs metatable |
|
luaL_newmetatable(L, "ahrs"); |
|
luaL_setfuncs(L, ahrsMeta, 0); |
|
lua_pushstring(L, "__index"); |
|
lua_pushvalue(L, -2); |
|
lua_settable(L, -3); |
|
lua_pop(L, 1); |
|
|
|
// ahrs userdata |
|
lua_newuserdata(L, 0); // lose the pointer, we don't really care about it |
|
luaL_getmetatable(L, "ahrs"); |
|
lua_setmetatable(L, -2); |
|
lua_setglobal(L, "ahrs"); |
|
} |
|
|
|
|