はじめに
こんにちは! Future Standardでエンジニアとしてインターンをしている長瀬です。
弊社は映像解析プラットフォームSCORERを開発しており、SCORERに利用できそうなデバイス・SDKの調査も行っています。今回はその一環として、Scanse社の超小型LiDARデバイスSweepを使ってみました。
Sweepとは
動画のように、LiDARセンサが360°高速回転(1[Hz]~10[Hz])することで、センサの周囲にある物体までの距離を計測できるというデバイスです。計測可能距離は最大40[m]で、24畳程度までの広さの部屋をセンシングできることになります。
弊社はRaspberry Pi + カメラで歩行者検知をするソリューションを提供していますが、SweepはRaspberry Pi, GoProと組み合わせることで歩行者を追従して撮影できるようです。
Sweepを使った開発
Sweepはシリアルインターフェイスを持っており、Arduino, mbed, Raspberry Pi等と接続して使えます。シリアル通信についてはこちらのデータシートにまとまっていました。また、ROS用のドライバも提供されています。
用途によってはシリアルで直接やり取りしてもいいですが、Arduino, C, Node.js, PythonにはSDKが提供されています。SDKを使うとサクッとLiDARを使ったアプリケーションが開発できます;)
Sweep SDKを使った開発
Sweep SDKは、下図のようにC/C++で書かれたlow-level ABIと、それを各プログラミング言語向けにラップしたAPIで構成されています。
CMakeを利用したクロスプラットフォームビルドに対応しており、Windows/Mac OS/Linuxで利用できます。ビルド時にDUMMYモードを指定すると、実測値ではなくダミーデータを返してくれるモードでビルドできます。実機がなくても開発できるため便利です。
Docker HubにSDK用のDockerイメージが公開されているのですが、先ほどのデータシートやGitHubリポジトリからリンクされておらず、イメージのタグもtestのみという状態だったので今回は利用しませんでした。(普通にインストールしました。)
Node.jsからこういったデバイスを制御できるのは斬新だなと思い、今回はsweepjsを使ってみることにしました。
sweepjsでテルミンをつくる
Sweepをしばらく触っていて、Sweepならテルミンが作れるのではないかと思いました。テルミンは、こうして両手を楽器に近づけたり離したりして音量・音程をコントロールする電子楽器です。
Sweepで取れる点群のうち、ある2直線上にある点群に注目し、それらの動きを見ることで音量・音程を調整できるのではないかという算段です💪 今回の記事(#1)では、まず音の高さが変えられるようにしたいと思います。
今回作ったアプリケーションはこちらで公開しています。記事の更新に合わせてリポジトリも更新していきます✌
アプリケーションの構成
sweepjsのリポジトリを見ると、WebSocketを使ったサンプルアプリがあります。このアプリケーションではWebsocketサーバを立ち上げ、Sweepから取得したデータを一定間隔でクライアントに送っています。テルミンのアプリケーションでもこの構成を利用してみることにします。
Websocketサーバ側はNode.js, クライアント(テルミン)側はangular-cli(Angular4, Jasmine, Protractor等のフレームワーク+Webpackな環境でWebアプリを開発するためのcliツール)で実装します。
サーバサイド
サーバサイドは、ただsweepのデータを送るだけです。しかし、ここで知見というかハマったポイントがありまして、sweepから取得できる点群の角度の値はmilli degreeで返ってきます。sweepのデータシートにはこの旨がきちんと書いてあるのですが、前述のWebsocketのサンプルアプリにさもそのままx, y座標上の位置に変換できるように書いてありハマってしまいました…
sweepjsもsweepyもそうなんですが、サンプルアプリがlibsweepのものに比べて簡素です。そのため、「データを取得した後どういう後処理をすればいいんだ*1」「コンソールに測定データを出力するだけのサンプルしかないの*2」となった場合には、libsweepやそのサンプルアプリのコードを見ると参考になるかと思います。
クライアント(テルミン)
クライアント側のアプリケーションは、サーバから送られてきた点群のデータを元に以下のことをします。
1. 点群の可視化
点群を3Dマップにプロットして、グリグリ動かして見られるようにします。3D表現のためにThree.jsというWebGLライブラリを使いました。
2. sweepのステータスの表示
sweepの回転スピード, サンプリングレート, etc… が取得できます。これらのステータスを確認できるようにします。もちろんAPI経由でこれらの値を変更することも出来ますが、それは次回以降の記事でできるようにしていきます。
3. 点群の状態によって音を鳴らす
今回は音の高さだけを変えるため、sweepから最も近い点との距離で音の高さを変えます。sweepの周りに何も置かなければ、自分の手との距離で音の高さが変わるようになるはずです。今出している音の周波数と、sweepとsweepから一番近い点との距離は確認できるようにします。
Webページ上での音の加工・再生にはWeb Audio APIを使います。音量・音高の調整はもちろん、音色を加工したりエフェクトをかけたりすることも簡単に出来ます。
画面構成
アプリケーションの画面構成はこんな感じです。
コードを見ていただくとわかりますが、コンポーネントは2つしか用意していません。SweepやWeb Audio APIのためのServiceもありません。(Angular界隈からのマサカリが怖いです…)
この辺りのリファクタリングとコンポーネント毎のユニットテストは、機能が増えていく次回以降に逐次やっていきます。
動かしてみて
実際に動かすとこんな感じです。
レスポンスが遅すぎるとか、音色がブザーみたいで怖いとかマサカリが飛んできそうなんですが、次回以降の投稿に期待してください!
sweepをお持ちでない方も、SDKをインストールすればダミーデータで遊ぶことができます。(ダミーデータはsweepからの距離が一定なので、ずっと同じ音が鳴りますが…)
所感として、
- sweepから一番近い点との距離を使おうとしたら、何故かsweepの周囲1[cm]くらいのところに3つくらい点が観測されてしまった。
- クライアント側で
filter()
し、あまりにもsweepから近い点は除外しました。
- クライアント側で
- Websocketで送っている分のタイムラグがあり、手を近づけたり離したりしてもなかなか音やヴィジュアライザに反映されない。
ということがありました。
次回以降の記事でやること
次回以降にやることは以下です。
- タイムラグ問題の解決
- サンプリングレート, 回転スピードを変更できるようにする
- 音色を変更できるようにする
- リファクタリング(Componentの分割, Serviceの作成など)
- テスト
引用動画
Theremin - Sounds aus dem Ur-Syntheziser | MDR [16.01.2014] - YouTube (https://youtu.be/Vf7sHLtOdos?t=5m2s)
(追記) Sweepが故障した!
記事の執筆中に突然、Sweepがおかしなデータを送るようになりました:( おかしなデータを送るタイミングでステータスLEDが赤く点灯するため、Sweepのフォーラムに問い合わせてみました。
すると直接サポートに連絡するように言われ、連絡したところすぐに対応してもらい、repair kitなるものを送ってもらうことになりました。repair kitはスリップリングの交換部品で、取り替えた所無事に修理出来ました。同様の症状が見られる方の参考になれば幸いです。