суббота, 19 апреля 2008 г.

Wiimote + Robotics Studio

Сегодня я хочу рассказать еще немного о замечательном устройстве ввода информации с обратной связью от компании Nintendo - Wii Remote. Для тех, кто забыл, или не знал (я уже о Wii Remote писал) - вот какие, например, возможности дает это устройство:

Этот прекрасный демонстрационный ролик от Джонни Ли (я был просто поражен, когда увидел это видео впервые...), конечно, больше относится к игровой индустрии, однако и для роботов Wii Remote может пригодиться. Например, вот в таком виде:

Это видео сделано французом по имени Альберто Биэтти (Alberti Bietti), который на своем блоге разместил целое руководство по подключению Wii Remote к Microsoft Robotics Studio, и использованию этой связки для управления роботом Lego Nxt. Достаточно вольный и немного укороченный перевод данного руководства я постараюсь привести здесь.

К сожалению, я сам в данный момент не могу себе позволить приобрести Wii Remote, чтобы проверить все, о чем сейчас напишу - на практике, хотя недавно видел этот прекрасный «девайс» в свободной продаже (отдельно от приставки), и обязательно куплю его позже, когда позволят финансовые возможности...

Помимо устройства WiiRemote, для создания описываемой программы, необходимо установить на Вашем компьютере .Net Framework, Microsoft Visual Studio, Microsoft Robotics Studio. Речь будет идти о программировании на C#, и подразумевается, что Вы уже имеете какие-то базовые знания о .Net и C#.

Итак, задача: совместить мощную среду разработки ПО для роботов - Microsoft Robotics Studio - с устройством Wii Remote (обычно его сокращают - до Wiimote).

Задача эта, на самом деле, уже решена на низком уровне совместимости. Так что драйвер мы писать не будем - ведь существует специальная библиотека для этих целей, Managed Library for Nintendo's Wiimote, которую можно свободно скачать с CodePlex.

Создание сервиса

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

Вообще говоря, веб-сервисы - это корень идеологии Robotics Studio, любая программа, созданная в MSRS, собственно, состоит из множества веб-сервисов. Использование веб-сервисов позволяет реализовать распределенные модели управления роботами - когда программа расположена сразу на нескольких серверах, возможно, значительно удаленных друг от друга.

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

Для создания заготовки для веб-сервиса, вам потребуется выполнить следующую команду (из командной строки, которая, кстати сказать, используется в MSRS очень часто):

dssnewservice /s:wiimoteNxt

Здесь параметр /s задает имя создаваемого сервиса.

Теперь перейдите в каталог (созданный при создании веб-сервиса) 'wiimoteNxt' в папке C:\Microsoft Robotics Studio (1.5)\ (или в другой, куда Вы установили MSRS 1.5). Откройте файл wiimoteNxt.sln (конечно, для этого у вас должна быть установлена среда разработки Visual Studio). Это и есть проект нашего веб-сервиса.

Добавление связей

Теперь, собственно, давайте добавим в проект связь с библиотекой WiimoteLib. Первая проблема, с которой придется столкнуться - это несовместимость версий, поскольку библиотека WiimoteLib была написана под использование с MSRS 1.0, а самая свежая версия - 1.5. Проблема решается просто, снова из командной строки:

dssProjectMigration "D:\wiimote\291133_WiimoteLib\WiimoteCS\WiimoteMSRS"

Параметром задается путь к библиотеке, исправьте, если у вас он другой.

Теперь библиотека совместима с версией 1.5 Robotics Studio, и можно перекомпилировать ее: открываем файл Wiimote.sln из студии, жмем Build, и затем закрываем проект - больше он нам не потребуется.

Вернемся к проекту нашего только что созданного веб-сервиса, и добавим ссылку на библиотеку WiimoteLib.

В появившемся окне выбираем вкладку .NET и ищем «Wiimote.Y2007.M06.Proxy» (каждый раз при создании подобных связей - необходимо выбирать сервисы типа Proxy).

Также следует добавить ссылку на «RoboticsCommon.Proxy».

Наконец, для упрощения записи, в начало файла WiimoteNxt.cs потребуется добавить примерно такие директивы «using»:

using wiimote = WiimoteLib.Proxy;
using drive = Microsoft.Robotics.Services.Drive.Proxy;

Благодаря этим двум нехитрым строчкам, мы сможем обращаться к нашим библиотекам максимально просто, поскольку это - алиасы для namespace-ов (область имен, т.е. все имена идентификаторов уникальны в пределах одной такой области). Drive означает двигатель, через этот namespace мы будем обращаться к моторам; область имен wiimote, как нетрудно догадаться - отвечает за хранение классов для манипуляций с нашим одноименным чудо-пультом.

Подписка на оповещения Wiimote

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

Прежде чем начать, следует учесть, что принятые оповещения нужно где-то хранить - для этого прекрасно подойдут существующий в Robotics Studio специальный класс объектов - «порт».

// порт Wiimote (со специальным атрибутом Partner)
[Partner("wiimote", Contract = wiimote.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]
private wiimote.WiimoteOperations _wiiPort = new wiimote.WiimoteOperations();

// порт для оповещений
private wiimote.WiimoteOperations _wiiNotify = new wiimote.WiimoteOperations();

В представленном фрагменте кода использованы так называемые атрибуты. Атрибуты могут быть связаны с классом, переменной, объектом, методом, и др. Атрибуты обрабатываются специальными классами-обработчиками, которые могут написаны любым программистом, и каким-либо образом воздействуют на объект, для которого назначен тот или иной атрибут; либо влияют на способы обработки этого объекта. Вообще, атрибуты и рефлексия - это отдельная тема, о которой можно говорить очень долго.

Вкратце определение рефлексии звучит так: рефлексия (синоним интроспекция, англ. reflection) — механизм языка программирования, позволяющий во время выполнения исследовать и изменять структуру программы. Один из инструментов рефлексии в C# - это как раз атрибуты.

Об атрибутах можно почитать, например, на сайте GotDotNet.ru.

В данном случае с помощью атрибута мы просто указали, что создаваемый порт будет взаимодействовать с веб-сервисом wiimote.

Теперь у нас есть порты, давайте подпишемся на оповещения. Во-первых, в метод Start() после строчки base.Start() следует добавить вот такой код:

_wiiPort.Subscribe(_wiiNotify);

Это означает, что главный порт - _wiiPort - будет пересылать оповещения порту _wiiNotify. Чтобы активировать прием на порту _wiiNotify, добавим еще одну строку:

Activate(
    Arbiter.Receive(true,
                                            _wiiNotify, wiimoteChangedHandler));

wiimoteChangedHandler - это имя еще пока не созданного метода обработчика оповещений. Создадим его:

//wiimote notifications handler
void wiimoteChangedHandler(wiimote.WiimoteChanged wiimoteChanged)
{

}

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

Управление моторами

Обращение к моторам осуществляется, как вы помните, через область имен drive. По аналогии с тем, что мы делали для wiimote, создаем порт для управления моторами (для оповещений нам порт не нужен, т.к. наши простые моторы не имеют обратной связи):

// Точно также, создаем порт с атрибутом Partner
[Partner("drive", Contract = drive.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]
private drive.DriveOperations _drivePort = new drive.DriveOperations();

Теперь вставим в обработчик оповещений от wiimote код для отсылки управляющих сигналов нашим моторам. Это достаточно просто:

void wiimoteChangedHandler(wiimote.WiimoteChanged wiimoteChanged)
{
    //для простоты дальнейшего горизонтального управления, меняем друг с другом X и Y
    float x = -wiimoteChanged.Body.AccelState.Y;
    float y = wiimoteChanged.Body.AccelState.X;

    //создаем управляющий сигнал для мотора
    drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
    //кстати, есть конструктор, который сразу же позволяет задать скорости, вот так:
    //drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest(leftSpeed, rightSpeed);
    // Здесь же мы зададим скорости вручную, вычислив их как разность координат:
    request.LeftWheelPower = y + x;
    request.RightWheelPower = y - x;
    //собственно, отсылаем наш управляющий сигнал!
    _drivePort.SetDrivePower(request);
}

Собственно, почти все.

Запускаем наш сервис

Перед тем, как запустить программу, необходимо указать файл манифеста, который определит для Robotics Studio, какого робота будет использовать программа (либо симуляцию какого робота требуется запускать).

Файл манифеста можно указать следующим образом через командную строку:

dsshost -port:50000 -tcpport:50001 -manifest:"wiimoteNxt/wiimoteNxt.manifest.xml" -m:"samples/config/Lego.NXT.Tribot.manifest.xml"

Также можно указать файл манифеста в свойствах проекта - это может потребоваться при отладке:

Варианты командной строки для других роботов:

  • Lego NXT robot (Tribot или любой другой робот с двумя отдельно управляемыми моторами): "samples\config\LEGO.NXT.TriBot.manifest.xml"
  • Tribot - симуляция: "samples\config\LEGO.NXT.TriBot.simulation.manifest.xml"
  • BOE-Bot: "samples\config\Parallax.BoeBot.Drive.manifest.xml"
  • iRobot: "samples\config\iRobot.manifest.xml"
  • iRobot Create - симуляция: "samples\config\IRobot.Create.Simulation.xml"

Весь проект можно скачать с сайта Альберто Биетти.

3 комментария:

  1. Привет, если ты сам пробовал всё, то может подскажешь в чём проблема. Я застрял на шаге когда конвертим библиотеку WiimoteLib (скачал последнюю ресию 14351). В примере почему-то указывается путь на папку WiimoteMSRS, там файл проекта WiimoteMSRS.sln, но потом в студии нужно открыть файл проекта Wiimote.sln, который находится в папке WiimoteCS. И она понятное дело ругается что файл создан более новой версией. Я пробовал конвертить оба файл - результат тот же, студия не могет их октрыть :(

    ОтветитьУдалить
  2. shred: Извиняюсь за поздний ответ. Был очень загружен работой :( В общем, я попробовал, сделал именно так, как написано в данном туториале - все работает.

    Опишу подробно как у меня все это происходило, может тебе поможет:
    1) Скачал с codeplex версию 1.2.1 библиотеки. Вот отсюда. Это zip-архив размером всего 450Кб.
    2) Разархивировал его в папку c:\wiimote.
    3) Пуск-->Программы-->Microsoft Robotics Studio (1.5)-->Command Prompt
    4) Скопировал туда строку из туториала, и поправил ее, получилось так:
    C:\Microsoft Robotics Studio (1.5)>dssProjectMigration "c:\Wiimote\WiimoteCS\WiimoteMSRS"
    Нажал Enter, в ответ получил следующее:
    ----------------------8<-----------
    * Searching Directory:
    c:\Wiimote\WiimoteCS\WiimoteMSRS
    * Updating project c:\Wiimote\WiimoteCS\WiimoteMSRS\Wiimote.csproj ...

    * Updating project c:\Wiimote\WiimoteCS\WiimoteMSRS\Wiimote.csproj.user ...

    * Updating project c:\Wiimote\WiimoteCS\WiimoteMSRS\Proxy\Wiimote.Y2007.M06.proxy.csproj ...

    * Updating project c:\Wiimote\WiimoteCS\WiimoteMSRS\Proxy\Wiimote.Y2007.M06.proxy.csproj.user ...

    * Updating source code
    c:\Wiimote\WiimoteCS\WiimoteMSRS\Proxy\AssemblyInfo.cs ...

    * Updating source code c:\Wiimote\WiimoteCS\WiimoteMSRS\Proxy\wiimote.source.transform.cs ...

    ----------->8----------------------
    5) Кликнул два раза на Wiimote.sln в папке C:\Wiimote\WiimoteCS

    Все открылось без проблем. Нажал Build->Build solution - все скомпилилось, Build succeeded.

    ОтветитьУдалить

Внимание! Реклама и прочий спам будут беспощадно удаляться.