depthaiのxLinkを通して任意のデータをやり取りする方法
Introduction
depthai はLuxonisが作っている(?)VPUやカメラなどをひとまとめにしたデバイス(OAK-Dなど)を扱う際に必要となるライブラリです。
OAK-D-WIFI(製品として出てるのはOAK-D-IoT)にはESP32が搭載されているのでセンサのデータをやり取りしたり、ESPを通してモータを制御したりなどいろいろやれることがあります。
OAK-D-WIFIはSPIのピンもそのままコネクタとして引き出されているのでVPU側からSPIでセンサデータを直接取り出すこともできそうです。
Motivation
公式のサンプルは各機能の扱い方よりは「カメラ周りですでにライブラリ化されたものたち(NNやDepthなど)でこんなことができますよ」みたいな側面を強く感じたので、今回はホストーデバイス間でのデータのやり取りの基礎となるxLinkプロトコル部分について、コールバックするスクリプトの作成を通して学んでいきます。
Script
import depthai as dai import time def main(): pipeline = dai.Pipeline() xIn = pipeline.createXLinkIn() xIn.setStreamName("stream_0") xOut = pipeline.createXLinkOut() xOut.setStreamName("stream_1") xIn.out.link(xOut.input) with dai.Device(pipeline) as device: start = time.time() xIn_queue = device.getInputQueue("stream_0") xOut_queue = device.getOutputQueue("stream_1",maxSize=5,blocking=False) while True: t = time.time() - start data_out = dai.RawBuffer() data_out.data = [t,t] xIn_queue.send(data_out) data_in = xOut_queue.tryGet() if data_in is not None: print(data_in.getData()) if __name__ == "__main__": main()
Explanation
import depthai as dai import time
depthaiは大抵のサンプルでdai
にエイリアスされているので私もそうします。
timeは結果を用意するために使います。
pipeline = dai.Pipeline() xIn = pipeline.createXLinkIn() xIn.setStreamName("stream_0") xOut = pipeline.createXLinkOut() xOut.setStreamName("stream_1") xIn.out.link(xOut.input)
まず,depthaiでデバイスを扱うにはpipelineを用意する必要があるためdai.Pipeline()
でインスタンスを生成します。
createXLinkIn()
やcreateXLinkOut()
メソッドによってパイプライン上にストリームを生成し、setStreamName
で命名します。
これらのcreateなんちゃらはcreate
メソッドのノードごとの固有ラッパみたいなのでノードを自作する場合などはcreate
メソッドから指定してあげる必要があります。(ノード自作のやり方や必要性はまだ理解していないです)
それぞれ名称設定等の初期設定が終わったら、出力の.out.link
メソッドに入力の.input
変数を与えてストリームをつなぐ先を指定します。
今回の場合、stream_0
がホストからのデータ取得、stream_1
がホストへのデータ吐き出しなのでVPUデバイス内では
stream_0 -> stream_1
とつないでいます。
with dai.Device(pipeline) as device: start = time.time() xIn_queue = device.getInputQueue("stream_0") xOut_queue = device.getOutputQueue("stream_1",maxSize=5,blocking=False) while True: t = time.time() - start data_in = dai.RawBuffer() data_in.data = [t] xIn_queue.send(data_in) data_out = xOut_queue.tryGet() if data_out is not None: print(data_out.getData())
デバイスーホスト間のデータのやり取りは``Queue```で行われます。
In/Outの関係性ですが、depthaiのAPIは基本的にデバイス視点で設定されているようです(In関数群がデータ取得、Out関数群データ吐き出し)
xIn_queue
のsend
メソッドでデータを送信できます。RawBuffer
のdata
変数にlist
を入れると好きにデータを遅れます。
また、データの取得はtryGet
メソッドでデータがあるかを確認してから、getData
でデータを取得します。
今回はtimeを入れて試してみました。
送受信できたdataは基本的に整数の1列のリストか同じ長さのリストのリストでした。[[0], [1,2]]
のようなデータは送れないようです。
また、リストのリストは1列に圧縮されます。( [[0,1],[2,3]]を送ると[0,1,2,3] )
どこでそうなるでかはわかっていませんが。
Conclusion
ひとまずやりたいこととして任意のデータ送信ができました。
目的はOAK上のESPによるサーボ制御なので整数型の一列listが送れれば十分です。
次回はSPIOutによるESP側とのコミュニケーションを実装します。