RRDといえばRRDtoolの阿部です。 最初に使ったときはMRTGよりきれいで感動したものです。
そして、今回もRRDなるものが登場しますが、RRDtoolとは無関係です。
今回のRRDはRerunというプラットフォームに関係するものです。 RerunはPhysical AI(ロボットとか)のデータをいい感じに記録して、いい感じに可視化するプラットフォームです。
そこで使われるファイルのフォーマットがRRDと呼ばれています。
Rerunとは?あたりの説明から入り、RRDファイルを作成し、可視化をして、Rerunを試してみるのが本記事です。
Rerunとは?
冒頭にも書いた通りですが、とても簡単に説明すると 「Physical AI(ロボットとか)のデータをいい感じに記録して、いい感じに可視化するプラットフォーム」 です。
「いい感じに記録」とはどういうことか、AIがよしなに判断してロボットアームが自動で何かつかむ場面を例に説明します。
ロボットアームが自動で何かをつかむためには、周りの状況を把握する必要があります。ということで、カメラも必要です。
それを踏まえてつかむまでの流れはおおまかに次のとおりです。
- カメラで周囲を把握し、対象物の位置を特定する
- その位置に向けてアームを動かす
- アームが動くにつれて対象物との距離が変わるので、カメラの情報を元に位置を補正する
- 対象物に到達したらつかむ
個別に事象が起こるような書き方をしましたが、実際にはアームを動かすこととカメラ情報の解析はほぼ同時に行われています。 つまり、データを記録する場合はある瞬間のアームの状態とカメラの状態を同時に記録する必要があります。
「アームの状態」と一言で書きましたが、アームには関節があり、肩・肘・手首・手のそれぞれにモーターがついています。 なので、複数のモーターの状態を記録する必要があります。 さらにモーターごとに「どの角度にあるか」「どのくらいの速さで動いているか」「どのくらいの力を出しているか」といった情報があります。
まとめると、ある瞬間の
- 複数のモーターの状態
- どの角度にあるか
- どのくらいの速さで動いているか
- どのくらいの力を出しているか
- カメラの画像
- (説明を割愛しましたが、多くの場合、カメラも複数台あります)
を記録する必要があります。 これらは時系列に発生するので、ある瞬間の複数のデータを時刻をそろえて記録しなければなりません。 また、数値のデータ、画像のデータとフォーマットの違うデータを記録しなければいけないところも忘れてはいけません。
どうでしょうか、大変感が伝わったでしょうか。
このような複雑なデータを時刻をそろえて記録・可視化するために生まれたのがRerunです!
詳しい話は公式のドキュメントをご覧ください: https://rerun.io/docs/overview/what-is-rerun
RRDとは
公式ドキュメント内でRRDが何の略か見つけられなかったのですが…。 おそらく Rerun Recording Data の略だと思われます。 (ここのコメントにそれらしきことが書いてある。)
RRDファイル自体はバイナリデータです。 RerunがSDKを提供しているのでそれで読み書きします。
RRDファイルを作ってみる
さっそく、簡単なPythonスクリプトの例でRRDファイルの作り方を紹介します。
import numpy as np
import rerun as rr
from PIL import Image, ImageDraw
rr.init("example")
# ちょっと違和感がありますが、最初にsaveを書いておきます。
# https://ref.rerun.io/docs/python/0.28.2/common/initialization_functions/#rerun.save
rr.save("example.rrd")
# 0.1秒ごとに、200回分のデータ(= 20秒分)を記録する例です。
delta_time = 0.1
for i in range(200):
t = i * delta_time
# 時間をセット。
# これで時系列データにできます。
rr.set_time("timestamp", duration=t)
# 「RRDファイルを作って、可視化する」を試すことが目的なので、
# データはテキトウです。
#
# `rr.log("ラベル", 値)` でデータを投入できます。
# * ラベルはわかりやすい名前を自由に設定できます。
# * 値はRerunが用意しているArchetypeでラップする必要があります。
# * https://ref.rerun.io/docs/python/0.28.2/common/archetypes/
rr.log("motor/position", rr.Scalars(np.sin(t)))
rr.log("motor/velocity", rr.Scalars(np.cos(t)))
torque = 5.0 + np.random.normal(0, 0.3)
rr.log("motor/torque", rr.Scalars(torque))
if i % 10 == 0:
# 可視化で何か画像が表示されるようにダミー画像の生成。
# 真ん中に秒数が表示されるだけの画像を生成しています。
# とある瞬間のカメラの画像データだと思ってください。
image = Image.new("RGB", (320, 320), color=(0, 0, 0))
draw = ImageDraw.Draw(image)
draw.text((160, 160), f"{t:.1f}s", fill=(255, 255, 255), anchor="mm")
# ここまでダミー画像の生成
# 直前のset_timeのタイムスタンプに紐づけて画像を記録
rr.log("camera/image", rr.Image(np.array(image)))
あとはこれを実行するとexample.rrdというファイルが生成されます。
ファイルが1個だけできて、これにすべてのデータが含まれています。
参考: https://github.com/abetomo/rrd-example
可視化する
上述の例を実行してできたexample.rrdを https://app.rerun.io/ へアップロードすることで可視化できます。
ちょっとわかりにくいのですが、左上にある「Surces +」をクリックすると、メニューが表示されます。
そこの「Open file」からRRDファイルをアップロードできるので、アップロードするだけです。

そうすると次のキャプチャのように可視化できます。

画面キャプチャだとわかりにくいですが、スライダーを操作すると、グラフや画像などの登録してあるデータが連動して変化して、あるタイミングの状況を確認できます。 また動画のように再生させることもできるので、各データソースが時間の経過とともにどう変化したかを、確認しやすくなっています。
まとめ
Rerunを試してみました。数値のグラフとともに画像のデータも確認できて便利です。 RRDファイルの生成も簡単に行えました。このファイルを共有するだけで可視化もできますし、複数のデータを1つのファイルに保存できて便利そうです。