Romo×iPhoneで楽しむロボット体験

第2回 Romoを自由に動かしてみよう!

この記事を読むのに必要な時間:およそ 3 分

デバイスとの接続

それでは,デバイスとの接続を検知するところからはじめて見ましょう。ベースとなるViewController.hにRMCoreをimportします。

ViewController.h

#import <RMCore/RMCore.h>

接続の検知は,RMCoreクラスのdelegateとして通知されます。起動時にdelegateの設定を行います。

ViewController.h

@interface ViewController : UIViewController <RMCoreDelegate>

ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    [RMCore setDelegate:self];
}

実際のDelegateメソッドを以下のように記述します。ここで1つの問題,iPhoneをPCから切り離してデバイスに接続しないと動作しないので,デバッグのテキストを画面上のUILabelに表示するようにしました。

ViewController.h

// デバッグ用テキスト表示
@property IBOutlet UILabel* debugText;

delegateでRomoの各種処理を提供するRMCoreRobotオブジェクトが渡されるのですが,Romoは今後の機能拡張を想定してRMCoreRobotに各機能を表すインターフェースを実装する形で拡張される設計になっています。HeadTiltProtocolがiPhoneの角度を変更するインターフェース,DriveProtocolが左右のキャタピラを操作するインターフェース,LEDProtocolがLEDの点灯を制御するインターフェースとなっています。

やや複雑な表記ですが,それぞれのインターフェースを指定した記述で,以下のようにRMCoreRobotオブジェクトを持つようにします。

ViewController.h

@property (nonatomic, strong) RMCoreRobot<HeadTiltProtocol, DriveProtocol, LEDProtocol> *myRobot;

ViewController.m

- (void)robotDidConnect:(RMCoreRobot *)robot
{
if (robot.isDrivable && robot.isHeadTiltable && robot.isLEDEquipped) {
       self.debugText.text = @"connected!";
       self.myRobot = (RMCoreRobot<HeadTiltProtocol, DriveProtocol, LEDProtocol> *) robot;
    }
}

なお,Romo から iPhone を外すと以下のメソッドが呼ばれます。

- (void)robotDidDisconnect:(RMCoreRobot *)robot
{
    if (robot == self.myRobot) {
       self.myRobot = nil;
       self.debugText.text = @"disconnected!";
    }
}

ちなみに今回は利用をしないのですが,開発する上で接続が手間となり,とりあえずデバイスに接続しなくてもシミュレータなどで処理を確認したい場合,deviceとの接続をダミーで知らせるRMCoreのconnectToSimulatedRobotというクラスメソッドと,接続解除をダミーで知らせるdisconnectFromSimulatedRobotというクラスメソッドがそれぞれ用意されています。

ViewController.m

// Romo との接続をシミュレーターで再現
[RMCore connectToSimulatedRobot];

以上のようにダミーで知らせると,robotDidConnectがdelegateで呼ばれます。

LED

続いて何かアクションをさせてみましょう。

画面にUIButtonを配置し,タップするとLEDを光らせるようにしました。RMCoreRobotオブジェクトが実装しているLEDProtocolインターフェースに,LEDsというRMCoreLEDsクラスのプロパティがあります。こちらのメソッドを呼び出して処理を行います。

ViewController.m

- (IBAction)pushLEDBtn:(id)sender
{
    [self.myRobot.LEDs blinkWithPeriod:0.5 dutyCycle:0.1];
}

この書き方で,0.5秒間隔で点灯と消灯を1:9の割合で行うようにできます。一瞬チカッと光るイメージです。

点灯や点滅,決められた明るさでの点灯など,より詳しいメソッドはクラスドキュメントRMCoreLEDsで確認することができます。

前傾,後傾

続いて,Romoに接続したiPhoneの傾斜を動かす方法です。RMCoreRobotオブジェクトが実装しているHeadTiltProtocolに各種プロパティとメソッドが用意されています。

ViewController.m

- (IBAction)pushTiltBtn:(id)sender
{
    // HeadTild
    if (self.myRobot.robot.headAngle < self.myRobot.robot.maximumHeadTiltAngle - 1) {
        [self.myRobot.robot tiltToAngle:self.myRobot.robot.maximumHeadTiltAngle completion:nil];
    } else {
        [self.myRobot.robot tiltToAngle:self.myRobot.robot.minimumHeadTiltAngle completion:nil];
    }
}

タップするごとに,頭が前後に傾くようになります。ちなみに最初の判定で-1を入れているのは,headAngleがモーターの状態などにより誤差が少し生じるためです。このあたりの調整が,デバイスをプログラミングしている実感を感じさせますね。

ちなみに,completionにblockを設定することで,処理の完了を受け取ることができます。

移動

最後に,Romoの左右のキャタピラを使って移動させる方法です。RMCoreRobotオブジェクトが実装しているDriveProtocolに各種プロパティとメソッドが用意されています。

ViewController.m

- (IBAction)pushMoveBtn:(id)sender
{
    // Drive
    if (self.myRobot.robot.driving) {
        [self.myRobot.robot stopDriving];
    } else {
        [self.myRobot.robot driveWithRadius:1.0 speed:1.0];
    }
}

タップすると,半径1m,秒速1mで回転移動を始めます(状況により誤差は出るようです⁠⁠。もう一度タップすると停止します。回転以外にも前後の移動,その場での回転などざまざまなメソッドが用意されています。

まとめ

さて,いかがでしたでしょうか?

実際にRomoが動き出すと手応えがあり,デバイスを利用したプログラミングの楽しさを実感できます。今回は比較的制御しやすい方法をご紹介させていただきましたが,直接それぞれのモーターを制御するなど,もっと掘り下げた処理を行うこともできるので,ぜひ一度クラスドキュメントに目を通されることをおすすめします。

Romoは現在,エデュケーショナルロボットとして販売していますが,スマートフォンで動かすことのできるロボットデバイスと捉えることで,皆さんが開発するアプリ次第で,エデュケーショナル以外にもさまざまな用途を見出すこともできるかと思います。

次回は,RomoのCharacter UIを制御するRMCharacterをご紹介します。

著者プロフィール

瀬尾浩二郎(せおこうじろう)

セオ商事 エンジニア / クリエイティブディレクター

2001年慶應大学環境情報学部卒業。大手SIerを経て,2005 年に面白法人カヤック入社。Webやモバイルアプリの制作を主に,エンジニア,クリエイティブディレクターとして勤務。2014年4月よりセオ商事として独立。

グッドデザイン賞を始め,国内外の広告祭など受賞経験多数。技術書の執筆や,各種媒体への記事の寄稿なども行っています。

サイト:http://theodoor.jp
ブログ:http://theodoor.hateblo.jp/
Twitter ID:theodoorjp