cylon.jsとleapmotionでspheroを動かす

# はじめに
最近ではRaspberry PiやArduino、Edison Boardなど気軽にIoTを楽しめる環境が整ってきました。
私が子供の頃流行っていた電子工作ブームが再びこんな形で花開くのを見るのは大変嬉しいです。どんどん自分なりの創意工夫を盛り込んだ物を共有してきましょう！

#でも開発って難しいんでしょう？
全く難しくありません！
最初のセットアップもだいぶ簡単になってきおり、GUIも増えてきています。
今回紹介するのは「Cylon.js」というJavaScriptでの開発フレームワーク。単眼のザクのようなクールなマスコットが目を引きます。結構すごいんです！シンプルかつ拡張性に富んでいて、現在では43のプラットフォームに対応しています。

◆Cylon.js
http://cylonjs.com/

#まずはサンプルから始めよう

Cylon.jsはNode.jsを使用します。Node.jsの使い方がわからない場合は、別の記事を読んでからインストールするとスムーズにいくかと思います。（紙面の都合上）

◆Node.jsについて
http://qiita.com/mucho0623/items/c355c36dbd51631ac9ea

そうしたらプロジェクトフォルダを作り、Cylon.js公式サイトTopの「The "Hello, World" Of Things」に載っているコードをscript.jsに写しましょう。

```
var Cylon = require("cylon");

// Initialize the robot
Cylon.robot({
  // Change the port to the correct port for your Arduino.
  connections: {
    arduino: { adaptor: 'firmata', port: '/dev/ttyACM0' }
  },

  devices: {
    led: { driver: 'led', pin: 13 }
  },

  work: function(my) {
    every((1).second(), function() {
      my.led.toggle();
    });
  }
}).start();
```

実行には以下のモジュールが必要です。
npmでインストールを行いましょう。

```
$ npm install cylon-firmata cylon-gpio cylon-i2c
$ node script.js
```

無事に動けば環境のセットアップはOKです！

#本題のSpheroとLeap Motionについて

さて本題となるSpheroとLeap Motionの連携についてです。

##そもそもSpheroとは
丸い球状の物体で、アプリを操作することで縦横無尽にぐりぐり部屋の中を走り回る大変キュートな遊び道具です。犬とかいると割と危険です。猫の反応は知りませんが...

◆Sphero
http://www.sphero.com/sphero

##Leap Motionとは
これはVR界隈では結構知名度があったと思うので、ご存知の方も多いと思いますが、手の動きを検知して様々なジェスチャーなどに対応した近未来的な操作を提供します。キネクトともよく似ていますが、近距離から中距離で使用して、細い指の動きをキャッチできるのが魅力です。

◆Leap Motion
https://www.leapmotion.com/

##サンプルはあるの？
二つのデバイスとも、Cylon.jsにはすでにサンプルがあります。特にLeap MotionとARDroneなどドローンが手の動きに合わせて動くのは大変面白いので、お持ちの方はぜひ試してみると良いのではないでしょうか。

◆Leap MotionとARDroneサンプルコード
http://cylonjs.com/documentation/examples/cylon/js/leap_ardrone/

◆Spheroのサンプルコード
http://cylonjs.com/documentation/examples/cylon/js/sphero_shakeometer

今回はこれらを組み合わせてLeap Motionの動きでSpheroを動かすコードを書いてみます。

#コードを書いてみよう
##プロジェクトの準備
プロジェクトフォルダを作り、コアとなるcylon、spheroとleapmotionを扱うためのモジュール、それと後々必要になるベクトル操作モジュールvictorをインストールします。

```
$ npm install cylon cylon-sphero cylon-leapmotion victor
```

## まずはキーボードで動くかどうか確かめる
index.jsを作成し、以下のコードを書き込みます。

```
"use strict";

var Cylon = require("cylon");

Cylon.robot({
    connections: {
        sphero: { adaptor: 'sphero', port: '/dev/tty.Sphero-WRR-AMP-SPP' },
        keyboard: { adaptor: "keyboard" }
    },

    devices: {
        sphero: { driver: 'sphero' },
        keyboard: { driver: "keyboard", connection: "keyboard" }
    },

    work: function (my) {    
        my.keyboard.on("right", function () {
            my.sphero.roll(35, 90);
        });
        my.keyboard.on("left", function () {
            my.sphero.roll(35, 270);
        });
        my.keyboard.on("up", function () {
            my.sphero.roll(35, 0);
        });
        my.keyboard.on("down", function () {
            my.sphero.roll(35, 180);
        });
    }
}).start();
```

connectionsとdevicesブロックにSpheroとキーボードを追加します。SpheroはBluetoothで接続するので、portには環境に応じたポートが入ります。（コードでは'/dev/tty.Sphero-WRR-AMP-SPP'と書いてあるところ）

これは以下のコマンドで調べることができます。それらしいものが見つかったらそれを入れてください。

```
ls /dev/tty.Sphero*
```

workブロックには実際の挙動が入ります。ここでは以下のような書き方でキーボードの十字右キーに応じてSpheroに90度の方向に35の加速度で移動を命令しています。

```
my.keyboard.on("right", function () {
    my.sphero.roll(35, 90);
});
```

できたら早速動かしてみましょう。
キーボードの十字キーでゆるゆるっと動いたら成功です！

##次はLeap Motionと連携
キーボードで成功したなら、次はLeap Motionとの連携を行います。ARDroneのコードを参考にしました。

まずベクトル操作と手の位置を保存しておくための変数previousPalmPositionを定義します。

```
var Cylon = require("cylon");
var Victor = require("victor");
var previousPalmPosition;
```

そしてconnectionとdevicesブロックにleapmotionを追加します。

```
connections: {
	sphero: { adaptor: 'sphero', port: '/dev/tty.Sphero-WRR-AMP-SPP' },
	keyboard: { adaptor: "keyboard" },
	leapmotion: { adaptor: "leapmotion" }
},

devices: {
	sphero: { driver: 'sphero' },
	keyboard: { driver: "keyboard", connection: "keyboard" },
	leapmotion: { driver: "leapmotion", connection: "leapmotion" }
},
```

最後にworkブロックに以下のコードを書き足します。

```
my.leapmotion.on("hand", function (hand) {
    var handOpen = !!hand.fingers.filter(function (f) {
        return f.extended;
    }).length;

    if (handOpen) {
        if (previousPalmPosition) {
            var delta = new Victor(hand.palmPosition[0] - previousPalmPosition[0], hand.palmPosition[2] - previousPalmPosition[2]);
            var angle = Math.floor(delta.angle() * 180 / Math.PI + 180);
            var magnitude = Math.floor(delta.length());

            if (magnitude > 2) {
                my.sphero.roll(magnitude * 12, angle);
            }
        }
    } else {
        my.sphero.stop();
    }

    previousPalmPosition = hand.palmPosition;
});
```

leapmotionが手を検知するとhandというイベントが発行されます。その中で処理を行っていくのが基本となります。

ここでは開いている手をかざした場合にhandOpenをtrueにしています。
開いている場合は、手の現在位置と前フレームで保存した手の位置の差を取り、移動した方向(angle)と距離(magnitude)を使用してSpheroの移動方向と距離を決定、手を閉じた場合はSpheroを停止するようにしています。

終わったら実行してみましょう。
ぐるぐるLeap Motionの上で手を回してるとSpheroもぐるぐる回るはずです。

#おわりに
いかがでしたか？
JavaScriptでここまで手軽にできるようになってきたのはすごく嬉しいです。
これからどんどんできることが広がっていくといいですね！

今回のコードはgithubに公開していますので、気になる人はぜひ参考にしてみてください。

https://github.com/quetz-design/cylonleap