Удаленное управление роботом. Управление роботом может происходить разными способами

Независимо от размера и числа людей, живущих в доме, жилое пространство быстро заполняется большим количеством вещей, которые надо где-то хранить. Решение, казалось бы, простое - приобрести дополнительные предметы мебели для хранения скарба, да только и они сами по себе загромождают помещение. Складные полки Clapperboard от Elsa призвана решить проблему громоздкой мебели, скрадывающей полезное пространство.

Идея проста: когда вам не нужно хранить что-либо на полках, они компактно складываются, экономя место. В закрытом виде плоские секции прилегают почти вплотную к стене комнаты и выглядят словно деревянная панель, дверь или какое-то современное произведение искусства. Но когда вам понадобится положить вещи, вы просто откидываете плоский элемент на себя и получаете полку (две, три или пять). Очень удобно для предметов, которые вы часто берете со своего места и используете, например, свежая периодика, книги, бумажник, телефон или ключи. Вещи забрали - полку закрыли, и вот место в помещении зря не загромождено. Среднюю полку можно использовать как столик для ноутбука, место для учебы, рисования, шитья и другой работы. Нижние полки в детской - для игрушек. Пока дети играются с ними, полки закрыты, освобождая место для активных действий. В любом жилом помещении офисе, общественных заведениях складные полки Clapperboard будут очень полезны.

Производитель предлагает складывающиеся полки из шпона дуба, шпона ореха и смешанного материала, а также в двух размерах S (ширина 250 х глубина 60/160 х 1900 мм) и L (ширина 360 х глубина 60/260 х 1900 мм).

Еще варианты складных полок с фотопечатью от Riveli Shelving:



Здравствуй, Хабрахабр! Я сидел вечером 11 июня, смотрел фильм. Неожиданно для себя я обнаружил, что мне написала незнакомая мне ранее женщина с предложением сделать робота для их нового квеста. Суть заключается в том, что нужно разгадывать головоломки, исследовать тайники, правильно применять подсказки, использовать доступные вещи и в итоге добывать ключи и открывать двери… От меня требовалось сделать робота, управляемого с компьютера с помощью отдельной программы. У мебя были сомнения по поводу некоторых проблем, например: успею ли я и как именно сделать беспроводную передачу данных (беспроводной передачей данных я занимался до этого только на NXT)? Взвесив все за и против я согласился. После этого я стал думать над передачей данных. Поскольку требовалось сделать робота быстро, то вспоминать и доосваивать, например, Delphi не было времени, поэтому возникла идея сделать модуль который будет заниматься отправкой команд. От компьютера требуется просто посылать данные в СОМ-порт. Этот способ странный, но наиболее быстрый. Его я и хочу описать здесь. Так же я приложу 3 программы которые помогут сделать радиоуправляемую машинку.
Сборка передатчика и его программа.
Я сделал модуль для компьютера из FTDI Basic Breakout 5/3.3V от DFrobot, довольно распространённого микроконтролера ATMEGA 328P-PU с загрузчиком Arduino и радиомодуля на основе микросхемы nRF24L01. По-сути это просто Arduino Uno с радиомодулем. Что есть, то есть. У радиомодуля есть особенность, которую я не сразу заметил: входное напряжение должно быть в диапазоне от 3 до 3.6 вольт (хотя подача на него 5 вольт его не убьёт, но работать не будет), верхняя граница логической единицы составляет 5В. Это означает то, что для подключения радиомодуля к меге не нужен преобразователь уровней между 3.3В и 5В, а вот стабилизатор на 3.3В установить нужно. У FTDI есть встроенный стабилизатор, от него я и подпитал радиомодуль.

Так выглядит сам модуль (внутри и в сборке) :

Программа состоит из инициализации, стартового сообщения и обработки команд из программы управления. Так было в моём случае. Основные команды библиотеки Mirf:

#include
#include
#include
#include
#include
Эти библиотеки нужны для работы радиомодуля

Mirf.csnPin = 4 - задаёт номер пина, отвечающего за «разрешение общаться» радиомодуля и МК
Mirf.cePin = 6 - задаёт номер пина, отвечающего за режим работы радиомодуля (приёмник/передатчик)
Mirf.spi = &MirfHardwareSpi - настраивает линию SPI
Mirf.init() - инициализирует радиомодуль
Mirf.payload = 1 - размер в байтах одного сообщения (поумолчанию 16, максимум 32)
Mirf.channel = 19 - задаёт канал (0 - 127, по умолчанию 0)
Mirf.config() - задаёт параметры передачи


Mirf.setTADDR((byte *)«serv1») - переводит радиомодуль в режим передатчика
Mirf.setRADDR((byte *)«serv1») - переводит радиомодуль в режим приёмника

Mirf.send(data) - отправляет массив типа byte
Mirf.dataReady() - сообщает об окончании обработки принятых данных
Mirf.getData(data) - записать принятые данные в массив data

Прилагаю код программы передатчика.

Программа передатчика

#include
#include
#include
#include
#include

Char active;
byte data;

Void setup()
{
Serial.begin(19200);

Mirf.csnPin = 4;
Mirf.cePin = 6;

Mirf.init();
Mirf.payload = 1;
Mirf.channel = 19;
Mirf.config();

Mirf.setTADDR((byte *)«serv1»);

//сигнальное сообщение о начале работы
data=7;
Mirf.send(data);
delay(200);
}

Void loop()
{
if (Serial.available()) //Если данные готовы к считыванию
{
active=Serial.read(); // Запись данных в переменную
}

If (active=="2")
{
data=2;
}

If (active=="3")
{
data=3;
}

If (active=="4")
{
data=4;
}

If (active=="5")
{
data=5;
}

If (active=="6")
{
data=6;
}

Mirf.send(data); //Отсылаем данные
while(Mirf.isSending()); // Ждём пока данные отсылаются
}

Программа управления.

Есть одна интересная штука - Processing. Синтаксис такой же как в Arduino, только вместо void loop() там расположился void draw(). Но она становилась ещё более интересной в моей ситуации с библиотекой processing Serial, которая позволяет работать с сериал-портом. Прочитав уроки на сайте Spurkfun`а, я поигрался с миганием светодиода на подключенной к компьютеру ардуинке по клику мышки. После этого я написал программу управления роботом с клавиатуры. Прилагаю код управления с помощью стрелок. В нём, в принципе, ничего необычного нет.

Программа управления машинкой

import processing.serial.*;
import cc.arduino.*;

Serial myPort;
PFont f=createFont(«LetterGothicStd-32.vlw», 24);

Void setup()
{
size(360, 160);
stroke(255);
background(0);
textFont(f);

String portName = «XXXX»; // Сюда нужно написать имя вашего порта
myPort = new Serial(this, portName, 19200);
}

Void draw() {
if (keyPressed == false)
{
clear();
myPort.write("6");
println(«6»);
}
}

Void keyPressed()
{
// 10 - enter
// 32 - probel
// 37/38/39/40 - keys
clear();

Fill(255);
textAlign(CENTER);
//text(keyCode, 180, 80);

Switch(keyCode)
{
case 37:
text(«Edem vlevo», 180, 80);
myPort.write("1");
break;

Case 38:
text(«Edem pryamo», 180, 80);
myPort.write("2");
break;

Case 39:
text(«Edem vpravo», 180, 80);
myPort.write("3");
break;

Case 40:
text(«Edem nazad», 180, 80);
myPort.write("4");
break;

Default:
text(«Takoy kommandi net», 180, 80);
myPort.write("6");
break;
}
}

Программа приёмника.

Инициализация этой программы отличается от инициализации программы передатчика буквально одной строчкой. Ключевая команда в бесконечном цикле Mirf.getData(data). Дальше полученная команда сравнивается с числами, которым соответствуют какие-либо действия робота. Ну а дальше робот действует точно по командам. Прилагаю код программы приёмника машинки.

Программ машинки

#include
#include
#include
#include
#include

Void setup()
{
Serial.begin(9600);

PinMode(13, OUTPUT); //LED

Mirf.csnPin = 10;
Mirf.cePin = 9;
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.payload = 1;
Mirf.channel = 19;
Mirf.config();
Mirf.setRADDR((byte *)«serv1»);
}

Void loop()
{
byte data;

If(!Mirf.isSending() && Mirf.dataReady())
{
Mirf.getData(data);
Serial.println(data);
}

Switch (data)
{
case 1:
motors(-100, 100); // поворачиваем влево
break;

Case 2:
motors(100, 100); // едем прямо
break;

Case 3:
motors(100, -100); // поворачиваем вправо
break;

Case 4:
motors(-100, -100); // едем назад
break;

Default:
motors(0, 0); // стоим
break;
}

Delay(50);
}

Заключение.

Что из этого всего вышло:

Этого робота я сделал для «Клаустрофобии» . Они проводят квесты в реальности в разных городах, и как раз для одного из таких квестов организаторам понадобился радиоуправляемый робот-сапер. Мне понравилось. Это, конечно, ущербно, т.к. на фоне управления с помощью встроенных в ноутбук средств связи, но зато своё, сделанное весьма быстро и без особых проблем. Надеюсь эта статья поможет сделать нечто подобное, а, может, даже сложнее. Тут уж кому что захочется.

Теги: Добавить метки

Основной модуль конструктора Lego Mindstorms EV3 может работать с прошивкой leJOS , позволяющей запускать Java-приложения. Специально для этого Oracle выпустил и поддерживает отдельную версию полноценной Java SE .

Нормальная JVM позволила мне использовать встроенный в нее протокол Java Management Extensions (JMX), чтобы реализовать удаленное управление роботом-манипулятором. Для объединения управляющих элементов, показаний датчиков и картинок с установленных на роботе IP-камер используется мнемосхема, сделанная на платформе AggreGate.


Сам робот состоит из двух основных частей: шасси и руки-манипулятора. Они управляются двумя полностью независимыми компьютерами EV3, вся их координация осуществляется через управляющий сервер. Прямого соединения между компьютерами нет.

Оба компьютера подключены к IP-сети помещения через Wi-Fi адаптеры NETGEAR WNA1100. Робот управляется восемью двигателями Mindstorms - из них 4 «большие» и 4 «маленькие». Также установлены инфракрасный и ультразвуковой датчики для автоматической остановки у препятствия при движении задним ходом, два датчика прикосновения для остановки поворота манипулятора из-за препятствия, и гироскопический датчик, облегчающий ориентировку оператора при помощи визуализации положения плеча.

В шасси установлены два двигателя, каждый из которых передает усилие на пару гусеничных приводов. Еще один двигатель поворачивает всю руку-манипулятор целиком на 360 градусов.

В самом манипуляторе два двигателя отвечают за подъем и опускание «плеча» и «предплечья». Еще три двигателя занимаются подъемом/опусканием кисти, ее поворотом на 360 градусов и сжиманием/разжиманием «пальцев».

Самым сложным механическим узлом является «кисть». Из-за необходимости выноса трех тяжелых двигателей в район «локтя» конструкция получилась достаточно хитрой.

В целом все выглядит так (коробок спичек был с трудом найден для масштаба):

Для передачи картинки установлены две камеры:

  • Обычный Android-смартфон с установленным приложением IP Webcam для общего обзора (на снимке HTC One)
  • Автономная Wi-Fi микро-камера AI-Ball , установленная прямо на «кисти» манипулятора и помогающая хватать предметы сложной формы

Программирование EV3

ПО самого робота получилось максимально простым. Программы двух компьютеров очень похожи, они запускают JMX сервер, регистрируют MBean"ы, соответствующие двигателям и датчикам, и засыпают в ожидании операций по JMX.

Код главных классов ПО руки-манипулятора

public class Arm { public static void main(String args) { try { EV3Helper.printOnLCD("Starting..."); EV3Helper.startJMXServer("192.168.1.8", 9000); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); EV3LargeRegulatedMotor motor = new EV3LargeRegulatedMotor(BrickFinder.getDefault().getPort("A")); LargeMotorMXBean m = new LargeMotorController(motor); ObjectName n = new ObjectName("robot:name=MotorA"); mbs.registerMBean(m, n); // Registering other motors here EV3TouchSensor touchSensor = new EV3TouchSensor(SensorPort.S1); TouchSensorMXBean tos = new TouchSensorController(touchSensor); n = new ObjectName("robot:name=Sensor1"); mbs.registerMBean(tos, n); // Registering other sensors here EV3Helper.printOnLCD("Running"); Sound.beepSequenceUp(); Thread.sleep(Integer.MAX_VALUE); } catch (Throwable e) { e.printStackTrace(); } } } public class EV3Helper { static void startJMXServer(String address, int port) { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); try { java.rmi.registry.LocateRegistry.createRegistry(port); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + address + ":" + String.valueOf(port) + "/server"); Map props = new HashMap(); props.put("com.sun.management.jmxremote.authenticate", "false"); props.put("com.sun.management.jmxremote.ssl", "false"); JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, props, server); connectorServer.start(); } catch (Exception e) { e.printStackTrace(); } } static void printOnLCD(String s) { LCD.clear(); LCD.drawString(s, 0, 4); } }

Для каждого типа датчика и мотора создан интерфейс MBean"а и реализующий его класс, которые напрямую делегирует все вызовы классу, входящему в leJOS API.

Пример кода интерфейса

public interface LargeMotorMXBean { public abstract void forward(); public abstract boolean suspendRegulation(); public abstract int getTachoCount(); public abstract float getPosition(); public abstract void flt(); public abstract void flt(boolean immediateReturn); public abstract void stop(boolean immediateReturn); public abstract boolean isMoving(); public abstract void waitComplete(); public abstract void rotateTo(int limitAngle, boolean immediateReturn); public abstract void setAcceleration(int acceleration); public abstract int getAcceleration(); public abstract int getLimitAngle(); public abstract void resetTachoCount(); public abstract void rotate(int angle, boolean immediateReturn); public abstract void rotate(int angle); public abstract void rotateTo(int limitAngle); public abstract boolean isStalled(); public abstract void setStallThreshold(int error, int time); public abstract int getRotationSpeed(); public abstract float getMaxSpeed(); public abstract void backward(); public abstract void stop(); public abstract int getSpeed(); public abstract void setSpeed(int speed); }

Пример кода реализации MBean"а

public class LargeMotorController implements LargeMotorMXBean { final EV3LargeRegulatedMotor motor; public LargeMotorController(EV3LargeRegulatedMotor motor) { this.motor = motor; } @Override public void forward() { motor.forward(); } @Override public boolean suspendRegulation() { return motor.suspendRegulation(); } @Override public int getTachoCount() { return motor.getTachoCount(); } @Override public float getPosition() { return motor.getPosition(); } @Override public void flt() { motor.flt(); } @Override public void flt(boolean immediateReturn) { motor.flt(immediateReturn); } // Similar delegating methods skipped }

Как ни странно, на этом программирование закончилось. На стороне сервера и операторского рабочего места не было написано ни одной строчки кода.

Подключение к серверу

Непосредственное управление роботом осуществляет сервер IoT-платформы AggreGate . Установленная бесплатная версия продукта AggreGate Network Manager включает драйвер протокола JMX и позволяет подключить до десяти JMX-хостов. Нам понадобится подключить два - по одному на каждый кирпичик EV3.

Прежде всего, нужно создать аккаунт JMX устройства, указав в настройках URL, заданный при запуске JMX сервера:

Свойства соединения с JMX-устройством


После этого выбираем активы (т.е. MBean"ы в данном случае), которые будут добавлены в профиль устройства:

Выбор MBean"ов


И через несколько секунд смотрим и меняем текущие значения всех опрошенных свойств MBean"ов:

Снимок устройства


Можно также потестировать различные операции вызывая вручную методы MBean"ов, например forward() и stop().

Список операций


Далее настраиваем периоды опроса для датчиков. Высокая частота опроса (100 раз в секунду) используется, так как управляющий сервер находится в локальной сети вместе с роботом и именно сервер принимает решения об остановке вращения при упоре в препятствие и т.п. Решение, безусловно, не промышленное, но в хорошо работающей Wi-Fi сети в рамках одной квартиры показало себя вполне адекватным.

Периоды опроса


Интерфейс оператора

Теперь переходим к созданию интерфейса оператора. Для этого сначала создаем новый виджет и накидываем в него нужные компоненты. В конечном работающем варианте выглядит он так:

По сути, весь интерфейс состоит из нескольких панелей с кнопками, слайдерами и индикаторами, сгруппированными в различные сеточные раскладки, и двух больших видео-плееров, транслирующих картинки с камер.

Вид изнутри редактора интерфейсов

Вся форма:

Вид с показанными панелями-контейнерами:


Теперь, как говорят АСУТПшники, осталось «оживить мнемосхему». Для этого применяются так называемые привязки связывающие свойства и методы графических компонентов интерфейса со свойствами и методами серверных объектов. Так как компьютеры EV3 уже подключены к серверу, серверными объектами могут быть и MBean"ы нашего робота.

Весь интерфейс оператора содержит около 120 привязок, большая часть из которых однотипна:

Половина однотипных привязок реализует управление при помощи кликов на кнопки, расположенные на мнемосхеме. Это красиво, удобно для тестирования, но совершенно непригодно для реального передвижения робота и перемещения грузов. Активаторами привязок из этой группы являются события mousePressed и mouseReleased различных кнопок.

Вторая половина привязок позволяет управлять роботом с клавиатуры, предварительно нажав на кнопку Keyboard Control. Эти привязки реагируют на события keyPressed и keyReleased , а в условии каждой привязки прописано, на какой именно код кнопки нужно реагировать.

Все управляющие привязки вызывают методы forward() , backward() и stop() различных MBean"ов. Поскольку доставка событий происходит асинхронно, важно, чтобы вызовы функций forward() /backward() и последующие вызовы stop() не перепутались. Для этого привязки, вызывающие методы одного MBean"а, добавлены в одну очередь (Queue).

Две отдельные группы привязок выставляют начальные скорости и ускорения двигателей (сейчас это реализовано на стороне сервера при помощи модели, поэтому эти привязки отключены) и меняют скорости/ускорения при перемещении ползунков Speed и Acceleration.

В прошлом сообщении блога я упомянул о том, что широкодоступный Wii Control - джойстик с обратной связью для приставки Nintendo Wii, может быть использован для дистанционного управления манипуляторами робота. Сейчас я хочу продолжить эту тему, и привести краткий обзор способов дистанционного управления...

Существует, вообще говоря, два широкоиспользуемых и повсеместно признанных способа дистанционного управления автономными и полуавтономными устройствами:

  1. Управление с помощью инфракрасных сигналов пульта ДУ (то же самое, что переключение каналов телевизора)
  2. Управление по радио

Первый способ, в отношении управления роботом, реализуется с помощью простенькой схемки, которую даже я, не любитель паяльника, сумел спаять за полчаса - и программы WinLIRC, являющейся по сути Windows-драйвером для такой модели управления (подробности - на моем сайте, в разделе Датчики робота).

Управление по радио - широкоиспользуемая практика, модель такого управления вы можете выдрать из любой радиоуправляемой игрушки, или же найти в каком-либо журнале для радиолюбителей.

В последнее время получают все большее распространение и другие способы беспроводного управления. Конечно же, речь идет о технологиях Bluetooth и Wi-Fi, которые в настоящее время используются практически повсеместно в компьютерах, КПК, коммуникаторах, мобильных телефонах...

Модель управления роботом при использовании технологий Wi-Fi и Bluetooth в основном такая: непосредственно на роботе закрепляются мобильный телефон или КПК, которые, через определенную самопайную схему, могут отсылать роботу управляющие сигналы, и забирать показания датчиков. Основная «мозговая» деятельность - осуществляется на основном, стационарном, компьютере (иногда - даже с помощью распределенной сети серверов). Такой подход позволяет порой в несколько раз уменьшить вес робота и потребляемую им мощность.

Кстати, известен случай, когда на одной из мировых презентаций робота, тот в один прекрасный момент замер на месте - на несколько минут. Это случилось как раз из-за перегрузок Wi-Fi сети здания, где проходила презентация.

Еще один способ управления роботом - визуальный. В простейшем варианте - робот просто движется на свет. Кстати, вариацией этого способа можно считать задачу движения по линии. Но, конечно, такое визуальное управление не слишком функционально и не слишком интерактивно. Более сложные варианты включают в себя использование веб-камеры, закрепляемой на роботе, и анализ изображения, приходящего с камеры. Например, именно таким способом роботов учат распознавать человеческую мимику. Для реализации управления с помощью веб-камеры удобно использовать программное обеспечение RoboRealm, о котором я уже .

Управление звуком - достаточно стандартная функция, для ее реализации можно использовать обычную ОС Windows Vista.

Кстати, в настоящее время существуют также сенсоры, реализующие искусственное обоняние (читайте - на английском - о применении искусственного обоняния в космосе), давно созданы материалы, позволяющие реализовать чувствительную кожу (даже клавиатура для моего старенького Palm m505 сделана из однородного материала, чувствительного к прикосновениям), ну и вкус роботы также могут чувствовать...

В заключение: дистанционное управление требуется практически для любого робота, сколь бы автономным он не был. Поэтому, при проектировании собственного робота, подойдите к этому вопросу серьезно, выберите наиболее доступный вариант, и ориентируйтесь на него - чтобы потом не пришлось все начинать сначала...