サービスロボット導入シミュレーション Log#23 | 導入前に、配膳ロボットの詰まりを動画で見比べる

サービスロボット導入シミュレーション Log#23 | 導入前に、配膳ロボットの詰まりを動画で見比べる

この記事の素材(コード・ログ・データ 10ファイル・まとめてダウンロードあり)

配膳ロボットのシミュレーションを動画で見せるなら、ロボットが店の中を走るだけの映像より、店の形を直す前と直した後を、同じお客さん・同じ時刻で左右に並べた映像のほうが、何が変わったのかが一目で伝わります。Unity(ゲームを作る道具)の3Dで再現したファミレスで、丸テーブル2つの間を1.1mから2.1mに広げる前と後を撮り、前はロボット2台が約8分動けず、後は同じ場面を通り抜ける映像を、配膳ロボットの導入前シミュレーションのページ(pixelstomotors.com/serving-robot-one-less-staff )に並べました。

このシリーズでは、配膳ロボットを店に入れるとどうなるかを、サイトの試算と、Unity で建てた3Dのファミレスの2つで調べています。調べた結果は、飲食店や、ロボットを提案するメーカー・販売会社の人が読む前提で、1枚のページ(LP:ランディングページ。1つの用件のために作る縦長のページ)にまとめています。そこに「Unity のシミュレーションのデモ動画を載せたら効果があるか」を考えたところ、ただ走っているだけの映像は、ゲームの画面のように見えて判断の材料にならない、というのが最初の見立てでした。導入を考える人が知りたいのは、自分の店で何が起きるか、直したら何が変わるか、です。

そこで題材を、前の記事(LOG402)で見つけた「記憶の店(② 定番の郊外型)」の丸テーブルにしました。丸テーブル2つの間が1.1mしかなく、1台が卓に止まると、もう1台が抜けられずに動けなくなっていた所です。右の丸テーブルを1.0m右へ寄せると、60秒以上動けなくなる回数は8回から0回になりました。この「直す前」と「直した後」を、お客さんの来方を決める番号(種)を同じにして2回走らせ、同じ時刻を同じ画角の真上から撮りました。違うのは右の丸テーブルの位置だけです。

同じ客・同じ時刻で撮ると、左右の違いは店の形のせいだと言い切れます。 録画した場面のロボットの位置は、画面なしで回した記録と1行も違いませんでした。録画するために動きが変わった、ということもありません。

やったことなぜ結果
デモ動画をどこに・何を載せるかを考えた
走るだけの映像では判断の材料にならない
LP の「どこで止まるか」に、前後を並べた動画を足すと決めた
②の丸テーブルの前後を、同じ種・同じ時刻で録画した(依頼26)
違いを店の形だけにするため
前は2台が約8分動けない。後は通り抜ける。位置は画面なしの回と同じ
並べる形と切り替える形を、確認用のページで見比べた
どちらが伝わるかは見て決める並べる形に決めた
光の角度を52°から75°に上げて撮り直した(依頼28)
斜めの長い影が、客や椅子より目立っていた
影が短くなった。動きは変わらない
LP に並べ、PC とスマホで確かめて公開した
実際の画面で崩れないか
公開後に2本が0.67秒ずれていたので、そろえて流す作りに直した

ここから下は作業ログです。デモ動画を載せる場所の考え方、Claude Code に頼んだ録画の依頼文と報告、確認用のページ、影の撮り直し、LP の差分と確かめまでを、コード・依頼文・報告・出力とあわせて載せます。効果のところは、公開した直後なので見込みで書いています(何の数字で確かめるかを添えています)。

配膳ロボットを自分の店に入れたらどうなるかは、このシリーズの試算をもとにした別のページで、この動画も含めて見られます。

店の立体図(席・キッチン・配膳ロボットの通り道)導入前シミュレーション配膳ロボットを、導入前に自分の店舗でシミュレーション店舗の図面と人数から、何人で回るか・どこで止まるか・月いくらかかるかを出します

作業ログ ― デモ動画は、走る様子より直す前と後を見せると決めた

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

ファイルの一覧(10本)

01_sec02.md ― 依頼文:LP用に店2の直す前と後を録画する(20261029_26)・3,320字

02_sec02.txt ― 報告:20261029_2102_lp_before_after_rec.txt・9,944字

03_sec02.md ― 依頼箱の結果:20261029_26_LP用に店2の直す前と後を録画する_20261029_2039.md・3,377字

04_sec03.html.txt ― 確認用のページ(影を撮り直したあとの版)・5,391字

05_sec04.txt ― 報告:20261029_2228_lp_rec_short_shadow.txt・6,863字

06_SimTimeRecorder.cs.txt ― 録画の部品 SimTimeRecorder.cs(cs:43・全文)・16,305字

07_sec04.txt ― 録画の部品を足したときの差分:cs:40 → cs:41・14,482字

08_sec04.txt ― 光の角度と静止画の回を足したときの差分:cs:41 → cs:42・7,428字

09_commands.txt ― 録画の実行ファイルを作って回したときのコマンド commands.txt・19,715字

10_sec05.txt ― LP に入れた差分(3つの commit をまとめたもの)・5,498字

LP(ランディングページ)は、導入を考える人が読む1枚のページ

LP は、1つの用件のために作る縦長の1枚のページです。このサイトの配膳ロボットの LP(/serving-robot-one-less-staff)は、飲食店の経営者・責任者と、ロボットを提案するメーカー・販売会社の人を読み手にして、「導入前に、自分の店で何人で回るか・どこで止まるか・月いくらかかるか」を試算と3Dの店で確かめられることを伝えています。ページの最後のボタンは、自分の店の条件で試算を相談するメッセージフォームにつながります。

載せる前のサイトの状態:LP には Unity の短い動画が4本あった

デモ動画を足す前に、サイトのコード(GitHub の p2m-site)を読んで、どこに何があるかを確かめました。

ページUnity の映像見立て
配膳ロボットの LP
最初の画面に3本(斜め・真上の混んだ時間・試算のコード)、「どこで止まるか」に4つの視点の1本
走っている様子はもうある。直す前と後を並べた映像はない
/series8(シリーズの一覧)
LP へのバナーの絵(立体の図)だけ
動画を入れる余地はあるが、記録の一覧から LP へ人を送る役目
トップいちばん上はハコブくんの動画
ここに入れると、1つの画面で伝えることが2つになる

そのうえで、載せる場所ごとの効き方を次のように見立てました。

載せる場所効き方の見立て理由
LP の「どこで止まるか」に、前後を並べた動画
高い
79→0回・112→31回の数字に、目で見える証拠が付く
/series8 のバナーの絵を Unity のループ動画に
中
一覧から LP へ進む人を増やせる
1〜2分の通しのデモ(YouTube に置いて埋め込む)
中
チャンネルの方向(入れたらどうなるかを数字とシミュレーションで確かめる)と合う
トップの一番上低いハコブくんとぶつかる

気をつけることも決めました。映像の中に入店待ちや必要な人数の数字を焼き込まないこと(そこはサイトの試算が正で、Unity の数字と並べるとずれて見える)。映像で扱うのは、Unity が測る側の「止まる場所と回数」だけにすること。キッチンのモニターの文字がスマホで読めない大きさなら、寄りで撮ること。暗い膜をかけた映像や、画質の悪い映像は使わないこと。

  • ねらい:LP にある「どこで止まるか」の数字に、目で見える証拠を付ける
  • 変わったこと:数字の欄の下に、同じ店・同じ時刻の直す前と直した後の動画が並ぶ
  • 見込める効果:メーカー・販売会社の人が、提案先にそのまま見せられる材料になり、相談のきっかけになる(見込み。公開後に、サイトの使われ方の記録 /api/ev で、この節まで読まれた割合と相談のボタンが押された数を見て確かめる)

題材は、前の記事で見つけた②の丸テーブルにした

前の記事(LOG402)で、記憶の店(② 定番の郊外型・19卓・88席)を Unity に建てたとき、丸テーブル T05・T06 の間(1.1m)で、ロボット2台の回に60秒以上動けなくなるのが8回出ました。右の丸テーブル T06 を右へ1.0m寄せて間を2.1mにすると、0回になりました。

LP にもともと載っていた 79→0回(細い通路の入口の鉢合わせ)と 112→31回(レジのまわり)は、ロボットを決まった線の上だけ走らせていた頃の古い作りの記録で、録画も残っていません。今の作りで同じ条件を撮り直せる題材として、店の形を1か所直しただけで止まりが消えた②の丸テーブルを選びました。店の側が自分で打てる手(卓を動かす)なので、LP の「自分の店の形で結果が変わる」という話にも合います。

丸テーブルのまわりの止まりを、回ごとにまとめた round_zone_stops.py

どの時刻を撮ればよいかを決めるために、丸テーブルのまわり(x 4.75〜6.85・y 11.3〜14.0)の止まりを、回ごと・ロボットと往復ごとにまとめるスクリプトを書きました。画面なしで回した直す前(p0check)と直した後(p0fixcheck)に加えて、あとで録画した4回も同じスクリプトで並べています。

"""②の丸テーブルのまわり(x 4.75〜6.85・y 11.3〜14.0)で起きた止まりを、回ごと・ロボットと往復ごとにまとめる(LOG404)。
録画にする場面を選ぶために、直す前(p0check)と直した後(p0fixcheck)の画面なしの回と、録画した回を並べる。"""
import csv, sys
from pathlib import Path

U = Path(sys.argv[1])
RUNS = [
    ("直す前・画面なし", "20261029_p0check_cs39_fam_p0_r2_s0_passon_sbret"),
    ("直した後・画面なし", "20261029_p0fixcheck_cs40_fam_p0_r2_s0_passon_sbret"),
    ("直す前・録画(52°)", "20261029_lpdemobefore_cs41_fam_p0_r2_s0_passon_sbret"),
    ("直した後・録画(52°)", "20261029_lpdemo_cs41_fam_p0_r2_s0_passon_sbret"),
    ("直す前・録画(75°)", "20261029_lpdemo2before_cs43_fam_p0_r2_s0_passon_sbret"),
    ("直した後・録画(75°)", "20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret"),
]
X0, X1, Y0, Y1 = 4.75, 6.85, 11.3, 14.0

for label, stem in RUNS:
    rows = list(csv.DictReader(open(U / stem / "stops.csv", encoding="utf-8")))
    z = [r for r in rows if X0 <= float(r["x"]) <= X1 and Y0 <= float(r["z"]) <= Y1]
    stuck = [r for r in z if float(r["duration_s"] or 0) >= 60]
    print(f"== {label}  {stem}")
    print(f"   止まりの行 全体 {len(rows)}・丸テーブルのまわり {len(z)}・そのうち60秒以上 {len(stuck)}")
    eps = {}
    for r in z:
        k = (r["robot_id"], r["trip_id"])
        e = eps.setdefault(k, {"t0": float(r["t_s"]), "t1": float(r["t_s"]), "n": 0, "dur": 0.0, "causes": {}})
        t = float(r["t_s"]); d = float(r["duration_s"] or 0)
        e["t0"] = min(e["t0"], t); e["t1"] = max(e["t1"], t + d); e["n"] += 1; e["dur"] += d
        c = r["cause"]; e["causes"][c] = e["causes"].get(c, 0) + 1
    for (rid, tid), e in sorted(eps.items(), key=lambda kv: kv[1]["t0"]):
        if 900 <= e["t0"] <= 1650 or e["dur"] >= 60:
            cs = "・".join(f"{c} {n}" for c, n in sorted(e["causes"].items(), key=lambda x: -x[1]))
            print(f"   ロボット{rid} 往復{tid:>3}  {e['t0']:7.1f}〜{e['t1']:7.1f} 秒  行 {e['n']:3}  止まりの合計 {e['dur']:6.1f} 秒  {cs}")

round_zone_stops.py の出力

== 直す前・画面なし  20261029_p0check_cs39_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 739・丸テーブルのまわり 158・そのうち60秒以上 8
   ロボット1 往復  3    948.1〜 1327.0 秒  行   3  止まりの合計  180.1 秒  椅子・荷物・ベビーカー 3
   ロボット2 往復  4   1021.2〜 1571.3 秒  行 130  止まりの合計  414.7 秒  もう1台のロボット 121・椅子・荷物・ベビーカー 5・スタッフとすれ違った 3・人が立ち止まっていた 1
   ロボット1 往復  6   1629.7〜 1630.7 秒  行   1  止まりの合計    1.0 秒  椅子・荷物・ベビーカー 1
== 直した後・画面なし  20261029_p0fixcheck_cs40_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 510・丸テーブルのまわり 6・そのうち60秒以上 0
   ロボット1 往復  3    975.9〜  979.9 秒  行   1  止まりの合計    4.0 秒  椅子・荷物・ベビーカー 1
== 直す前・録画(52°)  20261029_lpdemobefore_cs41_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 782・丸テーブルのまわり 167・そのうち60秒以上 8
   ロボット1 往復  3    948.1〜 1327.0 秒  行   3  止まりの合計  180.1 秒  椅子・荷物・ベビーカー 3
   ロボット2 往復  4   1021.2〜 1571.3 秒  行 130  止まりの合計  414.7 秒  もう1台のロボット 121・椅子・荷物・ベビーカー 5・スタッフとすれ違った 3・人が立ち止まっていた 1
   ロボット1 往復  6   1629.7〜 1630.7 秒  行   1  止まりの合計    1.0 秒  椅子・荷物・ベビーカー 1
== 直した後・録画(52°)  20261029_lpdemo_cs41_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 454・丸テーブルのまわり 8・そのうち60秒以上 0
   ロボット1 往復  3    975.9〜  979.9 秒  行   1  止まりの合計    4.0 秒  椅子・荷物・ベビーカー 1
== 直す前・録画(75°)  20261029_lpdemo2before_cs43_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 700・丸テーブルのまわり 153・そのうち60秒以上 8
   ロボット1 往復  3    948.1〜 1327.0 秒  行   3  止まりの合計  180.1 秒  椅子・荷物・ベビーカー 3
   ロボット2 往復  4   1021.2〜 1571.3 秒  行 130  止まりの合計  414.7 秒  もう1台のロボット 121・椅子・荷物・ベビーカー 5・スタッフとすれ違った 3・人が立ち止まっていた 1
   ロボット1 往復  6   1629.7〜 1630.7 秒  行   1  止まりの合計    1.0 秒  椅子・荷物・ベビーカー 1
== 直した後・録画(75°)  20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret
   止まりの行 全体 612・丸テーブルのまわり 5・そのうち60秒以上 0
   ロボット1 往復  3    975.9〜  979.9 秒  行   1  止まりの合計    4.0 秒  椅子・荷物・ベビーカー 1

直す前は、ロボット1が T03 へ料理を運ぶ途中、948秒ごろに丸テーブルの間で止まり、1021秒ごろに来たロボット2がその後ろで動けなくなります。ロボット2の止まりは130行・合計414.7秒で、理由のほとんど(121行)が「もう1台のロボット」です。直した後は、同じロボット1が同じ往復で4秒だけ止まって抜けていきます。6回とも、この区間の止まりは同じ時刻・同じ中身でした。

作業ログ ― 丸テーブルの直す前と後を、同じ時刻で録画した(依頼26)

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

ファイルの一覧(10本)

01_sec02.md ― 依頼文:LP用に店2の直す前と後を録画する(20261029_26)・3,320字

02_sec02.txt ― 報告:20261029_2102_lp_before_after_rec.txt・9,944字

03_sec02.md ― 依頼箱の結果:20261029_26_LP用に店2の直す前と後を録画する_20261029_2039.md・3,377字

04_sec03.html.txt ― 確認用のページ(影を撮り直したあとの版)・5,391字

05_sec04.txt ― 報告:20261029_2228_lp_rec_short_shadow.txt・6,863字

06_SimTimeRecorder.cs.txt ― 録画の部品 SimTimeRecorder.cs(cs:43・全文)・16,305字

07_sec04.txt ― 録画の部品を足したときの差分:cs:40 → cs:41・14,482字

08_sec04.txt ― 光の角度と静止画の回を足したときの差分:cs:41 → cs:42・7,428字

09_commands.txt ― 録画の実行ファイルを作って回したときのコマンド commands.txt・19,715字

10_sec05.txt ― LP に入れた差分(3つの commit をまとめたもの)・5,498字

Unity は、ゲームを作る道具で、3Dの店を動かしている

Unity は、米国の Unity Technologies が作っているゲームエンジン(ゲームを作るための道具)です。3Dの空間に床や壁や人を置き、物理の計算をしながら動かせます。このシリーズでは、ファミレスの店を3Dで建て、お客さん・スタッフ・配膳ロボットを1人ずつ動かして、待ち時間や詰まる場所を数えています。

この記事で使う言葉は、次のとおりです。

言葉意味
種(シード)
お客さんの来方や注文を決める乱数の番号。同じ種なら、同じお客さんが同じ時刻に来る
画面なしの実行ファイル
Unity の画面を開かずに、店を速く回すだけの書き出したプログラム。夜にまとめて回すのに使う
cs(チェンジセット)
Unity のプロジェクトの版の番号(Unity Version Control で記録している)。cs:43 のように書く
寄りの映像(映像A)
丸テーブルのまわりだけを真上から撮った映像。x 3.0〜10.0・y 10.5〜15.0 の範囲
台帳
Unity で回した1回ずつを1行で残している表(unity_ledger_v1.csv)。追記だけで、消さない

Claude Code と依頼箱で、Mac の Unity を動かしている

Unity と、Mac の中のファイルを触るのは Claude Code(Anthropic のプログラミング用の AI)の役目です。Claude(この記事を書いている側)が依頼文を iCloud の「依頼箱」というフォルダに置くと、Mac で待っている小さなプログラムがそれを見つけて Claude Code に渡し、終わると報告を書き戻します(作り方は LOG390)。依頼の頭に、作業してよいフォルダと上限の時間を書きます。

依頼文:LP用に店2の直す前と後を録画する(20261029_26)

01_sec02.md3,320字・68行・markdown
---
作業フォルダ: /Users/shimazueiichi/Robotics_UX/ServiceSim
上限時間: 150
---
# 依頼:配膳ロボットの LP に載せる「直す前・直した後」の動画の素材として、②の丸テーブルのまわりを同じ条件で2回録画する(2026-10-29)

## ねらい
別のタブで開く保存

報告:20261029_2102_lp_before_after_rec.txt

02_sec02.txt9,944字・193行・text
====================================================================
LP 用に、②の丸テーブルのまわりを「直す前・直した後」で録画した
依頼:20261029_26_LP用に店2の直す前と後を録画する.md
2026-10-29 21:02 check-in:cs:41(録画のしくみだけ) 最後の状態:cs:41 head・保留 0
====================================================================

結論
別のタブで開く保存

依頼箱の結果:20261029_26_LP用に店2の直す前と後を録画する_20261029_2039.md

03_sec02.md3,377字・55行・markdown
# 結果:20261029_26_LP用に店2の直す前と後を録画する

- 状態:完了
- 始めた時刻:2026-10-29 20:39
- 終わった時刻:2026-10-29 21:04(25分)
- 作業フォルダ:/Users/shimazueiichi/Robotics_UX/ServiceSim
- この続きを Claude Code で話すとき:作業フォルダで `claude --resume 685755d2-3a74-45bf-82aa-e5af669ecbb8`
- 止められた操作:1件(いちばん下に一覧)
別のタブで開く保存

Unity Recorder は使えず、店の時刻に合わせて撮る部品を足した

依頼では Unity Recorder(Unity の画面を動画にする部品)を想定していましたが、画面なしで回す作りでは、エディタの中でしか動かない Recorder は使えませんでした。Claude Code は代わりに、起動の引数に -ssRecord を付けたときだけ動く部品(SimTimeRecorder.cs)と、録画用の実行ファイルを別の場所に作る部品(RecordBuild.cs)を足しました。店の時刻0.2秒ごとに1コマを撮るので、Mac が忙しくても撮れる場面は変わりません。2つの部品の全文と、版ごとの差分は、影を撮り直した節のあとに載せます。

直す前の店は、cs:39 と同じデータ14ファイル(店の形の版 dffc100b269c)を写して建て直し、撮ったあと元に戻しています。cs:39 と cs:40 はコードが同じで、違うのは店の形と条件のデータだけだったためです。

録画した場面の動きは、画面なしで回した回と同じだった

比べたもの直す前直した後
丸テーブルのまわりの60秒以上の止まり
8回(画面なしの回と、時刻・場所・理由が1行ずつ同じ)
0回
ロボットの位置(900〜1650秒・5秒ごと)
画面なしの回と違う行 0画面なしの回と違う行 0
回全体でずれ始めた時刻6,550秒から6,290秒から

録画した900〜1650秒の範囲は、画面なしの回とまったく同じ動きでした。回の後半でずれ始める理由は、録画の範囲の外なので調べていません。LP に載せる数字(8→0回)は、画面なしで回した回(p0check・p0fixcheck)の数を使います。

もう1つ分かったのは、直した後の900〜1650秒には、「片方のロボットが卓に止まっている横を、もう1台が抜ける」場面がなかったことです。その場面は回の後半(経過81分ごろ)に1つだけあります。撮り足すかを考えましたが、同じ時刻で比べられることのほうが説得力があるので、同じ時刻のままにしました。

作業ログ ― 確認用のページで、並べる形と切り替える形を見比べた

録画の中身を、コマの一覧で確かめた

録画(125秒・3,751コマ)のどこに何が映っているかを、150コマおきに並べた一覧と、75コマおきの帯で確かめました。

#!/bin/bash
# 録画(寄り・125秒・3751コマ)のどこに何が映っているかを、コマの一覧で確かめる(LOG404)
S=/tmp/claude-0/-home-claude/32de2f9c-f50b-5d31-bb77-ea18dc2b20df/scratchpad/lp
cd $S/raw
# 150コマ(店の時刻30秒)おきに25枚を、5×5の1枚に並べる
ffmpeg -v error -y -i *after_A_close.mp4 -vf "select=not(mod(n\,150)),scale=336:-1,tile=5x5" -frames:v 1 $S/fr/after_sheet.jpg
ffmpeg -v error -y -i *before_A_close.mp4 -vf "select=not(mod(n\,150)),scale=336:-1,tile=5x5" -frames:v 1 $S/fr/before_sheet.jpg
# 150〜1050コマ目を75コマおきに13枚、横1列に並べ、直す前と直した後を上下に重ねる(左上の数字は何枚目か。コマは 150+75×その数)
for v in before after; do ffmpeg -v error -y -i *${v}_A_close.mp4 -vf "select=between(n\,150\,1050)*not(mod(n-150\,75)),scale=280:-1,drawtext=text='%{n}':x=5:y=5:fontsize=20:fontcolor=red,tile=13x1" -frames:v 1 $S/fr/${v}_strip.jpg; done
ffmpeg -v error -y -i $S/fr/before_strip.jpg -i $S/fr/after_strip.jpg -filter_complex vstack $S/fr/strips.jpg
# 決めたい時刻のコマを1枚ずつ取り出して、左右に並べる(1500コマ目=店の時刻1200秒)
for v in before after; do f=$(ls *${v}_A_close.mp4); for n in 0 606 1500 3000 3137 3300; do ffmpeg -v error -y -i $f -vf "select=eq(n\,$n)" -frames:v 1 $S/fr/${v}_$n.jpg; done; done
ffmpeg -v error -y -i $S/fr/before_1500.jpg -i $S/fr/after_1500.jpg -filter_complex "[0]scale=840:-1[a];[1]scale=840:-1[b];[a][b]hstack" $S/fr/pair_1500.jpg

直す前は、606コマ目(店の時刻1021秒)からロボット2台が丸テーブルの間で並んで止まり、青いスタッフがまわりを行き来します。直した後の同じ時刻は、ロボットが間を抜けて先へ進み、丸テーブルのまわりは空いています。直す前の1527秒ごろには、往復が打ち切られたロボット1が瞬間移動する(動けなくなった回を先へ進めるための、シミュレーションの逃がし弁)ので、その手前で切ることにしました。

経過15:30〜18:00を、12倍速・約12秒のループに切り出した cut_loops.sh

切り出しには ffmpeg(動画を切ったり縮めたりする、コマンドで動かす道具)を使いました。録画の150〜900コマ目(店の時刻930〜1080秒)を2倍にして12倍速にし、右のパントリーの壁から先を切り落として、右下に店の時刻を入れました。

#!/bin/bash
# LP(配膳ロボット)の「どこで止まるか」に並べる、②の丸テーブルの直す前・直した後のループを、Unity の寄りの録画(1680×1080・0.2秒ごとに1コマ・30コマ/秒=6倍速)から切り出す(LOG404)
# 使ったのは録画の 150〜900 コマ目=店の時刻 930〜1080 秒(経過 15:30〜18:00)。さらに2倍にして 12倍速・約12.5秒にする
# 右のパントリーの壁から先は要らないので、左から 1240px を切り取り、992×864 に縮める。右下に店の時刻(分:秒)を入れる
# 1回目(依頼26・光 52°)は箱の色を 0x121418、2回目(依頼28・光 75°・LP に載せた版)は LP の文字の色 0x242424 にした
set -e
RAW="$1"   # 録画を写したフォルダ(*_before_A_close.mp4 と *_after_A_close.mp4 がある)
OUT="$2"   # 書き出す先
mkdir -p "$OUT"
FONT=/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf
for v in before after; do
  ffmpeg -v error -y -i "$RAW"/*${v}_A_close.mp4 \
    -vf "trim=start_frame=150:end_frame=901,setpts=(PTS-STARTPTS)/2,fps=30,crop=1240:1080:0:0,scale=992:864:flags=lanczos,drawtext=fontfile=$FONT:text='%{eif\:(930+(n*0.4))/60\:d\:2}\:%{eif\:mod(930+n*0.4\,60)\:d\:2}':x=w-tw-20:y=h-th-18:fontsize=30:fontcolor=white:box=1:boxcolor=0x242424@0.75:boxborderw=10" \
    -c:v libx264 -preset veryfast -crf 22 -pix_fmt yuv420p -movflags +faststart -an "$OUT/round-${v}.mp4"
  # 動画が読み込まれる前に出す1コマ目(poster)
  ffmpeg -v error -y -i "$OUT/round-${v}.mp4" -frames:v 1 -c:v libwebp -quality 80 "$OUT/round-${v}.webp"
done
ffprobe -v error -show_entries format=duration -of csv=p=0 "$OUT/round-before.mp4"
ls -la "$OUT"

cut_loops.sh の出力

12.533333
total 292
drwxr-xr-x 2 root root   4096 Oct 29 22:57 .
drwxr-xr-x 4 root root   4096 Oct 29 22:57 ..
-rw-r--r-- 1 root root 124815 Oct 29 22:57 round-after.mp4
-rw-r--r-- 1 root root  12882 Oct 29 22:57 round-after.webp
-rw-r--r-- 1 root root 127990 Oct 29 22:57 round-before.mp4
-rw-r--r-- 1 root root  12796 Oct 29 22:57 round-before.webp

1本は約12.5秒で、大きさは約0.12MBでした。同じスクリプトを録画から回し直すと、LP に置いたファイルと1バイトも違わないものができます(cmp で確かめた)。

確認用のページで、並べる形(A)と切り替える形(B)を出した

LP に入れる前に、確認用のページ(サイトには載せない)を作りました。A は左右に並べて同時に流す形、B は1つの枠で「直す前」「直した後」をボタンで切り替える形です。見て決めてほしいところとして、見せ方・影・右の場面・長さの4つを並べました。

横並びで伝わるから切り替えボタンは必要ないね

影については、「消すのは変なので短くする」と決まりました。

影:影を短くする(全くないのは変)

右の場面は、同じ時刻に通り抜けるままにしました。

確認用のページ(影を撮り直したあとの版)

最初の版にあった B の節と「見て決めてほしいところ」の節は、決まったあとに外しました。外した2つの節は、このページの下に続けて載せます。

04_sec03.html.txt5,391字・92行・html
<title>丸テーブル前後比較</title>
<meta name="claude:viewport-fit-sides" content="cover">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700;900&family=IBM+Plex+Mono:wght@500;600&display=swap">
<style>
/* LP「どこで止まるか」に入れる前の確認用。LP と同じ明るいグレーの面・黒の文字・橙は1か所だけ */
:root{
  --bg:#f4f5f7; --panel:#ffffff; --fg:#121418; --sub:#5c616b; --line:#d9dce1; --accent:#f2600c; --dark:#121418; --on-dark:#ffffff;
  --sans:"Noto Sans JP","Hiragino Sans",system-ui,sans-serif; --mono:"IBM Plex Mono",ui-monospace,monospace;
別のタブで開く保存

確認用のページの最初の版にあった、切り替える形(B)と確かめの節

  <section class="sec" aria-labelledby="b-h">
    <p class="label">見せ方B:1つの枠で切り替える</p>
    <div class="switch">
      <div class="seg" role="group" aria-label="直す前と直した後を切り替える">
        <button type="button" id="swBefore" aria-pressed="true">直す前</button>
        <button type="button" id="swAfter" aria-pressed="false">直した後</button>
      </div>
      <div class="stack" id="stack">
        <video src="srl-before.mp4" poster="srl-before.jpg" muted playsinline preload="auto" aria-label="直す前"></video>
        <video src="srl-after.mp4" poster="srl-after.jpg" muted playsinline preload="auto" aria-label="直した後" hidden></video>
      </div>
      <p class="note">切り替えても時刻はそろったまま流れます。</p>
    </div>
  </section>

  <section class="checks">
    <h2>見て決めてほしいところ</h2>
    <ul>
      <li>見せ方:A(並べる)か B(切り替える)か</li>
      <li>影:斜めの長い影が、客や椅子より目立っています。録画のときだけ影を消す(光を真上にする)こともできます。シミュレーションの動きは変わりません</li>
      <li>右の場面:同じ時刻なので、直した後は「通り抜けて、空いている」が見えます。もう1台が卓に止まっている横を抜ける場面は、この回の後半(経過81分ごろ)に1つだけあり、撮り足すこともできます</li>
      <li>長さ:経過15:30〜18:00の2分半を12倍速にした約12秒のループです。直す前の2台目は17:00ごろに止まり、そこから約8分動けません。ループは止まって1分のところで終わります</li>
    </ul>
  </section>

作業ログ ― 光を52°から75°に上げて、影を短くして撮り直した(依頼28)

最初の録画では、店を照らす光(影を落とす Directional Light)の地面からの角度が52°で、客や椅子の影が斜めに長く伸び、ロボットより目立っていました。録画のときだけ光を高くするよう頼みました。比べるために、直した後の同じコマ(店の時刻1500秒)を70°・75°・80°で書き出してもらいました。

直した後の②の同じコマ(店の時刻1500秒)を、光の角度52°(最初の録画)・70°・75°・80°で並べた図。52°は客と椅子の影が斜めに長く伸び、75°では足元に少し出るくらい、80°ではほぼ真下になる

75°で撮り直しました。影は足元に少し残り、立体に見えます。光が真上に近づいたぶん、床が明るく見えますが、明るさの設定は変えていません。

  • ねらい:影より、ロボットとスタッフと客の動きが目に入るようにする
  • 変わったこと:光の角度 52° → 75°(録画のときだけ。夜に回すシミュレーションの見た目と動きは変えない)
  • 見込める効果:スマホの小さな画面でも、止まっている白いロボット2台がすぐ見分けられる。ロボットの位置は、52°の録画と900〜1650秒で1行も違わなかった(測った値)

依頼文:LP用の録画を影を短くして撮り直す(20261029_28)

---
作業フォルダ: /Users/shimazueiichi/Robotics_UX/ServiceSim
上限時間: 90
---
# 依頼:依頼26の寄りの録画(映像A)を、影を短くして直す前・直した後とも撮り直す(2026-10-29)

依頼26 の報告(20261029_2102_lp_before_after_rec.txt)の「決めてほしいこと」への答え(エイイチと決めた):
- 1:直す前のラベル lpdemobefore はこのままでよい
- 2:見せたい場面の撮り足しはしない。同じ時刻(900〜1650 秒)で比べる
- 3:LP の数字は画面なしの回(p0check・p0fixcheck)の 8 → 0 を使う
- 4:rectest のフォルダ2つは残す(触らない)

確認用に並べて見たところ、斜めの長い影が客や椅子より目立っていた。影は消さずに短くする(まったくないのは変)。

## やること

1. 録画のときだけ(-ssRecord のときだけ)、店を照らす光(Directional Light)の高さを上げて影を短くする。目安は地面からの角度 75°(今の向き=方角は変えない)。影のやわらかさ・濃さ・光の色と明るさは今のまま。録画しない実行(夜の回・確かめの回)の見た目と動きは何も変えない。変えた分は check-in する
2. 撮る前に、直した後の②で、t=1500 秒あたりの1コマを 70°・75°・80° の3通りで静止画に書き出し(寄りの範囲と同じ 1680×1080)、報告に場所を書く。録画は 75° で進める
3. 依頼26 と同じやり方・同じ条件で撮り直す(② × ロボット2台 × 種0・今の標準・900〜1650 秒・0.2 秒ごとに1コマ・30 コマ/秒・H.264 CRF 16・yuv420p・コマと時刻の CSV つき)
   - 撮るのは映像A(寄り:x 3.0〜10.0・y 10.5〜15.0・1680×1080)だけ。映像B(全体)は要らない
   - ラベル:直した後 `lpdemo2`、直す前 `lpdemo2before`
   - 直す前は依頼26 と同じく site_copy_dffc100b269c の14ファイルを写して②を建て直し、撮ったら cm undo で戻して保留 0 を確かめる
4. 依頼26 の録画と、900〜1650 秒のロボットの位置(5 秒ごと)が1行も違わないことを確かめる(光を変えても動きが変わっていないことの確かめ)

## 始める前に確かめること(違えば手を止めて報告)

1. Unity エディタが起動していない
2. /Volumes/KIOXIA がマウントされている。鍵ファイル unity_ledger_v1.lock がない
3. 台帳が 669 行
4. ServiceSim の保留が 0(cs:41 head)

## 変えないもの

- 店の回し方・人とロボットの動き・速さ・Stiffness(20,000)/Damping(2,000) などの物理の設定
- 録画しない実行の光と見た目
- 依頼26 の録画と出力(上書きしない。同じ名前のフォルダがあれば止める)
- 台帳の列と今までの行(追記だけ。669 → 671 行。先頭 669 行の md5 を始める前と比べる)
- サイト(p2m-site)は触らない。git clean・git add . は使わない

## 報告

依頼箱の結果に加えて、claude_code_reports に `20261029_HHMM_lp_rec_short_shadow.txt` を書く。
- 始める前の確かめの結果
- 光をどう変えたか(角度・どこで切り替えているか)と cs 番号、最後に保留 0
- 3通りの角度の静止画の場所
- 2本の録画の場所・解像度・長さ・大きさ・コマ数
- 依頼26 の録画とロボットの位置が同じだったか
- 台帳の行数と先頭 669 行の md5
- 決めてほしいこと(あれば)

報告:20261029_2228_lp_rec_short_shadow.txt

05_sec04.txt6,863字・144行・text
====================================================================
LP 用の寄りの録画(映像A)を、影を短くして直す前・直した後とも撮り直した
依頼:20261029_28_LP用の録画を影を短くして撮り直す.md
2026-10-29 22:28 check-in:cs:42・cs:43(録画のしくみだけ) 最後の状態:cs:43 head・保留 0
====================================================================

結論
別のタブで開く保存

依頼箱の結果:20261029_28_LP用の録画を影を短くして撮り直す_20261029_2202.md

# 結果:20261029_28_LP用の録画を影を短くして撮り直す

- 状態:完了
- 始めた時刻:2026-10-29 22:02
- 終わった時刻:2026-10-29 22:28(26分)
- 作業フォルダ:/Users/shimazueiichi/Robotics_UX/ServiceSim
- この続きを Claude Code で話すとき:作業フォルダで `claude --resume 5a3ac635-5f19-4f05-865f-416886b4b7cc`
- 止められた操作:1件(いちばん下に一覧)

## Claude Code の報告

**やったこと**
- 始める前の確かめ4つは、すべて合格でした。Unity エディタは起動しておらず、KIOXIA はマウントされ、鍵ファイルはありませんでした。台帳は 669 行、ServiceSim の保留は 0(cs:41)でした。
- 録画のとき(-ssRecord のとき)だけ、影を落とす光(Sun)の高さを 52° から 75° に上げるようにし、check-in しました(cs:42・cs:43)。方角(326°)・影のやわらかさ・濃さ・光の色・明るさは変えていません。切り替えは、録画の最初のコマを撮る直前に行います。録画しない回は何も変わりません。
- 直した後の②で、t=1500 秒のコマを 70°・75°・80° の3通りで静止画に書き出しました。
- 75° で、映像A だけを撮り直しました(直した後 `lpdemo2`、直す前 `lpdemo2before`)。
- 直す前は依頼26 と同じく、14 ファイルを写して②を建て直しました。撮ったあとは cm undo で戻し、保留が 0 になったことを確かめました。建て直しで上書きされた unity/screens/ の9ファイルは、先に控えを取っておき、そこから書き戻しました。
- **まちがいが1つあります。** 静止画を書き出す最初の回(cs:42)で、始まりと終わりの時刻を同じにしていました。そのため撮れないまま最後まで回り、台帳に余計な1行を書いてしまいました。cs:43 で直して撮り直しました。

**結果**
- 静止画(1680×1080)の置き場所は `/Volumes/KIOXIA/r2r2r-data/service_sim/unity/20261029_lpdemo2still_cs43_fam_p0_r2_s0_passon_sbret/recordings/` です。ファイル名の最後が `_sun70.png`・`_sun75.png`・`_sun80.png` の3枚です。
- 直した後の録画:`20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret/recordings/20261029_2220_lpdemo2_after_A_close.mp4`
  - 1680×1080・125.03 秒・3751 コマ・1,755,197 バイト
- 直す前の録画:`20261029_lpdemo2before_cs43_fam_p0_r2_s0_passon_sbret/recordings/20261029_2224_lpdemo2_before_A_close.mp4`
  - 1680×1080・125.03 秒・3751 コマ・2,702,127 バイト
- 2本とも、H.264・CRF 16・yuv420p・30 コマ/秒です。コマと時刻の CSV は、依頼26 のものと1字も違いません。
- 900〜1650 秒のロボットの位置(5 秒ごと・302 行)は、直す前・直した後とも依頼26 と違う行が 0 でした。光を変えても動きは変わっていません。
- 台帳は 669 → 672 行で、予定より1行多くなりました。追記だけで、先頭 669 行の md5 は 261326722474707bd8637f948a5183f7 のまま、始める前と同じです。
- 最後の状態は cs:43 head・保留 0 です。

**変えたファイル**
- `Assets/ServiceSim/Recording/SimTimeRecorder.cs`(cs:42・cs:43)
- 報告:`claude_code_reports/20261029_2228_lp_rec_short_shadow.txt`

**決めてほしいこと**
1. 台帳の余計な1行(`20261029_lpdemo2still_cs42_fam_p0_r2_s0_passon_sbret`・completed)をどうするか。台帳は追記だけの決まりなので、消していません。中身は、直した後の②を cs:42 で録画なしに1回回したものです。このまま残すか、印を付けるかを決めてください。
2. 光が真上に近くなったので、明るさの設定は同じでも、画面全体が少し明るく見えます。依頼26 の録画と並べると色合いが少し違いますが、このままでよいかを決めてください。

## 止められた操作

- {"tool_name": "Bash", "tool_use_id": "toolu_01MDVqauCr1qDEvD6oYCM3SY", "tool_input": {"command": "cd /Users/shimazueiichi/Robotics_UX/ServiceSim; cm status --machinereadable; rm -rf Builds/rec2_compiletest", "description": "Check pending changes, remove test build"}}

台帳に1行余計に入った件(静止画の回の始まりと終わりを同じ時刻にした間違いで、撮れないまま最後まで回った1回)は、消さずに残すことにしました。台帳は追記だけの決まりで、ラベルが lpdemo2still なので、夜の回の判定には混ざりません。明るさの変化も、このままにしました。

録画の部品 SimTimeRecorder.cs(cs:43・全文)

06_SimTimeRecorder.cs.txt16,305字・390行・csharp
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEngine;
別のタブで開く保存

録画用の実行ファイルを作る RecordBuild.cs(cs:43・全文)

using System;
using UnityEditor;
using UnityEngine;

namespace ServiceSim.EditorTools
{
    /// <summary>
    /// 録画に使う実行ファイルを、夜の実行ファイル(Builds/headless)とは別の場所に作る
    /// (2026-10-29・依頼 26。中身は BuildHeadless と同じ。置き場所だけ違う)。
    ///
    /// 夜の実行係が使う Builds/headless を、録画のための版で上書きしないため。
    /// 回すときは -nographics を付けない(-batchmode だけ)。付けると描けないので撮れない。
    ///
    ///   Unity -batchmode -quit -projectPath … \
    ///     -executeMethod ServiceSim.EditorTools.RecordBuild.Build -ssBuildOut Builds/rec_after
    /// </summary>
    public static class RecordBuild
    {
        public static void Build()
        {
            string outDir = Find(Environment.GetCommandLineArgs(), "-ssBuildOut");
            if (string.IsNullOrEmpty(outDir) || outDir.TrimEnd('/') == BuildHeadless.OutDir)
            {
                Debug.LogError("[ServiceSim] -ssBuildOut に Builds/headless 以外の置き場所を入れてください");
                EditorApplication.Exit(1);
                return;
            }
            string err;
            if (!BuildHeadless.BuildTo(outDir, out err))
            {
                Debug.LogError("[ServiceSim] 録画用の実行ファイルを作れませんでした\n  " + err);
                EditorApplication.Exit(1);
                return;
            }
            EditorApplication.Exit(0);
        }

        static string Find(string[] argv, string name)
        {
            for (int i = 0; i < argv.Length - 1; i++)
                if (argv[i] == name) return argv[i + 1];
            return null;
        }
    }
}

録画の部品を足したときの差分:cs:40 → cs:41

07_sec04.txt14,482字・375行・diff
# cm diff cs:40 cs:41 (ServiceSim)
# 1. cm diff の出力そのまま

A "Assets/ServiceSim/Recording/SimTimeRecorder.cs"
A "Assets/ServiceSim/Recording/SimTimeRecorder.cs.meta"
A "Assets/ServiceSim/Editor/RecordBuild.cs"
A "Assets/ServiceSim/Editor/RecordBuild.cs.meta"
別のタブで開く保存

光の角度と静止画の回を足したときの差分:cs:41 → cs:42

08_sec04.txt7,428字・175行・diff
# cm diff cs:41 cs:42 (ServiceSim)
# 1. cm diff の出力そのまま

C "Assets/ServiceSim/Recording/SimTimeRecorder.cs"

# 2. 中身の違い(補足。上の各ファイルを cm cat <path>#cs:N で取り出し、diff -u で比べたもの)

--- Assets/ServiceSim/Recording/SimTimeRecorder.cs#cs:41
別のタブで開く保存

静止画の回の間違いを直したときの差分:cs:42 → cs:43

# cm diff cs:42 cs:43 (ServiceSim)
# 1. cm diff の出力そのまま

C "Assets/ServiceSim/Recording/SimTimeRecorder.cs"

# 2. 中身の違い(補足。上の各ファイルを cm cat <path>#cs:N で取り出し、diff -u で比べたもの)

--- Assets/ServiceSim/Recording/SimTimeRecorder.cs#cs:42
+++ Assets/ServiceSim/Recording/SimTimeRecorder.cs#cs:43
@@ -115,7 +115,7 @@
             if (_stillAt >= 0f)
             {
                 if (_stillPitches.Count == 0) _stillPitches.Add(_sunPitch);
-                _from = _stillAt; _to = _stillAt;
+                _from = _stillAt; _to = _stillAt + _step;   // 1コマだけ撮る(_to <= _from の確かめに掛からないように)
             }
 
             for (int i = 0; i < argv.Length - 1; i++)
@@ -138,13 +138,13 @@
                 _fOffset == null || _fJobRunning == null || _fRunDir == null)
             {
                 Log("撮れません(引数か、ExperimentRunner / HeadlessRun の中の名前が合いません)。この回は撮らずに回します");
-                _failed = true;
+                FailSetup();
                 return;
             }
             if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Null)
             {
                 Log("描画の装置がありません(-nographics では撮れません)。この回は撮らずに回します");
-                _failed = true;
+                FailSetup();
                 return;
             }
             if (_stillAt >= 0f)
@@ -171,7 +171,7 @@
             if (target > _to + 1e-3f) { Close(); return; }
             if (t < target - 1e-3f) return;
 
-            if (!_started && !Begin()) { _failed = true; return; }
+            if (!_started && !Begin()) { _failed = true; QuitIfStill(); return; }
 
             if (_stillAt >= 0f) { WriteStills(t); return; }
 
@@ -255,8 +255,22 @@
             _csv.Write("frame,t_s\n");
             Log("撮り始めました: " + _dir);
             return true;
+        }
+
+        void FailSetup()
+        {
+            _failed = true;
+            QuitIfStill();
         }
 
+        /// <summary>静止画だけの回は、撮れないなら最後まで回さずに終える(台帳に行を残さない)</summary>
+        void QuitIfStill()
+        {
+            if (_stillAt < 0f) return;
+            Log("静止画だけの回なので、撮れないまま回さずに終えます");
+            Application.Quit(1);
+        }
+
         /// <summary>影を落とす Directional Light(Setup の Sun)。1つに決まらなければ null</summary>
         static Light FindSun()
         {

録画の実行ファイルを作って回したときのコマンド commands.txt

09_commands.txt19,715字・127行・text
====================================================================
LP 用の録画:実行ファイルを作って回したときのコマンド(依頼26・依頼28)
書いた日:2026-10-29(依頼29)
====================================================================

出どころ
  ・依頼26・28 の作業の記録(Claude Code のセッション記録)から、実際に打ったコマンドを
    そのまま写した。セッション:依頼26=685755d2-3a74-45bf-82aa-e5af669ecbb8、
別のタブで開く保存

依頼文:録画のスクリプトを記事用に写す(20261029_29)

上の3つ(部品の全文・差分・コマンド)は、記事に全量で載せるために、録画のデータの横に写してもらったものです。

---
作業フォルダ: /Users/shimazueiichi/Robotics_UX/ServiceSim
上限時間: 20
---
# 依頼:LP 用の録画に使ったスクリプトを、データと対のコードとして写す(2026-10-29)

LOG404(LP に丸テーブルの前後の動画を並べた記事)に全量で載せるため、依頼26・28 で足した録画のコードを、録画のデータの横に写してほしい。ファイルを写すだけで、プロジェクトは何も変えない(check-in もしない)。

## やること

1. 次の2つの今の版(cs:43)を、`/Volumes/KIOXIA/r2r2r-data/service_sim/unity/20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret/scripts/` に写す(フォルダがなければ作る。同じ名前のファイルがあれば止める)
   - `Assets/ServiceSim/Recording/SimTimeRecorder.cs`
   - `Assets/ServiceSim/Editor/RecordBuild.cs`
2. 同じフォルダに、cs:40→cs:41・cs:41→cs:42・cs:42→cs:43 の差分を、それぞれテキストで書き出す(`diff_cs40_cs41.txt` など。cm diff の出力そのまま)
3. 同じフォルダに、録画の実行ファイルを作って回したときのコマンド(依頼26・28 で実際に打ったもの。起動の引数を含む)を `commands.txt` に書く。覚えていない所は、作業記録(logs/)から拾い、拾えなかった所はそう書く

## 変えないもの

- ServiceSim のファイル・設定・保留(最後に保留 0 を確かめる)
- KIOXIA の今までの出力・録画・台帳

## 報告

依頼箱の結果に、写したファイルの名前と大きさ、保留 0 だったかを書く。

依頼箱の結果:20261029_29_録画のスクリプトを記事用に写す_20261029_2253.md

依頼26・28 のコマンドは作業の記録(logs/)に残っておらず、Claude Code の会話の記録から写したものです。人が手で打ったコマンドがあったかどうかは分かりません。

# 結果:20261029_29_録画のスクリプトを記事用に写す

- 状態:完了
- 始めた時刻:2026-10-29 22:53
- 終わった時刻:2026-10-29 23:01(8分)
- 作業フォルダ:/Users/shimazueiichi/Robotics_UX/ServiceSim
- この続きを Claude Code で話すとき:作業フォルダで `claude --resume d77f72e6-1981-4915-b64a-349cb3d9685f`

## Claude Code の報告

**やったこと**
- `scripts/` フォルダを新しく作り、その中に6つのファイルを書きました。作る前にフォルダが無いことを確かめたので、同じ名前のファイルとぶつかることはありませんでした。置き場所は `/Volumes/KIOXIA/r2r2r-data/service_sim/unity/20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret/scripts/` です。
- 2つのスクリプトは、cs:43 の版を `cm cat` で取り出して写しました。作業フォルダにあるファイルと1字も違わないことを cmp で確かめています。RecordBuild.cs は cs:41 から変わっていません。
- 差分のファイルについて:cm diff を cs と cs の間で回すと、変わったファイルの名前の一覧しか出ません(cs:40→41 は4件、cs:41→42 と cs:42→43 は SimTimeRecorder.cs の1件ずつ)。そこで各ファイルの最初に、その一覧をそのまま載せました。その後ろに「補足」と見出しを付けて、中身の違いを足しています。中身の違いは、各ファイルを `cm cat` で取り出し、`diff -u` で比べたものです。cs:40→41 は、足した .meta の2つも含みます。
- commands.txt:依頼26・28 のコマンドは、logs/ には残っていませんでした(r2r2r-scripts/logs/ にある 20261029 の2本は、依頼25・27 のものです)。代わりに、2つの依頼のときの Claude Code の作業の記録(セッションの記録)から、実際に打ったコマンドをそのまま写しました。中身は次のとおりです。
  - 試し、実行ファイルを作るところ、回すところ(起動の引数はすべて入っています)
  - check-in、直す前の版の14ファイルを写す・戻す(cm undo)、screens の書き戻し
  - `$(date +%H%M)` で決まった時刻:出力のファイル名や build_id から分かるものは、横に書き添えました

**結果**
- ServiceSim は cs:43 のままで、保留は 0 でした(最後に `cm status --machinereadable` で見て、STATUS の行だけでした)。
- KIOXIA でこれまでに出した出力・録画・台帳には、触っていません。
- 写したファイル(大きさはバイト)

| ファイル | 大きさ |
|---|---|
| SimTimeRecorder.cs | 18,616 |
| RecordBuild.cs | 1,788 |
| diff_cs40_cs41.txt | 16,160 |
| diff_cs41_cs42.txt | 8,878 |
| diff_cs42_cs43.txt | 2,675 |
| commands.txt | 22,724 |

- 拾えなかったこと:記録に残っているのは Claude Code が打ったコマンドだけです。人が手で打ったものがあったかどうかは分かりません。commands.txt にもそう書きました。
- 1つ気づいたこと:依頼26 の試しの出力(rectest の2フォルダ)は、今も KIOXIA に残っています。依頼26 の報告にあるとおり、消す許可が出なかったためです。commands.txt の注にも書き、触っていません。
- まちがいが1つありました。最初に差分を取ろうとしたとき、私が書いたシェルの書き方が誤っていて、`cm diff` が正しくない引数で動き、止まったままになりました。その処理は止めました。止めた後も保留は 0 のままで、何も変わっていないことを確かめています。

**変えたファイル**
- 新しく作ったのは、上の `scripts/` の6ファイルだけです。ServiceSim は何も変えておらず、check-in もしていません。

**決めてほしいこと**
1. 差分のファイルの形について。cm diff をそのまま出すとファイル名の一覧だけになるため、補足として `diff -u` の中身を足しました。記事に載せるのが cm diff の出力そのままだけでよいなら、補足の部分を外してください。

作業ログ ― LP の「どこで止まるか」に、前後の動画を並べた

LP に入れた差分(3つの commit をまとめたもの)

数字の欄に「丸テーブルの間で、ロボットが動けなくなる 8→0回」の行を足し、4つの視点の動画の下に、直す前と直した後を並べる枠を足しました。PC では2本を左右に、幅640px以下では上下に並べます。動画は1本約0.12MBなので、LP のほかの動画と同じ場所(public/site/srl/)に置きました。

5c987f4 2026-10-29 21:17 LP(配膳ロボット):どこで止まるかに、②の丸テーブルを直す前・直した後の動画を並べる下書き(動画は撮り直し待ち・未公開)
 src/pages/serving-robot-one-less-staff.astro | 35 +++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)
b84844e 2026-10-29 22:32 LP(配膳ロボット):丸テーブルの前後の動画(影を短くして撮り直した版)を入れ、PCで文字の下に並ぶよう順番を直す
 public/site/srl/round-after.mp4              | Bin 0 -> 124815 bytes
 public/site/srl/round-after.webp             | Bin 0 -> 12882 bytes
 public/site/srl/round-before.mp4             | Bin 0 -> 127990 bytes
 public/site/srl/round-before.webp            | Bin 0 -> 12796 bytes
 src/pages/serving-robot-one-less-staff.astro |   4 ++--
 5 files changed, 2 insertions(+), 2 deletions(-)
2f21f1e 2026-10-29 22:55 LP(配膳ロボット):丸テーブルの前後の動画を、2本とも読み込めてから同時に流し、ずれたら合わせ直す
 src/pages/serving-robot-one-less-staff.astro | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
10_sec05.txt5,498字・76行・diff
diff --git a/src/pages/serving-robot-one-less-staff.astro b/src/pages/serving-robot-one-less-staff.astro
index ec5b9ce..0158afa 100644
--- a/src/pages/serving-robot-one-less-staff.astro
+++ b/src/pages/serving-robot-one-less-staff.astro
@@ -151,12 +151,28 @@ const MENU = [
           <div class="kn-nums">
             <div><span>細い通路の入口で、ロボットどうしが鉢合わせ</span><b>79<i>→</i><em>0</em><small>回</small></b></div>
             <div><span>レジのまわりでロボットが止まる</span><b>112<i>→</i><em>31</em><small>回</small></b></div>
別のタブで開く保存

PC で、前後の動画が文字の上に割り込んでいた

最初の下書きをビルドして PC の幅で見ると、前後の動画が「どこで止まるか」の文字の上に入り、文字が動画の下へ押し出されていました。この節は、文字の列を order:2 で右に回す作りだったので、新しく足した枠(order なし)が先に並んでいたのが原因です。枠に order:3 を付け、文字の下に並ぶようにしました。

公開した直後、2本が0.67秒ずれていた

公開したページで撮った画面では、左の時刻が17:12、右が17:04で、店の時刻で8秒(動画で約0.67秒)ずれていました。最初の作りは、画面に入ったら2本に「頭から再生」を出すだけで、片方の読み込みが遅いと、先に読めた方だけが流れ始めていました。2本とも再生できる状態になってから頭をそろえて流し、流れている間も右を左の時刻に合わせ直す(0.15秒以上ずれたら)作りに直しました。

  • ねらい:同じ時刻の比べであることを、ずれのない2本で見せる
  • 変わったこと:2本とも読み込めてから同時に流す。流れている間に0.15秒以上ずれたら右を左に合わせる
  • 見込める効果:右の動画だけ2.5秒遅れて届く条件で試すと、ずれは0.01秒だった(測った値。下の sync.js の出力)

片方の動画を遅らせて、ずれを測った sync.js

確かめには Playwright(ブラウザを自動で動かす道具)を使い、ビルドしたページを手元で開いて、右の動画の読み込みだけを2.5秒遅らせました。

const { chromium } = require('playwright');
(async () => {
  const b = await chromium.launch();
  const p = await b.newPage({ viewport: { width: 1280, height: 900 } });
  await p.route('**/round-after.mp4', async r => { await new Promise(x=>setTimeout(x,2500)); await r.continue(); });
  await p.goto('http://localhost:4322/serving-robot-one-less-staff.html?p2m-notrack=1');
  await p.evaluate(() => document.getElementById('baPair').scrollIntoView({block:'center'}));
  for (const t of [1500, 5000, 9000, 15000]) { await p.waitForTimeout(t === 1500 ? 1500 : 3500);
    console.log(await p.evaluate(() => [...document.querySelectorAll('#baPair video')].map(v => v.currentTime.toFixed(2)+(v.paused?'p':'')).join(' / '))); }
  await b.close();
})();

sync.js の出力(右の動画を2.5秒遅らせたとき)

0.00p / 0.00p
2.44 / 2.43
5.94 / 5.93
9.45 / 9.44

公開したページを PC とスマホの幅で撮った shot2.js

const { chromium } = require('playwright');
(async () => {
  const b = await chromium.launch();
  for (const [w,h,name] of [[1280,1700,'03_lp_pc'],[390,2400,'04_lp_phone']]) {
    const p = await b.newPage({ viewport: { width: w, height: h }, deviceScaleFactor: 2 });
    await p.goto('https://pixelstomotors.com/serving-robot-one-less-staff?p2m-notrack=1', { waitUntil: 'networkidle' });
    await p.addStyleTag({content:'header,.site-header,[class*="header"]{position:static!important} body::before{display:none!important}'});
    await p.evaluate(() => { document.querySelectorAll('video').forEach(v=>{v.preload='auto';}); });
    await p.evaluate(() => document.querySelector('.kn.rev').scrollIntoView({block:'start'}));
    await p.waitForTimeout(9000);
    const el = await p.$('.kn.rev');
    await el.screenshot({ path: `${process.argv[2]}/img/LOG404_${name}.png` });
  }
  await b.close();
})();
公開した LP の「どこで止まるか」を PC の幅で見たところ。上に4つの視点の動画と数字の欄(79→0回・112→31回・8→0回)、その下に直す前と直した後の動画が左右に並ぶ
同じ節をスマホの幅(390px)で見たところ。数字の欄のあとに4つの視点の動画、その下に直す前と直した後が上下に並ぶ
店の時刻1500秒(経過25:00)の、直す前(左)と直した後(右)の同じコマ。左は丸テーブルの間で白いロボット2台が止まったまま、右は丸テーブルのまわりが空いている

作業ログ ― 次に別の店で前後を見せるときも、同じ撮り方が使える

録画のときだけ光を上げる作りと、店の時刻に合わせて撮る作りは、Unity のプロジェクトに残っています(cs:43)。夜に回すシミュレーションの見た目と動きは変えていません。別の店で店の形や回し方を直したときも、同じ種・同じ時刻で直す前と後を撮れば、同じ形で LP や記事に並べられます。

残したもの場所
寄りの録画(75°・直す前と直した後)
KIOXIA の service_sim/unity/20261029_lpdemo2*_cs43_fam_p0_r2_s0_passon_sbret/recordings/
最初の録画(52°・寄りと全体)
KIOXIA の service_sim/unity/20261029_lpdemo*_cs41_fam_p0_r2_s0_passon_sbret/recordings/
光の角度を比べた静止画
KIOXIA の service_sim/unity/20261029_lpdemo2still_cs43_fam_p0_r2_s0_passon_sbret/recordings/
録画の部品の全文と差分
KIOXIA の service_sim/unity/20261029_lpdemo2_cs43_fam_p0_r2_s0_passon_sbret/scripts/
LP に置いたループ
p2m-site の public/site/srl/round-before.mp4・round-after.mp4(と webp)

台帳は、672行(追記だけ)になりました。