フィジカルAI研究室を作る Log#18 | 学び直した π0.5 でも mechArm 270 には人の直しが要った

フィジカルAI研究室を作る Log#18 | 学び直した π0.5 でも mechArm 270 には人の直しが要った

この記事の素材(コード・ログ・データ 7ファイル・まとめてダウンロードあり)
AIで読む ChatGPT・Claude などで、この記事に質問できます

人が直した5回の動きで学び直した Physical Intelligence の π0.5 で、実物の小型ロボットアーム mechArm 270 を9回動かすと、ブロックを箱に入れられた6回はすべて人の補正つきで、補正なしで任せた1回は、根元の向きが人の直した回より約2°手前のまま爪を閉じて空振りしました。学び直しで、補正のあとは AI が箱まで自分で運べましたが、人が直す所(つかむ前の根元の向きと、つかんだあとの持ち上げ)は前のモデルと同じまま残りました。

この回でやったことで、次の3つが変わりました。

  • 良くなること:人が同じ直し方をした成功の記録が6本増え、前の回の5本と合わせて11本になった。次の学習データにすれば、AI が毎回ずれる所をもう一度覚え直させられる(使うかどうかは、手首の点検の結果で決める)
  • もたらされること:補正なしで最後まで任せた記録が1本取れた。爪を閉じたときの根元の角度が 11.5° で、人が根元を直して成功した5回は 12.9〜14.4° だった。次に学び直したモデルを、この数字と比べられる
  • 時間・費用:Mac で1行打ってから、AI が最初の動きを返すまで約6分(Pod とサーバーの準備247秒、位置合わせ72秒、最初の推論55秒)。1回あたりは、位置合わせ17〜27秒と推論82〜278秒。9回と、そのあとの手首の確かめで、借りた GPU は65分42秒・約102円だった

π0.5(パイレイテンゴ)は、米国の Physical Intelligence 社が公開しているロボット用の AI のモデルです。上から見たカメラの画像と6つの関節の角度を受け取り、次の1秒ぶんの関節の角度を返します。人が手で教えた19回の動き(お手本)で学習させ、赤いブロックをつかんで白い箱に入れる作業をさせています。前の回(LOG417)で、AI が失敗しかけたときに人がキーで関節を直した5回の記録を学習データにし、前のモデルから続けて1,500ステップ学習しました。この回は、その学び直したモデルを実機で試した記録です。

学び直したモデルも、人が直さなければ、ブロックの少し手前で爪を閉じました。 補正なしの3回目は、つかむ前の根元の角度が 11.5° のまま爪を閉じ、ブロックの角を押しただけで空振りしました。成功した6回のうち5回は、人が根元を +2〜6° 回してから閉じています。前のモデルでも、成功した5回はすべて根元を +2〜4° 直していました。

9回目が終わって HOME(始めの姿勢)に戻すとき、手首の関節(j4)が 0° を越えて +54° まで行き、そこから指令に応えなくなりました。アームの電源を入れ直しても戻らず、手首だけが垂れた状態です。その間、AI が出した目標は、安全範囲の確かめで送る前に止まり、アームには送られていません。やったことの全体は次のとおりです。

段階やったこと結果
実機で9回動かす
借りた GPU(Runpod の A40)の上の学び直したモデルで、mechArm 270 を動かした
成功6回・失敗3回。成功はすべて補正つき。補正なしの1回は空振り
補正をならべる
9回の記録から、補正の中身と、爪を閉じたときの根元の角度を取り出した
つかむ前の根元の直し(+2〜6°)と、つかんだあとの持ち上げ(肩かひじを 13〜34°)が、前のモデルと同じ形で残った
手首を調べる
止まったあとの関節のずれを、回ごとに出した
9回とも、止まったあとの手首のずれは 4.0° 以内。動いている間の遅れは大きく見えたが、止まると指令どおりに着いていた
手首が戻らなくなった
9回目のあとの HOME で、手首だけが +54° のまま。つなぎ直しを2回試した
指令が無視され、電源を入れ直しても戻らない。アームの実機はここで止めた
次の依頼を出す
成功6本の点検と次の学習データづくり(依頼57)、手首のサーボの点検スクリプト(依頼58)を依頼箱に置いた
依頼57・58 は、この記録の時点で作業中と順番待ち
上から撮った実機の録画のコマ。左上は1回目の始めの姿勢。右上は1回目に根元を直してから爪を閉じ、ブロックを挟めたところ。左下は3回目に直さずに爪を閉じ、ブロックの角を押しただけで空振りしたところ。右下は9回目のあとに HOME に戻しても、手首が +54° のまま戻らなかったところで、ブロックは箱の手前のマットに残っている

次は、手首のサーボを点検し、成功6本のうち使える回で学び直してから、補正なしの回の根元の角度がどこまで 13° 前後に近づくかを確かめます。

GPU を買うか借りるかの判断は、Runpod で実際に借りて学習させた費用をもとに、別のページにまとめています。

導入比較ガイドロボットAIの学習用GPU、買うか借りるか実際に借りて学習させた費用と、損益分岐の計算機で決められます

この回の作業は、Claude(手順と分析を一緒に組み立てた AI)と進めました。アームの操作と、目で見た判断はこちらで行い、記録の集計は Claude が行っています。プログラムの直しは Claude Code(プログラムを書く AI)に依頼箱を通して頼んでいます。ここから下は、使ったコマンド・出力・依頼文・集計のコードを全量で載せた作業ログです。ログの中の Pod の IP アドレスとポート番号は <POD_IP> と <SSH_PORT> に置き換えています。鍵(Runpod と Hugging Face のアクセストークン)は、どこにも載せていません。費用の円は 1ドル=158円 で計算しています。結果の数字は記録から数えた値で、見込みのものは見込みと書いています。

作業ログ ― 学び直した π0.5 で mechArm 270 を9回動かし、手首のサーボが応えなくなるまで

この回で使う言葉

言葉意味
チャンク
AI に1回問い合わせて返ってくる、次の1秒ぶん(10ステップ)の関節の角度。プログラムはチャンクを1つ受け取るたびに止まり、Enter で実行するかを聞く。記録の「推論3」は、0から数えて4つ目のチャンク
補正(c)
キーで関節を選び、1回押すごとに決まった角度(刻み)だけ動かすモード。Enter で、その姿勢から AI に戻す
j0〜j5
mechArm 270 の6つの関節。j0 は根元の回転、j1 は肩、j2 はひじ、j3〜j5 は手首
HOME
アームの始めの姿勢。j0〜j4 が 0°、j5 が −30°
位置合わせ
HOME の姿勢で、上カメラの画像とお手本の最初の画像を重ね、ブロックをお手本と同じ所に置く手順。ずれ(dx・dy)と、重なりの強さ(response)を出す
常駐プログラム(デーモン)
アームの中の小さな計算機(Raspberry Pi)で動き続け、Mac からの指令を受けて関節を動かすプログラム
サーボ
関節ごとに入っているモーター。指令された角度まで回り、その角度を保つ。力が抜けると、関節は重さで垂れる
新しいモデル(corr)
前のモデル(お手本19回で4,000ステップ学習)から、人が直した5回を足して1,500ステップ続けて学習したモデル。Hugging Face の非公開の置き場所 PixelstoMotors/pi05-mecharm-trim-corr-lora-v1 に置いている

Runpod は、GPU を時間で借りられるサービス

Runpod は、GPU を積んだ計算機(Pod)を、1時間いくらで借りられるサービスです。この研究室では、π0.5 を動かすサーバーを Pod の上で立て、Mac から通信のトンネル(Mac の 8000 番を Pod の 8000 番につなぐ道)を通して問い合わせています。この回は NVIDIA A40 を1時間 0.59ドル(約93円)で借りました。使い終わったら、止める(Stop)のではなく消す(Terminate)まで行います。止めただけでは、ディスクの料金がかかり続けるためです。

起動と片付けは、lab_start.sh と lab_stop.sh の1行ずつ

起動は Mac で次の1行です。--model corr を付けると、学び直したモデルでサーバーを立てます。付けないと、前のモデル(3999)で立ちます。

cd ~/r2r2r-scripts
./lab_stop.sh --check
./lab_start.sh --log Log18 --model corr

最初の1行目は、ホームフォルダのまま ./lab_start.sh --log Log17 を打って zsh: no such file or directory: ./lab_start.sh になったため、フォルダを移ってから打ち直したものです。ターミナルの画面がうまく表示されなくなったので、いったんターミナルを強制終了しました。依頼箱の見張り係も同じターミナルで動いていたので、次の1行で立ち上げ直しています。

open -a Terminal ~/r2r2r-scripts/inbox/start_inbox.command

lab_stop.sh --check は、消し忘れの Pod がないかを確かめる1行です。結果は [CHECK ] 残っている Pod はありません でした。

実機の1〜3回目(11/1 19:03〜19:17):成功2回と、補正なしで任せた空振り1回

この記事のコード・ログ・データは、1ファイルずつ下に置いています。全文はリンク先にあります。

ファイルの一覧(7本)

01_sec02.txt ― 1〜3回目の端末の記録 lab_start_20261101_185827.txt(1〜1198行目)・69,677字

02_sec03.txt ― 4〜9回目の端末の記録 lab_start_20261101_185827.txt(1199〜2731行目)・116,414字

03_pi05_20261101_194042_recording_states.csv ― pi05_20261101_194042/recording/states.csv(HOME へ送った所から最後まで)・10,107字

04_sec06.txt ― 10回目の端末の記録 lab_start_20261101_185827.txt(2732行目〜最後)・23,346字

05_sec07.txt ― lab_start_20261101_195459.txt・11,439字

06_sec07.txt ― lab_start_20261101_200154.txt・5,627字

07_serve.log.txt ― Pod のサーバーの記録 serve.log・4,700字

Pod を作ってからサーバーが待ち受けるまでは、247秒でした(Pod を作る2秒・立ち上がり41秒・スクリプトを送る65秒・鍵14秒・モデルを取る18秒・openpi 22秒・uv sync 20秒・設定4秒・サーバーの起動55秒・トンネル4秒・デーモンの確かめ2秒)。画面に [MODEL ] --model corr と --policy.dir=/workspace/ckpt/corr_v1_1499 が出て、学び直したモデルで立ったことを確かめています。

最初の推論だけ 54,609ms かかりました。サーバーが最初の1回だけ、計算の組み立て(コンパイル)をするためです。2回目からは 566〜2,936ms でした。

回記録の名前結果補正
1回目
pi05_20261101_190347
成功
推論3のあとに j0 を +6.0°、推論8のあとに j2 を −12.9°
2回目
pi05_20261101_190854
成功
推論3のあとに j0 を +3.0°、推論6のあとに j1 を −6.0°・j2 を −24.2°
3回目
pi05_20261101_191547
失敗
なし(推論5で爪を閉じ、推論7のあとに h で終えた)

1回目と2回目は、同じ2か所を直しています。つかむ前に、AI がブロックへ下り始めたところで根元を回し、爪の真ん中にブロックが来る向きにしました。つかんだあとは、持ち上げが足りないまま箱へ向かう動きだったので、ひじ(2回目は肩も)を動かして、箱の縁に当たらない高さまで持ち上げました。どちらの回も、直したあとは、AI が箱の上まで運んで爪を開き、HOME の方へ戻るところまで自分で続けています。

3回目は、新しいモデルだけでどこまでできるかを見るため、補正せずに Enter だけで進めました。AI は自分で下りて、推論5で爪を閉じました。そのときの根元の角度は 11.5° でした。そのあと持ち上げて、推論7で箱の方へ根元を回し始めたところで h を押して終えています。ブロックは爪に入っておらず、空振りでした。

1〜3回目の端末の記録 lab_start_20261101_185827.txt(1〜1198行目)

01_sec02.txt69,677字・1,198行・text
[LAB   ] 2026-11-01 18:58:27  GPU=NVIDIA A40  episode=run_0001_20261019_194818  log=/Volumes/KIOXIA/r2r2r-data/lab/Log18  
[MODEL ] --model corr: 3999 から trim2_corr_v3 で続きを学習した 1499 (依頼 49)
         PixelstoMotors/pi05-mecharm-trim-corr-lora-v1 → /workspace/ckpt/corr_v1_1499  設定 pi05_mecharm_trim_corr_lora  assets local/mecharm_redblock_box_teach_v1_trim2_corr_v3

=== 1. Pod を作る
[POD   ] 作った: id v7w5nerpf0hh1y  GPU=NVIDIA A40  1時間 0.59 ドル  (記録 /Volumes/KIOXIA/r2r2r-data/lab/Log18/pod/lab_pod.json)
    (2 秒)
別のタブで開く保存

実機の4〜9回目(19:20〜19:46):補正しながら成功4回・失敗2回

3回目のあと、補正しながら成功を集めることにしました。目安は、前の回の5本の倍近くになるように、成功8本です。補正の入れ方は、次の2つにそろえました。同じ直し方の記録がたまるほど、AI が覚えやすくなるためです。

  1. つかむ前:推論3あたりで、下り始める前に c を押し、j0 を足して、爪の真ん中にブロックが来る向きにする
  2. つかんだ後:持ち上げたら、根元を回して箱へ向かう前に c を押し、ひじ(j2)を下げて、箱に当たらない高さまで持ち上げる
回記録の名前結果補正
4回目
pi05_20261101_192101
成功
推論3のあとに j0 を +4.0°、推論6のあとに j2 を −22.6°
5回目
pi05_20261101_192418
成功
推論3のあとに j0 を +2.0°、推論6のあとに j1 を −16.9°・j4 を −10.3° ほか
6回目
pi05_20261101_192758
失敗
推論2のあとに j0 を +4.0°、推論6のあとに j2 を −21.2°・j4 を +18.7°
7回目
pi05_20261101_193041
成功
推論2のあとに j0 を +6.0°・j2 を −11.9°、推論5のあとに j2 を −33.9°・j4 を +5.4° ほか
8回目
pi05_20261101_193411
成功
推論5のあとに j1 を −20.8°・j2 を −9.7°・j4 を +6.8°(つかむ前の直しはなし)
9回目
pi05_20261101_194042
失敗
推論5のあとに j1 を −18.7°・j2 を −18.9°・j4 を +13.6°

5回目からは、つかんだあとの直しに手首(j4)も入っています。8回目は、つかむ前の根元を直さずに成功しました。そのとき爪を閉じた根元の角度は 11.9° で、空振りした3回目の 11.5° と 0.4° しか違いません。根元の角度だけで、つかめるかどうかが決まるわけではないことになります。6回目と9回目の失敗の中身は、目で見た記録を残していないため、ログからは決めていません。9回目のあとの画像では、ブロックは箱の手前のマットに残っています。

4〜9回目の端末の記録 lab_start_20261101_185827.txt(1199〜2731行目)

02_sec03.txt116,414字・1,533行・text
[SEND] arrival OK: max|Δ|=1.57° (tol 3.0°)
       [VIA   ] step  2  Δ= +0.8  -2.3  +1.9  -0.9  +1.1  +0.1  着いた
[SEND] pi05_chunk006_via05: send_angles (single) [ +11.75,  +55.29,  +25.54,   -2.79,  -62.88,  -26.87]  speed=20 wait=0.0s  (pre max|Δ|=5.33°, post-send timeout 8.0s)
[SEND] arrival OK: max|Δ|=2.15° (tol 3.0°)
       [VIA   ] step  5  Δ= +0.7  -4.6  +5.3  -1.0  -1.5  +0.4  着いた
[SEND] pi05_chunk006_via08: send_angles (single) [ +11.74,  +52.80,  +28.12,   -2.81,  -63.23,  -26.80]  speed=20 wait=0.0s  (pre max|Δ|=3.60°, post-send timeout 8.0s)
[SEND] arrival OK: max|Δ|=2.85° (tol 3.0°)
       [VIA   ] step  8  Δ= +0.7  -3.5  +3.6  +1.0  -2.5  +0.3  着いた
別のタブで開く保存

補正をならべると、新しいモデルでも直す2か所は前と同じだった

記録(log.jsonl)から、補正を1回ずつ取り出して、始めの姿勢と最後に送った目標の差をならべました。爪を閉じたときの根元の角度は、爪を閉じた推論のときの実測角です。

回run結果チャンク補正
補正の中身(開始→終わりの差)
爪を閉じたときの j0
1
pi05_20261101_190347
成功132
推論3のあと: j0 +6.0° / 推論8のあと: j2 -12.9°
+14.4°
2
pi05_20261101_190854
成功122
推論3のあと: j0 +3.0° / 推論6のあと: j1 -6.0°、j2 -24.2°
+14.1°
3
pi05_20261101_191547
失敗80なし+11.5°
4
pi05_20261101_192101
成功102
推論3のあと: j0 +4.0° / 推論6のあと: j2 -22.6°
+13.4°
5
pi05_20261101_192418
成功112
推論3のあと: j0 +2.0° / 推論6のあと: j0 +0.5°、j1 -16.9°、j3 +0.7°、j4 -10.3°
+13.2°
6
pi05_20261101_192758
失敗82
推論2のあと: j0 +4.0° / 推論6のあと: j2 -21.2°、j4 +18.7°
+13.4°
7
pi05_20261101_193041
成功112
推論2のあと: j0 +6.0°、j2 -11.9° / 推論5のあと: j1 +0.6°、j2 -33.9°、j4 +5.4°
+12.9°
8
pi05_20261101_193411
成功101
推論5のあと: j1 -20.8°、j2 -9.7°、j4 +6.8°
+11.9°
9
pi05_20261101_194042
失敗81
推論5のあと: j1 -18.7°、j2 -18.9°、j4 +13.6°
+11.2°

前のモデル(LOG417 の8回)と並べると、次のとおりです。

前のモデル(3999・LOG417)
学び直したモデル(corr・この回)
回数8回9回
成功5回(すべて補正つき)6回(すべて補正つき)
つかむ前の根元の直し
成功5回すべてで +2.0〜+4.0°
成功6回のうち5回で +2.0〜+6.0°
つかんだあとの持ち上げ
成功5回すべてで j2 を −15〜−31°
成功6回すべてで、j1 か j2 を −13〜−34°(後半は j4 も)
補正なしで任せた回なし
1回。根元 11.5° で爪を閉じて空振り

学び直しても、人が直す2か所(つかむ前の根元の向きと、つかんだあとの持ち上げ)は残りました。 足した5本は、お手本19本に対して少なく、1,500ステップの続きの学習では、AI の答えを動かしきれなかったと見ています(見込み)。直す2か所の記録は、この回でさらに6本たまりました。

ねらい・変わったこと・見込める効果は次のとおりです。

  • ねらい:人が同じ直し方をした成功の記録を増やし、AI が毎回ずれる2か所をもう一度覚え直させる
  • 変わったこと:直した成功の記録が、前の回の5本から11本になった(この回の6本を使うかは、依頼57の点検で決める)
  • 見込める効果:学び直したあと、補正なしの回で爪を閉じる根元の角度が、11.5° から、人が直した 12.9〜14.4° に近づく見込み。同じ置き方で、補正なしの回を数回回して確かめる

補正と止まったあとのずれをならべる計算 log18_table.py

"""Log18 の実機推論(2026-11-01・モデル corr)の記録を、回ごとの表にする。
- 結果・チャンク数・補正の数と中身(補正ごとの関節の動き)
- 爪を閉じたときの j0(根元の向き)
- 止まったあとの関節のずれ:次の推論を始める時点の実測角と、直前に送った目標の差(関節ごとの最大)
使い方: python3 log18_table.py <runs/pi05_policy のフォルダ>
"""
import json, sys, pathlib

ROOT = pathlib.Path(sys.argv[1])
RUNS = ["190347", "190854", "191547", "192101", "192418", "192758", "193041", "193411", "194042"]
J = ["j0", "j1", "j2", "j3", "j4", "j5"]

print("| 回 | run | 結果 | チャンク | 補正 | 補正の中身(開始→終わりの差) | 爪を閉じたときの j0 |")
print("|---|---|---|---|---|---|---|")
drift_rows = []
for n, r in enumerate(RUNS, 1):
    stem = f"pi05_20261101_{r}"
    d = ROOT / stem
    meta = json.load(open(d / f"{stem}.json"))
    chunks, accepts = [], []
    for line in open(d / "log.jsonl"):
        x = json.loads(line)
        t = x.get("type")
        if t is None and "chunk" in x:
            chunks.append(x)
        elif t == "correction" and x.get("action") == "accept":
            accepts.append(x)
    corr_txt = []
    for a in accepts:
        diff = [round(b - s, 1) for s, b in zip(a["start_pose"], a["final_target"])]
        moved = [f"{J[i]} {v:+.1f}°" for i, v in enumerate(diff) if abs(v) >= 0.5]
        corr_txt.append(f"推論{a['after_chunk']}のあと: " + "、".join(moved))
    close_j0 = "—"
    for c in chunks:
        if c.get("grip_cmd") == 1 and c.get("executed"):
            close_j0 = f"{c['measured_state'][0]:+.1f}°"
            break
    out = {"success": "成功", "failure": "失敗"}.get(meta.get("outcome"), str(meta.get("outcome")))
    print(f"| {n} | {stem} | {out} | {len(chunks)} | {len(accepts)} | {' / '.join(corr_txt) or 'なし'} | {close_j0} |")
    # 止まったあとのずれ: state_source=target のとき、state(=直前の目標) と measured_state の差
    worst = [0.0] * 6
    for c in chunks:
        if c.get("state_source") == "target":
            for i in range(6):
                worst[i] = max(worst[i], abs(c["measured_state"][i] - c["state"][i]))
    drift_rows.append((n, stem, out, worst))

print()
print("止まったあとのずれ(次の推論を始める時点の実測角 − 直前に送った目標、関節ごとの最大、度)")
print("| 回 | run | 結果 | " + " | ".join(J) + " |")
print("|---|---|---|" + "---|" * 6)
for n, stem, out, w in drift_rows:
    print(f"| {n} | {stem} | {out} | " + " | ".join(f"{v:.1f}" for v in w) + " |")

打ったコマンド(Claude のクラウドの作業環境で、KIOXIA から持ってきた記録に対して):

python3 log18_table.py /home/claude/log422/data/runs/pi05_policy

出力

| 回 | run | 結果 | チャンク | 補正 | 補正の中身(開始→終わりの差) | 爪を閉じたときの j0 |
|---|---|---|---|---|---|---|
| 1 | pi05_20261101_190347 | 成功 | 13 | 2 | 推論3のあと: j0 +6.0° / 推論8のあと: j2 -12.9° | +14.4° |
| 2 | pi05_20261101_190854 | 成功 | 12 | 2 | 推論3のあと: j0 +3.0° / 推論6のあと: j1 -6.0°、j2 -24.2° | +14.1° |
| 3 | pi05_20261101_191547 | 失敗 | 8 | 0 | なし | +11.5° |
| 4 | pi05_20261101_192101 | 成功 | 10 | 2 | 推論3のあと: j0 +4.0° / 推論6のあと: j2 -22.6° | +13.4° |
| 5 | pi05_20261101_192418 | 成功 | 11 | 2 | 推論3のあと: j0 +2.0° / 推論6のあと: j0 +0.5°、j1 -16.9°、j3 +0.7°、j4 -10.3° | +13.2° |
| 6 | pi05_20261101_192758 | 失敗 | 8 | 2 | 推論2のあと: j0 +4.0° / 推論6のあと: j2 -21.2°、j4 +18.7° | +13.4° |
| 7 | pi05_20261101_193041 | 成功 | 11 | 2 | 推論2のあと: j0 +6.0°、j2 -11.9° / 推論5のあと: j1 +0.6°、j2 -33.9°、j4 +5.4° | +12.9° |
| 8 | pi05_20261101_193411 | 成功 | 10 | 1 | 推論5のあと: j1 -20.8°、j2 -9.7°、j4 +6.8° | +11.9° |
| 9 | pi05_20261101_194042 | 失敗 | 8 | 1 | 推論5のあと: j1 -18.7°、j2 -18.9°、j4 +13.6° | +11.2° |

止まったあとのずれ(次の推論を始める時点の実測角 − 直前に送った目標、関節ごとの最大、度)
| 回 | run | 結果 | j0 | j1 | j2 | j3 | j4 | j5 |
|---|---|---|---|---|---|---|---|---|
| 1 | pi05_20261101_190347 | 成功 | 0.6 | 2.2 | 1.6 | 0.6 | 2.1 | 0.8 |
| 2 | pi05_20261101_190854 | 成功 | 0.6 | 2.7 | 1.6 | 0.5 | 2.5 | 0.3 |
| 3 | pi05_20261101_191547 | 失敗 | 0.8 | 1.4 | 1.1 | 1.2 | 2.6 | 0.4 |
| 4 | pi05_20261101_192101 | 成功 | 0.5 | 2.3 | 1.9 | 0.5 | 1.2 | 0.9 |
| 5 | pi05_20261101_192418 | 成功 | 0.4 | 1.3 | 1.6 | 0.8 | 2.1 | 0.3 |
| 6 | pi05_20261101_192758 | 失敗 | 0.5 | 1.0 | 0.7 | 0.8 | 2.0 | 0.5 |
| 7 | pi05_20261101_193041 | 成功 | 0.5 | 2.6 | 1.0 | 1.1 | 4.0 | 0.8 |
| 8 | pi05_20261101_193411 | 成功 | 0.6 | 1.3 | 1.8 | 0.5 | 3.8 | 0.8 |
| 9 | pi05_20261101_194042 | 失敗 | 0.4 | 2.0 | 1.7 | 0.5 | 1.9 | 0.5 |

手首(j4)の、指令と実測の差は回ごとに大きくなっていた

9回目のあとに手首が戻らなくなったので、成功6本を学習に使う前に、手首が早い回から弱っていなかったかを見ました。最初は、上カメラの記録(states.csv)で、直前に送った指令と実測の差の最大を、回ごとに出しました。

Mac の shell で動かしたコマンド:

cd "$HOME/mnt/KIOXIA/r2r2r-data/runs/pi05_policy"; for d in 190347 190854 192101 192418 192758 193041 193411 194042; do python3 - "pi05_20261101_$d" <<'PY'
import csv,sys
d=sys.argv[1];rows=list(csv.reader(open(f"{d}/recording/states.csv")))
last=None;worst=0
for r in rows[1:]:
    if r[1]=="send_angles": last=float(r[7])
    elif r[1]=="actual" and last is not None and r[7]:
        worst=max(worst,abs(float(r[7])-last))
n=sum(1 for r in rows if r[1]=="actual")
print(d,"j4 指令と実測の最大差 %.1f°"%worst, "コマ",n)
PY
done

出力:

pi05_20261101_190347 j4 指令と実測の最大差 3.5° コマ 2118
pi05_20261101_190854 j4 指令と実測の最大差 2.5° コマ 1355
pi05_20261101_192101 j4 指令と実測の最大差 1.8° コマ 1101
pi05_20261101_192418 j4 指令と実測の最大差 10.3° コマ 1389
pi05_20261101_192758 j4 指令と実測の最大差 19.5° コマ 1036
pi05_20261101_193041 j4 指令と実測の最大差 18.4° コマ 1223
pi05_20261101_193411 j4 指令と実測の最大差 8.0° コマ 1435
pi05_20261101_194042 j4 指令と実測の最大差 59.5° コマ 1188

5回目から差が大きくなり、9回目は 59.5° でした。ただ、この数字には、アームが動いている途中の遅れも入っています。指令を送った直後は、まだ着いていないので、差が大きく出ます。

そこで、止まったあとのずれを別に出しました。上の log18_table.py の後半の表です。次の推論を始める時点(前のチャンクの動きを送り終え、着いたと判定したあと)の実測角と、直前に送った目標の差です。9回とも、手首(j4)のずれは 1.2〜4.0° でした。7回目と8回目は 4.0° と 3.8° で、ほかの回より少し大きいものの、9回目は 1.9° です。

見方手首(j4)の最大9回目
指令と実測の差(動いている途中も含む)
1.8〜59.5°59.5°
止まったあとのずれ1.2〜4.0°1.9°

手首は、推論の間は止まると指令どおりに着いていて、外れたのは9回目のあとに HOME へ戻す動きの中でした。 9回目の 59.5° は、その HOME への動きで出た差です。成功6本の中身に手首の垂れが入っているかは、着いたと判定した直後・爪の開け閉めの前後・補正の1刻みのあと、と細かく分けて、依頼57で Claude Code に調べてもらっています。

9回目の HOME で、手首は −47° から +54° まで回って止まった

9回目の記録(pi05_20261101_194042)の states.csv から、HOME へ送った前後の行を取り出しました。HOME への指令は j4=0° です。ところが手首は 0° で止まらず、+28° → +54° と回り、そこで止まりました。

pi05_20261101_194042/recording/states.csv(HOME へ送った所から最後まで)

ts,event_type,stage,j0,j1,j2,j3,j4,j5,speed,gripper_state,ts_send,ts_arrival,attempt,arrived,note
1793529788.195595,actual,wait,36.030,45.430,1.230,0.790,-47.630,-28.210,,,,,,,
1793529788.297478,actual,wait,36.030,45.430,1.230,0.790,-47.630,-28.210,,,,,,,
1793529788.389322,actual,wait,36.030,45.430,1.230,0.790,-47.630,-28.210,,,,,,,
1793529788.454687,stage,home,,,,,,,,,,,,,
1793529788.470801,actual,home,36.030,45.430,1.230,0.790,-47.630,-28.210,,,,,,,main
1793529788.470897,send_angles,home,0.000,0.000,0.000,0.000,0.000,-30.000,20,,1793529788.470897,,,,rpc_sec=1.544
1793529790.026671,actual,home,0.000,1.490,1.230,0.610,-3.510,-29.610,,,,,,,
別のタブで開く保存

10回目の HOME で、手首 j4 だけが +54.49° のまま戻らなかった

9回目のあと、続けて10回目に進みました。HOME へ送ると、j0〜j3 と j5 は 0° と −30° の近くにありますが、j4 だけが +54.49° のままで、84秒待っても変わりませんでした。Ctrl-C で止めています。このときアームは、手首だけが垂れ下がっていました。手首の関節は、手で触っても硬くなっておらず、熱も持っていませんでした。

そのまま位置合わせに進むと、重なりの強さ(response)が 0.08〜0.13 で「測れない」になりました。手首の向きが変わり、上カメラに写る爪の形がお手本と違ってしまったためと見ています。続く10回目の推論では、AI が返した目標の j4 が安全範囲(−90〜+10.4°)の外になり、送る前に止まりました。h で HOME へ戻しても、手首は応えませんでした。記録には [RETRY] 1回目送信が無視された(pre→last max|Δ| 0.00°) と出ています。指令を送っても、関節が少しも動かなかったということです。

10回目の端末の記録 lab_start_20261101_185827.txt(2732行目〜最後)

04_sec06.txt23,346字・614行・text
       [LIMIT] step 5 (実測から): j4 移動量 -34.1° を ±20° に制限
[SEND] pi05_chunk006_via05: send_angles (single) [ +27.83,  +43.30,   +0.87,   -0.28,  -34.67,  -28.31]  speed=20 wait=0.0s  (pre max|Δ|=20.00°, post-send timeout 8.0s)
[SEND] arrival OK: max|Δ|=2.13° (tol 3.0°)
       [VIA   ] step  5  Δ= +8.6  -2.1  -2.6  +1.3 -20.0  -0.3  着いた
[SEND] pi05_chunk006_via08: send_angles (single) [ +34.79,  +43.18,   -0.45,   +0.31,  -47.63,  -28.70]  speed=20 wait=0.0s  (pre max|Δ|=12.04°, post-send timeout 8.0s)
[SEND] arrival OK: max|Δ|=2.25° (tol 3.0°)
       [VIA   ] step  8  Δ= +7.3  -2.3  -2.6  +0.7 -12.0  -0.7  着いた
[SEND] pi05_chunk006_via09: send_angles (single) [ +36.08,  +43.46,   -0.49,   +0.34,  -47.85,  -28.67]  speed=20 wait=0.0s  (pre max|Δ|=1.97°, post-send timeout 8.0s)
別のタブで開く保存

19:54 と 20:01 に、電源を入れ直してつなぎ直したが、手首は戻らなかった

アームを手で支えて電源を切り、少し置いてから入れ直しました。Pod は残したまま、./lab_start.sh --log Log18 --model corr でつなぎ直しています。つなぎ直しでは、Pod の中のモデルとサーバーが同じ(--policy.dir=/workspace/ckpt/corr_v1_1499)ことを確かめ、準備とサーバーの起動を飛ばしました。

どちらの回も、HOME の前の姿勢が [0.00, 1.31, 1.23, -0.08, 54.49, -29.70] のままで、HOME へ送っても j4 は動きませんでした。19:54 の回は、推論まで進みましたが、AI の目標が安全範囲の外で送る前に止まっています。20:01 の回も同じでした。ここで、実機はこの日は止めることにしました。

lab_start_20261101_195459.txt

05_sec07.txt11,439字・280行・text
[LAB   ] 2026-11-01 19:54:59  GPU=NVIDIA A40  episode=run_0001_20261019_194818  log=/Volumes/KIOXIA/r2r2r-data/lab/Log18  
[MODEL ] --model corr: 3999 から trim2_corr_v3 で続きを学習した 1499 (依頼 49)
         PixelstoMotors/pi05-mecharm-trim-corr-lora-v1 → /workspace/ckpt/corr_v1_1499  設定 pi05_mecharm_trim_corr_lora  assets local/mecharm_redblock_box_teach_v1_trim2_corr_v3

=== 1. Pod を作る
[POD   ] Log18 の Pod (id v7w5nerpf0hh1y) につなぎ直します (状態 RUNNING  GPU=NVIDIA A40  1時間 0.59 ドル  作った時刻 2026-11-01 18:58:29)
[POD   ] 記録の最後のモデル: corr  今回: --model corr
    (1 秒)
別のタブで開く保存

lab_start_20261101_200154.txt

06_sec07.txt5,627字・122行・text
[LAB   ] 2026-11-01 20:01:54  GPU=NVIDIA A40  episode=run_0001_20261019_194818  log=/Volumes/KIOXIA/r2r2r-data/lab/Log18  
[MODEL ] --model corr: 3999 から trim2_corr_v3 で続きを学習した 1499 (依頼 49)
         PixelstoMotors/pi05-mecharm-trim-corr-lora-v1 → /workspace/ckpt/corr_v1_1499  設定 pi05_mecharm_trim_corr_lora  assets local/mecharm_redblock_box_teach_v1_trim2_corr_v3

=== 1. Pod を作る
[POD   ] Log18 の Pod (id v7w5nerpf0hh1y) につなぎ直します (状態 RUNNING  GPU=NVIDIA A40  1時間 0.59 ドル  作った時刻 2026-11-01 18:58:29)
[POD   ] 記録の最後のモデル: corr  今回: --model corr
    (2 秒)
別のタブで開く保存

Pod を消して、65分42秒・約102円

./lab_stop.sh --log Log18 で、Pod のサーバーの記録(serve.log)を持ち帰り、Pod を消しました。消えたことは API で確かめています。

lab_stop_20261101_200402.txt

[STOP  ] Log18 の Pod: id v7w5nerpf0hh1y  GPU=NVIDIA A40  作った時刻 2026-11-01 18:58:29
[LOG   ] serve.log を持ち帰った → /Volumes/KIOXIA/r2r2r-data/lab/Log18/serve.log (54 行)
[STOP  ] Terminate を送った (20:04:11)
[STOP  ] Pod (id v7w5nerpf0hh1y) が消えたことを API で確かめた
[COST  ] 借りていた時間 65 分 42 秒 (1.09 時間) × 1時間 0.59 ドル = 約 0.65 ドル (約 102 円. 1ドル=158円)
[TUNNEL] 8000 番のトンネルは残っていません

Pod の記録 lab_pod.json

{
  "id": "v7w5nerpf0hh1y",
  "gpu": "NVIDIA A40",
  "log": "Log18",
  "costPerHr": 0.59,
  "created_epoch": 1793527109,
  "created_at": "2026-11-01 18:58:29",
  "model": "corr",
  "model_repo": "PixelstoMotors/pi05-mecharm-trim-corr-lora-v1",
  "terminated_epoch": 1793531051,
  "terminated_at": "2026-11-01 20:04:11",
  "rented_sec": 3942
}

Pod のサーバーの記録 serve.log

07_serve.log.txt4,700字・54行・text
INFO:root:Loading model...
INFO:2026-11-01 10:02:00,331:jax._src.xla_bridge:925: Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'
INFO:jax._src.xla_bridge:Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'
INFO:2026-11-01 10:02:00,333:jax._src.xla_bridge:925: Unable to initialize backend 'tpu': INTERNAL: Failed to open libtpu.so: libtpu.so: cannot open shared object file: No such file or directory
INFO:jax._src.xla_bridge:Unable to initialize backend 'tpu': INTERNAL: Failed to open libtpu.so: libtpu.so: cannot open shared object file: No such file or directory
INFO:absl:orbax-checkpoint version: 0.11.13
INFO:absl:Created BasePyTreeCheckpointHandler: use_ocdbt=True, use_zarr3=False, pytree_metadata_options=PyTreeMetadataOptions(support_rich_types=False), array_metadata_store=<orbax.checkpoint._src.metadata.array_metadata_store.Store object at 0x767f7346dc90>
INFO:absl:Restoring checkpoint from /workspace/ckpt/corr_v1_1499/params.
別のタブで開く保存

依頼57:成功6本の手首を点検し、次の学習データ corr_v4 と続きの学習を用意する

成功6本を次の学習データに使うかは、手首の点検の結果で決めることにしました。点検・学習データづくり・続きの学習の設定までを、1つの依頼にまとめています。アームは使わず、学習も回しません。報告が来たら、入れる回の案を確かめてから、Runpod で学習を回します。

ねらい・変わったこと・見込める効果は次のとおりです。

  • ねらい:手首が力負けしたまま記録した動きを、正しい動きとして AI に覚えさせない
  • 変わったこと:成功の記録を学習に入れる前に、止まったあとの関節のずれで点検する手順を入れた
  • 見込める効果:垂れた手首の姿勢を覚えさせるのを防げる見込み。点検の結果は、依頼57の報告の数字で確かめる

依頼文 20261101_57_今日の成功6本の手首を点検し補正データcorr_v4と続きの学習を用意する.md

---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 120
---
# 依頼:今日の補正つきの成功6本の手首(j4)を点検し、使える回で補正データ corr_v4 と続きの学習を用意する(2026-11-01)

依頼 52(コミット eb491c5)で用意した新しいモデル corr(pi05-mecharm-trim-corr-lora-v1 の 1499)で、今日 Log18 として実機推論を9回回した。

## 今日の9回(KIOXIA の runs/pi05_policy/)

| run | 結果 | 補正 |
|---|---|---|
| pi05_20261101_190347 | 成功 | 2 |
| pi05_20261101_190854 | 成功 | 2 |
| pi05_20261101_191547 | 失敗(補正なし。根元 j0 が 2〜3° 足りずに空振り) | 0 |
| pi05_20261101_192101 | 成功 | 2 |
| pi05_20261101_192418 | 成功 | 2 |
| pi05_20261101_192758 | 失敗 | 2 |
| pi05_20261101_193041 | 成功 | 2 |
| pi05_20261101_193411 | 成功 | 1 |
| pi05_20261101_194042 | 失敗。最後の HOME で j4 が 0° を越えて +54° に行き、そのまま戻らなくなった | 1 |

(195421・195807 は手首が戻らなくなったあとの再起動の試しで、推論していない。使わない)

9回目のあと、手首が戻らずアームが垂れ下がった。電源を入れ直してもだめだったので、今日の実機はここで終えた。手首のサーボは、エイイチがあとで点検する。

states.csv から、j4 の「直前に送った指令と実測の差」の最大を出すと、回ごとに大きくなっていた(動いている途中の遅れも含んだ粗い値)。
190347: 3.5° / 190854: 2.5° / 192101: 1.8° / 192418: 10.3° / 192758: 19.5° / 193041: 18.4° / 193411: 8.0° / 194042: 59.5°

手首が力負けしたまま記録した動きを学習に入れると、垂れた手首を正しい動きとして覚えてしまうおそれがある。そのため、成功6本を使う前に点検する。

## A. 成功6本の手首の点検(読むだけ)

- 対象:190347・190854・192101・192418・193041・193411
- 止まっているはずの所で、j4 が指令よりどれだけ垂れているかを run ごとに出す。止まっているはずの所の例は、着いたと判定したあと・爪の開け閉めの前後・補正の1刻みのあと。ほかの関節(特に j1・j2)も同じように出す
- 動いている途中の遅れと、止まったあとも残るずれ(垂れ)を分けて出す。分け方は Claude Code が決め、理由を報告に書く
- 9回目(194042)で、外れる前に兆しがあったかも見る。いつから、どの関節で、どう出ていたか
- 結果から、学習に入れてよい回・入れない回を Claude Code が案として決め、理由を書く。決め手になる数字(止まったあとの j4 のずれの目安など)も書く

## B. 補正データ corr_v4 を作る

- A で入れてよいとした回だけを使う
- 作り方は corr_v3 と同じにする:依頼 46 の角度の作り直し(ウ)と、依頼 48 の止まりの詰め方を、同じ処理・同じしきい値で使う
- 今日の回は依頼 46 のあとの記録なので、動いている間の角度の取れ方が corr_v1 の5本と違うかもしれない。作り直しが要るかどうかを確かめて書く
- 前回の5本(corr_v3)と今日の回を合わせて `mecharm_redblock_box_corr_v4` を作る。お手本と合わせたデータセット(`..._trim2_corr_v4`)と、Pod に送る tar も作る。corr_v1〜v3 は残す
- データの点検(check_dataset)を通し、run ごとに次を出す:コマ・補正のコマ・止まりの割合・1コマの最大の動き

## C. 続きの学習の設定(学習は回さない)

- 今のモデル corr_v1_1499(Hugging Face の PixelstoMotors/pi05-mecharm-trim-corr-lora-v1。KIOXIA の checkpoints/ に原本)から続けて学習する設定を足す
  - 設定名の例:`pi05_mecharm_trim_corr_v4_lora`
  - ステップ数:1,500
  - 学習率の予定と正規化の値:前回(依頼 48)と同じ考え方にする。正規化は trim2 の値のまま
- lab_train.sh で1行で回せるようにする。続きの元(init)がこれまでの 3999 ではなく 1499 になる点に気をつける。由来の記録(依頼 54・56)が、そのまま残ることも確かめる
- 新しいモデルの Hugging Face のリポジトリ名の案:`pi05-mecharm-trim-corr-lora-v2`
- lab_start.sh の `--model` に、この新しいモデルを足す(例 `--model corr2`)
- Pod で回す1行を報告に書く。学習は Claude が回す

## 確かめ

- 既存のテストが全部通ること。A・B・C のテストを足す
- codex のレビューを通す(docs/ に依頼文と結果を残す)
- 測定データ(runs/・datasets/・checkpoints/ の既存のもの)は上書き・移動・削除しない。書く前に KIOXIA のマウントを確かめる
- アームは使わない(手首の点検前のため)
- git は個別ファイルを指定して add する

## 報告に書くこと

- A:run ごとの手首(と他の関節)の、動いている途中の遅れと止まったあとのずれ。9回目の兆し。入れる回・入れない回の案と理由
- B:corr_v4 の場所と、run ごとの数
- C:変えた設定、学習を回す1行、lab_start.sh の新しい `--model`
- 変えたファイル、コミット、テストの件数
- 決めてほしいこと

依頼58:手首(j4)のサーボを、1行で点検するスクリプトを作る

手首は硬くも熱くもなく、垂れるのは手首だけでした。そこで、関節の軸やギアより、サーボの電気や通信の側を疑っています。次にアームの前に立ったとき、1行で回せる点検を Claude Code に頼みました。6つのサーボの、力が入っているか・角度・電圧・温度・エラーを読み、そのあと手首だけに力を入れ直して、5°ずつ 0° の方へ動かします。

依頼文 20261101_58_手首j4のサーボを点検するスクリプトを作る.md

---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 60
---
# 依頼:手首(j4)のサーボを点検するスクリプトを作る(2026-11-01)

## 起きたこと

- 今日(Log18)の実機推論の9回目(runs/pi05_policy/pi05_20261101_194042)で、最後に h で HOME に戻すとき、j4 が -47° から 0° を越えて +54° まで行き、そのまま戻らなくなった
- 次の HOME(lab_start の 10 回目)では、j4 だけが +54.49° のまま。ほかの関節は HOME に着いた。待っても動かなかった
- そのあと、アームが垂れ下がった。エイイチの見立てでは、垂れているのは手首だけ
- アームの電源を入れ直してもだめだった
- 手首の関節は、手で触って硬くなっていない。熱も持っていない
- 今日の回ごとに、j4 の「指令と実測の差」の最大が大きくなっていた(3.5 → 2.5 → 1.8 → 10.3 → 19.5 → 18.4 → 8.0 → 59.5°)。詳しくは依頼 57 で調べている

## やってほしいこと

アームの前にエイイチがいるときに、1行で回せる点検のスクリプトを作る(例 `tools/servo_check.sh`。Pi 側の処理が要るなら、その分も作る)。**この依頼では実機に流さない。**

### 1. 読むだけの点検(アームを動かさない)
- 6つのサーボそれぞれについて、次を出す(mechArm 270-Pi の pymycobot で取れるもの)
  - 力が入っているか(is_servo_enable など)
  - 角度
  - 電圧・温度・状態やエラーの値
  - 応答があるか
- 取れないものは「取れない」と出す。pymycobot の版で使えない関数は、代わりの取り方を調べて使う
- デーモンがシリアルを持っている間は、直接つなぐとぶつかる。デーモン経由で読むか、いったんデーモンを止めて読み、終わったら戻すかを Claude Code が決める。止めるなら、戻すところまでスクリプトに入れる

### 2. 力を入れ直して、少しだけ動かす(エイイチが見ている前で)
- 1 の結果を画面に出したあと、Enter で次へ進む形にする
- j4 だけに力を入れ直す(focus_servo など)。入れ直した直後の角度も出す
- j4 を今の位置から 0° の方へ、5° ずつ動かす。1回ごとに、指令と実測と、着いたかどうかを出す。q でいつでも止める
- 手首を手で支えておくよう、最初に1行だけ表示する。それ以外の確認や止める条件は増やさない
- 0° に戻れたら、HOME(全関節 0°、j5 -30°)へ送り、着いたかを出す

### 3. 結果を残す
- 画面の出力を `diag/servo_check_{日時}/` に残す(MASTER の保存先テーブルの「測定スクリプトの出力(単軸診断など)」)

## 確かめ

- 偽のデーモン・偽の pymycobot で流れを試すテストを足す。既存のテストが全部通ること
- 関節を動かすので、codex のレビューを通す(docs/ に依頼文と結果を残す)
- 既存の runs/・datasets/ には書かない。書く前に KIOXIA のマウントを確かめる
- git は個別ファイルを指定して add する

## 報告に書くこと

- 打つ1行と、画面の見方(何が出たら何を疑うか:力が入っていない・応答がない・電圧が低い・角度の読みだけずれている、など)
- 変えたファイル、コミット、テストの件数
- 決めてほしいこと

記事の画像を録画から取り出すコード grab_frames.py

冒頭の画像は、上カメラの録画(top.mp4・1920×1080)から、決めた推論の時刻に近いコマを取り出して 2×2 に並べたものです。Mac で動かしたあと、ラベルの文字だけを日本語に書き直しています。

"""LOG422 の画像:上カメラの録画(top.mp4, 1920x1080)から、決めた時刻のコマを取り出して 2x2 に並べる。
使い方: python3 grab_frames.py <runs/pi05_policy> <出力png>
"""
import cv2, csv, json, sys, pathlib
R = pathlib.Path(sys.argv[1]); OUT = sys.argv[2]

def chunk_t(stem, k):
    for line in open(R / stem / "log.jsonl"):
        x = json.loads(line)
        if x.get("type") is None and x.get("chunk") == k:
            return x["t"]

def frame_at(stem, t):
    rows = list(csv.DictReader(open(R / stem / "recording" / "top_frame_log.csv")))
    if t is None:
        idx = 0
    else:
        idx = min(range(len(rows)), key=lambda i: abs(float(rows[i]["capture_ts"]) - t))
    cap = cv2.VideoCapture(str(R / stem / "recording" / "top.mp4"))
    cap.set(cv2.CAP_PROP_POS_FRAMES, int(rows[idx]["frame_idx"]))
    ok, im = cap.read()
    return im, idx

panels = [
    ("pi05_20261101_190347", None, "1: HOME (start)"),
    ("pi05_20261101_190347", 6, "1: after close (corrected) - grasped"),
    ("pi05_20261101_191547", 6, "3: after close (no correction) - missed"),
    ("pi05_20261101_195421", None, "after run 9: HOME, wrist j4 stuck at +54"),
]
tiles = []
for stem, k, label in panels:
    im, idx = frame_at(stem, chunk_t(stem, k) if k is not None else None)
    im = cv2.resize(im, (960, 540))
    cv2.rectangle(im, (0, 0), (960, 44), (13, 13, 13), -1)
    cv2.putText(im, label, (14, 31), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (240, 245, 245), 2, cv2.LINE_AA)
    tiles.append(im)
    print(stem, k, "frame", idx)
grid = cv2.vconcat([cv2.hconcat(tiles[:2]), cv2.hconcat(tiles[2:])])
cv2.imwrite(OUT, grid)
print(OUT, grid.shape)

Mac で打ったコマンド:

cd "$HOME/mnt/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/LOG422_sources"
mkdir -p ../LOG422_images && python3 grab_frames.py "$HOME/mnt/KIOXIA/r2r2r-data/runs/pi05_policy" ../LOG422_images/LOG422_01_grasp_and_wrist.png

出力:

pi05_20261101_190347 None frame 0
pi05_20261101_190347 6 frame 1368
pi05_20261101_191547 6 frame 552
pi05_20261101_195421 None frame 0
../LOG422_images/LOG422_01_grasp_and_wrist.png (1080, 1920, 3)

ラベルを日本語に書き直したコード(Claude のクラウドの作業環境):

from PIL import Image, ImageDraw, ImageFont
src="/mnt/user-data/uploads/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/LOG422_images/LOG422_01_grasp_and_wrist.png"
im=Image.open(src).convert("RGB"); d=ImageDraw.Draw(im)
f=ImageFont.truetype("/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc",26,index=0)
labels=["1回目:始めの HOME","1回目:根元を直してから爪を閉じた → つかめた","3回目:直さずに爪を閉じた → 空振り","9回目のあと:HOME に戻しても手首 j4 が +54° のまま"]
for i,t in enumerate(labels):
    x=(i%2)*960; y=(i//2)*540
    d.rectangle([x,y,x+959,y+43],fill=(13,13,13))
    d.text((x+14,y+6),t,font=f,fill=(245,245,240))
im.save("/mnt/user-data/outputs/LOG422/LOG422_images/LOG422_01_grasp_and_wrist.png")

費用

何に借りた時間費用
実機の9回と、手首の確かめの Pod(A40)
65分42秒約0.65ドル(約102円)

次に実機で確かめること

  1. 依頼58の点検スクリプトで、手首のサーボに力が入るか・指令に応えるかを見る。HOME で6つの関節がすべて 0°(j5 は −30°)の近くに戻るか
  2. 依頼57の報告で、成功6本のうち学習に入れる回を決め、corr_v4 で学び直す
  3. 学び直したモデルで、補正なしの回を数回回し、爪を閉じる根元の角度が 11.5° からどこまで 13° 前後に近づくか、つかんだあとの持ち上げが足りるかを数える