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

Ссылки
http://www.lua.org
http://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


0 комментариев на «“Использование Lua в робототехнике”»

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

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение