👌

mocopiの通信内容を解析してみた Vol.01

2023/01/23に公開約18,700字

1月20日(金)に慣性式のモーションキャプチャデバイス(とアプリ)mocopiが発売されました。
SONYという大手メーカが販売しており、流通もしっかりしていそうなこと、デバイスが全部で6つと装着の手間が少ないこと、価格が5万円とモーションキャプチャデバイスとしては低価格であること、単体で完結せずVRChatやUnityなどとの連携も想定していることなどからある程度のマーケットを構築しそうです。

開発関連ドキュメントやSDK・プラグインの状況

mocopiは低価格のモーションキャプチャであり、色んなソフトで使えそうですが、1月23日現在連携可能な環境は限られています

  • VRChat
  • Unity
  • Motion Builder

また、SDKは近日提供予定とのことですが、こちらはMobile App用のSDKということで恐らくmocopiデバイスの値を直接受けて動作するスマホアプリの開発のためのSDKと想定されます。
そのため、UnrealEngineなどの他のゲームエンジンやBlenderなどの他のプリレンダソフトとの連携との直接的な連携を考えた場合、自作する必要があります。
mocopiはデバイスのモーションデータをスマホアプリで受け、データを加工してPCにネットワーク経由でストリーミングすることができます。このストリーミングされている通信パケットの仕様は現在開発者サイトには公開されていませんが、この通信内容を解析して仕様を明らかにすれば、PCの受信側は開発者やクリエイターが各々得意なツールに持ち込むプラグインやインターフェースを用意することができる筈です。

通信内容を解析してみた

ということで独自プラグインが作れるように通信仕様を把握するべく、パケットをキャプチャしてみました。

#\x00\x00\x00head\x12\x00\x00\x00ftypsony motion format\x01\x00\x00\x00vrsn\x01\x1a\x00\x00\x00sndf\x08\x00\x00\x00ipad\x17\x0c1\r(\x00\x00\x00\x02\x00\x00\x00rcvp?0\xd2\x05\x00\x00fram\x04\x00\x00\x00fnumq\x13\x00\x00\x04\x00\x00\x00timez\x9c\xc7N\xb2\x05\x00\x00btrs.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x00\x00\x1c\x00\x00\x00tranu@Q\xbe=\xf0\xc9=\xf7T\x7f=\xed\xcfx?\x8a\xfa\x05\xbf\xdc\xa57?9"?\xbf.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x01\x00\x1c\x00\x00\x00tran?,k=\x80\x17\x86\xbb\x9f\xf6a\xbc\x19\x8d\x7f?\x00\x00\x00\x00\xa1\x02J=\x9507\xbc.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x02\x00\x1c\x00\x00\x00tran\xcccZ=\x01\xd6\xb9\xbbU\x88\x14\xbc\x07\x9f\x7f?\x00\x00\x00\x00Rh_=\x13x*<.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x03\x00\x1c\x00\x00\x00tran\x8cnX=X2\xcf\xbb^v\xa8\xbbD\xa2\x7f?\x05D\xeb\x9f#@n={c\x92:.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x04\x00\x1c\x00\x00\x00tran\x0fC[=\x0e\xf5\xcf\xbb\xef!>\xba\xb2\xa0\x7f?/E\xfd\x9fsc\x81=\x15"\x8d\xbb.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x05\x00\x1c\x00\x00\x00tranc5>=\x1ev\xb9\xbb\x11];\xdd\xb7\x7f?V1b\xa0+B\x97=\x91\x99o\xbc.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x06\x00\x1c\x00\x00\x00tran=\x1d8=\x92\xea\xe0\xbb\x97\xc3\xed;}\xba\x7f?O4\x91\xa0n\xe2\xbc=\x04\x80\x11\xbc.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x07\x00\x1c\x00\x00\x00tran\xf4)\x0c:\xcf\x86m\xb9\xa5\xcc\xb09\xfc\xff\x7f?\xccw\xa6\xa0\x9a\xd8\xd1=\xc8\xe4z<.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x08\x00\x1c\x00\x00\x00tran\x9c\xdb)=m\xfe-=\xa7\x9dY<\xa0\x86\x7f?\xaa\x1d\x14\xa0\xedb>=\xa7\xa0\xe3;.\x00\x00\x00btdt\x02\x00\x00\x00bnid\t\x00\x1c\x00\x00\x00tran\xd2Z\x80\xba\x0bI\x9c<\x9drm<(\xed\x7f?\xe6\xb1O\xa0\xb6\xc3?=\xbf7\x86;.\x00\x00\x00btdt\x02\x00\x00\x00bnid\n\x00\x1c\x00\x00\x00tran\xa7\xc5\x0f=\x8c\x85i<\xfc\xcb\x89<\xad\xc7\x7f?\x8edf\xa0\xa2"@=.s\xf3;.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x0b\x00\x1c\x00\x00\x00tran^\xfd\xf2\xbbx\xe2\x03\xbdh\x96\xea<S\xc1\x7f?\xbf,D<xK\x97\xbd\xf1\xd4\x95=.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x0c\x00\x1c\x00\x00\x00tran?(\xd8=\x95\xe3\xfa\xbej\x14\x06\xbfvT0?\x81\xd2\x00>\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00btdt\x02\x00\x00\x00bnid\r\x00\x1c\x00\x00\x00tran:\x04\xa69\x1d\xac\x96\xbe3\tz=\x15*t?&9\x91>\x82@\x18:\xaem\xae:.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x0e\x00\x1c\x00\x00\x00tran0\x98\xa4\xbe\x80J\x92\xbc\x91p\x81<\x94Ur?\xc9\xfbp>\x83\xa4\xfc98\xb9\x90:.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x0f\x00\x1c\x00\x00\x00tran=\xcf"\xbd\xe7[-=\x98L\x8e\xbd\xc9\xf2~?\xbf,D\xbceK\x97\xbds\xd4\x95=.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x10\x00\x1c\x00\x00\x00tran\x127\x8f\xbe\x06B\x95>\xb57\xfd>\x0f\x00E?\x81\xd2\x00\xbe\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x11\x00\x1c\x00\x00\x00tran\xd2X\xdc9\\\x98\xc8>aq\xa6\xbd\x12\x9dj?&9\x91\xbe\x82@\x18:\xaem\xae:.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x12\x00\x1c\x00\x00\x00tran\xf6\xe6\x0c>\xd4\xae\x9b;g\x1f"\xbd\x05\\}?\xc9\xfbp\xbeL\xa4\xfc9B\xb9\x90:.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x13\x00\x1c\x00\x00\x00tran\xf5\xbbg\xbec\xb3\xe1=\x1d\xc43>\xb6\xa5s?v\xb3\xb7=\xfcG\'\xbd\xc9\xb4\xa1<.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x14\x00\x1c\x00\x00\x00tranAj\xfd>T\x8c\r\xbcM\xd3\x07\xbeX\xd3[?\x05\x9d\x07\xbc\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x15\x00\x1c\x00\x00\x00tranflo\xbd\xdf_\x07>\'a\x88<\x8dF}?h\x0e\xb9\xbc\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x16\x00\x1c\x00\x00\x00tran\x00\x00\x00\xa3\x00\x00\x00 \x00\x00\x00!\x00\x00\x80?i\xea\xf7;\xf4\x94\xc4\xbd \x85\xf8=.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x17\x00\x1c\x00\x00\x00tran\xdf\xb3\x98\xbeY\x8cn>\x04\x9c?\xbba\xf5l?v\xb3\xb7\xbd\xfcG\'\xbd\xc9\xb4\xa1<.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x18\x00\x1c\x00\x00\x00tran\x946\xd6>\x95M\xef;\xc3\xa0\xe5="\xbbf?\x05\x9d\x07<\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x19\x00\x1c\x00\x00\x00tran\x9b\xe8\xc5<n\xd7\x00\xbe\x919\xec\xbcj\xc8}?h\x0e\xb9<\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00btdt\x02\x00\x00\x00bnid\x1a\x00\x1c\x00\x00\x00tran\x00\x00\xbc\xa2\x00\x00\xa5\x00\x00\x00\xa2\x00\x00\x80?k\xea\xf7\xbb\xf4\x94\xc4\xbd \x85\xf8=

mocopiアプリからの通信はUDPで行われており、基本的には1575byteの固定長で通信されているようです(あとは1821Byteの数秒ごとに送られるデータもあります)。
UDP通信ということはパケットロストの可能性などもあるし、送達確認もできないため恐らく初期情報などはなく、毎回送られるパケット情報である程度完結して処理できるものなのかと思います。

キャプチャしたパケットにヘッダのように頻出するデータがありそうなのでタグっぽいところごとに改行してみました。

#\x00\x00\x00
head\x12\x00\x00\x00ftyp
sony motion format\x01\x00\x00\x00
vrsn\x01\x1a\x00\x00\x00
sndf\x08\x00\x00\x00
ipad\x17\x0c1\r(\x00\x00\x00\x02\x00\x00\x00
rcvp?0\xd2\x05\x00\x00
fram\x04\x00\x00\x00
fnumq\x13\x00\x00\x04\x00\x00\x00
timez\x9c\xc7N\xb2\x05\x00\x00
btrs.\x00\x00\x00btdt\x02\x00\x00\x00

bnid\x00\x00\x1c\x00\x00\x00
tranu@Q\xbe=\xf0\xc9=\xf7T\x7f=\xed\xcfx?\x8a\xfa\x05\xbf\xdc\xa57?9"?\xbf.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x01\x00\x1c\x00\x00\x00
tran?,k=\x80\x17\x86\xbb\x9f\xf6a\xbc\x19\x8d\x7f?\x00\x00\x00\x00\xa1\x02J=\x9507\xbc.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x02\x00\x1c\x00\x00\x00
tran\xcccZ=\x01\xd6\xb9\xbbU\x88\x14\xbc\x07\x9f\x7f?\x00\x00\x00\x00Rh_=\x13x*<.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x03\x00\x1c\x00\x00\x00
tran\x8cnX=X2\xcf\xbb^v\xa8\xbbD\xa2\x7f?\x05D\xeb\x9f#@n={c\x92:.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x04\x00\x1c\x00\x00\x00
tran\x0fC[=\x0e\xf5\xcf\xbb\xef!>\xba\xb2\xa0\x7f?/E\xfd\x9fsc\x81=\x15"\x8d\xbb.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x05\x00\x1c\x00\x00\x00
tranc5>=\x1ev\xb9\xbb\x11]`;\xdd\xb7\x7f?V1b\xa0+B\x97=\x91\x99o\xbc.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x06\x00\x1c\x00\x00\x00
tran=\x1d8=\x92\xea\xe0\xbb\x97\xc3\xed;}\xba\x7f?O4\x91\xa0n\xe2\xbc=\x04\x80\x11\xbc.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x07\x00\x1c\x00\x00\x00
tran\xf4)\x0c:\xcf\x86m\xb9\xa5\xcc\xb09\xfc\xff\x7f?\xccw\xa6\xa0\x9a\xd8\xd1=\xc8\xe4z<.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x08\x00\x1c\x00\x00\x00
tran\x9c\xdb)=m\xfe-=\xa7\x9dY<\xa0\x86\x7f?\xaa\x1d\x14\xa0\xedb>=\xa7\xa0\xe3;.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\t\x00\x1c\x00\x00\x00
tran\xd2Z\x80\xba\x0bI\x9c<\x9drm<(\xed\x7f?\xe6\xb1O\xa0\xb6\xc3?=\xbf7\x86;.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\n\x00\x1c\x00\x00\x00
tran\xa7\xc5\x0f=\x8c\x85i<\xfc\xcb\x89<\xad\xc7\x7f?\x8edf\xa0\xa2"@=.s\xf3;.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x0b\x00\x1c\x00\x00\x00
tran^\xfd\xf2\xbbx\xe2\x03\xbdh\x96\xea<S\xc1\x7f?\xbf,D<xK\x97\xbd\xf1\xd4\x95=.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x0c\x00\x1c\x00\x00\x00
tran?(\xd8=\x95\xe3\xfa\xbej\x14\x06\xbfvT0?\x81\xd2\x00>\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\r\x00\x1c\x00\x00\x00
tran:\x04\xa69\x1d\xac\x96\xbe3\tz=\x15*t?&9\x91>\x82@\x18:\xaem\xae:.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x0e\x00\x1c\x00\x00\x00
tran0\x98\xa4\xbe\x80J\x92\xbc\x91p\x81<\x94Ur?\xc9\xfbp>\x83\xa4\xfc98\xb9\x90:.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x0f\x00\x1c\x00\x00\x00
tran=\xcf"\xbd\xe7[-=\x98L\x8e\xbd\xc9\xf2~?\xbf,D\xbceK\x97\xbds\xd4\x95=.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x10\x00\x1c\x00\x00\x00
tran\x127\x8f\xbe\x06B\x95>\xb57\xfd>\x0f\x00E?\x81\xd2\x00\xbe\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x11\x00\x1c\x00\x00\x00
tran\xd2X\xdc9\\x98\xc8>aq\xa6\xbd\x12\x9dj?&9\x91\xbe\x82@\x18:\xaem\xae:.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x12\x00\x1c\x00\x00\x00
tran\xf6\xe6\x0c>\xd4\xae\x9b;g\x1f"\xbd\x05\}?\xc9\xfbp\xbeL\xa4\xfc9B\xb9\x90:.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x13\x00\x1c\x00\x00\x00
tran\xf5\xbbg\xbec\xb3\xe1=\x1d\xc43>\xb6\xa5s?v\xb3\xb7=\xfcG'\xbd\xc9\xb4\xa1<.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x14\x00\x1c\x00\x00\x00
tranAj\xfd>T\x8c\r\xbcM\xd3\x07\xbeX\xd3[?\x05\x9d\x07\xbc\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x15\x00\x1c\x00\x00\x00
tranflo\xbd\xdf_\x07>'a\x88<\x8dF}?h\x0e\xb9\xbc\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x16\x00\x1c\x00\x00\x00
tran\x00\x00\x00\xa3\x00\x00\x00 \x00\x00\x00!\x00\x00\x80?i\xea\xf7;\xf4\x94\xc4\xbd \x85\xf8=.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x17\x00\x1c\x00\x00\x00
tran\xdf\xb3\x98\xbeY\x8cn>\x04\x9c?\xbba\xf5l?v\xb3\xb7\xbd\xfcG'\xbd\xc9\xb4\xa1<.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x18\x00\x1c\x00\x00\x00
tran\x946\xd6>\x95M\xef;\xc3\xa0\xe5="\xbbf?\x05\x9d\x07<\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x19\x00\x1c\x00\x00\x00
tran\x9b\xe8\xc5<n\xd7\x00\xbe\x919\xec\xbcj\xc8}?h\x0e\xb9<\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00
btdt\x02\x00\x00\x00

bnid\x1a\x00\x1c\x00\x00\x00
tran\x00\x00\xbc\xa2\x00`\x00\xa5\x00\x00\x00\xa2\x00\x00\x80?k\xea\xf7\xbb\xf4\x94\xc4\xbd \x85\xf8=

パケットキャプチャを見ていると1回のメッセージの中でbnidとtranが27個入っており、mocopiの技術仕様を見る限りmocopiの想定するスケルトンのボーンの数も27個であることから、これが恐らくモーションデータとボーンのIDになっているのかな、と推測できます。BoneIDがbnid、Transform Dataがtran、みたいな。

tranがモーションデータの本丸のようですが、どのような形式で値が入っているのかさらに調べてみます。
tranのタグの後は大体どれも28バイトのバイナリがくっついています。Unity側のプラグインのスクリプトを見ると角ボーンのデータはクォータニオン4つ(XYZW)と位置情報3つ(XYZ)を持っているようなので7個x4byte=28byteということでパケットのデータと一致します。ということで32bit(4byte)のFloatがtranの後に7つ連続して入っているのでは、と予想できます。
数字の変換はリトルエンディアンかビッグエンディアンかで全然結果が変わってしまうのでどちらも試してみました。リトルエンディアンだと全般的に「これ計算で使えないやろ!」的なあり得ない数字が出てきたのでビッグエンディアンだと推定できます。

id:0
b'u@Q\xbe=\xf0\xc9=\xf7T\x7f=\xed\xcfx?\x8a\xfa\x05\xbf\xdc\xa57?9"?\xbf.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.20434744656085968, 0.09860274940729141, 0.062336888164281845, 0.9719226956367493, -0.523354172706604, 0.7173745632171631, -0.7466159462928772)

id:1
b'?,k=\x80\x17\x86\xbb\x9f\xf6a\xbc\x19\x8d\x7f?\x00\x00\x00\x00\xa1\x02J=\x9507\xbc.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.05741524323821068, -0.004092156887054443, -0.013791709206998348, 0.9982467293739319, 0.0, 0.049318913370370865, -0.011181016452610493)

id:2
b'\xcccZ=\x01\xd6\xb9\xbbU\x88\x14\xbc\x07\x9f\x7f?\x00\x00\x00\x00Rh_=\x13x*<.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.053317829966545105, -0.0056712632067501545, -0.009065707214176655, 0.9985203146934509, 0.0, 0.054542846977710724, 0.010404604487121105)

id:3
b'\x8cnX=X2\xcf\xbb^v\xa8\xbbD\xa2\x7f?\x05D\xeb\x9f#@n={c\x92:.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.05283980071544647, -0.006323140114545822, -0.005141063593327999, 0.9985697269439697, -9.963890017743018e-20, 0.058166634291410446, 0.0011168563505634665)

id:4
b'\x0fC[=\x0e\xf5\xcf\xbb\xef!>\xba\xb2\xa0\x7f?/E\xfd\x9fsc\x81=\x15"\x8d\xbb.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.053530748933553696, -0.006346351467072964, -0.0007252981304191053, 0.99854576587677, -1.0726412248258248e-19, 0.06317796558141708, -0.00430704141035676)

id:5
b'c5>=\x1ev\xb9\xbb\x11]`;\xdd\xb7\x7f?V1b\xa0+B\x97=\x91\x99o\xbc.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.04643763229250908, -0.005659832619130611, 0.0034235159400850534, 0.9988992810249329, -1.915926850034804e-19, 0.07385667413473129, -0.014624015428125858)

id:6
b'=\x1d8=\x92\xea\xe0\xbb\x97\xc3\xed;}\xba\x7f?O4\x91\xa0n\xe2\xbc=\x04\x80\x11\xbc.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.04494975879788399, -0.00686390046030283, 0.007255982141941786, 0.9989393353462219, -2.459857039407064e-19, 0.09222875535488129, -0.008880618959665298)

id:7
b'\xf4)\x0c:\xcf\x86m\xb9\xa5\xcc\xb09\xfc\xff\x7f?\xccw\xa6\xa0\x9a\xd8\xd1=\xc8\xe4z<.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.0005346827674657106, -0.00022652301413472742, 0.0003372180799487978, 0.9999997615814209, -2.820076877079832e-19, 0.10246391594409943, 0.01531333476305008)

id:8
b'\x9c\xdb)=m\xfe-=\xa7\x9dY<\xa0\x86\x7f?\xaa\x1d\x14\xa0\xedb>=\xa7\xa0\xe3;.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.04146920144557953, 0.04247896745800972, 0.013282216154038906, 0.9981479644775391, -1.254590263431947e-19, 0.04648106172680855, 0.006946641486138105)

id:9
b'\xd2Z\x80\xba\x0bI\x9c<\x9drm<(\xed\x7f?\xe6\xb1O\xa0\xb6\xc3?=\xbf7\x86;.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.0009792691562324762, 0.01907779835164547, 0.014492657966911793, 0.9997124671936035, -1.7592443663565408e-19, 0.04681750386953354, 0.004096000920981169)

id:10
b'\xa7\xc5\x0f=\x8c\x85i<\xfc\xcb\x89<\xad\xc7\x7f?\x8edf\xa0\xa2"@=.s\xf3;.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.035100605338811874, 0.014253031462430954, 0.01682090014219284, 0.9991405606269836, -1.951502854204944e-19, 0.04690802842378616, 0.007429501973092556)

id:11
b'^\xfd\xf2\xbbx\xe2\x03\xbdh\x96\xea<S\xc1\x7f?\xbf,D<xK\x97\xbd\xf1\xd4\x95=.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.007415457628667355, -0.03219839930534363, 0.02863617241382599, 0.9990436434745789, 0.01197355892509222, -0.07387441396713257, 0.07316005975008011)

id:12
b'?(\xd8=\x95\xe3\xfa\xbej\x14\x06\xbfvT0?\x81\xd2\x00>\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.1055455133318901, -0.4900175631046295, -0.5237489938735962, 0.6887887716293335, 0.12580300867557526, 0.031555864959955215, -0.03174249082803726)

id:13
b':\x04\xa69\x1d\xac\x96\xbe3\tz=\x15*t?&9\x91>\x82@\x18:\xaem\xae:.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.0003166513633914292, -0.29428187012672424, 0.06104392930865288, 0.9537671208381653, 0.283639132976532, 0.000580795225687325, 0.0013307833578437567)

id:14
b'0\x98\xa4\xbe\x80J\x92\xbc\x91p\x81<\x94Ur?\xc9\xfbp>\x83\xa4\xfc98\xb9\x90:.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.3214735984802246, -0.017857789993286133, 0.01580074615776539, 0.9466183185577393, 0.23533548414707184, 0.00048187756328843534, 0.001104152761399746)

id:15
b'=\xcf"\xbd\xe7[-=\x98L\x8e\xbd\xc9\xf2~?\xbf,D\xbceK\x97\xbds\xd4\x95=.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.0397484190762043, 0.04232397302985191, -0.06948202848434448, 0.9958921074867249, -0.01197355892509222, -0.07387427240610123, 0.0731591209769249)

id:16
b'\x127\x8f\xbe\x06B\x95>\xb57\xfd>\x0f\x00E?\x81\xd2\x00\xbe\xb9@\x01=j\x04\x02\xbd.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-0.27971702814102173, 0.2915193438529968, 0.4945656359195709, 0.7695321440696716, -0.12580300867557526, 0.031555864959955215, -0.03174249082803726)

id:17
b'\xd2X\xdc9\\x98\xc8>aq\xa6\xbd\x12\x9dj?&9\x91\xbe\x82@\x18:\xaem\xae:.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.0004202784621156752, 0.39178740978240967, -0.08127094060182571, 0.9164592027664185, -0.283639132976532, 0.000580795225687325, 0.0013307833578437567)

id:18
b'\xf6\xe6\x0c>\xd4\xae\x9b;g\x1f"\xbd\x05\}?\xc9\xfbp\xbeL\xa4\xfc9B\xb9\x90:.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.13759979605674744, 0.004751065745949745, -0.039580728858709335, 0.9896853566169739, -0.23533548414707184, 0.0004818759625777602, 0.0011041539255529642)

id:19
b"\xf5\xbbg\xbec\xb3\xe1=\x1d\xc43>\xb6\xa5s?v\xb3\xb7=\xfcG'\xbd\xc9\xb4\xa1<.\x00\x00\x00btdt\x02\x00\x00\x00"
tran:(-0.22630293667316437, 0.11020543426275253, 0.17555280029773712, 0.9517472982406616, 0.08969776332378387, -0.040840134024620056, 0.019739525392651558)

id:20
b'Aj\xfd>T\x8c\r\xbcM\xd3\x07\xbeX\xd3[?\x05\x9d\x07\xbc\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.4949512779712677, -0.008639413863420486, -0.1326419860124588, 0.8586935997009277, -0.008277182467281818, -0.3765147924423218, -0.006362504791468382)

id:21
b"flo\xbd\xdf_\x07>'a\x88<\x8dF}?h\x0e\xb9\xbc\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00btdt\x02\x00\x00\x00"
tran:(-0.05845298618078232, 0.1322016566991806, 0.016647888347506523, 0.9893577694892883, -0.022589877247810364, -0.39234063029289246, -0.05873928591609001)

id:22
b'\x00\x00\x00\xa3\x00\x00\x00 \x00\x00\x00!\x00\x00\x80?i\xea\xf7;\xf4\x94\xc4\xbd \x85\xf8=.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(-6.938893903907228e-18, 1.0842021724855044e-19, 4.336808689942018e-19, 1.0, 0.00756578566506505, -0.0959872305393219, 0.12134766578674316)

id:23
b"\xdf\xb3\x98\xbeY\x8cn>\x04\x9c?\xbba\xf5l?v\xb3\xb7\xbd\xfcG'\xbd\xc9\xb4\xa1<.\x00\x00\x00btdt\x02\x00\x00\x00"
tran:(-0.2982473075389862, 0.23295725882053375, -0.0029237279668450356, 0.9256191849708557, -0.08969776332378387, -0.040840134024620056, 0.019739525392651558)

id:24
b'\x946\xd6>\x95M\xef;\xc3\xa0\xe5="\xbbf?\x05\x9d\x07<\x8c\xc6\xc0\xbe\x8f|\xd0\xbb.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.4183851480484009, 0.007302949670702219, 0.1121230348944664, 0.9012929201126099, 0.008277182467281818, -0.3765147924423218, -0.006362504791468382)

id:25
b'\x9b\xe8\xc5<n\xd7\x00\xbe\x919\xec\xbcj\xc8}?h\x0e\xb9<\xdf\xe0\xc8\xbe\x9b\x98p\xbd.\x00\x00\x00btdt\x02\x00\x00\x00'
tran:(0.024158766493201256, -0.1258217990398407, -0.028836043551564217, 0.9913393259048462, 0.022589877247810364, -0.39234063029289246, -0.05873928591609001)

id:26
b'\x00\x00\xbc\xa2\x00`\x00\xa5\x00\x00\x00\xa2\x00\x00\x80?k\xea\xf7\xbb\xf4\x94\xc4\xbd \x85\xf8='
tran:(-5.095750210681871e-18, -1.113475631142613e-16, -1.734723475976807e-18, 1.0, -0.007565786596387625, -0.0959872305393219, 0.12134766578674316)

これらのリサーチを元にパケットから取り出した値がこちらです。

なんとなく合ってそうな値な気がします。
ただ、実際にボーンに当てはめてみないと合ってるかどうか判断つかないので次はそれらをボーンに実際に当てはめてみます。

ちなみに検証は TouchDesigner上のPythonでやりましたが、Python部分は一般的なコードなので他でも動くと思います。

import struct

def onReceive(dat, rowIndex, message, bytes, peer):
	print('-----start----')
	print(bytes)
	# bnid区切りで分解
	target = b'bnid'
	dataArray = bytes.split(target)
	#print(dataArray)
	# 1575byteのデータ以外は要らない
	if len(bytes) != 1575: return
	for index, item in enumerate(dataArray):
		# 1個目の配列は基本情報でtranが入ってないので除外
		if index != 0:
			# ボーンのidを確認
			id = int.from_bytes(item[0:1], 'little')
			print('id:' + str(id))
			
			# tran以下のデータとそれ以前を分解
			key = b'tran'
			trans = item.split(key)
			
			for index2, item2 in enumerate(trans):
				#print('index:' + str(index2))
				if index2 != 0:
					# バイナリ書き出し
					print(item2)
					
					# 28バイトぶん切り取り
					dat = item2[0:4*7]
					# 4byteのFloat7個としてデコード
					vals = struct.unpack('<fffffff', dat)
					print('tran:' + str(vals))
					
					# 結果を書き込み
					op('table2')[0, index] = vals[0]
					op('table2')[1, index] = vals[1]
					op('table2')[2, index] = vals[2]
					op('table2')[3, index] = vals[3]
					op('table2')[4, index] = vals[4]
					op('table2')[5, index] = vals[5]
					op('table2')[6, index] = vals[6]
	print('-----end----')
	return

Discussion

ログインするとコメントできます