CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Использование Lua в робототехнике


На примере мигания светодиодом на роутере 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 — модуль для работы с последовательным портом

Ссылки:
www.lua.org
ru.wikipedia.org/wiki/Lua
ROS Client Library for Lua (http://github.com/timn/roslua)
pbLua — порт Lua для Lego Mindstorms

По теме:
Исследование Wi-Fi-роутера TP-LINK TL-MR3020
  • +2
  • 25 октября 2012, 19:51
  • noonv

Комментарии (2)

RSS свернуть / развернуть
+
+1
Интересно.
Но примеры разрозненные. Было б лучше придерживаться одного примера — например blinkLED
помигать из lua скрипта, помигать из Lua через Си, и наоборот.
avatar

marshallab

  • 26 октября 2012, 08:38
+
0
Приятный биндинг с С++ luabind
avatar

Asmodey

  • 27 октября 2012, 08:10

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.