Windows 8でロボットをプログラミングします。加速度計と衝突センサーを使用して、タブレットからSpheroを制御します。

画像



SpheroとそのSDKの機能を引き続き調査します

アジェンダでは、タブレットの加速度計を使用してロボットを制御し、障害物との衝突を検出しています。



理論のビット



前回の記事では、既にSpheroが誰であるかと、 Visual Studio 2013を使用してWindows 8.1でプログラムによる管理を開始する方法を検討しました。

次に、より複雑なものを扱います。 タブレットをさまざまな方向に傾けてロボットを「操縦」し、障害物との衝突を検出する方法を学習します。 これを行うには、タブレットの加速度計とロボットの外界との衝突センサーを使用します。



加速度計


Windows 8.1オペレーティングシステムとWinRTオブジェクトモデルは、もちろんデバイスに搭載されていない限り、次のセンサーの使用をサポートしています。



加速度計は、3方向の動きを測定するモジュールです。 このモジュールには多くの最新のデバイスが搭載されています。 加速度計データにアクセスするには、 Accelerometerオブジェクトにアクセスする必要があります。Accelerometerオブジェクトは、次のプロパティでAccelerometerReadingオブジェクトへのアクセスを提供します。



加速度計の読み取り値が変化したときにイベントにサブスクライブし、読み取り値に応じてロボットを加速、減速、または方向転換します。



画像



加速度計の読み取りイベントに登録できます。



加速度計イベントサブスクリプション
protected override void OnNavigatedTo(NavigationEventArgs e) { … Accelerometer _accelerometer = Accelerometer.GetDefault(); _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged); … } async private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e) { … }
      
      







引越し


タブレットから加速度計データを取得したとします。 次に、それらを使用してSpheroを宇宙で移動する必要があります。

Windows 8.1用のSphero SDKには、Spheroの動きを処理し、2つのパラメーターを受け入れるRollメソッドがあります。



デフォルトでは、Spheroはインジケーターx = 0、y = 0、見出し= 0、速度= 0で作業を開始します。



衝突検知器


Spheroは、 衝突検出などの楽しい機能をサポートしています。 座標の違いに対して、非常に原始的に機能します。



Windows 8.1用Sphero SDKには、既成のCollisionDetectedEventイベントが既にあり、これを使用して、実際のオブジェクトとの衝突をサブスクライブおよびキャッチできます。



イベントの説明
 private void OnRobotConnected(object sender, Robot robot) { … robot.CollisionControl.StartDetectionForWallCollisions(); robot.CollisionControl.CollisionDetectedEvent += OnCollisionDetectedEvent; … }
      
      





最初に衝突センサーをオンにすることを忘れない場合、イベントがトリガーされます:

 robot.CollisionControl.StartDetectionForWallCollisions();
      
      





センサーが不要になったら、オフにします。

 robot.CollisionControl.StopDetection();
      
      







Sphero SDKのいくつかの便利な機能


ロボットを使用するには、Windows 8.1用の次のSphero SDKメソッドも必要です。



SetBackLED(強度)-ロボットのバックライトをオンにして、どこに行くかを理解できるようにします。 値:

1.0f-フルパワーでオンになります。

0.0f-無効にします。



SetHeading(見出し)-ロボットを回転させます。 0から359の値を取ります。



SetRGBLED(赤、緑、青)-ボールの色を設定します。



ロール(見出し、速度)-移動の方向と移動の速度を設定します。

見出し-動きの角度。 0から359の範囲の値を取ります。

速度-動きの速度。 0-移動しません。 255-最高速度。



スリープ()-ロボットをスリープ状態にします。



開発



挑戦する


加速度計を使用してロボットを動かします。 障害に遭遇した場合は、ロボットを赤く塗ります。



ツール




プロセス


1. Visual Studio 2013を開き、プロジェクトFile / New / Project / Blank Appを作成します。



画像



2.アセンブリRobotKit.dllをWindows 8.1のSphero SDKから接続します



画像



3.アプリケーションにBluetooth RFCOMMサポートを追加します。 Package.appxmanifestをコード編集モードで開き、以下のコードを機能セクションに追加します。



アプリケーションのBluetooth RFCOMMサポート
 <wb:DeviceCapability Name="bluetooth.rfcomm"> <wb:Device Id="any"> <wb:Function Type="serviceId:00001101-0000-1000-8000-00805F9B34FB" /> </wb:Device> </wb:DeviceCapability>
      
      







4.アプリケーションのメイン画面で、次を入力します。



MainPage.xamlファイルを開き、そこにすべて追加します。



アプリケーションのメイン画面
 <Page x:Class="SpheroRace.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SpheroRace" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" > <Grid Margin="100" > <Grid.RowDefinitions > <RowDefinition Height="60"/> <RowDefinition Height="60"/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock x:Name="SpheroName" Grid.Row="0" Grid.Column="0" Text="No Sphero Connected" FontSize="24"/> <ToggleSwitch x:Name="ConnectionToggle" Grid.Row="1" Grid.Column="0" Toggled="ConnectionToggle_Toggled" /> <Button Name="StartBtn" Click="StartBtn_Click" Grid.Row="2" Grid.Column="0" Content="Start" VerticalAlignment="Bottom" HorizontalAlignment="Left" Padding="100" ></Button> <Button Name="StopBtn" Click="StopBtn_Click" Grid.Row="2" Grid.Column="1" Content="Stop" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="100" IsEnabled="False" ></Button> </Grid> </Page>
      
      







5. MainPage.xaml.csに移動して、ゲームのロジックを説明します。 Spheroと通信するには、SDKが提供するオブジェクトモデルを使用します。



ゲームロジック
 public sealed partial class MainPage : Page { private Sphero m_robot = null; private long m_lastTimeMs; private double m_currentX = 0; private double m_currentY = 0; private bool m_isStarted = 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; Accelerometer _accelerometer = Accelerometer.GetDefault(); _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged); } // .     protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); ShutdownRobotConnection(); Application app = Application.Current; app.Suspending -= OnSuspending; Accelerometer _accelerometer = Accelerometer.GetDefault(); _accelerometer.ReadingChanged -= new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged); } //handle the application entering the background 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.ConnectionState == ConnectionState.Connected) { m_robot.SensorControl.StopAll(); m_robot.CollisionControl.StopDetection(); m_robot.Sleep(); m_robot.Disconnect(); ConnectionToggle.OffContent = "Disconnected"; SpheroName.Text = c_noSpheroConnected; SetRedColor(); 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); if (m_robot != null && m_robot.ConnectionState == ConnectionState.Connected) { m_robot.CollisionControl.StartDetectionForWallCollisions(); m_robot.CollisionControl.CollisionDetectedEvent += OnCollisionDetectedEvent; SetRedColor(); } } //    async private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e) { if (!m_isStarted) return; await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { Windows.Devices.Sensors.AccelerometerReading reading = e.Reading; SendRollCommand(reading.AccelerationX, reading.AccelerationY, reading.AccelerationZ); }); } //    private void OnCollisionDetectedEvent(object sender, RobotKit.CollisionData data) { SetRedColor(); m_robot.Roll(0, 0); } //    private void ConnectionToggle_Toggled(object sender, RoutedEventArgs e) { ConnectionToggle.OnContent = "Connecting..."; if (ConnectionToggle.IsOn) { if (m_robot == null || m_robot.ConnectionState != ConnectionState.Connected) { SetupRobotConnection(); } } else { ShutdownRobotConnection(); } } //  private void StartBtn_Click(object sender, RoutedEventArgs e) { m_isStarted = true; StartBtn.IsEnabled = false; StopBtn.IsEnabled = true; SetGreenColor(); m_robot.Roll(0, 0); } //  private void StopBtn_Click(object sender, RoutedEventArgs e) { m_isStarted = false; StartBtn.IsEnabled = true; StopBtn.IsEnabled = false; SetRedColor(); m_robot.Roll(0, 0); } //  .      private void SetGreenColor() { m_robot.SetHeading(0); m_robot.SetBackLED(1.0f); m_robot.SetRGBLED(0, 255, 0); } //      private void SetRedColor() { m_robot.SetHeading(0); m_robot.SetBackLED(1.0f); m_robot.SetRGBLED(255, 0, 0); } //       private async void SendRollCommand(double newX, double newY, double newZ) { float x = (float)newX; float y = (float)newY; float z = (float)newZ; float speed = Math.Abs(z); speed = (speed == 0) ? 0 : (float)Math.Sqrt(speed); if (speed > 1f) speed = 0.01f; int heading = Convert.ToInt32(Math.PI / 2.0 - Math.Atan2((double)y - m_currentY, (double)x - m_currentX)); long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; if ((milliseconds - m_lastTimeMs) > 1000) { SetGreenColor(); m_robot.Roll(heading, speed); m_lastTimeMs = milliseconds; m_currentX = x; m_currentY = y; } } }
      
      







6. Bluetooth経由でSpheroに接続する



画像



7.アプリケーションを起動します。



画像



8. [スタート]ボタンをクリックし、実際にゲームを確認します。



画像



結果


簡単なおもちゃができました。 マルチプレイヤーロボットレースをアレンジしたり、ペットと遊ぶために使用できます。



作品の結果はビデオで見ることができます。





ソースはこちらから入手できます: github.com/MissUFO/SpheroRace



便利なリンク



Windows 8でロボットをプログラミングします。Spheromagic ball

Sphero公式ウェブサイト

Sphero開発者センター

Windows 8.1用Sphero SDK

Windows 8.1用のSphero SDKの例

Windows 8.1での加速度計の例

Sphero YouTube開発者チャンネル

Visual Studio 2013をダウンロードする

Visual Studio Onlineの詳細をご覧ください。

Visual Studio Onlineにサインアップする



All Articles