---
title: "フィジカルAI研究室の中身を一目で伝える ― 構成・実験・技術の解説を /series6 に"
slug: physical-ai-lab-page-explained-at-a-glance
date: 2026-11-08
day: 462
meta_description: "pixelstomotors.com のフィジカルAI研究室のページ（/series6）に、構成・実験・いま調べていること・技術の解説を足し、HTML から読める説明が2,298字増えた。数字は記録22本の値で元の LOG へつないだ。"
tags: [サイト改善, フィジカルAI研究室, π0.5, mechArm 270, CSS subgrid, 射影変換, サーボの電流]
series: "ひとり研究所の裏側"
---

**pixelstomotors.com のフィジカルAI研究室のページ（/series6）に、研究室の構成・いま回している実験・いま調べていること・使っている技術の4つの解説を足し、ページの HTML から読める研究室の説明に2,298字が加わりました。** 研究室は、小型のロボットアーム mechArm 270 と Mac に、Runpod で時間単位で借りる GPU（NVIDIA A40）を足しただけの構成で、[Physical Intelligence の π0.5](https://www.pi.website/blog/pi05)（ロボット用の AI のモデル）に、赤いブロックを白い箱へ入れる作業を覚えさせています。

足したことで、次のことが変わりました。

- 初めて来た人は、研究室の記録（Log#1〜#22）を1本も開かずに、何を使い、何を試し、いまどこまで来たかを1ページでつかめる。解説の数字はすべて記録の値で、元の記録へのリンクを18本付けた
- AI と検索エンジンは、図ではなく HTML の文字として説明を読める。見出しの下の説明は、導入比較ガイドのバナーを含めて295字だった
- 時間：依頼（11月7日 16:10）から最初の公開（16:20）まで10分。画面写真に一言ずつ付いた直しと足しを5回入れ、最後の公開は18:13。前に同じ量の解説を作ったときの時間は測っていない
- 引き換え：研究室の構成に実機の動画（0.77MB）を入れたので、ページは重くなった

始まりは、フィジカルAI研究室のページが、見出しと短い紹介文、GPU の導入比較ガイドのバナー、記録のカードの並び、だけだったことです。記録のカードを開けば全部書いてありますが、記録は作業ログなので、1本ずつ読んで全体をつかむのは、初めての人にはかなりきつい。

> フィジカルAI研究所にページの解説セクションを追加してください。どんな構成で、どんな実験を行なっていて、どんな技術的なことなのかを一目でわかるようにしたです。

最初の版は10分で出せましたが、矢印の図と、意味の分からない黒いカード、見出しの長さで段々になったカード、斜めに写った写真が残っていました。そこから、画面写真に一言の指示 → 直して公開 → 実際の画面で確かめる、を5回回しています（5回目は爪の電流の図を足す依頼）。

| やったこと | なぜ | 結果 |
|---|---|---|
| 研究室の記録22本から、解説に載せる数字と道具を拾った | 解説の数字を、記録で確かめられる値だけにするため | 19本・4,000ステップ・15回中9回・13秒・11本など。どれも元の LOG へリンク |
| 構成・実験・技術の3つの節を作った（commit c7caad9） | 依頼の3つ（構成・実験・技術）に1節ずつ答えるため | 10分で最初の公開 |
| 実験のカードの段をそろえた（commit 09c80f5） | 見出しが2行のカードだけ数字が下がり、段々に見えた | CSS の subgrid で、5枚の数字の高さが同じになった。上の線も外した |
| 矢印の図と黒いカードをやめた（commit c556a04・43cf04c） | 矢印はごちゃつき、黒いカードは意図が伝わらなかった | 実機の動画と、手元に置くもの・時間で借りるものの2つの一覧 |
| 上のカメラの写真の傾きを直した（commit 965efdb） | マットが斜めに写っていた | 元の録画（1920×1080）から、マットの縁で射影変換して切り直した |
| 爪の電流の図を足した（commit 3a73764・43f5322） | 別のチャットで、爪の電流でつかめたかが分かると出た | 空で閉じた15前後・つかんだ870前後の図。LOG461 の公開後に数字とリンクをそろえた |

【図解】LOG462_subgrid_align.html

【画像】LOG462_01_before_series6.png 解説を足す前のフィジカルAI研究室のページ。見出しと紹介文、GPU の導入比較ガイドのバナーの下に、すぐ記録のカードが並んでいた


## 作業ログ ― 解説に載せる数字を、研究室の記録22本から拾う

### 載せた数字は、記録で確かめられる値だけにした

解説の数字は、あとで変わってもたどれるように、すべて記録（LOG）の値から取り、その LOG へのリンクを付けました。数字は 2026年11月6日（LOG450）までの記録の値で、ページの実験の節の下にもそう書いています。

| 載せた所 | 数字 | 出どころ |
|---|---|---|
| 構成：Runpod の A40 | GPU のメモリ 48GB、1時間あたり約98円 | LOG401・LOG450 |
| 構成：Hugging Face | 学習済みのモデル 6.3GB、借りた GPU が13秒で取ってくる | LOG401・LOG450 |
| 構成：ゲームパッド | 3,198円の互換品 | LOG419 |
| 実験 01 お手本を集める | 19本（置き場所5か所） | LOG349・LOG352 |
| 実験 02 π0.5 に覚えさせる | 4,000ステップ、学習の誤差（loss）0.0858 → 0.0037 | LOG341・LOG355・LOG358 |
| 実験 03 実機で動かす | 15回中9回（腕を伸ばしきる位置は5回中1回） | LOG361・LOG401 |
| 実験 04 人が直す | 1回あたり中央の値で13秒（キーで直していた頃は41〜51秒） | LOG403・LOG446・LOG450 |
| 実験 05 直した成功を学習に足す | 11本、前のモデルから1,500ステップ続けて学ぶ | LOG417・LOG422 |
| 技術：推論サーバー | π0.5 の計算は1回平均97ミリ秒、Mac から送って返るまでの往復は391ミリ秒（A40） | LOG326 |
| いま調べていること | 爪の値は、空で閉じると15前後、つかむと870前後 | LOG461 |

### 研究室の記録の一覧（作業を始めた時点で Log#1〜#22）

Studio から移した記事（src/data/cards.json）と、新しい記事（src/content/records/）の両方から、シリーズがフィジカルAI研究室の記事を拾いました。下の一覧は記事化のときに出し直したもので、作業のあとに公開された Log#23（LOG461）と Log#24（LOG460）も入っています。

```python
# フィジカルAI研究室の記録の一覧を、p2m-site の中から作る（cards.json は Studio から移した記事、records は新しい記事）
import json,glob,re
c=json.load(open('src/data/cards.json'))
rows={}
num=lambda s:int(re.sub(r'\D','',str(s)))
for x in c:
    if x['series']=='フィジカルAI研究室': rows[num(x['day'])]=(x['title'],x['slug'])
for f in glob.glob('src/content/records/*.md'):
    s=open(f).read(3000)
    if 'series: "フィジカルAI研究室"' in s:
        t=re.search(r'^title: "(.*)"',s,re.M).group(1); sl=re.search(r'^slug: (.*)',s,re.M).group(1); d=num(re.search(r'^day: (\S+)',s,re.M).group(1))
        rows[d]=(t,sl)
for d in sorted(rows): print(d,'|',rows[d][0])
print(len(rows))
```

```
225 | SO-101 失敗から学ぶアームを作る Log#1 | 精度を上げることと、失敗から学ぶことは違う
234 | SO-101 失敗から学ぶアームを作る Log#2 | 2TBの外付けSSDを、学習データの定位置にする
277 | フィジカルAI研究室を作る Log#1 | 自宅にゼロから、誰でも再現できる形で
326 | フィジカルAI研究室を作る Log#2 | Physical Intelligence の π0.5 を借りたGPUで動かした
327 | フィジカルAI研究室を作る Log#3 | Physical Intelligence の π0.5 に要るGPUメモリを測った
337 | フィジカルAI研究室を作る Log#4 | Physical Intelligence の π0.5 を mechArm 270 で追加学習
341 | フィジカルAI研究室を作る Log#5 | Physical Intelligence の π0.5 を学習。予測はお手本とほぼ一致
345 | フィジカルAI研究室を作る Log#6 | Physical Intelligence の π0.5 で実機を動かすと、爪がブロックに乗った
348 | フィジカルAI研究室を作る Log#7 | Physical Intelligence の π0.5 を倍学習しても、爪は奥へずれた
349 | フィジカルAI研究室を作る Log#8 | 手で教えた動きを再生し、4回続けて箱に入れた
352 | フィジカルAI研究室を作る Log#9 | 手で教えてお手本19本。肩88°を超えた姿勢は動かなかった
355 | フィジカルAI研究室を作る Log#10 | 位置を変えたお手本で、Physical Intelligence の π0.5 を学習し直した
358 | フィジカルAI研究室を作る Log#11 | Physical Intelligence の π0.5 は「待ち時間」まで覚えた
361 | フィジカルAI研究室を作る Log#12 | Physical Intelligence の π0.5 が初めてブロックを箱に入れた
363 | フィジカルAI研究室を作る Log#13 | Physical Intelligence の π0.5 がお手本の3か所すべてで箱に入れた
401 | フィジカルAI研究室を作る Log#14 | π0.5 を回数で測ったら、苦手な置き場所が見えた
403 | フィジカルAI研究室を作る Log#15 | mechArm 270 の失敗を巻き戻し、直して覚えさせる
407 | フィジカルAI研究室を作る Log#16 | 直した mechArm 270 の動きを π0.5 に覚えさせる手前まで
417 | フィジカルAI研究室を作る Log#17 | 人が直した mechArm 270 の5回で π0.5 を学び直す
419 | フィジカルAI研究室を作る Log#19 | ゲームパッドで mechArm 270 を直す準備ができた
422 | フィジカルAI研究室を作る Log#18 | 学び直した π0.5 でも mechArm 270 には人の直しが要った
436 | フィジカルAI研究室を作る Log#20 | ゲームパッドで動いた mechArm 270、遅さは pymycobot の版
446 | フィジカルAI研究室を作る Log#21 | ゲームパッドで mechArm 270 を直す形が固まった
450 | フィジカルAI研究室を作る Log#22 | mechArm 270 の AI の直しが、ゲームパッドで1回13秒に
460 | フィジカルAI研究室を作る Log#24 | π0.5 の失敗の原因を探ると、浅いお手本だった
461 | フィジカルAI研究室を作る Log#23 | 手応えを学習に足すため、mechArm 270 の電流を読んだ
26
```

### 先に決めたこと：1つの節で伝えることは1つ

デザインの進め方の決まり（LOG369 で整理したもの）に沿って、節ごとに伝えることを先に1つ決めました。研究室の構成は、机の上と借りる GPU の何で動いているか。実験は、お手本 → 学習 → 実機 → 人の直し → 学び直し のループ。技術は、使っている5つの技術の名前と中身です。1つの節に3つ以上のことを入れない、要らない飾りは入れない、ボタン・矢印・角丸はサイトのほかのページ（画像認識の /series7 の解説）にそろえる、も最初から守るつもりで作りました。


## 作業ログ ― 最初の版：構成・実験・技術の3つの節（commit c7caad9・16:20）

### 部品 LabGuide.astro を作り、/series6 だけに出す

画像認識のページ（/series7）には、同じ日の朝に入れた解説の部品 VisionGuide.astro があります。同じ置き方で、研究室用の部品 LabGuide.astro を作り、シリーズの設定（src/lib/records.ts）に lab: true を足したページだけに出すようにしました。中身の図はすべて HTML の文字と CSS で組み、画像の中に説明の文字を焼き込まないようにしています（AI が読めるように）。

### 写真の素材：横からの録画のコマと、π0.5 に渡したお手本のコマ

研究室の構成の写真には、10月29日に π0.5 で実機を回したときの横からの録画（LOG401 の15回の試し）からコマを抜きました。技術の節の π0.5 の行には、π0.5 に実際に渡したお手本のコマ（384×216）を置きました。

```bash
# 横からの録画（2026-10-29・IMG_4215.MOV・3840×2160）から5コマを抜く（Mac 連携の shell）
cd "$HOME/mnt/KIOXIA/r2r2r-data/recordings/20261029_iphone"
mkdir -p $HOME/frames
for t in 5 40 80 120 160; do ffmpeg -v error -y -ss $t -i IMG_4215.MOV -frames:v 1 -vf scale=1600:-2 -q:v 3 "$HOME/frames/a_$t.jpg"; done
D="$HOME/mnt/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/series6_guide_images"
mkdir -p "$D" && cp $HOME/frames/*.jpg "$D/"

# π0.5 に渡したお手本のコマ（corr_v5 の pi05_20261106_183926・384×216）
cd "$HOME/mnt/KIOXIA/r2r2r-data/datasets/mecharm_redblock_box_teach_v1_trim2_corr_v5/raw_episodes/pi05_20261106_183926"
cp frames/000000.jpg "$D/top_000.jpg"; n=$(ls frames | wc -l); cp frames/$(printf %06d $((n/2))).jpg "$D/top_mid.jpg"
```

```python
# 最初の版の写真2枚（commit c7caad9）。desk.webp はのちに動画へ替えて消した
from PIL import Image
U='/mnt/user-data/uploads/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/series6_guide_images/'
im=Image.open(U+'a_80.jpg').convert('RGB'); im=im.crop((60,0,1600-60,900-60)); im=im.resize((1200,round(1200*im.size[1]/im.size[0])),Image.LANCZOS); print(im.size); im.save('public/site/lab/desk.webp',quality=84)
t=Image.open(U+'top_mid.jpg').convert('RGB'); print(t.size); t.save('public/site/lab/top-camera.webp',quality=92)
```

```
(1200, 681)
(384, 216)
```

### 最初の版の画面

研究室の構成は、机の上・手元の Mac・時間で借りる GPU の3つの箱を横に並べ、間を矢印でつなぎました。借りる GPU の箱だけを黒く塗っています。実験は5枚のカードを横に並べ、カードの上に黒い線を引きました。

【画像】LOG462_02_setup_arrows.png 最初の版の研究室の構成。机の上・手元の Mac・時間で借りる GPU の3つの箱が矢印でつながり、右の GPU の箱だけが黒い

### 最初の版の差分（commit c7caad9）

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
new file mode 100644
index 0000000..51bc453
--- /dev/null
+++ b/src/components/LabGuide.astro
@@ -0,0 +1,238 @@
+---
+// /series6（フィジカルAI研究室）の見出しの下に置く解説（2026-11-07）
+// 1 研究室の構成：机の上・Mac・借りた GPU の3か所と、その間を行き来するもの（図は HTML で組む。AI も読めるように）
+// 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
+// 3 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
+// 写真は public/site/lab/（desk.webp は 2026-10-29 の横からの録画 IMG_4215.MOV の80秒目、
+// top-camera.webp は corr_v5 のお手本 pi05_20261106_183926 の真ん中のコマ。元は iCloud の
+// フィジカルAI研究室を作る/series6_guide_images/）
+// 数字はどれも LOG の記録の値。新しい LOG で数字が変わったら、ここも書き換える
+type Link = { log: string; slug: string; t: string };
+
+const zones = [
+  { key: 'desk', name: '机の上', img: true, items: [
+    { h: 'mechArm 270', p: '6つの関節を持つ小型のロボットアーム。中の Raspberry Pi が指令を受けて関節を動かします。' },
+    { h: '上のカメラ', p: 'スマホを真上に付けて、マットとブロックと箱を撮ります。π0.5 が見るのはこの画像だけです。' },
+    { h: 'ゲームパッド', p: 'AI が失敗しかけたとき、人が関節を直すのに使います。3,198円の互換品です。' },
+  ] },
+  { key: 'mac', name: '手元の Mac', items: [
+    { h: '記録と中継', p: 'カメラの画像と関節の角度を1秒10コマで記録し、借りた GPU に送り、返ってきた動きをアームへ渡します。' },
+    { h: 'AI と組み立てる', p: '手順と分析は Claude、アームを動かすプログラムは Claude Code と一緒に書いています。' },
+  ] },
+  { key: 'gpu', name: '時間で借りる GPU', items: [
+    { h: 'Runpod の A40', p: 'GPU のメモリは 48GB、1時間あたり約98円。π0.5 の学習と推論は、すべてここで行います。' },
+    { h: 'Hugging Face', p: '学習済みのモデル（6.3GB）の置き場所。GPU を借りるたびに、ここから13秒で取ってきます。' },
+  ] },
+];
+
+const loop: { h: string; num: string; unit: string; p: string; links: Link[] }[] = [
+  { h: 'お手本を集める', num: '19', unit: '本',
+    p: '要所の姿勢だけ手でアームに教え、間は再生でつないで録りました。ブロックの置き場所は5か所です。',
+    links: [
+      { log: 'LOG349', slug: 'drag-teach-waypoint-replay', t: '手で教えた動きを再生' },
+      { log: 'LOG352', slug: 'teach-replay-19-demos', t: 'お手本19本' },
+    ] },
+  { h: 'π0.5 に覚えさせる', num: '4,000', unit: 'ステップ',
+    p: '借りた A40 で追加学習し、学習の誤差（loss）は 0.0858 から 0.0037 に下がりました。',
+    links: [
+      { log: 'LOG341', slug: 'pi05-mecharm-lora-2000-steps', t: '最初の学習' },
+      { log: 'LOG355', slug: 'pi05-retrain-five-positions', t: '5か所で学習し直す' },
+      { log: 'LOG358', slug: 'pi05-learned-the-pauses', t: '待ち時間まで覚えた' },
+    ] },
+  { h: '実機で動かす', num: '9/15', unit: '回',
+    p: '3か所に5回ずつブロックを置き、人が手を出さずに箱へ入れた回数です。腕を伸ばしきる位置は5回中1回でした。',
+    links: [
+      { log: 'LOG361', slug: 'pi05-first-block-in-box', t: '初めて箱に入れた' },
+      { log: 'LOG401', slug: 'pi05-weak-position-d', t: '回数で測る' },
+    ] },
+  { h: '失敗しかけたら人が直す', num: '13', unit: '秒',
+    p: '動きを巻き戻し、ゲームパッドで関節を直して AI に戻すまでの、1回あたりの中央の値です。キーで直していた頃は41〜51秒でした。',
+    links: [
+      { log: 'LOG403', slug: 'rewind-and-correct-pi05', t: '巻き戻しの仕組み' },
+      { log: 'LOG446', slug: 'gamepad-correction-mecharm-270-settled', t: 'ゲームパッドの形' },
+      { log: 'LOG450', slug: 'gamepad-fixes-mecharm-270-ai-in-13-seconds', t: '1回13秒に' },
+    ] },
+  { h: '直した成功を学習に足す', num: '11', unit: '本',
+    p: '人が直して成功した記録をお手本に足し、前のモデルから1,500ステップ続けて学び直します。',
+    links: [
+      { log: 'LOG417', slug: 'retrain-pi05-with-human-corrections', t: '直した5回で学び直す' },
+      { log: 'LOG422', slug: 'retrained-pi05-still-needs-human-corrections', t: 'それでも直しが要った' },
+    ] },
+];
+
+const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[] }[] = [
+  { name: 'π0.5', sub: 'Physical Intelligence', fig: true,
+    p: '米国の Physical Intelligence 社が公開している、ロボット用の AI のモデルです。上のカメラの画像、6つの関節と爪の角度、指示文（赤いブロックを白い箱に入れる）を受け取り、次の1秒ぶん（10コマ）の関節の角度を返します。どの順番で動くかを書いたプログラムはありません。',
+    links: [{ log: 'LOG337', slug: 'pi05-mecharm-demo-to-inference', t: 'mechArm 270 で動かすまでの流れ' }] },
+  { name: '追加学習', sub: 'LoRA',
+    p: 'たくさんのロボットのデータで学習済みの π0.5 に、mechArm 270 のお手本だけを足して覚えさせます。モデル全体ではなく、足した小さな部品だけを学習するので、A40 を1枚借りれば足ります。',
+    links: [{ log: 'LOG341', slug: 'pi05-mecharm-lora-2000-steps', t: '予測がお手本とほぼ一致' }] },
+  { name: '時間で借りる GPU', sub: 'Runpod',
+    p: 'π0.5 は NVIDIA の GPU を積んだ Linux のマシンでしか動かず、Mac では動きません。そこで GPU を時間単位で借ります。学習は自動で回し、終わるとモデルを持ち帰って、借りたマシンを消します。',
+    links: [{ log: 'LOG401', slug: 'pi05-weak-position-d', t: 'モデルを Hugging Face に置いた' }] },
+  { name: '推論サーバー', sub: 'Remote inference',
+    p: '借りたマシンの上で π0.5 を起動し、Mac とは SSH の中継でつなぎます。π0.5 の計算は1回平均97ミリ秒、Mac から送って答えが返るまでの往復は391ミリ秒でした（A40）。',
+    links: [{ log: 'LOG326', slug: 'openpi-remote-inference-first-run', t: '借りた GPU で初めて動かした' }] },
+  { name: '巻き戻しと人の直し', sub: 'Human correction',
+    p: '米国の MicroFactory の卓上ロボットを参考にしました。失敗しかけた区間をアームごと巻き戻し、人が関節を直してから AI に戻します。直す人の手はカメラに写らないので、直した動きをそのまま学習データにできます。',
+    links: [{ log: 'LOG403', slug: 'rewind-and-correct-pi05', t: '直した動きだけを学習データにする' }] },
+];
+---
+<section class="sec lg"><div class="panel">
+  <h2 class="sec-h">研究室の構成 | Setup</h2>
+  <p class="lg-lead">机の上のアーム、手元の Mac、時間で借りる GPU の3か所でできています。AI の学習と推論は、すべて借りた GPU の上で行っています。</p>
+  <div class="lg-map">
+    {zones.map((z, i) => (
+      <>
+        {i > 0 && (
+          <div class="lg-flow" aria-hidden="true">
+            <span class="lg-flow-go"><i class="ms">arrow_forward</i>{i === 1 ? '画像と関節の角度' : '画像・角度・指示文'}</span>
+            <span class="lg-flow-back"><i class="ms">arrow_back</i>次の1秒の動き</span>
+          </div>
+        )}
+        <div class={`lg-zone lg-zone-${z.key}`}>
+          <p class="lg-zone-name">{z.name}</p>
+          {z.img && <img class="lg-desk" src="/site/lab/desk.webp" alt="マットの上の mechArm 270 が赤いブロックをつかみ、右に白い箱が置いてある" width="1200" height="681" loading="lazy" />}
+          <dl class="lg-items">
+            {z.items.map((it) => (<div><dt>{it.h}</dt><dd>{it.p}</dd></div>))}
+          </dl>
+        </div>
+      </>
+    ))}
+  </div>
+  <p class="lg-flow-text">Mac は上のカメラの画像と関節の角度を、指示文と一緒に借りた GPU へ送ります。π0.5 は次の1秒ぶんの関節の角度を返し、Mac がそれをアームへ渡します。</p>
+</div></section>
+
+<section class="sec lg"><div class="panel">
+  <h2 class="sec-h">いま回している実験 | Experiment</h2>
+  <p class="lg-lead">赤いブロックをつかんで、白い箱に入れる。この1つの作業を π0.5 に覚えさせ、失敗しかけた所を人が直し、直した動きをまた学習に回しています。人の直しが要らなくなるまで、このループを回します。</p>
+  <ol class="lg-loop">
+    {loop.map((s, i) => (
+      <li class="lg-step">
+        <span class="lg-step-no">{String(i + 1).padStart(2, '0')}</span>
+        <h3 class="lg-step-h">{s.h}</h3>
+        <p class="lg-num">{s.num}<small>{s.unit}</small></p>
+        <p class="lg-p">{s.p}</p>
+        <ul class="lg-links">
+          {s.links.map((l) => <li><a href={`/record/${l.slug}`} title={l.t} aria-label={`${l.log} ${l.t}`}><b>{l.log}</b><i class="ms">arrow_forward</i></a></li>)}
+        </ul>
+      </li>
+    ))}
+  </ol>
+  <p class="lg-return"><i class="ms" aria-hidden="true">replay</i>05 のあとは 03 に戻り、学び直したモデルで実機をもう一度動かします</p>
+  <p class="lg-note">数字は 2026年11月6日（LOG450）までの記録の値です。</p>
+</div></section>
+
+<section class="sec lg"><div class="panel">
+  <h2 class="sec-h">使っている技術 | Technology</h2>
+  <dl class="lg-tech">
+    {tech.map((t) => (
+      <div class="lg-tech-row">
+        <dt><span class="lg-tech-name">{t.name}</span><span class="lg-tech-sub">{t.sub}</span></dt>
+        <dd>
+          <div class={t.fig ? 'lg-tech-body has-fig' : 'lg-tech-body'}>
+            <div>
+              <p class="lg-p">{t.p}</p>
+              <ul class="lg-links">
+                {t.links.map((l) => <li><a href={`/record/${l.slug}`}><b>{l.log}</b>{l.t}<i class="ms">arrow_forward</i></a></li>)}
+              </ul>
+            </div>
+            {t.fig && (
+              <figure class="lg-fig">
+                <img src="/site/lab/top-camera.webp" alt="真上のカメラの画像。mechArm 270 の爪が赤いブロックをつかみ、右に白い箱がある" width="384" height="216" loading="lazy" />
+                <figcaption>π0.5 に渡している、上のカメラの画像（384×216）</figcaption>
+              </figure>
+            )}
+          </div>
+        </dd>
+      </div>
+    ))}
+  </dl>
+</div></section>
+
+<style>
+  .lg { padding-bottom: 0; }
+  .lg-lead { margin: -16px 0 32px; max-width: 46em; font: 400 16px/28px var(--sans); color: var(--ink-2); }
+  .lg-p { margin: 0; font: 400 15px/27px var(--sans); color: var(--ink-2); word-break: auto-phrase; text-wrap: pretty; }
+
+  /* 1 構成：3つの場所と、その間を行き来するもの */
+  .lg-map { display: grid; grid-template-columns: minmax(0, 1.35fr) 112px minmax(0, 1fr) 112px minmax(0, 1fr); align-items: start; }
+  .lg-zone { padding: 24px; border-radius: 8px; background: var(--bg); }
+  .lg-zone-gpu { background: var(--dark); color: #fff; }
+  .lg-zone-name { margin: 0 0 16px; font: 700 18px/28px var(--sans); color: var(--ink); }
+  .lg-zone-gpu .lg-zone-name { color: #fff; }
+  .lg-desk { display: block; width: 100%; height: auto; margin: 0 0 16px; border-radius: 6px; }
+  .lg-items { margin: 0; display: grid; gap: 14px; }
+  .lg-items dt { font: 700 15px/24px var(--sans); color: var(--ink); }
+  .lg-items dd { margin: 2px 0 0; font: 400 14px/24px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
+  .lg-zone-gpu .lg-items dt { color: #fff; }
+  .lg-zone-gpu .lg-items dd { color: #c8c8c2; }
+  .lg-flow { display: grid; align-content: start; gap: 28px; padding: 72px 8px 0; }
+  .lg-flow span { display: grid; justify-items: center; gap: 4px; text-align: center; font: 500 12px/18px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
+  .lg-flow .ms { font-size: 28px; color: var(--ink); }
+  .lg-flow-back .ms { color: var(--ink-3); }
+  .lg-flow-text { margin: 24px 0 0; max-width: 46em; font: 400 14px/24px var(--sans); color: var(--ink-3); }
+
+  /* 2 実験のループ */
+  .lg-loop { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
+  .lg-step { display: flex; flex-direction: column; padding: 20px; border-radius: 8px; border-top: 4px solid var(--dark); background: var(--bg); }
+  .lg-step-no { font: 700 13px/20px var(--sans); color: var(--ink-3); font-variant-numeric: tabular-nums; }
+  .lg-step-h { margin: 4px 0 12px; font: 700 16px/24px var(--sans); color: var(--ink); word-break: auto-phrase; }
+  .lg-num { margin: 0 0 12px; font: 700 40px/1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
+  .lg-num small { margin-left: 4px; font: 600 14px/1 var(--sans); color: var(--ink-2); letter-spacing: 0; }
+  .lg-step .lg-p { font-size: 14px; line-height: 24px; }
+  .lg-step .lg-links { margin-top: auto; padding-top: 16px; gap: 6px; }
+  .lg-step .lg-links a { gap: 4px; padding: 5px 8px 5px 10px; }
+  .lg-step .lg-links a { background: #fff; }
+  .lg-step .lg-links a:hover { background: #e6e6e6; }
+  .lg-return { display: flex; align-items: center; gap: 10px; margin: 12px 0 0; padding: 14px 20px; border-radius: 8px; background: var(--dark); color: #fff; font: 600 15px/24px var(--sans); }
+  .lg-return .ms { font-size: 22px; }
+  .lg-note { margin: 16px 0 0; font: 400 13px/22px var(--sans); color: var(--ink-3); }
+
+  /* 3 技術 */
+  .lg-tech { margin: 0; display: grid; }
+  .lg-tech-row { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 32px; padding: 28px 0; border-top: 1px solid #e6e6e6; }
+  .lg-tech-row:last-child { padding-bottom: 0; }
+  .lg-tech-row dt { display: grid; align-content: start; gap: 2px; }
+  .lg-tech-name { font: 700 20px/30px var(--sans); color: var(--ink); }
+  .lg-tech-sub { font: 400 13px/20px var(--sans); color: var(--ink-3); }
+  .lg-tech-row dd { margin: 0; }
+  .lg-tech-body { max-width: 52em; }
+  .lg-tech-body.has-fig { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 32px; align-items: start; }
+  .lg-fig { margin: 0; }
+  .lg-fig img { display: block; width: 100%; height: auto; border-radius: 6px; }
+  .lg-fig figcaption { margin: 8px 0 0; font: 400 12px/18px var(--sans); color: var(--ink-3); }
+
+  /* 記録へのリンク（/series7 の解説と同じ形） */
+  .lg-links { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
+  .lg-links a { display: inline-flex; align-items: center; gap: 8px; padding: 7px 10px 7px 12px; border-radius: 4px; background: #f2f2f2;
+    color: var(--ink); font: 500 13px/20px var(--sans); text-decoration: none; transition: background .15s; }
+  .lg-links a b { font-weight: 700; font-variant-numeric: tabular-nums; }
+  .lg-links a .ms { font-size: 15px; color: var(--ink-3); transition: transform .2s; }
+  .lg-links a:hover { background: #e6e6e6; }
+  .lg-links a:hover .ms { transform: translateX(2px); }
+
+  @media (max-width: 1199px) {
+    .lg-loop { grid-template-columns: repeat(3, minmax(0, 1fr)); }
+  }
+  @media (max-width: 1023px) {
+    .lg-map { grid-template-columns: minmax(0, 1fr); }
+    .lg-flow { grid-auto-flow: column; justify-content: center; gap: 32px; padding: 12px 0; }
+    .lg-zone { align-self: stretch; }
+    .lg-flow span { display: flex; align-items: center; gap: 6px; }
+    .lg-flow .ms { font-size: 22px; transform: rotate(90deg); }
+    .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+    .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
+    .lg-tech-body.has-fig { grid-template-columns: minmax(0, 1fr); gap: 20px; }
+    .lg-fig { max-width: 384px; }
+  }
+  @media (max-width: 599px) {
+    .lg-lead { margin: -16px 0 24px; font-size: 15px; line-height: 26px; }
+    .lg-zone { padding: 20px 18px; }
+    .lg-flow { gap: 16px; }
+    .lg-loop { grid-template-columns: minmax(0, 1fr); }
+    .lg-num { font-size: 36px; }
+    .lg-tech-row { padding: 22px 0; }
+    .lg-tech-name { font-size: 18px; line-height: 28px; }
+  }
+</style>
diff --git a/src/lib/records.ts b/src/lib/records.ts
index 991477d..440d586 100644
--- a/src/lib/records.ts
+++ b/src/lib/records.ts
@@ -44,7 +44,7 @@ export type SimTab = { id: string; task: string; place: string; src: string; tit
 
 // シリーズのページ（URL → 記事のシリーズ名）。Studio の一覧の絞り込み条件と同じ
 // intro はシリーズのページの見出しの下に出す説明（ないシリーズは出さない）
-export const SERIES_PAGES: Record<string, { series: string; title: string; pageTitle: string; limit: number; intro?: string; points?: { h: string; items: string[] }[]; guide?: boolean; thinking?: boolean; serving?: boolean; vision?: boolean; sim?: { src: string; title: string; note: string; obs?: { src: string; title: string; label: string; note: string; points: string[] }; tabs?: SimTab[] } }> = {
+export const SERIES_PAGES: Record<string, { series: string; title: string; pageTitle: string; limit: number; intro?: string; points?: { h: string; items: string[] }[]; guide?: boolean; thinking?: boolean; serving?: boolean; vision?: boolean; lab?: boolean; sim?: { src: string; title: string; note: string; obs?: { src: string; title: string; label: string; note: string; points: string[] }; tabs?: SimTab[] } }> = {
   series1: { series: 'HRI', title: 'Drug Delivery Robot | 薬剤搬送ロボットハコブくん', pageTitle: 'Series1 | 薬剤搬送ロボット', limit: 12,
     intro: '病院で薬を運ぶロボット「ハコブくん」を題材に、人とロボットの関わり（HRI）を設計している記録です。病院で使う画面（UI）の設計、Unity での自律移動、Fusion での形づくり、分身ロボット（アバター）の考察までを、4コママンガと一緒に残しています。' },
   series2: { series: 'R2R2R', title: 'R2R2R | デジタルツイン学習-R2R2R（Real to Render to Real）', pageTitle: 'Series2 | R2R2R', limit: 12,
@@ -59,7 +59,7 @@ export const SERIES_PAGES: Record<string, { series: string; title: string; pageT
     intro: 'フィジカルAIの研究をひとりで続けるために、AIと一緒に作ってきた仕組みの記録です。サイトの移行、動画の制作、記録の整理など、研究の外側の作業をどう回しているかを残しています。' },
   series5: { series: '考察記事', title: 'Deep Dive | 考察記事', pageTitle: 'Series5 | 考察記事', limit: 12, thinking: true,
     intro: '実装の記録とは別に、フィジカルAIやロボットについて、なぜそうなるのか、何を意味するのかを考えた記事です。論文や企業の発表、市場の動きを読み、対話の形で考えたことを、外れた議論も含めてそのまま残しています。' },
-  series6: { series: 'フィジカルAI研究室', title: 'Physical AI Lab | フィジカルAI研究室', pageTitle: 'Series6 | フィジカルAI研究室', limit: 12, guide: true,
+  series6: { series: 'フィジカルAI研究室', title: 'Physical AI Lab | フィジカルAI研究室', pageTitle: 'Series6 | フィジカルAI研究室', limit: 12, guide: true, lab: true,
     intro: 'ロボットアームが動きを覚える環境を、自宅にひとりで作っている記録です。机の上のアームでお手本の動きを集め、ロボット用のAI（Physical Intelligence の π0.5 など）に学習させ、実機で動かして確かめます。借りたGPUの種類・時間・費用も含めて、誰でも同じ手順で始められる形で残しています。' },
   series7: { series: '画像認識・物体検出', title: 'Image recognition and Object detection | 画像認識と物体検出', pageTitle: 'Series7 | 画像認識と物体検出', limit: 12, vision: true,
     intro: 'ロボットのカメラが物を見つける仕組みを、下の層から学び直している記録です。画素の数字、色の見分け方、しきい値、輪郭、特徴点といった昔からの手法を、机の上のアームを撮った写真で1つずつ測って確かめ、その上で SAM 3 のような新しいモデルも試します。評価の物差し（IoU・適合率・再現率など）を先に決め、結果は数字で残しています。' },
diff --git a/src/pages/[series].astro b/src/pages/[series].astro
index e760a06..8cb7246 100644
--- a/src/pages/[series].astro
+++ b/src/pages/[series].astro
@@ -9,6 +9,7 @@ import ServingBanner from '../components/ServingBanner.astro';
 import SeriesSheet from '../components/SeriesSheet.astro';
 import SeriesDoc from '../components/SeriesDoc.astro';
 import VisionGuide from '../components/VisionGuide.astro';
+import LabGuide from '../components/LabGuide.astro';
 import { seriesCards, SERIES_PAGES } from '../lib/records';
 import { media } from '../lib/media';
 import staticPages from '../data/static.json';
@@ -56,6 +57,7 @@ const jsonLd = {
     ))}
   </div></section>
   {conf.vision && <VisionGuide />}
+  {conf.lab && <LabGuide />}
   {conf.sim && (
     <section class="sec s-sim" data-ev-area="sim"><div class="panel">
       <h2 class="sec-h">試算を試す | Simulator</h2>
```


## 作業ログ ― 実験のカードが段々になった：CSS の subgrid で段をそろえる（commit 09c80f5・17:21）

### カードの見出しが2行になると、そのカードだけ数字が下がる

> この段々になっているのを修正。カードの上にライン入っているのは無しで削除

5枚のカードは、1枚ずつ上から番号・見出し・数字・文・リンクを積んでいました。04（失敗しかけたら人が直す）と05（直した成功を学習に足す）のように見出しが2行になるカードだけ、数字が1行分下がります。5枚が横に並ぶと、数字の高さがそろわず段々に見えました。

【画像】LOG462_03_experiment_staggered.png 直す前の実験のカード。見出しが2行の04と05だけ数字が下がり、カードの上に黒い線がある

### subgrid は、子の要素の段を親の格子とそろえる CSS の仕組み

[CSS の subgrid（サブグリッド）](https://developer.mozilla.org/ja/docs/Web/CSS/CSS_grid_layout/Subgrid)は、格子（grid）の中に置いたカードの中身を、親の格子の行に合わせて並べる仕組みです。カード1枚を親の格子の5行にまたがせ（grid-row: span 5）、カードの中の5つの段（番号・見出し・数字・文・リンク）を親の行に乗せる（grid-template-rows: subgrid）と、5枚のどれかの見出しが2行になったとき、その行の高さが5枚とも同じに伸びます。上の図解で、前と後を切り替えて確かめられます。

- ねらい：5枚の数字を同じ高さに置き、横に読み比べられるようにする
- 変わったこと：数字の上の位置の差が、図解の幅（カード1枚約125px）で測って21px から 0px になった。カードの上の黒い線は外した
- 見込める効果：LOG が進んで見出しや数字を書き換えても、段がくずれない

ページの幅を 1240px にしたとき、4,000ステップの単位が折り返して数字の段だけ高くなったので、数字に white-space: nowrap を付け、字の大きさを画面の幅に合わせて 32〜40px で変えるようにしました。

【画像】LOG462_08_experiment_aligned.png 直したあとの実験のカード。5枚の見出し・数字・文・リンクが同じ高さに並び、カードの上の線はない

### 段をそろえた差分（commit 09c80f5）

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index 51bc453..e33cf3f 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -168,6 +168,7 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   .lg-zone-gpu .lg-items dt { color: #fff; }
   .lg-zone-gpu .lg-items dd { color: #c8c8c2; }
   .lg-flow { display: grid; align-content: start; gap: 28px; padding: 72px 8px 0; }
+  .lg-flow-go { min-height: 76px; align-content: start; }
   .lg-flow span { display: grid; justify-items: center; gap: 4px; text-align: center; font: 500 12px/18px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
   .lg-flow .ms { font-size: 28px; color: var(--ink); }
   .lg-flow-back .ms { color: var(--ink-3); }
@@ -175,13 +176,14 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
 
   /* 2 実験のループ */
   .lg-loop { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
-  .lg-step { display: flex; flex-direction: column; padding: 20px; border-radius: 8px; border-top: 4px solid var(--dark); background: var(--bg); }
+  /* 5枚の見出し・数字・文・リンクの高さを、subgrid で行ごとにそろえる（段々にしない） */
+  .lg-step { display: grid; grid-row: span 5; grid-template-rows: subgrid; row-gap: 0; align-content: start; padding: 20px; border-radius: 8px; background: var(--bg); }
   .lg-step-no { font: 700 13px/20px var(--sans); color: var(--ink-3); font-variant-numeric: tabular-nums; }
-  .lg-step-h { margin: 4px 0 12px; font: 700 16px/24px var(--sans); color: var(--ink); word-break: auto-phrase; }
-  .lg-num { margin: 0 0 12px; font: 700 40px/1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
+  .lg-step-h { align-self: start; margin: 4px 0 12px; font: 700 16px/24px var(--sans); color: var(--ink); word-break: auto-phrase; }
+  .lg-num { align-self: start; white-space: nowrap; margin: 0 0 12px; font: 700 clamp(32px, 2.8vw, 40px)/1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
   .lg-num small { margin-left: 4px; font: 600 14px/1 var(--sans); color: var(--ink-2); letter-spacing: 0; }
   .lg-step .lg-p { font-size: 14px; line-height: 24px; }
-  .lg-step .lg-links { margin-top: auto; padding-top: 16px; gap: 6px; }
+  .lg-step .lg-links { margin: 0; padding-top: 16px; gap: 6px; align-self: start; }
   .lg-step .lg-links a { gap: 4px; padding: 5px 8px 5px 10px; }
   .lg-step .lg-links a { background: #fff; }
   .lg-step .lg-links a:hover { background: #e6e6e6; }
@@ -219,7 +221,7 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
     .lg-map { grid-template-columns: minmax(0, 1fr); }
     .lg-flow { grid-auto-flow: column; justify-content: center; gap: 32px; padding: 12px 0; }
     .lg-zone { align-self: stretch; }
-    .lg-flow span { display: flex; align-items: center; gap: 6px; }
+    .lg-flow span { display: flex; align-items: center; gap: 6px; min-height: 0; }
     .lg-flow .ms { font-size: 22px; transform: rotate(90deg); }
     .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
     .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
```


## 作業ログ ― 矢印の図と黒いカードをやめ、手元に置くもの・時間で借りるもの に分ける（commit c556a04・43cf04c）

### 黒いカードの意図は、ページのどこにも書いていなかった

> 矢印やデザイン性の低い構成を考え直してください。右のカードがなぜ黒いかの意図もわからない

借りる GPU の箱を黒くしたのは、AI の計算はここで動いていると示すためでした。ただ、ページのどこにもそう書いておらず、ほかの2つが灰色の中で1つだけ黒い理由が見えません。矢印も、何が行き来するかを見せるつもりで置いたものの、ラベルの長さで上下の位置がずれ、図をごちゃつかせただけでした。

そこで、伝えることを1つに絞り直しました。机の上のアームとカメラと Mac に、時間で借りる GPU を足しただけ、ということです。矢印で見せたかった流れ（Mac がカメラの画像と関節の角度を送り、π0.5 が次の1秒の関節の角度を返す）は、導入の1文に入れています。

### 1回目：机の写真と、2つに分けた一覧（commit c556a04・17:29）

左に机の写真、右に手元に置くもの（mechArm 270・上のカメラ・ゲームパッド・Mac）と時間で借りるもの（Runpod の A40・Hugging Face）の2つの一覧を置きました。写真は、腕・ブロック・箱が入るように、ブロックから箱までを約1.75:1で切り直しています。

【画像】LOG462_04_setup_photo_list.png 1回目の直し。左に机の写真、右に手元に置くもの・時間で借りるものの一覧。2つの分け目は小さな灰色の見出しだけ

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index e33cf3f..e507d91 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -1,6 +1,6 @@
 ---
 // /series6（フィジカルAI研究室）の見出しの下に置く解説（2026-11-07）
-// 1 研究室の構成：机の上・Mac・借りた GPU の3か所と、その間を行き来するもの（図は HTML で組む。AI も読めるように）
+// 1 研究室の構成：机の写真と、手元に置くもの・時間で借りるものの一覧（矢印の図は 2026-11-07 にやめた）
 // 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
 // 3 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
 // 写真は public/site/lab/（desk.webp は 2026-10-29 の横からの録画 IMG_4215.MOV の80秒目、
@@ -9,19 +9,17 @@
 // 数字はどれも LOG の記録の値。新しい LOG で数字が変わったら、ここも書き換える
 type Link = { log: string; slug: string; t: string };
 
-const zones = [
-  { key: 'desk', name: '机の上', img: true, items: [
-    { h: 'mechArm 270', p: '6つの関節を持つ小型のロボットアーム。中の Raspberry Pi が指令を受けて関節を動かします。' },
-    { h: '上のカメラ', p: 'スマホを真上に付けて、マットとブロックと箱を撮ります。π0.5 が見るのはこの画像だけです。' },
-    { h: 'ゲームパッド', p: 'AI が失敗しかけたとき、人が関節を直すのに使います。3,198円の互換品です。' },
+// 構成は、手元に置くものと時間で借りるものの2つに分ける（2026-11-07 に矢印の図から改めた）
+const kit: { group: string; items: { h: string; p: string }[] }[] = [
+  { group: '手元に置くもの', items: [
+    { h: 'mechArm 270', p: '6つの関節を持つ小型のロボットアーム。中の Raspberry Pi が関節を動かす' },
+    { h: '上のカメラ', p: '真上に付けたスマホ。π0.5 が見るのはこの画像だけ' },
+    { h: 'ゲームパッド', p: 'AI が失敗しかけたとき、人が関節を直す。3,198円の互換品' },
+    { h: 'Mac', p: '画像と関節の角度を記録し、借りた GPU とやり取りする' },
   ] },
-  { key: 'mac', name: '手元の Mac', items: [
-    { h: '記録と中継', p: 'カメラの画像と関節の角度を1秒10コマで記録し、借りた GPU に送り、返ってきた動きをアームへ渡します。' },
-    { h: 'AI と組み立てる', p: '手順と分析は Claude、アームを動かすプログラムは Claude Code と一緒に書いています。' },
-  ] },
-  { key: 'gpu', name: '時間で借りる GPU', items: [
-    { h: 'Runpod の A40', p: 'GPU のメモリは 48GB、1時間あたり約98円。π0.5 の学習と推論は、すべてここで行います。' },
-    { h: 'Hugging Face', p: '学習済みのモデル（6.3GB）の置き場所。GPU を借りるたびに、ここから13秒で取ってきます。' },
+  { group: '時間で借りるもの', items: [
+    { h: 'Runpod の A40', p: 'π0.5 の学習と推論をする GPU。メモリ 48GB、1時間あたり約98円' },
+    { h: 'Hugging Face', p: '学習済みのモデル（6.3GB）の置き場所' },
   ] },
 ];
 
@@ -80,27 +78,20 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
 ---
 <section class="sec lg"><div class="panel">
   <h2 class="sec-h">研究室の構成 | Setup</h2>
-  <p class="lg-lead">机の上のアーム、手元の Mac、時間で借りる GPU の3か所でできています。AI の学習と推論は、すべて借りた GPU の上で行っています。</p>
-  <div class="lg-map">
-    {zones.map((z, i) => (
-      <>
-        {i > 0 && (
-          <div class="lg-flow" aria-hidden="true">
-            <span class="lg-flow-go"><i class="ms">arrow_forward</i>{i === 1 ? '画像と関節の角度' : '画像・角度・指示文'}</span>
-            <span class="lg-flow-back"><i class="ms">arrow_back</i>次の1秒の動き</span>
-          </div>
-        )}
-        <div class={`lg-zone lg-zone-${z.key}`}>
-          <p class="lg-zone-name">{z.name}</p>
-          {z.img && <img class="lg-desk" src="/site/lab/desk.webp" alt="マットの上の mechArm 270 が赤いブロックをつかみ、右に白い箱が置いてある" width="1200" height="681" loading="lazy" />}
+  <p class="lg-lead">机の上のアームとカメラと Mac に、時間で借りる GPU を足しただけの構成です。Mac が上のカメラの画像と関節の角度を借りた GPU へ送り、π0.5 が次の1秒ぶんの関節の角度を返して、Mac がそれをアームへ渡します。</p>
+  <div class="lg-setup">
+    <img class="lg-desk" src="/site/lab/desk.webp" alt="マットの上の mechArm 270 が赤いブロックをつかみ、右に白い箱が置いてある" width="1400" height="799" loading="lazy" />
+    <div class="lg-kit">
+      {kit.map((g) => (
+        <div class="lg-kit-group">
+          <h3 class="lg-kit-h">{g.group}</h3>
           <dl class="lg-items">
-            {z.items.map((it) => (<div><dt>{it.h}</dt><dd>{it.p}</dd></div>))}
+            {g.items.map((it) => (<div><dt>{it.h}</dt><dd>{it.p}</dd></div>))}
           </dl>
         </div>
-      </>
-    ))}
+      ))}
+    </div>
   </div>
-  <p class="lg-flow-text">Mac は上のカメラの画像と関節の角度を、指示文と一緒に借りた GPU へ送ります。π0.5 は次の1秒ぶんの関節の角度を返し、Mac がそれをアームへ渡します。</p>
 </div></section>
 
 <section class="sec lg"><div class="panel">
@@ -156,23 +147,14 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   .lg-p { margin: 0; font: 400 15px/27px var(--sans); color: var(--ink-2); word-break: auto-phrase; text-wrap: pretty; }
 
   /* 1 構成：3つの場所と、その間を行き来するもの */
-  .lg-map { display: grid; grid-template-columns: minmax(0, 1.35fr) 112px minmax(0, 1fr) 112px minmax(0, 1fr); align-items: start; }
-  .lg-zone { padding: 24px; border-radius: 8px; background: var(--bg); }
-  .lg-zone-gpu { background: var(--dark); color: #fff; }
-  .lg-zone-name { margin: 0 0 16px; font: 700 18px/28px var(--sans); color: var(--ink); }
-  .lg-zone-gpu .lg-zone-name { color: #fff; }
-  .lg-desk { display: block; width: 100%; height: auto; margin: 0 0 16px; border-radius: 6px; }
+  /* 写真はブロックから箱まで入れたいので、切り抜かずに元の比率のまま置く */
+  .lg-setup { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 40px; align-items: center; }
+  .lg-desk { display: block; width: 100%; height: auto; border-radius: 8px; }
+  .lg-kit { display: grid; align-content: start; gap: 28px; }
+  .lg-kit-h { margin: 0 0 12px; font: 700 13px/20px var(--sans); color: var(--ink-3); }
   .lg-items { margin: 0; display: grid; gap: 14px; }
-  .lg-items dt { font: 700 15px/24px var(--sans); color: var(--ink); }
-  .lg-items dd { margin: 2px 0 0; font: 400 14px/24px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
-  .lg-zone-gpu .lg-items dt { color: #fff; }
-  .lg-zone-gpu .lg-items dd { color: #c8c8c2; }
-  .lg-flow { display: grid; align-content: start; gap: 28px; padding: 72px 8px 0; }
-  .lg-flow-go { min-height: 76px; align-content: start; }
-  .lg-flow span { display: grid; justify-items: center; gap: 4px; text-align: center; font: 500 12px/18px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
-  .lg-flow .ms { font-size: 28px; color: var(--ink); }
-  .lg-flow-back .ms { color: var(--ink-3); }
-  .lg-flow-text { margin: 24px 0 0; max-width: 46em; font: 400 14px/24px var(--sans); color: var(--ink-3); }
+  .lg-items dt { font: 700 16px/24px var(--sans); color: var(--ink); }
+  .lg-items dd { margin: 2px 0 0; font: 400 14px/22px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
 
   /* 2 実験のループ */
   .lg-loop { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
@@ -218,11 +200,7 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
     .lg-loop { grid-template-columns: repeat(3, minmax(0, 1fr)); }
   }
   @media (max-width: 1023px) {
-    .lg-map { grid-template-columns: minmax(0, 1fr); }
-    .lg-flow { grid-auto-flow: column; justify-content: center; gap: 32px; padding: 12px 0; }
-    .lg-zone { align-self: stretch; }
-    .lg-flow span { display: flex; align-items: center; gap: 6px; min-height: 0; }
-    .lg-flow .ms { font-size: 22px; transform: rotate(90deg); }
+    .lg-setup { grid-template-columns: minmax(0, 1fr); gap: 28px; }
     .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
     .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
     .lg-tech-body.has-fig { grid-template-columns: minmax(0, 1fr); gap: 20px; }
@@ -230,8 +208,6 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   }
   @media (max-width: 599px) {
     .lg-lead { margin: -16px 0 24px; font-size: 15px; line-height: 26px; }
-    .lg-zone { padding: 20px 18px; }
-    .lg-flow { gap: 16px; }
     .lg-loop { grid-template-columns: minmax(0, 1fr); }
     .lg-num { font-size: 36px; }
     .lg-tech-row { padding: 22px 0; }
```

### 2回目：写真を動画に、2つの一覧を面で分ける（commit 43cf04c・17:46）

> 手元に置くもの・時間で借りるもので分けられていた方がいいね（よくわかんない）。左の写真は動画がいいね（画角もう少し見直して）

2つの分け目が小さな灰色の文字だけだったので、それぞれを灰色の面で囲み、見出しを大きくしました。写真は、π0.5 が人の手を入れずに成功した1回（10月29日、LOG401 の試しの1つ）を横から撮った録画に替えました。録画の左側の何も起きていないマットを外し、右寄りに4:3で切っています。元の録画は、腕を立てた姿勢だと腕の上が画面の外に出るので、腕が下りてから箱に入れ終わるまで（12〜140秒）を6倍速にしました。

- ねらい：π0.5 が何をしているのかを、文を読む前に見て分かるようにする
- 変わったこと：止まった写真が、ブロックをつかんで箱に入れるまでの約21秒の動画（音なし・繰り返し）になった。手元に置くものと時間で借りるものが、別々の面になった
- 見込める効果：初めて来た人が、研究室の作業の中身（何を・どこへ）を動画1本でつかめる。代わりにページは 0.77MB 重くなった（読み込みの速さへの影響は測っていない）

```bash
# 研究室の構成の動画（commit 43cf04c）。2026-10-29 の横からの録画 IMG_4222.MOV（3840×2160）の12〜140秒を、
# 右寄りに4:3で切り出して6倍速にする。元の録画は腕を立てた姿勢で上が画面の外に出るので、腕が下りてからを使う
cd "$HOME/mnt/KIOXIA/r2r2r-data/recordings/20261029_iphone"
D="$HOME/mnt/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/series6_guide_images"
mkdir -p "$D/upload"
ffmpeg -v error -y -ss 12 -t 128 -i IMG_4222.MOV -an -vf "crop=2700:2025:1140:0,setpts=PTS/6,fps=30,scale=1200:900" -c:v libx264 -preset veryfast -crf 26 -pix_fmt yuv420p -movflags +faststart "$D/upload/lab-setup-pi05-run-v2.mp4"
ffmpeg -v error -y -ss 12 -i IMG_4222.MOV -frames:v 1 -vf "crop=2700:2025:1140:0,scale=1200:900" -q:v 3 "$D/lab-setup-pi05-run-v2-poster.jpg"
ls -la "$D/upload"
```

```
total 1824
-rw-------  1 … 772542 Nov  7 08:45 lab-setup-pi05-run-v2.mp4
-rw-------  1 … 1090633 Nov  7 08:41 lab-setup-pi05-run.mp4
```

最初は0〜165秒（27.5秒・1.09MB）で作って R2 に入れましたが、腕を立てた最初の姿勢で上が切れていたので、12〜140秒の v2 を作り直してページはそちらを読むようにしました。R2 へは、同じ名前がすでにあれば入れない形で1本ずつ入れています（Cloudflare の鍵は KIOXIA のファイルから読むだけで、記事には載せていない）。

```python
# 動画1本を R2（p2m-media）へ入れる。同じ名前がすでにあれば入れない（上書きしない）
# Mac 連携の shell で: python3 - <動画のパス> <<'PYEOF' … PYEOF の形で動かした。鍵は KIOXIA のファイルから読むだけ
import json, sys, time, urllib.parse, urllib.request
from pathlib import Path
API='https://api.cloudflare.com/client/v4/accounts/21d7aed1b193796b89287df10913f2dc/r2/buckets/p2m-media/objects'
tok=(Path.home()/'mnt/KIOXIA/p2m_cloudflare_token.txt').read_text().strip().split()[0]
p=Path(sys.argv[1]); name=p.name
def req(m,u,data=None,ct=None):
    r=urllib.request.Request(u,data=data,method=m); r.add_header('Authorization','Bearer '+tok)
    if ct: r.add_header('Content-Type',ct)
    with urllib.request.urlopen(r,timeout=300) as res: return json.loads(res.read() or b'{}')
try:
    req('GET',API+'/'+urllib.parse.quote(name)); print('すでにある・入れない')
except Exception:
    d=req('PUT',API+'/'+urllib.parse.quote(name),p.read_bytes(),'video/mp4'); print('入れた',d.get('success'))
```

```
入れた True
```

```
$ curl -s -o /dev/null -w "%{http_code} %{size_download} %{content_type}\n" https://pixelstomotors.com/media/lab-setup-pi05-run.mp4
200 1090633 video/mp4
```

【画像】LOG462_05_setup_video.png 2回目の直しのあとの研究室の構成。左に実機の動画、右に手元に置くものと時間で借りるものが別々の灰色の面に分かれている

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index e507d91..1175b66 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -1,9 +1,11 @@
 ---
 // /series6（フィジカルAI研究室）の見出しの下に置く解説（2026-11-07）
-// 1 研究室の構成：机の写真と、手元に置くもの・時間で借りるものの一覧（矢印の図は 2026-11-07 にやめた）
+// 1 研究室の構成：実機の動画と、手元に置くもの・時間で借りるものの一覧（矢印の図は 2026-11-07 にやめた）
+//   動画は R2 の lab-setup-pi05-run-v2.mp4（2026-10-29 の横からの録画 IMG_4222.MOV の12〜140秒を、右寄りに4:3で切り出し6倍速。
+//   元の録画は腕を立てた姿勢で上が画面の外に出るので、腕が下りてから箱に入れ終わるまでを使う）
 // 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
 // 3 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
-// 写真は public/site/lab/（desk.webp は 2026-10-29 の横からの録画 IMG_4215.MOV の80秒目、
+// 絵は public/site/lab/（run-poster.webp は動画の最初のコマ、
 // top-camera.webp は corr_v5 のお手本 pi05_20261106_183926 の真ん中のコマ。元は iCloud の
 // フィジカルAI研究室を作る/series6_guide_images/）
 // 数字はどれも LOG の記録の値。新しい LOG で数字が変わったら、ここも書き換える
@@ -80,7 +82,11 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   <h2 class="sec-h">研究室の構成 | Setup</h2>
   <p class="lg-lead">机の上のアームとカメラと Mac に、時間で借りる GPU を足しただけの構成です。Mac が上のカメラの画像と関節の角度を借りた GPU へ送り、π0.5 が次の1秒ぶんの関節の角度を返して、Mac がそれをアームへ渡します。</p>
   <div class="lg-setup">
-    <img class="lg-desk" src="/site/lab/desk.webp" alt="マットの上の mechArm 270 が赤いブロックをつかみ、右に白い箱が置いてある" width="1400" height="799" loading="lazy" />
+    <figure class="lg-run">
+      <video src="/media/lab-setup-pi05-run-v2.mp4" poster="/site/lab/run-poster.webp" width="1200" height="900" autoplay muted loop playsinline preload="metadata"
+        aria-label="mechArm 270 が赤いブロックをつかみ、持ち上げて右の白い箱に入れるまで"></video>
+      <figcaption>π0.5 が動かした mechArm 270。人の手を入れずに成功した1回（2026年10月29日・6倍速）</figcaption>
+    </figure>
     <div class="lg-kit">
       {kit.map((g) => (
         <div class="lg-kit-group">
@@ -148,12 +154,16 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
 
   /* 1 構成：3つの場所と、その間を行き来するもの */
   /* 写真はブロックから箱まで入れたいので、切り抜かずに元の比率のまま置く */
-  .lg-setup { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 40px; align-items: center; }
-  .lg-desk { display: block; width: 100%; height: auto; border-radius: 8px; }
-  .lg-kit { display: grid; align-content: start; gap: 28px; }
-  .lg-kit-h { margin: 0 0 12px; font: 700 13px/20px var(--sans); color: var(--ink-3); }
+  .lg-setup { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 32px; align-items: start; }
+  .lg-run { margin: 0; }
+  .lg-run video { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; border-radius: 8px; background: #e9e7e2; }
+  .lg-run figcaption { margin: 8px 0 0; font: 400 12px/18px var(--sans); color: var(--ink-3); }
+  /* 手元に置くもの・時間で借りるもの を、それぞれ面で囲んで分ける */
+  .lg-kit { display: grid; gap: 12px; }
+  .lg-kit-group { padding: 24px; border-radius: 8px; background: var(--bg); }
+  .lg-kit-h { margin: 0 0 16px; font: 700 18px/28px var(--sans); color: var(--ink); }
   .lg-items { margin: 0; display: grid; gap: 14px; }
-  .lg-items dt { font: 700 16px/24px var(--sans); color: var(--ink); }
+  .lg-items dt { font: 700 15px/24px var(--sans); color: var(--ink); }
   .lg-items dd { margin: 2px 0 0; font: 400 14px/22px var(--sans); color: var(--ink-2); word-break: auto-phrase; }
 
   /* 2 実験のループ */
```


## 作業ログ ― 上のカメラの写真の傾きを、マットの縁から射影変換で直す（commit 965efdb・17:56）

### 384×216 のまま直すと、さらに粗くなる

> 写真をトリミングと補正をかけてください。斜めになっています

技術の節の π0.5 の行の写真は、π0.5 に渡したお手本のコマそのもの（384×216）で、マットが少し傾いて写っていました。この大きさのまま傾きを直して切ると、さらに粗くなります。そこで、同じ上のカメラの元の録画（11月6日の実機の回 pi05_20261106_183926、1920×1080）から、爪がブロックをつかみ、横に箱がある125秒目のコマを取り直しました。

【画像】LOG462_06_top_camera_tilted.png 直す前の π0.5 の行。上のカメラの写真のマットが斜めに写っている

### 射影変換は、写真の中の四角を長方形に写し直す計算

[射影変換](https://docs.opencv.org/4.x/da/d54/group__imgproc__transform.html)（OpenCV の getPerspectiveTransform と warpPerspective）は、写真の中で斜めに写った四角の4つの角を、きっちりした長方形の4つの角へ写すように、写真全体をゆがめ直す計算です。マットは白い机の上の暗い面なので、明るさが白から暗へ変わる所を左・右・下の縁として拾い、それぞれに直線を当てました。上の縁は画面の外なので、左右の直線が画面の上端と交わる点を上の角にしています。

```python
# 上のカメラの1コマ（1920×1080）から、マットの左・右・下の縁を拾って直線を当てる（commit 965efdb の前）
import numpy as np, cv2
src='/mnt/user-data/uploads/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/series6_guide_images/top_full_125.jpg'
im=cv2.imread(src); g=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY).astype(int)
L=[];R=[];B=[]
for y in range(10,880,10):
    r=g[y]
    for x in range(250,500):
        if r[x-3]>180 and r[x+3]<150: L.append((x,y)); break   # 白い机 → 暗いマット
    for x in range(1800,1550,-1):
        if r[x+3]>180 and r[x-3]<150: R.append((x,y)); break
for x in range(350,1700,10):
    c=g[:,x]
    for y in range(1060,800,-1):
        if c[y+3]>180 and c[y-3]<150: B.append((x,y)); break
def fit(pts,vert):
    p=np.array(pts,float)
    return np.polyfit(p[:,1],p[:,0],1) if vert else np.polyfit(p[:,0],p[:,1],1)
la,lb=fit(L,1); ra,rb=fit(R,1); ba,bb=fit(B,0)
print(len(L),la,lb,len(R),ra,rb,len(B),ba,bb)
def xl(y): return la*y+lb
def xr(y): return ra*y+rb
yl=(ba*lb+bb)/(1-ba*la); xbl=xl(yl)
yr=(ba*rb+bb)/(1-ba*ra); xbr=xr(yr)
tl=(xl(0),0); tr=(xr(0),0)
print('tl',tl,'tr',tr,'bl',(xbl,yl),'br',(xbr,yr))
```

```
87 0.015934606692425454 304.9427960438384 87 0.05026791572501142 1680.3303929430633 135 -0.03310896497902642 970.7933665008289
tl (np.float64(304.9427960438384), 0) tr (np.float64(1680.3303929430633), 0) bl (np.float64(320.24305322185177), np.float64(960.1904504669302)) br (np.float64(1726.257110154082), np.float64(913.638780295942))
```

左の縁は下へ行くほど右へ（1,000px 下がって約16px）、下の縁は右へ行くほど上へ（1,400px 進んで約46px）ずれていました。この4つの角を 1391×937 の長方形へ写し、アーム・ブロック・箱が入る右寄りを4:3で切りました。明るさと色は少しだけ上げ、マス目がきつく見えないよう、コントラストを強める処理（CLAHE）は試したうえで使っていません。

```python
# 上のカメラの写真を作り直す（commit 965efdb）。拾ったマットの4隅を長方形へ写し（射影変換）、右寄りに4:3で切り、明るさを少し上げる
import numpy as np, cv2
src='/mnt/user-data/uploads/PixelstoMotors/デジタルツイン学習R2R2R/フィジカルAI研究室を作る/series6_guide_images/top_full_125.jpg'
im=cv2.imread(src)
tl=(304.94,0); tr=(1680.33,0); bl=(320.24,960.19); br=(1726.26,913.64)
Wd,Hd=1391,937
M=cv2.getPerspectiveTransform(np.float32([tl,tr,br,bl]),np.float32([(0,0),(Wd,0),(Wd,Hd),(0,Hd)]))
out=cv2.warpPerspective(im,M,(Wd,Hd),flags=cv2.INTER_CUBIC)
x1=Wd-14; x0=x1-1110; y1=Hd-14; y0=y1-832
c=out[y0:y1,x0:x1].astype(np.float32)
c=np.clip(c*1.06+4,0,255).astype(np.uint8)
hsv=cv2.cvtColor(c,cv2.COLOR_BGR2HSV).astype(np.float32); hsv[...,1]*=1.08; c=cv2.cvtColor(np.clip(hsv,0,255).astype(np.uint8),cv2.COLOR_HSV2BGR)
c=cv2.resize(c,(800,600),interpolation=cv2.INTER_AREA)
cv2.imwrite('public/site/lab/top-camera.png',c)
from PIL import Image
Image.open('public/site/lab/top-camera.png').save('public/site/lab/top-camera.webp',quality=86)
import os; os.remove('public/site/lab/top-camera.png'); print('ok')
```

```
ok
```

写真の下の説明も、「π0.5 に渡している、上のカメラの画像（384×216）」から「上のカメラの画像。傾きを直して切り出しています。π0.5 には、この画像を 384×216 に縮めて渡します」に替えました。いまの写真は、π0.5 に渡したそのものではないためです。

【画像】LOG462_07_tech_rows.png 直したあとの使っている技術の節。π0.5 の行の写真はマットの縁がまっすぐになり、その下に追加学習・時間で借りる GPU・推論サーバー・巻き戻しと人の直しが並ぶ

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index 1175b66..9089371 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -6,7 +6,8 @@
 // 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
 // 3 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
 // 絵は public/site/lab/（run-poster.webp は動画の最初のコマ、
-// top-camera.webp は corr_v5 のお手本 pi05_20261106_183926 の真ん中のコマ。元は iCloud の
+// top-camera.webp は pi05_20261106_183926 の上のカメラの録画（KIOXIA runs/pi05_policy/…/recording/top.mp4、1920×1080）の125秒目。
+// マットの左・右・下の縁から傾きを直して右寄りに4:3で切り出し、明るさを少し上げた。元は iCloud の
 // フィジカルAI研究室を作る/series6_guide_images/）
 // 数字はどれも LOG の記録の値。新しい LOG で数字が変わったら、ここも書き換える
 type Link = { log: string; slug: string; t: string };
@@ -136,8 +137,8 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
             </div>
             {t.fig && (
               <figure class="lg-fig">
-                <img src="/site/lab/top-camera.webp" alt="真上のカメラの画像。mechArm 270 の爪が赤いブロックをつかみ、右に白い箱がある" width="384" height="216" loading="lazy" />
-                <figcaption>π0.5 に渡している、上のカメラの画像（384×216）</figcaption>
+                <img src="/site/lab/top-camera.webp" alt="真上のカメラの画像。mechArm 270 の爪が赤いブロックをつかみ、右に白い箱がある" width="800" height="600" loading="lazy" />
+                <figcaption>上のカメラの画像。傾きを直して切り出しています。π0.5 には、この画像を 384×216 に縮めて渡します</figcaption>
               </figure>
             )}
           </div>
@@ -214,7 +215,7 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
     .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
     .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
     .lg-tech-body.has-fig { grid-template-columns: minmax(0, 1fr); gap: 20px; }
-    .lg-fig { max-width: 384px; }
+    .lg-fig { max-width: 480px; }
   }
   @media (max-width: 599px) {
     .lg-lead { margin: -16px 0 24px; font-size: 15px; line-height: 26px; }
```


## 作業ログ ― 爪の電流の図を、いま調べていることの節として足す（commit 3a73764・18:13）

### 別のチャットで、爪の電流でつかめたかが分かると出た

同じ日に別のチャット（のちの LOG461）で、mechArm 270 のサーボの電流を読んでいました。爪のサーボの値は、空で閉じたときとブロックをつかんだときで大きく違い、つかめたかどうかがカメラなしで分かります。

> それとこの電流値の図解をこのページのセクションに入れ込めますか? 別のチャットで進めているものです。

伝えることは、つかめたかは爪の電流でカメラなしに分かる、の1つにし、別のチャットで描いた肩の図は入れませんでした（押されたことは分かっても向きが分からず、この節の1つのことから外れるため）。左に2つの大きな数字、右に爪の値の線だけの図を置き、空で閉じた区間とつかんだ区間を灰色の面で示しています。並びは、実験の節のあと、技術の節の前です。

### 図の値は、KIOXIA の実機の記録から読み直した

図は別のチャットの画面写真ではなく、KIOXIA の diag/servo_current_20261107/180051_pad/samples.csv から読み直して描きました。爪（サーボ7番）の値は、番地69（下位）と70（上位）の2つに分かれていて、70の一番上のビットが向き（マイナス）を表します。

```
$ cat marks.csv
t_mac,key,name,sample_i
1794042097.898721,1,static,449
1794042118.407143,2,close_empty,663
1794042140.794489,3,grasp,876
1794042154.007000,4,pull,1013
1794042183.396141,6,push_arm,1298
```

```
1492 (0.0, -5, 11) (144.36, -47, 3)
0 40 435 2 -7 8
55 62 75 16 7 21
66 78 113 -48 -63 -3
80 82 20 946.0 923 977
82 88 61 885 854 926
100 106 61 802 793 809
112 140 301 -45 -66 -24
```

上は、区間ごとの始めの秒・終わりの秒・数・中央値・最小・最大です。読めた数は144.36秒で1,492回、1秒に10.34回でした。値が変わった所を拾うと、空で閉じたのは51〜65秒、つかんだのは79.6〜109.4秒でした。

```
n 1492 dur 144.36 hz 10.34
0.0 -5 z
50.95 39 pos
53.04 8 z
53.14 16 pos
55.49 7 z
55.58 10 pos
60.77 8 z
60.88 16 pos
67.39 -3 z
67.47 -43 neg
79.0 1 z
79.1 39 pos
79.6 627 hi
109.4 349 pos
109.5 -49 neg
```

```python
# 爪（サーボ7番）の電流の値を、0.5秒ごとの中央値にして JSON に書き出す（commit 3a73764）
# Mac 連携の shell で KIOXIA の diag/servo_current_20261107/180051_pad の中で動かし、出力を iCloud に置いた
import csv,json,statistics
rows=list(csv.DictReader(open('samples.csv')))
t0=float(rows[0]['t_mac_recv']); b={}
for r in rows:
    try: regs=json.loads(r['regs'])
    except: continue
    v={(a,c):d for a,c,d,*_ in regs}
    lo,hi=v.get((7,69)),v.get((7,70))
    if lo is None or hi is None: continue
    t=float(r['t_mac_recv'])-t0
    b.setdefault(int(t*2),[]).append((lo+(hi&0x7f)*256)*(-1 if hi&0x80 else 1))
print(json.dumps({"source":"KIOXIA r2r2r-data/diag/servo_current_20261107/180051_pad/samples.csv（爪＝サーボ7の番地69・70。70の最上位ビットを符号として読む）","step_sec":0.5,"stat":"0.5秒ごとの中央値","points":[[k/2,round(statistics.median(x))] for k,x in sorted(b.items())]},ensure_ascii=False))
```

### 爪の値のデータ（src/data/lab/gripper_current_20261107.json）

```json
{"source": "KIOXIA r2r2r-data/diag/servo_current_20261107/180051_pad/samples.csv（爪＝サーボ7の番地69・70。70の最上位ビットを符号として読む）", "step_sec": 0.5, "stat": "0.5秒ごとの中央値", "points": [[0.0, -3], [0.5, -3], [1.0, -1], [1.5, 1], [2.0, 0], [2.5, -4], [3.0, -4], [3.5, -3], [4.0, 2], [4.5, 0], [5.0, 2], [5.5, 4], [6.0, -2], [6.5, 1], [7.0, 2], [7.5, -1], [8.0, 0], [8.5, 4], [9.0, 7], [9.5, 5], [10.0, -1], [10.5, 6], [11.0, 4], [11.5, 5], [12.0, 6], [12.5, 5], [13.0, 3], [13.5, 2], [14.0, 4], [14.5, 0], [15.0, -4], [15.5, 4], [16.0, 4], [16.5, 4], [17.0, 5], [17.5, 2], [18.0, -4], [18.5, 4], [19.0, -3], [19.5, -2], [20.0, 5], [20.5, 0], [21.0, 0], [21.5, -4], [22.0, -3], [22.5, 4], [23.0, 3], [23.5, 2], [24.0, 5], [24.5, 2], [25.0, 4], [25.5, -1], [26.0, 2], [26.5, 6], [27.0, -2], [27.5, 0], [28.0, 2], [28.5, 0], [29.0, -1], [29.5, 5], [30.0, 3], [30.5, 4], [31.0, 2], [31.5, -2], [32.0, -3], [32.5, -1], [33.0, 3], [33.5, -1], [34.0, 2], [34.5, 2], [35.0, 2], [35.5, 4], [36.0, 1], [36.5, 5], [37.0, 3], [37.5, 4], [38.0, 1], [38.5, 1], [39.0, -2], [39.5, 4], [40.0, 0], [40.5, 2], [41.0, 4], [41.5, 0], [42.0, 7], [42.5, 0], [43.0, 3], [43.5, 2], [44.0, 5], [44.5, 4], [45.0, 2], [45.5, -1], [46.0, 6], [46.5, -2], [47.0, 4], [47.5, 0], [48.0, 0], [48.5, 4], [49.0, -2], [49.5, 1], [50.0, 3], [50.5, 2], [51.0, 79], [51.5, 23], [52.0, 15], [52.5, 16], [53.0, 19], [53.5, 15], [54.0, 13], [54.5, 17], [55.0, 16], [55.5, 14], [56.0, 18], [56.5, 16], [57.0, 16], [57.5, 12], [58.0, 18], [58.5, 17], [59.0, 11], [59.5, 14], [60.0, 17], [60.5, 16], [61.0, 17], [61.5, 14], [62.0, 16], [62.5, 15], [63.0, 12], [63.5, 14], [64.0, 20], [64.5, 16], [65.0, 15], [67.0, -23], [67.5, -47], [68.0, -52], [68.5, -46], [69.0, -51], [69.5, -46], [70.0, -47], [70.5, -52], [71.0, -47], [71.5, -48], [72.0, -48], [72.5, -47], [73.0, -48], [73.5, -44], [74.0, -51], [74.5, -49], [75.0, -48], [75.5, -47], [76.0, -47], [76.5, -49], [77.0, -53], [77.5, -49], [78.0, -50], [78.5, -47], [79.0, 116], [79.5, 896], [80.0, 966], [80.5, 951], [81.0, 940], [81.5, 930], [82.0, 921], [82.5, 910], [83.0, 905], [83.5, 897], [84.0, 890], [84.5, 887], [85.0, 877], [85.5, 876], [86.0, 870], [86.5, 865], [87.0, 860], [87.5, 860], [88.0, 856], [88.5, 851], [89.0, 848], [89.5, 848], [90.0, 845], [90.5, 843], [91.0, 840], [91.5, 837], [92.0, 835], [92.5, 834], [93.0, 831], [93.5, 832], [94.0, 824], [94.5, 823], [95.0, 820], [95.5, 819], [96.0, 816], [96.5, 816], [97.0, 814], [97.5, 813], [98.0, 812], [98.5, 808], [99.0, 809], [99.5, 810], [100.0, 806], [100.5, 806], [101.0, 806], [101.5, 803], [102.0, 805], [102.5, 800], [103.0, 800], [103.5, 799], [104.0, 798], [104.5, 796], [105.0, 797], [105.5, 800], [106.0, 800], [106.5, 793], [107.0, 800], [109.0, 558], [109.5, -36], [110.0, -57], [110.5, -52], [111.0, -50], [111.5, -53], [112.0, -49], [112.5, -58], [113.0, -50], [113.5, -54], [114.0, -54], [114.5, -62], [115.0, -60], [115.5, -61], [116.0, -58], [116.5, -60], [117.0, -58], [117.5, -58], [118.0, -60], [118.5, -54], [119.0, -57], [119.5, -58], [120.0, -57], [120.5, -53], [121.0, -57], [121.5, -58], [122.0, -59], [122.5, -58], [123.0, -44], [123.5, -45], [124.0, -38], [124.5, -44], [125.0, -47], [125.5, -45], [126.0, -39], [126.5, -46], [127.0, -48], [127.5, -39], [128.0, -34], [128.5, -39], [129.0, -32], [129.5, -38], [130.0, -36], [130.5, -40], [131.0, -42], [131.5, -30], [132.0, -38], [132.5, -33], [133.0, -36], [133.5, -45], [134.0, -27], [134.5, -39], [135.0, -45], [135.5, -38], [136.0, -30], [136.5, -36], [137.0, -35], [137.5, -33], [138.0, -37], [138.5, -34], [139.0, -36], [139.5, -45], [140.0, -36], [140.5, -37], [141.0, -30], [141.5, -39], [142.0, -42], [142.5, -31], [143.0, -38], [143.5, -43], [144.0, -46]]}
```

### 最初は16と960、LOG461 の公開後に15前後と870前後へそろえた（commit 43f5322・11月8日 15:37）

最初に公開したときは、0.5秒ごとの中央値から、空で閉じた値を16、つかんだ値を960（つかんだ直後の高い所）と書き、およそ60倍としていました。そのあと公開された LOG461 は、同じ記録を区間の中央値で、空で閉じると15前後、つかむと870前後、差は50倍以上と書いています。ページの数字が記録と食い違わないよう、記事化の前に、ページを LOG461 の書き方にそろえ、LOG461 へのリンクを付けました。図の線はそのままです。

【画像】LOG462_09_gripper_current.png いま調べていることの節。左に空で閉じた15前後とつかんだ870前後の数字と LOG461 へのリンク、右に爪の値の線の図

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index 9089371..4c55dd0 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -4,7 +4,8 @@
 //   動画は R2 の lab-setup-pi05-run-v2.mp4（2026-10-29 の横からの録画 IMG_4222.MOV の12〜140秒を、右寄りに4:3で切り出し6倍速。
 //   元の録画は腕を立てた姿勢で上が画面の外に出るので、腕が下りてから箱に入れ終わるまでを使う）
 // 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
-// 3 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
+// 3 いま調べていること：爪のサーボの電流（2026-11-07 追加。並びは実験のあと・技術の前）
+// 4 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
 // 絵は public/site/lab/（run-poster.webp は動画の最初のコマ、
 // top-camera.webp は pi05_20261106_183926 の上のカメラの録画（KIOXIA runs/pi05_policy/…/recording/top.mp4、1920×1080）の125秒目。
 // マットの左・右・下の縁から傾きを直して右寄りに4:3で切り出し、明るさを少し上げた。元は iCloud の
@@ -78,6 +79,20 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
     p: '米国の MicroFactory の卓上ロボットを参考にしました。失敗しかけた区間をアームごと巻き戻し、人が関節を直してから AI に戻します。直す人の手はカメラに写らないので、直した動きをそのまま学習データにできます。',
     links: [{ log: 'LOG403', slug: 'rewind-and-correct-pi05', t: '直した動きだけを学習データにする' }] },
 ];
+
+// 4 いま調べていること：爪のサーボの電流の値（2026-11-07 の実機。0.5秒ごとの中央値。元は KIOXIA の diag/servo_current_20261107/180051_pad）
+// 帯の時刻は値から読んだ（空で閉じた：51〜65秒、つかんだ：79〜109秒）。LOG を出したらリンクを足す
+import grip from '../data/lab/gripper_current_20261107.json';
+const CW = 800, CH = 300, PL = 64, PR = 12, PT = 36, PB = 34, TMAX = 145, YMIN = -100, YMAX = 1050;
+const cx = (t: number) => PL + (t / TMAX) * (CW - PL - PR);
+const cy = (v: number) => PT + (1 - (v - YMIN) / (YMAX - YMIN)) * (CH - PT - PB);
+const gripPath = (grip.points as [number, number][]).map(([t, v], i) => `${i ? 'L' : 'M'}${cx(t).toFixed(1)},${cy(v).toFixed(1)}`).join('');
+const bands = [
+  { t0: 51, t1: 65, label: '空で閉じた' },
+  { t0: 79, t1: 109, label: 'つかんだ' },
+];
+const yTicks = [0, 500, 1000];
+const xTicks = [0, 30, 60, 90, 120];
 ---
 <section class="sec lg"><div class="panel">
   <h2 class="sec-h">研究室の構成 | Setup</h2>
@@ -121,6 +136,34 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   <p class="lg-note">数字は 2026年11月6日（LOG450）までの記録の値です。</p>
 </div></section>
 
+<section class="sec lg"><div class="panel">
+  <h2 class="sec-h">いま調べていること | Now</h2>
+  <p class="lg-lead">お手本の記録に、爪のモーターの電流を足せるかを調べています。11月7日、実機で爪を空で閉じる・ブロックをつかむ・放すを行い、その間の値を1秒に約10回読みました。</p>
+  <div class="lg-now">
+    <div class="lg-now-nums">
+      <div><p class="lg-now-label">空で閉じた</p><p class="lg-num">16</p></div>
+      <div><p class="lg-now-label">ブロックをつかんだ</p><p class="lg-num">960</p></div>
+      <p class="lg-p">値はおよそ60倍違います。つかめたか空振りしたかが、カメラを見なくても分かります。</p>
+    </div>
+    <figure class="lg-chart">
+      <svg viewBox={`0 0 ${CW} ${CH}`} role="img" aria-label="爪のサーボの電流の値の時間の変化。空で閉じた間は約16、ブロックをつかんだ間は約960から800へゆっくり下がり、放すと0の近くへ戻る">
+        {bands.map((b) => (
+          <g>
+            <rect x={cx(b.t0)} y={PT} width={cx(b.t1) - cx(b.t0)} height={CH - PT - PB} fill="#f2f2f2" />
+            <text x={(cx(b.t0) + cx(b.t1)) / 2} y={PT - 12} text-anchor="middle" class="lg-chart-band">{b.label}</text>
+          </g>
+        ))}
+        {yTicks.map((v) => (<text x={PL - 10} y={cy(v) + 4} text-anchor="end" class="lg-chart-tick">{v}</text>))}
+        <line x1={PL} x2={CW - PR} y1={cy(0)} y2={cy(0)} stroke="#d6d6d6" stroke-width="1" />
+        {xTicks.map((t) => (<text x={cx(t)} y={CH - 10} text-anchor="middle" class="lg-chart-tick">{t}</text>))}
+        <text x={CW - PR} y={CH - 10} text-anchor="end" class="lg-chart-tick">秒</text>
+        <path d={gripPath} fill="none" stroke="#242424" stroke-width="2.5" stroke-linejoin="round" />
+      </svg>
+      <figcaption>爪のサーボの電流の値（単位なしの読み値・0.5秒ごとの中央値）。つかんだあとは、30秒かけて960から800へゆっくり下がりました。つかんだブロックを引っ張ったときの変化は、この下がり方に埋もれて見えていません。</figcaption>
+    </figure>
+  </div>
+</div></section>
+
 <section class="sec lg"><div class="panel">
   <h2 class="sec-h">使っている技術 | Technology</h2>
   <dl class="lg-tech">
@@ -184,6 +227,17 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
   .lg-return .ms { font-size: 22px; }
   .lg-note { margin: 16px 0 0; font: 400 13px/22px var(--sans); color: var(--ink-3); }
 
+  /* 4 いま調べていること */
+  .lg-now { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 40px; align-items: start; }
+  .lg-now-nums { display: grid; gap: 20px; }
+  .lg-now-label { margin: 0 0 6px; font: 600 14px/20px var(--sans); color: var(--ink-2); }
+  .lg-now-nums .lg-num { margin: 0; }
+  .lg-chart { margin: 0; }
+  .lg-chart svg { display: block; width: 100%; height: auto; }
+  .lg-chart-tick { font: 400 12px var(--sans); fill: var(--ink-3); }
+  .lg-chart-band { font: 600 14px var(--sans); fill: var(--ink); }
+  .lg-chart figcaption { margin: 12px 0 0; max-width: 46em; font: 400 13px/22px var(--sans); color: var(--ink-3); }
+
   /* 3 技術 */
   .lg-tech { margin: 0; display: grid; }
   .lg-tech-row { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 32px; padding: 28px 0; border-top: 1px solid #e6e6e6; }
@@ -214,6 +268,14 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
     .lg-setup { grid-template-columns: minmax(0, 1fr); gap: 28px; }
     .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
     .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
+    .lg-now { grid-template-columns: minmax(0, 1fr); gap: 24px; }
+    .lg-now-nums { grid-template-columns: 1fr 1fr; }
+    .lg-now-nums .lg-p { grid-column: 1 / -1; }
+  }
+  @media (max-width: 599px) {
+    /* 図は幅に合わせて縮むので、文字だけ大きくしておく */
+    .lg-chart-tick { font-size: 24px; }
+    .lg-chart-band { font-size: 28px; }
     .lg-tech-body.has-fig { grid-template-columns: minmax(0, 1fr); gap: 20px; }
     .lg-fig { max-width: 480px; }
   }
diff --git a/src/data/lab/gripper_current_20261107.json b/src/data/lab/gripper_current_20261107.json
new file mode 100644
index 0000000..5847224
--- /dev/null
+++ b/src/data/lab/gripper_current_20261107.json
@@ -0,0 +1 @@
+{"source": "KIOXIA r2r2r-data/diag/servo_current_20261107/180051_pad/samples.csv（爪＝サーボ7の番地69・70。70の最上位ビットを符号として読む）", "step_sec": 0.5, "stat": "0.5秒ごとの中央値", "points": [[0.0, -3], [0.5, -3], [1.0, -1], [1.5, 1], [2.0, 0], [2.5, -4], [3.0, -4], [3.5, -3], [4.0, 2], [4.5, 0], [5.0, 2], [5.5, 4], [6.0, -2], [6.5, 1], [7.0, 2], [7.5, -1], [8.0, 0], [8.5, 4], [9.0, 7], [9.5, 5], [10.0, -1], [10.5, 6], [11.0, 4], [11.5, 5], [12.0, 6], [12.5, 5], [13.0, 3], [13.5, 2], [14.0, 4], [14.5, 0], [15.0, -4], [15.5, 4], [16.0, 4], [16.5, 4], [17.0, 5], [17.5, 2], [18.0, -4], [18.5, 4], [19.0, -3], [19.5, -2], [20.0, 5], [20.5, 0], [21.0, 0], [21.5, -4], [22.0, -3], [22.5, 4], [23.0, 3], [23.5, 2], [24.0, 5], [24.5, 2], [25.0, 4], [25.5, -1], [26.0, 2], [26.5, 6], [27.0, -2], [27.5, 0], [28.0, 2], [28.5, 0], [29.0, -1], [29.5, 5], [30.0, 3], [30.5, 4], [31.0, 2], [31.5, -2], [32.0, -3], [32.5, -1], [33.0, 3], [33.5, -1], [34.0, 2], [34.5, 2], [35.0, 2], [35.5, 4], [36.0, 1], [36.5, 5], [37.0, 3], [37.5, 4], [38.0, 1], [38.5, 1], [39.0, -2], [39.5, 4], [40.0, 0], [40.5, 2], [41.0, 4], [41.5, 0], [42.0, 7], [42.5, 0], [43.0, 3], [43.5, 2], [44.0, 5], [44.5, 4], [45.0, 2], [45.5, -1], [46.0, 6], [46.5, -2], [47.0, 4], [47.5, 0], [48.0, 0], [48.5, 4], [49.0, -2], [49.5, 1], [50.0, 3], [50.5, 2], [51.0, 79], [51.5, 23], [52.0, 15], [52.5, 16], [53.0, 19], [53.5, 15], [54.0, 13], [54.5, 17], [55.0, 16], [55.5, 14], [56.0, 18], [56.5, 16], [57.0, 16], [57.5, 12], [58.0, 18], [58.5, 17], [59.0, 11], [59.5, 14], [60.0, 17], [60.5, 16], [61.0, 17], [61.5, 14], [62.0, 16], [62.5, 15], [63.0, 12], [63.5, 14], [64.0, 20], [64.5, 16], [65.0, 15], [67.0, -23], [67.5, -47], [68.0, -52], [68.5, -46], [69.0, -51], [69.5, -46], [70.0, -47], [70.5, -52], [71.0, -47], [71.5, -48], [72.0, -48], [72.5, -47], [73.0, -48], [73.5, -44], [74.0, -51], [74.5, -49], [75.0, -48], [75.5, -47], [76.0, -47], [76.5, -49], [77.0, -53], [77.5, -49], [78.0, -50], [78.5, -47], [79.0, 116], [79.5, 896], [80.0, 966], [80.5, 951], [81.0, 940], [81.5, 930], [82.0, 921], [82.5, 910], [83.0, 905], [83.5, 897], [84.0, 890], [84.5, 887], [85.0, 877], [85.5, 876], [86.0, 870], [86.5, 865], [87.0, 860], [87.5, 860], [88.0, 856], [88.5, 851], [89.0, 848], [89.5, 848], [90.0, 845], [90.5, 843], [91.0, 840], [91.5, 837], [92.0, 835], [92.5, 834], [93.0, 831], [93.5, 832], [94.0, 824], [94.5, 823], [95.0, 820], [95.5, 819], [96.0, 816], [96.5, 816], [97.0, 814], [97.5, 813], [98.0, 812], [98.5, 808], [99.0, 809], [99.5, 810], [100.0, 806], [100.5, 806], [101.0, 806], [101.5, 803], [102.0, 805], [102.5, 800], [103.0, 800], [103.5, 799], [104.0, 798], [104.5, 796], [105.0, 797], [105.5, 800], [106.0, 800], [106.5, 793], [107.0, 800], [109.0, 558], [109.5, -36], [110.0, -57], [110.5, -52], [111.0, -50], [111.5, -53], [112.0, -49], [112.5, -58], [113.0, -50], [113.5, -54], [114.0, -54], [114.5, -62], [115.0, -60], [115.5, -61], [116.0, -58], [116.5, -60], [117.0, -58], [117.5, -58], [118.0, -60], [118.5, -54], [119.0, -57], [119.5, -58], [120.0, -57], [120.5, -53], [121.0, -57], [121.5, -58], [122.0, -59], [122.5, -58], [123.0, -44], [123.5, -45], [124.0, -38], [124.5, -44], [125.0, -47], [125.5, -45], [126.0, -39], [126.5, -46], [127.0, -48], [127.5, -39], [128.0, -34], [128.5, -39], [129.0, -32], [129.5, -38], [130.0, -36], [130.5, -40], [131.0, -42], [131.5, -30], [132.0, -38], [132.5, -33], [133.0, -36], [133.5, -45], [134.0, -27], [134.5, -39], [135.0, -45], [135.5, -38], [136.0, -30], [136.5, -36], [137.0, -35], [137.5, -33], [138.0, -37], [138.5, -34], [139.0, -36], [139.5, -45], [140.0, -36], [140.5, -37], [141.0, -30], [141.5, -39], [142.0, -42], [142.5, -31], [143.0, -38], [143.5, -43], [144.0, -46]]}
```

```diff
diff --git a/src/components/LabGuide.astro b/src/components/LabGuide.astro
index 4c55dd0..e93c331 100644
--- a/src/components/LabGuide.astro
+++ b/src/components/LabGuide.astro
@@ -81,7 +81,8 @@ const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[]
 ];
 
 // 4 いま調べていること：爪のサーボの電流の値（2026-11-07 の実機。0.5秒ごとの中央値。元は KIOXIA の diag/servo_current_20261107/180051_pad）
-// 帯の時刻は値から読んだ（空で閉じた：51〜65秒、つかんだ：79〜109秒）。LOG を出したらリンクを足す
+// 帯の時刻は値から読んだ（空で閉じた：51〜65秒、つかんだ：79〜109秒）。
+// 大きい数字（15前後・870前後）は LOG461 の書き方にそろえる（2026-11-08。最初は0.5秒ごとの値から16と960と書いていた）
 import grip from '../data/lab/gripper_current_20261107.json';
 const CW = 800, CH = 300, PL = 64, PR = 12, PT = 36, PB = 34, TMAX = 145, YMIN = -100, YMAX = 1050;
 const cx = (t: number) => PL + (t / TMAX) * (CW - PL - PR);
@@ -141,12 +142,13 @@ const xTicks = [0, 30, 60, 90, 120];
   <p class="lg-lead">お手本の記録に、爪のモーターの電流を足せるかを調べています。11月7日、実機で爪を空で閉じる・ブロックをつかむ・放すを行い、その間の値を1秒に約10回読みました。</p>
   <div class="lg-now">
     <div class="lg-now-nums">
-      <div><p class="lg-now-label">空で閉じた</p><p class="lg-num">16</p></div>
-      <div><p class="lg-now-label">ブロックをつかんだ</p><p class="lg-num">960</p></div>
-      <p class="lg-p">値はおよそ60倍違います。つかめたか空振りしたかが、カメラを見なくても分かります。</p>
+      <div><p class="lg-now-label">空で閉じた</p><p class="lg-num">15<small>前後</small></p></div>
+      <div><p class="lg-now-label">ブロックをつかんだ</p><p class="lg-num">870<small>前後</small></p></div>
+      <p class="lg-p">値は50倍以上違います。つかめたか空振りしたかが、カメラを見なくても分かります。</p>
+      <ul class="lg-links"><li><a href="/record/reading-mecharm-270-servo-current-for-learning" title="電流を読んだ記録" aria-label="LOG461 電流を読んだ記録"><b>LOG461</b>電流を読んだ記録<i class="ms">arrow_forward</i></a></li></ul>
     </div>
     <figure class="lg-chart">
-      <svg viewBox={`0 0 ${CW} ${CH}`} role="img" aria-label="爪のサーボの電流の値の時間の変化。空で閉じた間は約16、ブロックをつかんだ間は約960から800へゆっくり下がり、放すと0の近くへ戻る">
+      <svg viewBox={`0 0 ${CW} ${CH}`} role="img" aria-label="爪のサーボの電流の値の時間の変化。空で閉じた間は15前後、ブロックをつかんだ直後に最も高くなり、30秒ほどで800前後までゆっくり下がり、放すとマイナス50前後になる">
         {bands.map((b) => (
           <g>
             <rect x={cx(b.t0)} y={PT} width={cx(b.t1) - cx(b.t0)} height={CH - PT - PB} fill="#f2f2f2" />
@@ -159,7 +161,7 @@ const xTicks = [0, 30, 60, 90, 120];
         <text x={CW - PR} y={CH - 10} text-anchor="end" class="lg-chart-tick">秒</text>
         <path d={gripPath} fill="none" stroke="#242424" stroke-width="2.5" stroke-linejoin="round" />
       </svg>
-      <figcaption>爪のサーボの電流の値（単位なしの読み値・0.5秒ごとの中央値）。つかんだあとは、30秒かけて960から800へゆっくり下がりました。つかんだブロックを引っ張ったときの変化は、この下がり方に埋もれて見えていません。</figcaption>
+      <figcaption>爪のサーボの電流の値（単位なしの読み値・0.5秒ごとの中央値）。つかんだ直後に最も高くなり、30秒ほどかけて800前後までゆっくり下がりました。つかんだブロックを引っ張ったときの変化は、この下がり方に埋もれて見えていません。</figcaption>
     </figure>
   </div>
 </div></section>
@@ -232,6 +234,7 @@ const xTicks = [0, 30, 60, 90, 120];
   .lg-now-nums { display: grid; gap: 20px; }
   .lg-now-label { margin: 0 0 6px; font: 600 14px/20px var(--sans); color: var(--ink-2); }
   .lg-now-nums .lg-num { margin: 0; }
+  .lg-now-nums .lg-links { margin: 0; grid-column: 1 / -1; }
   .lg-chart { margin: 0; }
   .lg-chart svg { display: block; width: 100%; height: auto; }
   .lg-chart-tick { font: 400 12px var(--sans); fill: var(--ink-3); }
```


## 作業ログ ― 公開した7回と、確かめたこと

### commit の一覧

| commit | 時刻 | 中身 |
|---|---|---|
| c7caad9 | 11/7 16:20 | 構成・実験・技術の3つの節を足した |
| 09c80f5 | 11/7 17:21 | 実験のカードの段を subgrid でそろえ、上の線を外した |
| c556a04 | 11/7 17:29 | 矢印の図と黒いカードをやめ、机の写真と2つの一覧にした |
| 43cf04c | 11/7 17:46 | 写真を実機の動画に替え、2つの一覧を面で分けた |
| 965efdb | 11/7 17:56 | 上のカメラの写真の傾きを射影変換で直した |
| 3a73764 | 11/7 18:13 | いま調べていること（爪の電流）を足した |
| 43f5322 | 11/8 15:37 | 爪の数字を LOG461 にそろえ、LOG461 へのリンクを足した |

### 公開のたびに、ビルドと実際の画面で確かめた

公開の前に npm run build を通し、手元で astro preview を開いて、幅 1440px・1240px・390px の画面写真を撮って見ました。公開したあとは、ページの HTML に新しい文が入ったことを curl で待ってから、公開されたページで同じように確かめています。

```javascript
const { chromium } = require('playwright');
(async () => {
  const [w, out] = process.argv.slice(2);
  const b = await chromium.launch(); const p = await b.newPage({ viewport: { width: +w, height: 900 } });
  await p.goto('http://localhost:4321/series6', { waitUntil: 'networkidle' });
  await p.addStyleTag({content:'[class*=toast]{display:none!important}'});
  const el = (await p.$$('.lg'))[2]; await el.scrollIntoViewIfNeeded(); await p.waitForTimeout(500);
  await el.screenshot({ path: out });
  await b.close();
})();
```

### HTML から読める文字の数を数えた

公開されたページで、解説の4つの節の文字（空白を除く）を数えました。見出しの下の説明（導入比較ガイドのバナーを含む）は295字、解説の4つの節は403字・745字・288字・862字で、合わせて2,298字です。節の中のリンクは17本で、LOG461 へのリンクを足して18本になりました。

```javascript
const { chromium } = require('playwright');
(async () => {
  const b = await chromium.launch(); const p = await b.newPage();
  await p.goto('https://pixelstomotors.com/series6', { waitUntil: 'networkidle' });
  const r = await p.evaluate(() => {
    const lg=[...document.querySelectorAll('.lg')].map(e=>e.innerText.replace(/\s+/g,'').length);
    const hero=document.querySelector('.panel')?.innerText.replace(/\s+/g,'').length;
    const links=[...document.querySelectorAll('.lg a')].length;
    return {lg, hero, links};
  });
  console.log(JSON.stringify(r));
  await b.close();
})();
```

```
{"lg":[403,745,288,862],"hero":295,"links":17}
69456
```

2行目は、そのときのページの HTML の大きさ（バイト）です。

### 記事の画面写真を撮ったスクリプト

```javascript
const { chromium } = require('playwright');
(async () => {
  const b = await chromium.launch(); const p = await b.newPage({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 2 });
  await p.goto('https://pixelstomotors.com/series6', { waitUntil: 'networkidle' });
  await p.addStyleTag({content:'[class*=toast],[class*=parade],[class*=hakobu-walk]{display:none!important} header,.site-header,nav{position:static!important}'});
  const secs = await p.$$('.lg');
  const names = ['05_setup_video','08_experiment_aligned','09_gripper_current','07_tech_rows'];
  for (let i=0;i<secs.length;i++){ await secs[i].scrollIntoViewIfNeeded(); await p.waitForTimeout(i===0?6000:800); await secs[i].screenshot({path:`LOG462_images/LOG462_${names[i]}.png`}); }
  await b.close();
})();
```


## 作業ログ ― 最後の LabGuide.astro（commit 43f5322 の時点の全文）

```astro
---
// /series6（フィジカルAI研究室）の見出しの下に置く解説（2026-11-07）
// 1 研究室の構成：実機の動画と、手元に置くもの・時間で借りるものの一覧（矢印の図は 2026-11-07 にやめた）
//   動画は R2 の lab-setup-pi05-run-v2.mp4（2026-10-29 の横からの録画 IMG_4222.MOV の12〜140秒を、右寄りに4:3で切り出し6倍速。
//   元の録画は腕を立てた姿勢で上が画面の外に出るので、腕が下りてから箱に入れ終わるまでを使う）
// 2 いま回している実験：お手本 → 学習 → 実機 → 人の直し → 直した成功を学習に足す、のループと各段の数字
// 3 いま調べていること：爪のサーボの電流（2026-11-07 追加。並びは実験のあと・技術の前）
// 4 使っている技術：π0.5・追加学習（LoRA）・借りる GPU・推論サーバー・巻き戻しと人の直し
// 絵は public/site/lab/（run-poster.webp は動画の最初のコマ、
// top-camera.webp は pi05_20261106_183926 の上のカメラの録画（KIOXIA runs/pi05_policy/…/recording/top.mp4、1920×1080）の125秒目。
// マットの左・右・下の縁から傾きを直して右寄りに4:3で切り出し、明るさを少し上げた。元は iCloud の
// フィジカルAI研究室を作る/series6_guide_images/）
// 数字はどれも LOG の記録の値。新しい LOG で数字が変わったら、ここも書き換える
type Link = { log: string; slug: string; t: string };

// 構成は、手元に置くものと時間で借りるものの2つに分ける（2026-11-07 に矢印の図から改めた）
const kit: { group: string; items: { h: string; p: string }[] }[] = [
  { group: '手元に置くもの', items: [
    { h: 'mechArm 270', p: '6つの関節を持つ小型のロボットアーム。中の Raspberry Pi が関節を動かす' },
    { h: '上のカメラ', p: '真上に付けたスマホ。π0.5 が見るのはこの画像だけ' },
    { h: 'ゲームパッド', p: 'AI が失敗しかけたとき、人が関節を直す。3,198円の互換品' },
    { h: 'Mac', p: '画像と関節の角度を記録し、借りた GPU とやり取りする' },
  ] },
  { group: '時間で借りるもの', items: [
    { h: 'Runpod の A40', p: 'π0.5 の学習と推論をする GPU。メモリ 48GB、1時間あたり約98円' },
    { h: 'Hugging Face', p: '学習済みのモデル（6.3GB）の置き場所' },
  ] },
];

const loop: { h: string; num: string; unit: string; p: string; links: Link[] }[] = [
  { h: 'お手本を集める', num: '19', unit: '本',
    p: '要所の姿勢だけ手でアームに教え、間は再生でつないで録りました。ブロックの置き場所は5か所です。',
    links: [
      { log: 'LOG349', slug: 'drag-teach-waypoint-replay', t: '手で教えた動きを再生' },
      { log: 'LOG352', slug: 'teach-replay-19-demos', t: 'お手本19本' },
    ] },
  { h: 'π0.5 に覚えさせる', num: '4,000', unit: 'ステップ',
    p: '借りた A40 で追加学習し、学習の誤差（loss）は 0.0858 から 0.0037 に下がりました。',
    links: [
      { log: 'LOG341', slug: 'pi05-mecharm-lora-2000-steps', t: '最初の学習' },
      { log: 'LOG355', slug: 'pi05-retrain-five-positions', t: '5か所で学習し直す' },
      { log: 'LOG358', slug: 'pi05-learned-the-pauses', t: '待ち時間まで覚えた' },
    ] },
  { h: '実機で動かす', num: '9/15', unit: '回',
    p: '3か所に5回ずつブロックを置き、人が手を出さずに箱へ入れた回数です。腕を伸ばしきる位置は5回中1回でした。',
    links: [
      { log: 'LOG361', slug: 'pi05-first-block-in-box', t: '初めて箱に入れた' },
      { log: 'LOG401', slug: 'pi05-weak-position-d', t: '回数で測る' },
    ] },
  { h: '失敗しかけたら人が直す', num: '13', unit: '秒',
    p: '動きを巻き戻し、ゲームパッドで関節を直して AI に戻すまでの、1回あたりの中央の値です。キーで直していた頃は41〜51秒でした。',
    links: [
      { log: 'LOG403', slug: 'rewind-and-correct-pi05', t: '巻き戻しの仕組み' },
      { log: 'LOG446', slug: 'gamepad-correction-mecharm-270-settled', t: 'ゲームパッドの形' },
      { log: 'LOG450', slug: 'gamepad-fixes-mecharm-270-ai-in-13-seconds', t: '1回13秒に' },
    ] },
  { h: '直した成功を学習に足す', num: '11', unit: '本',
    p: '人が直して成功した記録をお手本に足し、前のモデルから1,500ステップ続けて学び直します。',
    links: [
      { log: 'LOG417', slug: 'retrain-pi05-with-human-corrections', t: '直した5回で学び直す' },
      { log: 'LOG422', slug: 'retrained-pi05-still-needs-human-corrections', t: 'それでも直しが要った' },
    ] },
];

const tech: { name: string; sub: string; p: string; fig?: boolean; links: Link[] }[] = [
  { name: 'π0.5', sub: 'Physical Intelligence', fig: true,
    p: '米国の Physical Intelligence 社が公開している、ロボット用の AI のモデルです。上のカメラの画像、6つの関節と爪の角度、指示文（赤いブロックを白い箱に入れる）を受け取り、次の1秒ぶん（10コマ）の関節の角度を返します。どの順番で動くかを書いたプログラムはありません。',
    links: [{ log: 'LOG337', slug: 'pi05-mecharm-demo-to-inference', t: 'mechArm 270 で動かすまでの流れ' }] },
  { name: '追加学習', sub: 'LoRA',
    p: 'たくさんのロボットのデータで学習済みの π0.5 に、mechArm 270 のお手本だけを足して覚えさせます。モデル全体ではなく、足した小さな部品だけを学習するので、A40 を1枚借りれば足ります。',
    links: [{ log: 'LOG341', slug: 'pi05-mecharm-lora-2000-steps', t: '予測がお手本とほぼ一致' }] },
  { name: '時間で借りる GPU', sub: 'Runpod',
    p: 'π0.5 は NVIDIA の GPU を積んだ Linux のマシンでしか動かず、Mac では動きません。そこで GPU を時間単位で借ります。学習は自動で回し、終わるとモデルを持ち帰って、借りたマシンを消します。',
    links: [{ log: 'LOG401', slug: 'pi05-weak-position-d', t: 'モデルを Hugging Face に置いた' }] },
  { name: '推論サーバー', sub: 'Remote inference',
    p: '借りたマシンの上で π0.5 を起動し、Mac とは SSH の中継でつなぎます。π0.5 の計算は1回平均97ミリ秒、Mac から送って答えが返るまでの往復は391ミリ秒でした（A40）。',
    links: [{ log: 'LOG326', slug: 'openpi-remote-inference-first-run', t: '借りた GPU で初めて動かした' }] },
  { name: '巻き戻しと人の直し', sub: 'Human correction',
    p: '米国の MicroFactory の卓上ロボットを参考にしました。失敗しかけた区間をアームごと巻き戻し、人が関節を直してから AI に戻します。直す人の手はカメラに写らないので、直した動きをそのまま学習データにできます。',
    links: [{ log: 'LOG403', slug: 'rewind-and-correct-pi05', t: '直した動きだけを学習データにする' }] },
];

// 4 いま調べていること：爪のサーボの電流の値（2026-11-07 の実機。0.5秒ごとの中央値。元は KIOXIA の diag/servo_current_20261107/180051_pad）
// 帯の時刻は値から読んだ（空で閉じた：51〜65秒、つかんだ：79〜109秒）。
// 大きい数字（15前後・870前後）は LOG461 の書き方にそろえる（2026-11-08。最初は0.5秒ごとの値から16と960と書いていた）
import grip from '../data/lab/gripper_current_20261107.json';
const CW = 800, CH = 300, PL = 64, PR = 12, PT = 36, PB = 34, TMAX = 145, YMIN = -100, YMAX = 1050;
const cx = (t: number) => PL + (t / TMAX) * (CW - PL - PR);
const cy = (v: number) => PT + (1 - (v - YMIN) / (YMAX - YMIN)) * (CH - PT - PB);
const gripPath = (grip.points as [number, number][]).map(([t, v], i) => `${i ? 'L' : 'M'}${cx(t).toFixed(1)},${cy(v).toFixed(1)}`).join('');
const bands = [
  { t0: 51, t1: 65, label: '空で閉じた' },
  { t0: 79, t1: 109, label: 'つかんだ' },
];
const yTicks = [0, 500, 1000];
const xTicks = [0, 30, 60, 90, 120];
---
<section class="sec lg"><div class="panel">
  <h2 class="sec-h">研究室の構成 | Setup</h2>
  <p class="lg-lead">机の上のアームとカメラと Mac に、時間で借りる GPU を足しただけの構成です。Mac が上のカメラの画像と関節の角度を借りた GPU へ送り、π0.5 が次の1秒ぶんの関節の角度を返して、Mac がそれをアームへ渡します。</p>
  <div class="lg-setup">
    <figure class="lg-run">
      <video src="/media/lab-setup-pi05-run-v2.mp4" poster="/site/lab/run-poster.webp" width="1200" height="900" autoplay muted loop playsinline preload="metadata"
        aria-label="mechArm 270 が赤いブロックをつかみ、持ち上げて右の白い箱に入れるまで"></video>
      <figcaption>π0.5 が動かした mechArm 270。人の手を入れずに成功した1回（2026年10月29日・6倍速）</figcaption>
    </figure>
    <div class="lg-kit">
      {kit.map((g) => (
        <div class="lg-kit-group">
          <h3 class="lg-kit-h">{g.group}</h3>
          <dl class="lg-items">
            {g.items.map((it) => (<div><dt>{it.h}</dt><dd>{it.p}</dd></div>))}
          </dl>
        </div>
      ))}
    </div>
  </div>
</div></section>

<section class="sec lg"><div class="panel">
  <h2 class="sec-h">いま回している実験 | Experiment</h2>
  <p class="lg-lead">赤いブロックをつかんで、白い箱に入れる。この1つの作業を π0.5 に覚えさせ、失敗しかけた所を人が直し、直した動きをまた学習に回しています。人の直しが要らなくなるまで、このループを回します。</p>
  <ol class="lg-loop">
    {loop.map((s, i) => (
      <li class="lg-step">
        <span class="lg-step-no">{String(i + 1).padStart(2, '0')}</span>
        <h3 class="lg-step-h">{s.h}</h3>
        <p class="lg-num">{s.num}<small>{s.unit}</small></p>
        <p class="lg-p">{s.p}</p>
        <ul class="lg-links">
          {s.links.map((l) => <li><a href={`/record/${l.slug}`} title={l.t} aria-label={`${l.log} ${l.t}`}><b>{l.log}</b><i class="ms">arrow_forward</i></a></li>)}
        </ul>
      </li>
    ))}
  </ol>
  <p class="lg-return"><i class="ms" aria-hidden="true">replay</i>05 のあとは 03 に戻り、学び直したモデルで実機をもう一度動かします</p>
  <p class="lg-note">数字は 2026年11月6日（LOG450）までの記録の値です。</p>
</div></section>

<section class="sec lg"><div class="panel">
  <h2 class="sec-h">いま調べていること | Now</h2>
  <p class="lg-lead">お手本の記録に、爪のモーターの電流を足せるかを調べています。11月7日、実機で爪を空で閉じる・ブロックをつかむ・放すを行い、その間の値を1秒に約10回読みました。</p>
  <div class="lg-now">
    <div class="lg-now-nums">
      <div><p class="lg-now-label">空で閉じた</p><p class="lg-num">15<small>前後</small></p></div>
      <div><p class="lg-now-label">ブロックをつかんだ</p><p class="lg-num">870<small>前後</small></p></div>
      <p class="lg-p">値は50倍以上違います。つかめたか空振りしたかが、カメラを見なくても分かります。</p>
      <ul class="lg-links"><li><a href="/record/reading-mecharm-270-servo-current-for-learning" title="電流を読んだ記録" aria-label="LOG461 電流を読んだ記録"><b>LOG461</b>電流を読んだ記録<i class="ms">arrow_forward</i></a></li></ul>
    </div>
    <figure class="lg-chart">
      <svg viewBox={`0 0 ${CW} ${CH}`} role="img" aria-label="爪のサーボの電流の値の時間の変化。空で閉じた間は15前後、ブロックをつかんだ直後に最も高くなり、30秒ほどで800前後までゆっくり下がり、放すとマイナス50前後になる">
        {bands.map((b) => (
          <g>
            <rect x={cx(b.t0)} y={PT} width={cx(b.t1) - cx(b.t0)} height={CH - PT - PB} fill="#f2f2f2" />
            <text x={(cx(b.t0) + cx(b.t1)) / 2} y={PT - 12} text-anchor="middle" class="lg-chart-band">{b.label}</text>
          </g>
        ))}
        {yTicks.map((v) => (<text x={PL - 10} y={cy(v) + 4} text-anchor="end" class="lg-chart-tick">{v}</text>))}
        <line x1={PL} x2={CW - PR} y1={cy(0)} y2={cy(0)} stroke="#d6d6d6" stroke-width="1" />
        {xTicks.map((t) => (<text x={cx(t)} y={CH - 10} text-anchor="middle" class="lg-chart-tick">{t}</text>))}
        <text x={CW - PR} y={CH - 10} text-anchor="end" class="lg-chart-tick">秒</text>
        <path d={gripPath} fill="none" stroke="#242424" stroke-width="2.5" stroke-linejoin="round" />
      </svg>
      <figcaption>爪のサーボの電流の値（単位なしの読み値・0.5秒ごとの中央値）。つかんだ直後に最も高くなり、30秒ほどかけて800前後までゆっくり下がりました。つかんだブロックを引っ張ったときの変化は、この下がり方に埋もれて見えていません。</figcaption>
    </figure>
  </div>
</div></section>

<section class="sec lg"><div class="panel">
  <h2 class="sec-h">使っている技術 | Technology</h2>
  <dl class="lg-tech">
    {tech.map((t) => (
      <div class="lg-tech-row">
        <dt><span class="lg-tech-name">{t.name}</span><span class="lg-tech-sub">{t.sub}</span></dt>
        <dd>
          <div class={t.fig ? 'lg-tech-body has-fig' : 'lg-tech-body'}>
            <div>
              <p class="lg-p">{t.p}</p>
              <ul class="lg-links">
                {t.links.map((l) => <li><a href={`/record/${l.slug}`}><b>{l.log}</b>{l.t}<i class="ms">arrow_forward</i></a></li>)}
              </ul>
            </div>
            {t.fig && (
              <figure class="lg-fig">
                <img src="/site/lab/top-camera.webp" alt="真上のカメラの画像。mechArm 270 の爪が赤いブロックをつかみ、右に白い箱がある" width="800" height="600" loading="lazy" />
                <figcaption>上のカメラの画像。傾きを直して切り出しています。π0.5 には、この画像を 384×216 に縮めて渡します</figcaption>
              </figure>
            )}
          </div>
        </dd>
      </div>
    ))}
  </dl>
</div></section>

<style>
  .lg { padding-bottom: 0; }
  .lg-lead { margin: -16px 0 32px; max-width: 46em; font: 400 16px/28px var(--sans); color: var(--ink-2); }
  .lg-p { margin: 0; font: 400 15px/27px var(--sans); color: var(--ink-2); word-break: auto-phrase; text-wrap: pretty; }

  /* 1 構成：3つの場所と、その間を行き来するもの */
  /* 写真はブロックから箱まで入れたいので、切り抜かずに元の比率のまま置く */
  .lg-setup { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 32px; align-items: start; }
  .lg-run { margin: 0; }
  .lg-run video { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; border-radius: 8px; background: #e9e7e2; }
  .lg-run figcaption { margin: 8px 0 0; font: 400 12px/18px var(--sans); color: var(--ink-3); }
  /* 手元に置くもの・時間で借りるもの を、それぞれ面で囲んで分ける */
  .lg-kit { display: grid; gap: 12px; }
  .lg-kit-group { padding: 24px; border-radius: 8px; background: var(--bg); }
  .lg-kit-h { margin: 0 0 16px; font: 700 18px/28px var(--sans); color: var(--ink); }
  .lg-items { margin: 0; display: grid; gap: 14px; }
  .lg-items dt { font: 700 15px/24px var(--sans); color: var(--ink); }
  .lg-items dd { margin: 2px 0 0; font: 400 14px/22px var(--sans); color: var(--ink-2); word-break: auto-phrase; }

  /* 2 実験のループ */
  .lg-loop { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
  /* 5枚の見出し・数字・文・リンクの高さを、subgrid で行ごとにそろえる（段々にしない） */
  .lg-step { display: grid; grid-row: span 5; grid-template-rows: subgrid; row-gap: 0; align-content: start; padding: 20px; border-radius: 8px; background: var(--bg); }
  .lg-step-no { font: 700 13px/20px var(--sans); color: var(--ink-3); font-variant-numeric: tabular-nums; }
  .lg-step-h { align-self: start; margin: 4px 0 12px; font: 700 16px/24px var(--sans); color: var(--ink); word-break: auto-phrase; }
  .lg-num { align-self: start; white-space: nowrap; margin: 0 0 12px; font: 700 clamp(32px, 2.8vw, 40px)/1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
  .lg-num small { margin-left: 4px; font: 600 14px/1 var(--sans); color: var(--ink-2); letter-spacing: 0; }
  .lg-step .lg-p { font-size: 14px; line-height: 24px; }
  .lg-step .lg-links { margin: 0; padding-top: 16px; gap: 6px; align-self: start; }
  .lg-step .lg-links a { gap: 4px; padding: 5px 8px 5px 10px; }
  .lg-step .lg-links a { background: #fff; }
  .lg-step .lg-links a:hover { background: #e6e6e6; }
  .lg-return { display: flex; align-items: center; gap: 10px; margin: 12px 0 0; padding: 14px 20px; border-radius: 8px; background: var(--dark); color: #fff; font: 600 15px/24px var(--sans); }
  .lg-return .ms { font-size: 22px; }
  .lg-note { margin: 16px 0 0; font: 400 13px/22px var(--sans); color: var(--ink-3); }

  /* 4 いま調べていること */
  .lg-now { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 40px; align-items: start; }
  .lg-now-nums { display: grid; gap: 20px; }
  .lg-now-label { margin: 0 0 6px; font: 600 14px/20px var(--sans); color: var(--ink-2); }
  .lg-now-nums .lg-num { margin: 0; }
  .lg-now-nums .lg-links { margin: 0; grid-column: 1 / -1; }
  .lg-chart { margin: 0; }
  .lg-chart svg { display: block; width: 100%; height: auto; }
  .lg-chart-tick { font: 400 12px var(--sans); fill: var(--ink-3); }
  .lg-chart-band { font: 600 14px var(--sans); fill: var(--ink); }
  .lg-chart figcaption { margin: 12px 0 0; max-width: 46em; font: 400 13px/22px var(--sans); color: var(--ink-3); }

  /* 3 技術 */
  .lg-tech { margin: 0; display: grid; }
  .lg-tech-row { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 32px; padding: 28px 0; border-top: 1px solid #e6e6e6; }
  .lg-tech-row:last-child { padding-bottom: 0; }
  .lg-tech-row dt { display: grid; align-content: start; gap: 2px; }
  .lg-tech-name { font: 700 20px/30px var(--sans); color: var(--ink); }
  .lg-tech-sub { font: 400 13px/20px var(--sans); color: var(--ink-3); }
  .lg-tech-row dd { margin: 0; }
  .lg-tech-body { max-width: 52em; }
  .lg-tech-body.has-fig { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 32px; align-items: start; }
  .lg-fig { margin: 0; }
  .lg-fig img { display: block; width: 100%; height: auto; border-radius: 6px; }
  .lg-fig figcaption { margin: 8px 0 0; font: 400 12px/18px var(--sans); color: var(--ink-3); }

  /* 記録へのリンク（/series7 の解説と同じ形） */
  .lg-links { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
  .lg-links a { display: inline-flex; align-items: center; gap: 8px; padding: 7px 10px 7px 12px; border-radius: 4px; background: #f2f2f2;
    color: var(--ink); font: 500 13px/20px var(--sans); text-decoration: none; transition: background .15s; }
  .lg-links a b { font-weight: 700; font-variant-numeric: tabular-nums; }
  .lg-links a .ms { font-size: 15px; color: var(--ink-3); transition: transform .2s; }
  .lg-links a:hover { background: #e6e6e6; }
  .lg-links a:hover .ms { transform: translateX(2px); }

  @media (max-width: 1199px) {
    .lg-loop { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  @media (max-width: 1023px) {
    .lg-setup { grid-template-columns: minmax(0, 1fr); gap: 28px; }
    .lg-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .lg-tech-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
    .lg-now { grid-template-columns: minmax(0, 1fr); gap: 24px; }
    .lg-now-nums { grid-template-columns: 1fr 1fr; }
    .lg-now-nums .lg-p { grid-column: 1 / -1; }
  }
  @media (max-width: 599px) {
    /* 図は幅に合わせて縮むので、文字だけ大きくしておく */
    .lg-chart-tick { font-size: 24px; }
    .lg-chart-band { font-size: 28px; }
    .lg-tech-body.has-fig { grid-template-columns: minmax(0, 1fr); gap: 20px; }
    .lg-fig { max-width: 480px; }
  }
  @media (max-width: 599px) {
    .lg-lead { margin: -16px 0 24px; font-size: 15px; line-height: 26px; }
    .lg-loop { grid-template-columns: minmax(0, 1fr); }
    .lg-num { font-size: 36px; }
    .lg-tech-row { padding: 22px 0; }
    .lg-tech-name { font-size: 18px; line-height: 28px; }
  }
</style>
```
