TouchDesignerからHoudiniへKinectの情報を持っていきたい

この記事はHoudini Apprentice Advent Calendar 2021　25日目の記事です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/0c9be56e-a009-05a2-3647-547fa0db1d09.png)


#HoudiniとTouchDesigner
HoudiniとTouchDesignerは兄弟のようなソフトで、どちらももとはPRISMSというソフトです。
この記事に、これまでの経緯含めて非常に詳しく載っています。非常に興味深いのでぜひ読んでほしい内容です。

https://tech-branch.9999ch.com/archives/609
https://tech-branch.9999ch.com/archives/917

また、Houdiniアドベントカレンダーが毎年行われている時を同じくして、
TouchDesigner Advent Calendarも毎年精力的に実施されています。ユーザーがコミュニティを盛り上げようとする文化も非常に似ているように感じています。
https://qiita.com/advent-calendar/2017/touchdesigner
https://qiita.com/advent-calendar/2018/touchdesigner
https://qiita.com/advent-calendar/2018/touchdesigner
https://qiita.com/advent-calendar/2019/touchdesigner
https://qiita.com/advent-calendar/2020/touchdesigner
https://qiita.com/advent-calendar/2021/touchdesigner

UIも非常に似通っており、Houdiniを普段から慣れ親しんでいれば、「これ見たことある！」という～OPなインターフェースになっています。

##背景

なぜHoudiniアドベントカレンダーなのにTouchDesignerの話をするかというと、フェイシャルやモーションキャプチャ周りの技術を調べている際にOSCや、Kinectの情報取得が非常に簡単に容易にCHOPに落とし込めるという情報を知り、そのデータをHoudiniに持ってこれたら面白そうだなと思ったのがきっかけです。

最近ではウマ娘のモーションキャプチャスタジオが話題となりましたが、
https://www.youtube.com/watch?v=nBg-FJtBi0A
個人勢ではとても太刀打ちできないので（高額なモーションアクタースーツも無理なので）手元にあったAzure Kinectでどこまでできるのか検証したかったことも背景にあります

##Houdiniでモーションキャプチャのデータを取り扱う場合

話の腰を折るようですが、Houdiniでモーションキャプチャを本格的に行う場合は、最近追加されたmocapstreamを利用する方が無難かと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/3157c4eb-97e8-6fcb-32bd-194ea6c7d3a8.png)


もしくは普通にAcclaim(.amc、.asf)ファイル、BioVision(.bvhファイル)、MotionAnalysic(trcファイル)をmocapimportで読み込んでKineFXでリターゲティングを行うのが一般的かと思います。

よって、AzureKinect　→　Touchdesigner　→　Houdini　という手法は必ずしも簡単で便利というわけではないことについてはご了承ください。HoudiniにAzureKinectSOPがあったならそれで終わりなのですが、現状はTouchDesignerにしかありません。

あとはHoudiniとTouchDesignerとのデータ接続は以前からみんなどうやっているんだろうという技術的な好奇心も背景の一つです。

##AzureKinectの準備
まずはAzureKinectを用意します。
https://www.microsoft.com/en-us/d/azure-kinect-dk/8pp5vxmd9nhq?activetab=pivot:overviewtab
在庫がずーーっとなかったのですが、、今は買えるのかな？フォームは入力できる状態になっています。

https://docs.microsoft.com/ja-jp/azure/kinect-dk/body-sdk-download

からSDKをダウンロードします
現時点では1.1.0が最新のようです
https://www.microsoft.com/en-us/download/details.aspx?id=102901

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/534e856e-069c-8dd3-cc6b-6c936567bb09.png)

インストールするとWindowsの場合
C:\Program Files\Azure Kinect Body Tracking SDK\tools
にk4abt_simple_3d_viewer.exe　で動作を確認します、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/ae7e2362-a09f-d5a2-e6cc-0e46cedc4967.png)

※ＮＶＩＤＩＡのドライバは最新のものに更新しておく必要があります。

動いた！

#これをHoudiniに持っていきたいけど、、、

他の人のケースを見ると

processing経由でHoudiniのPipeInCHOPに接続するケース
※引用：Processingスケッチによって作成されたサーバーに接続するPipe InChopを使用してこの情報を収集できます。
https://vimeo.com/98992198

kinectのデータは別どりで行ってローカルで保存したモーションキャプチャデータを読込みKineFXで調整する方法
https://www.youtube.com/watch?v=7mdiVu069Ss

TouchDesignerとHoudiniの連携
これはHoudini→TouchDesignerのオブジェクト連携の事例ですが、hclassic拡張子での受け渡し
https://qiita.com/snafkinliberty/items/2dbf4b7066754eb99036

PipeIn / PipeOutTDからHoudiniへ
最も簡単な方法は、touchdesignerで使用し、必要に応じてチョップストリームをhoudiniにパイプすることです。
https://forum.derivative.ca/t/pipein-pipeout-from-td-to-houdini/5702


結局OSCで？
HoudiniのOpenSoundControl（OSC）
https://www.sidefx.com/forum/topic/21313/

色々調べた結果TouchDesiner経由でHoudiniに持っていくのが簡単では？とその時は判断して調査を始めました。

#TouchDesinerPipeOUT→HoudinhiPipeOUT
TouchDesiner側でKinectを受信できる環境を整えてKinectAzureSOP　→　KinectAzureCHOP　→　PipeOUT
として準備しました。Houdini側もPipeInを用意して準備万端。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/37d31c4c-ec88-cd85-7b28-20f31fab93e1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/62cf6767-79fb-7d04-94c6-1603f9e26a11.png)

ポートは何番でもいいですが、Houdini側と合わせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/b21bd886-7985-1527-b305-4c72e380d2e6.png)

これがサーバー側で

Houdini側はCHOP内にPipeInを用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/00c7a4bd-a4d8-3b29-641d-43ca17634a54.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/d532522d-1883-78e7-a8c2-01e349498a64.png)

しかし、、、
コンソールエラーに謎の文字列の無限ループ
Unknown command type: 2319389199166349360
が出て動きません。それどころかHoudiniがハングアップします。
![nanikore.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/afe57dec-04a3-2aff-7269-a289bf79a625.png)

どうやらそのままでは動かないようです。


##HoudiniのPipeInPipeOUTを整理する

そもそも。このPipeIn、PipeOutはどのような情報がやり取りされているのでしょうか。
ヘルプを見ると。

>　Houdini開発キットがなくても、またHoudiniの内部を知らなくても、独自のデバイスから吐き出されたデータをCHOPに繋げることができます。
>　LinuxとMac OS Xの“named pipe”または“FIFO”(First In, First Out)を使用することができます(man -S 7 pipeを参照)。 または、Windows, Linux, Mac OS Xのネットワーク接続(リモート接続用)を使用することができます。
>　入力デバイスから値を取得し、FilenameまたはNetworkポートで指定したファイルにそれらの値を出力するプログラムが必要です。 あなたが書いたプログラムは、書式化されたメッセージをそのファイルやポートに書き出し、Pipe In CHOPは、そのメッセージを読み込んで、 そのメッセージで指定されたチャンネルを作成します。

とあります。
man -S 7 pipeって何よ？ということで調べに行きます。
http://linuxjm.osdn.jp/html/LDP_man-pages/man7/pipe.7.html
http://linuxjm.osdn.jp/html/LDP_man-pages/man2/pipe.2.html

https://ja.wikipedia.org/wiki/%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%91%E3%82%A4%E3%83%97

##pipe - パイプと FIFO の概要  
パイプと FIFO (名前付きパイプともいう) は、 単方向のプロセス間通信チャネルを提供する。 パイプには「読み出し側」と「書き込み側」がある。 パイプの書き込み側で書き込まれたデータは、 パイプの読み出し側から読み出すことができる。
パイプを作成するには pipe(2) を使用する。 pipe(2) は新しいパイプを作成し、ファイルディスクリプターを二つ返す。 ディスクリプターのうち、一方はパイプの読み出し側を、もう一方は 書き込み側を参照している。 パイプは関連するプロセス間の通信を作成するのに使用できる。 例は pipe(2) を参照。

FIFO (First In First Out の省略) はファイルシステムでの名前を持ち、 open(2) を使ってオープンできる (mkfifo を使って作成される)。 どんなプロセスでも、ファイルのアクセス許可があれば FIFO をオープンする ことができる。 読み出し側をオープンするには O_RDONLY フラグを使用し、書き込み側をオープンするには O_WRONLY フラグを使用する。


##PIPE書式

```c
#include <unistd.h>

/* On Alpha, IA-64, MIPS, SuperH, and SPARC/SPARC64; see NOTES */
struct fd_pair {
long fd[2];
};
struct fd_pair pipe();

/* On all other architectures */
int pipe(int pipefd[2]);

#define _GNU_SOURCE             /* feature_test_macros(7) 参照 */
#include <fcntl.h>              /* O_* 定数の定義の取得 */
#include <unistd.h>

int pipe2(int pipefd[2], int flags);
```

- 配列 pipefd ：パイプの両端を参照する二つのファイルディスクリプターを返すのに使用される。 
- pipefd[0] ：パイプの読み出し側
- pipefd[1] ：パイプの書き込み側

パイプの書き込み側に書き込まれたデータは、 パイプの読み出し側から読み出されるまでカーネルでバッファーリングされる。 らしい。

###Windowsでは
Windowsでは、名前付きパイプはクライアントサーバ型通信に基づいて設計されており、通常の読み書き操作以外にソケットのようにも働く。サーバアプリケーションのための明示的な「受動」モードを備えている。Windows 95 では名前付きパイプのクライアントをサポートしている。Windows NT 系OSではクライアントとサーバの両方をサポートしている。

名前付きパイプはファイルのようにアクセスでき、Win32 SDK の CreateFile（オープン）、ReadFile（リード）、WriteFile（ライト）、CloseHandle（クローズ）が使える。Unix系のようなコマンドラインインタフェースは存在しない。

Unix系とは異なり、通常のファイルシステム内に作成することはできない。また永続性もなく、オープンしていたものが全てクローズすると消滅する。全てのパイプは named pipe filesystem (NPFS) のルートディレクトリに置かれ、\\.\pipe\ という特別なパスにマウントされる（つまり、"foo" という名前付きパイプのパス名は "\\.\pipe\foo" となる）。無名パイプも実際にはランダムな名前の名前付きパイプとして実装されている。

ということは、Houdiniのpipe読み込みはLinuxとmacだけってこと？


うん。仕様はなんとなくわかった。でHoudiniで使うにはどうすれば？
もう一度Houdiniのヘルプを見に行きます。

#Pipe In CHOPのプログラミング
Pipe In CHOPは、2つのパラメータを持ち、3つのコマンドフォーマットを解読します。 1番目のパラメータには、読み込むファイルを指定し、2番目のパラメータは、アクティブモード(読み込み)と非アクティブモード(データの破棄)をトグルします。 サポートされているフォーマットは、以下の機能です:

- 最新のサンプルデータをアップロード
- すべてのサンプルデータをアップロードして完全な波形を作成
- チャンネル名をアップロード


odforceにいいスレッドがないか探しましたが、、
https://forums.odforce.net/topic/15067-pipe-in-fifo-file/

PythonでOpenCVの顔認識を行って、pipeInにデータを流し込んでいる人がいました！
https://www.youtube.com/watch?v=-BUVpvGpNus
しかし、networkではなく、tmp/chop2pipe　を参照しています。
![chop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/044247b6-6874-bef8-7f02-49335a0c9882.png)

よけいわからん。


わからん・・・・。

それを探るため、Houdiniを２つのWindowで立ち上げて、Housiniから別のHoudiniにnoiseを飛ばす検証を行います。
![pipechop.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/7836a01f-49f2-9a97-d2e5-07729fcb7dbe.gif)

動いている。。！！
localhost間でポートをしっかり合わせる。
PipeOut側が疎通確認を行っている状態で、PipeInのActiveを切り替えると、TCP/IPのaccept→connectが通り、通信が始まります。

Wiresharkで通信内容を覗いてみます。
※Wiresharkは、LAN上に流れているパケットを「見える化」するパケットキャプチャツールです。
https://www.wireshark.org/download.html

![wire.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/c46d3a44-892d-248d-f441-5952b75ffcee.png)

PipeIn PipeOutの通信がTCPで行われていることが確認できます。
しかしdataはセグメント化されているのか、値までは確認できません。

もう一度odforceの議論を振り返ってみます
https://forums.odforce.net/topic/15067-pipe-in-fifo-file/

14時現在執筆中
お待ちください　すみません