На примере мигания светодиодом на роутере 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 через Си, и наоборот.
Приятный биндинг с С++luabind