
На примере мигания светодиодом на роутере TP-LINK MR3020, можно понять, что Lua — замечательная штука!
Это скриптовый язык программирования, который замечательно подходит для использования в робототехнике.
Lua C API позволяет использовать его совместно с языками C, C++, C#, Java, Python, интегрировать его в свои программы и расширять сценарии базового языка.
Написание конфигурационных файлов, а главное — изменение маршрутного задания и поведения робота путём простой правки скриптового файла, которое не требует перекомпиляции программы управления — это замечательный бонус, который позволит изменять траекторию движения или последовательность действий робота на-лету.
Это очень удобно для отладки и участия робота в различных презентациях, конкурсах и соревнованиях.
Простой, но мощный скриптовый язык Lua, позволяет из своих скриптов вызывать заранее реализованные функции, написанные на С/С++.
Т.о., на С/С++ можно реализовать необходимый функционал для управления роботом (можно назвать этот слой «драйвер»), а вызывать эти функции уже из Lua-срипта.
Т.о. и достигается, что логика работы робота может изменяться на-лету.
Кратко о Lua
Lua (порт. «луна») — интерпретируемый язык программирования, разработанный в 1993 году подразделением Tecgraf Католического университета Рио-де-Жанейро (Computer Graphics Technology Group of Pontifical Catholic University of Rio de Janeiro in Brazil). Является свободно распространяемым, с открытыми исходными текстами на языке Си.
Lua — язык с динамическим определением типов данных.
В Lua восемь основных типов:
nil (неопределенный)
boolean (логический)
number (числовой)
string (строковый)
function (функция)
userdata (пользовательские данные)
thread (поток)
table (таблица)
nil [пустое значение] — обозначает отсутствие пригодного значения.
Boolean — false (ложь) и true (истина) (ложными считаются только значения nil и false, любое другое значение считается истинным).
Number — числа (обычно типа double, но это может быть изменено при сборке интерпретатора.
String — неизменяемый массив символов (любые 8-битные символы, включая ноль (‘\0’).
Таблицы — набор пар значений — (Ключ, Значение) — самый важный тип данных, так как являются фундаментом для пользовательских типов данных (структуры, массивы, списки, множества).
userdata — позволяет сохранять в переменных Lua любые произвольные данные из языка C (userdata — указатель на блок памяти).
операторы: + — * / % ^
сравнение: == ~= < > <= >=
управляющие структуры:
while exp do block end
repeat block until exp
if exp then block {elseif exp then block} [else block] end
Установка Lua
можно скачать Lua из репозитория, а можно собрать из исходников.
Так как первый способ трудностей не представляет, рассмотрим второй.
скачиваем архив с последней версией
lua-5.2.1.tar.gz
распаковываем архив, переходим в каталог и выполняем make
cd lua-5.2.1/ $ make Please do 'make PLATFORM' where PLATFORM is one of these: aix ansi bsd freebsd generic linux macosx mingw posix solaris See doc/readme.html for complete instructions.
— требуется указать платформу, а ещё для сборки под Linux требуется наличие библиотек readline и ncurses. Если их нет, то устанавливаем и выполняем:
make linux
проверим сборку
$ make test src/lua -v Lua 5.2.1 Copyright (C) 1994-2012 Lua.org, PUC-Rio
в директории lua-5.2.1/src/ появилось три важных файла:
liblua.a — статическая библиотека
lua — интерпретатор Lua
luac — компилятор Lua, переводящий скрипты в бинарный формат Lua
Первый скрипт Lua
Создадим файл my.lua следующего содержания:
-- comment var='hello world!'; print(var); a='123'; print(a); b=tonumber(a); print(b); c=234; d=b+c; print(d); var2 =" world"; --[[ comment1 comment2 ]]--
запускаем
./lua-5.2.1/src/lua ./my.lua hello world! 123 123 357
в принципе, тут всё понятно.
пример рассчёта факториала:
fractal.lua
-- определяет функцию факториала
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number")
print(fact(a))
$ ./lua-5.2.1/src/lua ./fractal.lua enter a number: 5 120
Здесь мы видим не только пример использования функции, но и стандартной библиотеки ввода-вывода io, которая использовалась для управления светодиодами роутера TP-LINK MR3020, в скрипте blink.lua
--[[ blink ]]--
led=io.open("/sys/devices/platform/leds-gpio/leds/tp-link:green:3g/brightness", "w");
if led==nil then
print("Error open file!");
os.exit(-1);
end
val = 0;
t0 = os.time();
t1 = 0;
while 1 do
t1 = os.time();
led:seek(beg, 0);
if t1 > t0 then
t0 = t1;
print(val);
led:write(val);
if val == 0 then
val = 1;
else
val = 0;
end
end
end
Функционал стандартных библиотек Lua реализован на С и его можно посмотреть в каталоге src:
io - liolib.c os - loslib.c math - lmathlib.c
Теперь разберёмся с двумя важными моментами:
1. как встраивать Lua в свою программу
2. как расширять Lua своим функционалом
Встраивание Lua в С/С++
test.cpp
//
// test read Lua script
//
#include <stdio.h>
#include <stdlib.h>
#include "lua.hpp"
int get_lua_vars(char* filename);
int main(int argc, char* argv[])
{
printf("[i] Start...\n");
char file_name[] = "my.lua";
char* filename=file_name;
if(argc >= 2) {
filename = argv[1];
}
printf("[i] file: %s\n", filename);
get_lua_vars(filename);
printf("[i] End.\n");
return 0;
}
int get_lua_vars(char* filename)
{
if(!filename)
return -1;
lua_State * L;
L = luaL_newstate();
if(!L) {
printf("[!] Error: luaL_newstate()\n");
return -2;
}
luaL_openlibs(L);
luaL_dofile(L, filename);
lua_getglobal(L, "d");
lua_getglobal(L, "c");
lua_getglobal(L, "b");
lua_getglobal(L, "var");
printf("var= %s\n", lua_tostring(L, -1));
printf("b= %f\n", lua_tonumber(L, -2));
printf("c= %f\n", lua_tonumber(L, -3));
printf("d= %f\n", lua_tonumber(L, -4));
lua_close(L);
return 0;
}
сборка:
g++ -I/usr/src/lua-5.2.1/src -o test test.cpp -L/usr/src/lua-5.2.1/src -llua -ldl
Makefile для сборки:
CPP := g++ LUAPATH := /usr/src/lua-5.2.1/src INCLUDE = -I$(LUAPATH) .PHONY: test test: $(CPP) $(INCLUDE) -o test test.cpp -L$(LUAPATH) -llua -ldl
результат выполнения:
$ ./test [i] Start... [i] file: my.lua hello world! 123 123 357 var= hello world! b= 123.000000 c= 234.000000 d= 357.000000 [i] End.
Расширение функционала Lua своими функциями на С/С++
mytest.c
//
// example of library for use in Lua
//
// compile:
// gcc mytest.c -shared -fpic -I/usr/src/lua-5.2.1/src -o mytest.so
//
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#ifdef __cplusplus
}
#endif
int test_add1(lua_State *L)
{
double d = luaL_checknumber(L, 1); // get item 1 (argument by position)
printf("[i] test_add1(%0.2f)\n", d);
lua_pushnumber(L, d + 1); // return the result
return 1; // number of items returned
}
static const struct luaL_Reg mytestlib[] =
{
{"add1", test_add1},
{0, 0}
};
#ifdef __cplusplus
extern "C"
#endif
int luaopen_mytest (lua_State *L)
{
//luaL_register(L, "mytest", mytestlib);
luaL_openlib(L, "mytest", mytestlib, 0);
return 1;
}
сборка:
gcc mytest.c -shared -fpic -I/usr/src/lua-5.2.1/src -o mytest.so
тестовый скрипт
call.lua
print("start lua...");
require('mytest');
res = mytest.add1(12);
print(res);
print("end lua...");
$ ./lua-5.2.1/src/lua ./call.lua start lua... [i] test_add1(12.00) 13 end lua...
Чтож, полученные примеры вполне демонстрируют потенциальные возможности по использованию Lua для гибкого расширения функционала программ, в том числе — управляющих программ для роботов.
Далее: Кросс-компиляция Lua для TP-LINK TL-MR3020
Lua — модуль для работы с последовательным портом
Ссылки
http://www.lua.org
http://ru.wikipedia.org/wiki/Lua
ROS Client Library for Lua (http://github.com/timn/roslua)
pbLua — порт Lua для Lego Mindstorms

0 комментариев на «“Использование Lua в робототехнике”»
Интересно.
Но примеры разрозненные. Было б лучше придерживаться одного примера — например blinkLED
помигать из lua скрипта, помигать из Lua через Си, и наоборот.
Приятный биндинг с С++