Cylon.jsでCrazyflieを飛ばす

# Cylon.jsについて

たぶんQiitaを見ている、JavaScriptを主戦場の一つにしている人たちなら、あまり説明の必要もないと思う。タグにもすでにCylonがあるようだし、いくつか投稿もあがっているので、特に詳しい説明は割愛してしまうが、Cylonは簡単に言うとIoTやロボティクス向けに作られたJavaScriptのフレームワークだ。

現状35のハードウェアプラットフォームに対応していて、それぞれ毎にドライバが用意されている。基本的な使い方はそれぞれのハード用のドライバを利用して、させたい動作、取りたいデータなどに関する処理を実装していくことになる。

利用できる35のハードのリストは本家サイトの[こちら](http://cylonjs.com/documentation/platforms/)に出ているので参考にするとよい。RaspiやEdisonなどの話題のハード、プラットフォームにも当然ながら対応している。

# Crazyflieとは

昨今何かとDrone流行りでいろいろなところで話題になっているが、[Crazyflie](https://www.bitcraze.io/crazyflie/)もその範疇に入るものとしてよいと思う（正確にはDroneは自律航行可能な飛行体や自走体なので、RCとして人がオペして飛ばすマルチローター機が全てひと括りにDroneと言われているのには違和感があるのだけど）。と言っても、世の中的に認識されている空撮メインで飛ばされているような比較的出力もある中型機以上のものとは違ってとても小さい。nano quadと呼ばれるカテゴリに入るものだ。作っているのはスウェーデンのハードウェアスタートアップである[Bitcraze](https://www.bitcraze.io/)。

![DSC_0032.JPG](https://qiita-image-store.s3.amazonaws.com/0/5315/89e7798f-a4ed-7b50-2ee1-c30d41daa27a.jpeg)

小さいからと言って、侮るなかれで、姿勢を制御するためのジャイロセンサーや気圧センサーなど諸々のセンサーを搭載し、飛行中のテレメトリー情報を取得することもできるようになっている。また、ハードの仕様はオープンソースになっていて、ペイロード限界を超えない範囲でカメラなどを付け足す拡張も可能だ。ということもあって、例えば[ミュンヘン工大によるSLAMによる自律安定飛行の実験](http://www.nikkeibp.co.jp/article/news/20140916/415633/?rt=nocnt)に使われていたりもする。

_※SLAM:簡単に言うと自分の位置の推定と置かれている環境のマップ作成をセンサーなどの観測値から同時に行う技術のこと。_

いきなり屋外でGPS使ってオートパイロットなんていうのは敷居が高いかもしれないけど、室内でプログラマブルに飛ばせるものを試してみるというのにはちょうどよいかも、ということで、このCrazyflieをCylonを使って飛ばしてみようと思う。

(ちなみにこの手の超小型機では、日本の東大発ベンチャーの[Phenox](http://phenoxlab.com/?lang=ja)にとても期待してます。)

# CylonでCrazyflieを飛ばす準備

## Crazyflieを手に入れる

さて、まずは何はともあれ、実機がないといけないので、試してみたいと思った場合は調達する必要がある。[Seeed Studio](http://www.seeedstudio.com/depot/)さんから購入可能なので、興味があって使ってみたくなったら、購入を検討してみるとよい。

ちなみにSeeedさんは中国深圳にあるプロトタイピングツールやパーツを扱っている企業だが、今まで何回か利用した限りでは比較的安心して購入できる先だと思う。以上、余談。

手元にあるCrazeflieは初代の10DOFというバージョンだが、最新は[Crazeflie2.0](https://www.bitcraze.io/crazyflie-2/)で、こちらは諸々機能増強されているのと、拡張が容易にできるような機構になっている。さらに、初代はPCから操作するのにPC側に接続する専用の送受信モジュールが必要だったが、2.0はBLEに対応しているため、専用のモジュールがなくても飛ばせる。

また、初代は組み立て時に一部分だけだが、ハンダ付けが必要（とても細かい部分）だったのに対して、2.0はハンダ付け不要で組み立てることが出来るようになっている。今購入するなら、こちらをおすすめする（というか、たぶん今はもう2.0しか在庫がないはず）。価格は今のレートだと多分２万円強になるはず。

## 諸々開発環境を構築する

ということで、CylonとCylonのCrazyflie用ドライバを利用して飛ばすための諸々の環境を構築する。手元で問題なく動作することが出来た環境の主なものの各バージョンは以下の通り。Nodeのバージョンが最新の0.12.x系ではないのには事情があって、詳しくは後述する。

* OS: Ubuntu14.04
* Node.js: 0.10.36
* Cylon.js: 1.0
* cylon-crazyflie: 0.15.0

この他にCrazyflie自体のファームが最新になっていることと、CrazyflieをPCを利用して飛ばす際必要な諸々がCrazeflieのガイドに従ってすべてインストール済みとなっていることが前提になる。この辺りは割愛。ちなみにこちらの環境を作るのにはPythonが必要になる。

### Cylon.jsとcylon-crazyflieのインストール

Cylon本体は単純にnpm install cylonすればよいので、特別な手順は必要ない。


問題はドライバの[cylon-crazyflie](https://github.com/hybridgroup/cylon-crazyflie)の方で、そのままでは動作する状態にできない。cylon-crazyflieは[aerogel](https://github.com/ceejbot/aerogel)という、それ単独でもCrazyflieを飛ばすことができるNodeのモジュールに依存している。そのaerogelがさらにusbモジュールを使っているが、何も考えずにnpmでcylon-crazyfileをインストールすると依存関係の指定から、（すでにusbモジュールがインストールされている場合はのぞいて）通常最新のバージョンのusbモジュールがインストールされる。

実はこのusbモジュールへの依存関係がクセモノで、usbモジュール自体の実装はバージョン0.3.xから1.0.xに上がったタイミングでかなり変わっている。ところがaerogelはそれらの変更に対応した実装のアップデートを行っていない。ということで、本当はこの当たりを修正してpull requestを送ろうかと考えていたのだが、とりあえず動かしてみるということで、usbモジュールを0.3.xより以前のものにして試すことにする。以下、実際に行った作業。

* libusb-devのインストール

```shell-session
$ sudo apt-get install libusb-1.0-0-dev
```

* node-usbのインストール

```shell-session
$ npm install usb@0.3.11
```

* cylon-crazyflieのインストール

```shell-session
$ npm install cylon-crazeflie
```

node-usbをインストールする際に、バージョンを指定してインストールしている。また、最初に書いたNodeのバージョンは0.12.x系ではなく、以前のバージョンである0.10.x系にしてある理由もここにある。実はv8のバージョンが新しいとnode-usbのインストール時に実行されるビルドが通らない。Node自体も以前のものにしておく必要があるのはこのためだ。

公式のcylon-crazeflieのインストール手順にはbuild-essentialのインストールなども書いてあるが、こちらは以前に入れたことがなければ入れる。

## 簡単な飛行用コード

実際に簡単な飛行のためのコードを書いて飛ばしてみる。[cylon-crazeflieの公式ページのHow-to](http://cylonjs.com/documentation/platforms/crazyflie/)にも離陸→着陸→停止のサンプルコードが提示されているが、こちらも一部現行のバージョンでは機能しないコード（コード詳細は割愛するがサンプルコード内で利用しているstopメソッドがそもそもない）があったため、そのまま試すのではなく、操作を追加して、以下のようにしてみた。

```js:flight.js
var Cylon = require('cylon');

Cylon.robot({
  connections:{
    crazyflie:{adaptor:'crazyflie'} //接続先crazyflieへのコネクション設定.
  },
  devices:{
    drone:{driver:'crazyflie'} //デバイスとドライバーの設定
  },

  work: function(my){
    my.drone.takeoff(); //離陸コマンドの実行
    after((1.5).seconds(),function(){
      my.drone.hover(); //1.5秒後にホバリングに移行
    });
    after((5).seconds(),function(){
      my.drone.land(); //5秒後に着陸へ移行
    });
    after((8).seconds(),function(){
      my.drone.shutdown(); //8秒後に停止
    });
  }
}).start();
```

シンプルに離陸してホバリングに移行し、着陸するだけのコードで、基本は指示コマンドに対応するメソッドを順に実行している。

Crazyflieとのコネクション確立の設定（connectionsの部分）で、公式サイトのサンプルでは通信ポートの指定まで含めているが、ポート指定はなくても、接続可能なCrazyflieを探して接続してくれる。

他にヨー、ピッチ、ロール値の投入を試してみたのだが、まだあまりうまく行っていない。使えるコマンドのメソッドは[こちら](https://github.com/hybridgroup/cylon-crazyflie/blob/add0718ee77bad3bb408146d85ca42a50db983ff/docs/commands.md)。

## 試してみて

Cylon自体は簡単に使えるのでいろいろ試してみるのに使ってみるのはよいと思う。ただ、飛びモノについては、ドライバーの出来次第でだいぶ変わりそう。特に今回のCrazyflieのような基本機能は揃っているけど、飛ばす側がある程度諸々調整してやらないとうまく飛ばないものはけっこう難しい。同じ飛びモノでCylonが対応しているAR.Droneのような、そもそもあまり考えないでも安定飛行するように設計されているものなら、プログラムだけで飛ばすのも現実的かもしれないが、Crazeflieのような機体だと、例えばWebブラウザ上から操作できるような画面を作って、そいつの裏でCylonを使って人が操縦というのであればやれるかもしれないが、自律で飛ばすはなかなか苦戦しそう。

ドライバの中で使っているaerogelではCrazyflieからのテレメトリー値を取ることができるので、もし自律で飛ばすとなると、直接aerogelを使ってテレメトリー値を取りながら、プログラムの中で値によって調整して飛ばすようにしたほうがよいかもしれない（そもそももっと言えば、遅延の少ないファームウェアに自律飛行を組み込んでしまうのが一番かもだが）。

ちなみに実際どんな飛び方するのかは、今回のプログラムを実行して飛ばしているのも動画に撮ってみたけど、イマイチなので、もう少しうまく飛ばせるようになったら、そちらの動画を撮ってのちのちリンクでも追加するかも。