こんにちは、プロジェクトマネージャの後藤です。
タイトルからしてかなりナゾな感じですが今回はビジュアルコーディングツールTouchDesignerを使ってマイコンから吐き出されるデータをいい感じに可視化してくれるツールを作りたいと思います。

目次
ビジュアルコーディングの使い所
組み込みソフト開発において各種センサがある場合、センサの値をモニタリングしたい状況が多々発生します。専用の各種ツールや自分でデバッグ用アプリを書く状況も多いかと思いますが、データが正しいかどうか判断するために可視化する部分が意外に面倒だったりします(例えば三軸加速度センサの出力から加速度ベクトルを可視化したい、とか)。
ビジュアルコーディングツールをつかうと比較的素早くこういったデータの加工、可視化ができます。

TouchDesignerについて
TouchDesignerはカナダのDerivative社の開発しているビジュアルコーディングツールで、ノード式のネットワーク(パッチと呼びます)を構築することで映像や音声、3Dなどのデータを高速で処理、可視化することができるツールです。
ハードコアなエンジニアの皆さんはノード系のツールは素人向けだろ!なんてお思いかもしれませんがいえいえ、ゲーム開発系ではUnrealEngineやUnityでのノード開発環境がメインストリームになりつつありますし、プログラミング環境とは少し違いますがHoudiniやGrashopperなどノード系モデリングツールもかなり普及してきました。
今回その中からTouchDesignerを選んだのはノードごとにデータが可視化されており、データ流れが直感的で分かりやすいためです。商用で使う場合は年間ライセンスを購入する必要がありますが、個人で使用する場合は無料ですし、同系のツールとしてはVVVVというツールもありますのでそちらも見てみてください。僕は前職がどちらかというと映像演出系だったためこういったツールを多用していました。
使い方
Step1: インストール
derivative.caからTouchDesignerをインストールしておきます。
また、インストール時にderivative.caにてアカウントを作成しておいてください。
TouchDesignerを起動します。
一番上部のメニューからDialogs>Key Managerを選択するとウィンドウが現れます。

UsernameとPasswordを入力してSign Inボタンを押すとログイン出来、1年間無料使用できるライセンスが付与されます。
Step2: シリアルデバイス
センサデータをシリアル経由で流せるデバイスを用意します。なんでもよいのですが、今回はその辺に転がっていたM5StickCを使いました。データは加速度センサの値AccX, AccY, AccZを取得することにします。今回はArduinoベースでM5StickCライブラリのexamples/Basics/IMU/IMU.inoにシリアル出力だけ追加しました。
センサからのデータ取得は適当に20Hzとし、吐き出すデータは各々カンマ区切り、LFまでで1パケット送信完了、通信速度は115200bpsにしました。サンプルコードより追加したのは実質これだけです。
Serial.printf("%f,%f,%f\n", accX, accY, accZ);
delay(50);

Step3: シリアルストリームの読み込み
TouchDesignerに戻ります。左側のPalleteウィンドウを閉じ、左ボタンドラッグでフィールド上にあるノード達を全て選択してDeleteしてください。
右ダブルクリックするとウインドウが表示されます。このウィンドウから必要なノードを選択して配置していきます。ノードは以下のような種類があります。なおTouchDesignerで扱うデータはGPU演算させる情報が多いため基本Floatとして扱われます。
- COMP: 各種コンポーネントが置かれている。UI用やウィンドウ制御等で使用
- TOP: テクスチャオペレータ、2Dテクスチャ情報を扱う各種オペレータ(ノード)
- CHOP: チャンネルオペレータ オーディオストリームなど1次元の情報を扱う
- SOP: サーフェースオペレータ 3Dデータを扱うオペレータ
- MAT: マテリアル情報を扱うオペレータ
- DAT: データオペレータ 数値情報をセル形式で扱うオペレータ
- Custom: カスタムノード類はここに置かれます。今回は関係なし

それではDATのタブからSerialを選んでください。

スクショのようにCOMポートを選び、BaudRateを115200とするとシリアルデータが流れ始めたのが確認できるかと思います。

Serialノードの右サイドのピンク色の出口側を右クリックするとまた先ほどのウィンドウが現れますのでSelect DATを選択して配置してください。
Select DATを選択し緑の枠がついた状態で右上のウィンドウにプロパティが表示されます。Select Rowsからby Indexを選択、Start Row Index 10, End Row Index 10としてください。データが一行だけ表示されましたか?

次にConvert DATを繋げ、Split Cells atの欄に前とスペースを空けてコンマ’,’を入れてください。ノード内のデータが別のセルに分割されたでしょうか?

Step4: トレイルを引く
同じようにConvert DATの出力を右クリックし、今度はCHOPタブからDAT toを選択します。

次にTrailノードを繋げ、Window Lengthを10くらいにします。ノードを選択した状態でキーボードから”D”を押すと背景にプレビューとして選択したノードが表示されます(もう一度Dを押すと表示が解除されます)。M5StickCを動かしてしてみてください。データの変化がいい感じにグラフ化されましたでしょうか?

さて、これだけでも結構便利なのですがよく見るとグラフはデータの最大値ー最小値にスケーリングされておりあまりよろしくありません。せっかく視覚表現に強いツールをいじっているのでその辺りもカスタマイズしてみましょう。
Step5: グラフの描画
今度はTrail CHOPの出力を右クリックし、SOPタブからTOP toを選択します。プロパティウィンドウからChannel Scopeをchan1に、次のAttribute ScopeからP(1)を選択します。

次にCOMPからGeometryを選びます。

MATタブからConstantオペレータを選択し、プロパティから適当な色を選択します。ConstantノードをGeometryタブにドラッグ&ドロップし、マテリアルとして設定します。


COMPタブからCamera、TOPタブからRenderを選択します。3D系のツールを触ったことのある方なら察していただけると思いますが、上記の手順にて3Dジオメトリをカメラを使って撮影しレンダリングしています。今回はマテリアルがConstantなので照明が無くても見た目が変わりませんが、通常は照明(Light COMP)も用意します。
Render TOPを選択してDを押すと背景にTOPの映像が表示されます。グラフが表示されたのですが位置とサイズが微妙なのでCameraCOMPを選択し、ScaleXを0.5にしました。こちらは表示されるデータに応じて調整してください。

ジオメトリCOMP、Material、chop to SOPをコピーして二つ用意しましょう。二段目と三段目のchop to SOPのプロパティ画面ではChannel Scopeをそれぞれchan2とchan3とすることでCHOPにある3つのチャンネルをそれぞれ選択するようにします。またそれぞれのマテリアル色を変えておくことで見分けが付くようにします。

グラフの線以外は透明なので背景が格子模様になっています。これだと見にくいのでConstant TOPで灰色の背景を作り、Over TOPの入力1つめをグラフ、二つめをConstantにすると下図のように見やすくなります。

Step6: ベクトルの描画
ついでに加速度ベクトルも表示してみましょう。trailに入る前のDAT to CHOPの出力を中ボタンクリック、または付近で左ダブルクリックしCHOPのNullを配置、DAT to出力を繋げます。Null CHOPをどこか空いているエリアにドラッグさせます。
Line SOPを配置し、プロパティ画面を開きます。

NullCHOPの右下をクリック(またはD)したうえでマウスオーバーするとノード内のデータが緑になり選択出来るようになります。

chan1をLineSOPのPointB Yに、chan2をPointB Xに、chan3をPointB Zにそれぞれドラッグし、CHOP Referenceを選択します。それぞれのフィールドにNullCHOPの値が参照・反映されます。

先ほど作成したGeometryCOMPとConstantMATのどれかをコピーしてもってきて、LineSOPからの出力を繋げます。

画面の真ん中に加速度ベクトルが赤線で表示されたでしょうか?おや、PointB Xに入れた値の方向が逆のようなのでフィールドにマイナスを追加しました。
カメラが正面に向いているためZ方向の回転は表示されませんがひとまず重力加速度に対応したベクトルを表示出来るようになりました。こういったカスタマイズ性やデータがリアルタイムに流れてくる中でパッチを組んでいけるTouchDesignerは映像表現だけでなくエンジニアリング用途にも便利なのではないかと思います。
なお今回のパッチはこちらからダウンロードできます。

おわりに
今回はグラフ表示させるだけでしたが、吐き出したデータをCSVに書き出したり、映像で保存したりすることももちろん可能です。
そのほか、TouchDesignerからできること(のほんの一部)には
- カメラ画像の取り込み、映像書き出し
- マルチチャンネルオーディオ入力/出力
- TCP/UDP通信
- NDIやRTSP
- Pythonスクリプティング
- C++でカスタムノード作成
などなどがあり非常に高機能なのですが、一方で処理が複雑になるとそれなりにGPUのパワーも消費しますので注意してください。
もしご興味があれば TDSWのYoutubeシリーズやBackSpaceTokyoの比嘉さんやBassdrumの森岡さんのチュートリアルなどが日本語でとても分かりやすいので参考にしてみてください。
それではまたー
Cerevoからのお知らせ
現在Cerevoでは各種エンジニアの採用、またハードウェア共同開発・受託開発を絶賛募集しております。それぞれご関心お持ちいただける方は、以下の専用お問い合わせフォームよりご連絡お待ちしております。
- 現在募集している職種
https://cerevo.com/recruit/
- ハードウェア共同開発および受託開発のご相談
https://cerevo.com/contact/sales/
著者プロフィール

- 開発部でプロジェクトマネージャをしています。