- PVSM.RU - https://www.pvsm.ru -

Программируем роботов на Windows 8. Магический шар Sphero

image

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

Вашему вниманию предлагается…

Sphero (www.gosphero.com [1]) – маленький робот шарик сделанный компанией Orbotix.

image

В комплекте поставляется зарядное устройство, инструкция по эксплуатации и, непосредственно, сам шарик.

image

Sphero выглядит как отличная платформа для постижения азов программирования роботов, а еще, это веселая игрушка для гиков, их друзей, детей и домашних животных.

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

Производитель рекомендует использовать робота в следующих сценариях.

image

Используя фантазию и SDK вы можете создавать собственные игры или пользоваться уже готовыми приложениями.

Готовые приложения для управления Sphero и SDK для разработчиков доступны на многих популярных платформах:

Цена вопроса

Стоит такое удовольствие в России от 4 000 до 7 000 тыс. руб. на Яндекс.Маркет [7]. За границей его можно купить за сумму от 80 до 130$. Да, это не самая дешевая игрушка.

Немного теории

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

image

Ось Y отвечает за движение вперед и назад (положительное значение – вперед, отрицательное — назад). Ось X — за движение в стороны. Ось Z — за перемещение вверх или вниз.
Sphero можно калибровать. Перемешать тот самый зад и перед куда следует. Заднюю часть робота можно опознать по синему огоньку, который горит, когда робот едет.

Разработка

Наконец мы дошли до самого интересного. До программного управления этой штуковиной. В качестве примера, мы создадим простую игру на реакцию для небольшой компании. Назовем её Sphero Party Game.

Правила игры

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

Инструменты

Для разработки я буду использовать:

  • Планшет Microsoft Surface 2 Pro
  • OS Windows 8.1
  • Среду разработки: Visual Studio 2013
  • Язык: C#
  • Sphero SDK для Windows 8.1 [4]

Приступаем к работе

1. Первое что нам надо будет сделать – это скачать Sphero SDK [4]. Оно будет представлять собой сборку, которую мы подключим к проекту и будем использовать.
2. Sphero SDK [4] использует Bluetooth RFCOMM [8] для работы с устройством. Для того, чтобы мы программно могли работать с устройством, нам необходимо включить Bluetooth и установить с ним соединение.

image

3. Далее открываем Visual Studio 2013 и создаём проект File / New / Project / Blank App.

image

4. Подключаем сборку из SDK RobotKit.dll

image

5. Добавляем поддержку Bluetooth RFCOMM для приложения. Открываем Package.appxmanifest в режиме правки кода и добавляем в секцию Capabilities следующий код.

Поддержка Bluetooth RFCOMM для приложения

<wb:DeviceCapability Name="bluetooth.rfcomm">
  	    <wb:Device Id="any">
        <wb:Function Type="serviceId:00001101-0000-1000-8000-00805F9B34FB" />
      </wb:Device>
</wb:DeviceCapability>

image

6. На основной экран приложения кладем:

  • переключатель состояния робота (подключенне подключен);
  • текстовое поле для отображения состояния;
  • кнопку “Start” для запуска игры.

Откроем файл MainPage.xaml и добавим туда всё это.

Основной экран приложения

<Grid Background="#0094D0">
        <TextBlock x:Name="SpheroName" HorizontalAlignment="Left" Margin="82,97,0,0" TextWrapping="Wrap" Text="No Sphero Connected" VerticalAlignment="Top" FontSize="24"/>
        <ToggleSwitch x:Name="ConnectionToggle" HorizontalAlignment="Left" Margin="76,122,0,0" VerticalAlignment="Top" Toggled="ConnectionToggle_Toggled" />
        <Grid HorizontalAlignment="Center" Height="512" Margin="0,0,0,0" VerticalAlignment="Center" Width="512">
            <Button Name="startGameBtn" Click="startGameBtn_Click" Content="Start" Height="113"  Width="334" />
        </Grid>
</Grid>

image

7. Перейдем в MainPage.xaml.cs и опишем логику игры. Для общения со Sphero используем объектную модель, предоставленную SDK.

Логика игры

public sealed partial class MainPage : Page
    {
        private Sphero m_robot = null;
        private long m_lastCommandSentTimeMs;
        private bool m_gameIsStarted = false;

        private const string c_noSpheroConnected = "No Sphero Connected";
        private const string c_connectingToSphero = "Connecting to {0}";
        private const string c_spheroConnected = "Connected to {0}";

        public MainPage()
        {
            this.InitializeComponent();
        }
         
        //Начало работы. Переход на основной экран
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            SetupRobotConnection();
            Application app = Application.Current;
            app.Suspending += OnSuspending;
        }

        //Завершение работы. Переход с основного экрана
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            ShutdownRobotConnection();
           
            Application app = Application.Current;
            app.Suspending -= OnSuspending;
        }

        //Переход приложения в фоновый режим
        private void OnSuspending(object sender, SuspendingEventArgs args)
        {
            ShutdownRobotConnection();
        }

        //Ищем робота и подключаемся к нему
        private void SetupRobotConnection()
        {
            SpheroName.Text = c_noSpheroConnected;

            RobotProvider provider = RobotProvider.GetSharedProvider();
            provider.DiscoveredRobotEvent += OnRobotDiscovered;
            provider.NoRobotsEvent += OnNoRobotsEvent;
            provider.ConnectedRobotEvent += OnRobotConnected;
            provider.FindRobots();
        }

        //Завершаем работу с роботом
        private void ShutdownRobotConnection()
        {
            if (m_robot != null)
            {
                m_robot.SensorControl.StopAll();
                m_robot.Sleep();                
                m_robot.Disconnect();

                ConnectionToggle.OffContent = "Disconnected";
                SpheroName.Text = c_noSpheroConnected;

                m_robot.SensorControl.AccelerometerUpdatedEvent -= OnAccelerometerUpdated;
               
                RobotProvider provider = RobotProvider.GetSharedProvider();
                provider.DiscoveredRobotEvent -= OnRobotDiscovered;
                provider.NoRobotsEvent -= OnNoRobotsEvent;
                provider.ConnectedRobotEvent -= OnRobotConnected;
            }
        }
       
        //Робот найден!
        private void OnRobotDiscovered(object sender, Robot robot)
        {          
            if (m_robot == null)
            {                
                RobotProvider provider = RobotProvider.GetSharedProvider();
                provider.ConnectRobot(robot);
                ConnectionToggle.OnContent = "Connecting...";
                m_robot = (Sphero)robot;
                SpheroName.Text = string.Format(c_connectingToSphero, robot.BluetoothName);
            }
        }

        //Робот не найден :(
        private void OnNoRobotsEvent(object sender, EventArgs e)
        {
            MessageDialog dialog = new MessageDialog(c_noSpheroConnected);
            dialog.DefaultCommandIndex = 0;
            dialog.CancelCommandIndex = 1;
            dialog.ShowAsync();
        }


        //Робот готов исполнять команды
        private void OnRobotConnected(object sender, Robot robot)
        {
            ConnectionToggle.IsOn = true;
            ConnectionToggle.OnContent = "Connected";
                       
            SpheroName.Text = string.Format(c_spheroConnected, robot.BluetoothName);
            SetRobotDefault();

            m_robot.SensorControl.Hz = 10;
            m_robot.SensorControl.AccelerometerUpdatedEvent += OnAccelerometerUpdated;
           
        }

        //Изменение местоположения робота
        private void OnAccelerometerUpdated(object sender, AccelerometerReading reading)
        {           
            if (m_gameIsStarted)
                MoveRobot(reading.X, reading.Y);
        }
        
        //Начальное состояние робота. Он зеленый и неподвижно стоит
        private void SetRobotDefault()
        {
            m_robot.SetHeading(0);
            m_robot.SetRGBLED(0, 255, 0);
            m_robot.Roll(0, 0);
        }

        //Герератор случайных цветов робота и интервала их смены
        public async void ChangeRobotColor()
        {
            int colorsCount = 20;
            Random r = new Random();

            List<Color> colors = new List<Color> { Color.FromArgb(100, 0, 255, 0) };
            for (int c = 0; c < colorsCount; c++)
                colors.Add(Color.FromArgb(100, (byte)r.Next(255), 0, (byte)r.Next(255)));

            List<int> miliseconds = new List<int>();
            for (int m = 0; m <= 5; m++)
                miliseconds.Add(r.Next(1000));

            while (true)
            {
                int colorNumber = r.Next(colorsCount);
                Color color = colors[colorNumber];
                int milisecond = miliseconds[r.Next(5)];

                m_robot.SetRGBLED(color.R, color.G, color.B);
                await Task.Delay(TimeSpan.FromMilliseconds(milisecond));
            }
        }

        //Вращение робота по кругу. На 10 градусов в милисекунду
        public void MoveRobot(float x, float y)
        {
            m_robot.SetHeading(0);

            int angleDegrees = 10;

            long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            if ((milliseconds - m_lastCommandSentTimeMs) > 1)
            {
                m_robot.Roll(angleDegrees, 0);
                m_lastCommandSentTimeMs = milliseconds;
            }
        }

        //Кнопка для запуска и остановки игры
        private void startGameBtn_Click(object sender, RoutedEventArgs e)
        {
            m_gameIsStarted = !m_gameIsStarted;

            if (m_gameIsStarted)
            {
                startGameBtn.Content = "Stop";
                ChangeRobotColor();
            }
            else
            {
                startGameBtn.Content = "Start";
                SetRobotDefault();
            }
        }

        //Кнопка для отключения робота
        private void ConnectionToggle_Toggled(object sender, RoutedEventArgs e)
        {
            ConnectionToggle.OnContent = "Connecting...";
            if (ConnectionToggle.IsOn)
            {
                if (m_robot == null)
                {
                    SetupRobotConnection();
                }
            }
            else
            {
                ShutdownRobotConnection();
            }
        }
 }

8. Запускаем приложение. Моё приложение выглядит следующим образом:

image

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

image

image

9. Нажимаем на кнопку Start и проверяем игру на деле.

Скачать исходники можно тут: http://1drv.ms/MXwR6w [9]

Заключение

На этом сегодня всё. Если кто-то заинтересовался или имеет такой девайс, делитесь своими забавными играми, приложениями, сценариями использования и открытиями. Я планирую продолжить данный цикл статей и через некоторое время вернусь к вам с еще одной статьей про Sphero и использование её API.

Полезные ссылки

Официальный сайт Sphero [10]
Центр разработчика Sphero [11]
Windows 8.1 Sphero SDK [4]
Пример использования Sphero SDK для Windows 8.1 [12]
Канал разработчиков Sphero на youtube [13]
Скачать Visual Studio 2013 [14]
Подробнее о Visual Studio Online [15]
Зарегистрироваться на Visual Studio Online [16]

Автор: MissUFO

Источник [17]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/windows/55887

Ссылки в тексте:

[1] www.gosphero.com: http://www.gosphero.com

[2] IOS SDK: https://github.com/orbotix/Sphero-iOS-SDK

[3] Android SDK: https://github.com/orbotix/Sphero-Android-SDK

[4] Windows 8 SDK: https://github.com/orbotix/Sphero-Win-SDK

[5] Windows Phone (пример приложения): http://www.developer.nokia.com/community/wiki/What's_new_in_Windows_Phone_8#Bluetooth:_Phone_to_device

[6] Unity плагин: http://u3d.as/content/orbotix-inc-/sphero-unity-plugin/4co

[7] Яндекс.Маркет: http://market.yandex.ru/search.xml?text=sphero

[8] Bluetooth RFCOMM: http://msdn.microsoft.com/library/windows/apps/dn263529

[9] http://1drv.ms/MXwR6w: https://onedrive.live.com/download?resid=DA8C144CFF7C40EE%2151848

[10] Официальный сайт Sphero: http://www.gosphero.com/

[11] Центр разработчика Sphero: https://developer.gosphero.com/

[12] Пример использования Sphero SDK для Windows 8.1: http://code.msdn.microsoft.com/windowsapps/Sphero-SDK-Sample-2b18913c

[13] Канал разработчиков Sphero на youtube: http://www.youtube.com/playlist?list=PLECE4BD55445BDA51&feature=plcp

[14] Скачать Visual Studio 2013: http://www.visualstudio.com/downloads/download-visual-studio-vs

[15] Подробнее о Visual Studio Online: http://www.visualstudio.com/products/visual-studio-online-overview-vs

[16] Зарегистрироваться на Visual Studio Online: http://go.microsoft.com/fwlink/?LinkId=307137&clcid=0x419

[17] Источник: http://habrahabr.ru/post/213797/