==================================================================== 依頼 v12 の 4 章:夜の実行係の道具(tools/)を作った 2026-10-25 19:45 ==================================================================== 結論 ・tools/ に4本作り、**Unity 抜きで通しの試験まで通しました**。 check-in は **cs:4**(tools)と **cs:5**(ignore.conf)です。 ・**Assets は1バイトも触っていません**(18回を回している途中なので)。 ・1〜3 章(Assets の中)は手を付けていません。18回が終わってからです。 ★ 先に2つ、見ておいてほしいことがあります(6 章)。 (1) いま **Assets の Robot まわり4本が書き換わっています**(19:41〜19:43)。 私の分ではありません。「依頼 v13」と書かれているので、別の手で すれ違いの実装が進んでいるようです。 **スクリプトの読み込み直しが起きるので、18回が止まっている疑いがあります。** (2) 段階Bの18回は、台帳に cs:3 の行が **0 件**・出力フォルダも **0 件**で、 出力先に 30 分なにも書かれていません。 ==================================================================== 1. 作ったもの(tools/・Python の標準ライブラリだけ) ==================================================================== tools/make_queue.py 条件 × 種を queue.json に並べる tools/night_runner.py N 本同時に回す・台帳に書く・判定を呼ぶ tools/ledger.py 台帳に鍵をかけて1行足す(night_runner が使う) tools/judge_night.py judge_night_v0.py を **1バイトも変えずに** 入れた 依頼文には3本と書いてありましたが、**台帳に書く所だけ ledger.py に分けました**。 依頼 5 章 D で「台帳を壊すと戻しにくいので codex にレビューをかける」と決まっているので、 レビューの的を1ファイル(230 行)にしたかったからです。 ### make_queue.py 条件は **手で写さず** Unity と同じ所から引きます。 Assets/ServiceSim/Experiment/serving-robot-params.json の unity_conditions 条件の名前は Unity の SimParams.Condition.Id と同じ形(fam_p1_s4_r1_a42)で、 そのまま実行ファイルの -ssCondition に渡せます。 python3 tools/make_queue.py --out queue.json → 試算の版 v2.8 / 店の形の版 8a5b2f6a016a 条件 6 / 種 0〜9 / 合わせて 60 回 queue.json には、条件ごとに store・staff・robots・arrivals_per_h・mode・trays・ fragile_by・registers も入れました(実行係が台帳の行を書くときに使います)。 ### night_runner.py python3 tools/night_runner.py --queue queue.json --parallel 2 --night 20261026 依頼 4 章のとおり: ・始める前に KIOXIA・実行ファイル・台帳のヘッダ・版を確かめ、 どれかが駄目なら **始めない** ・caffeinate でスリープを止め、終わりに必ず解く(KeyboardInterrupt でも解く) ・N 本まで同時。1本終わったら次を起こす(--stagger で少しずらす。既定5秒) ・台帳に completed の行がある回は飛ばす(途中で止めても続きから) ・1回の上限(--limit-min。既定90分)を超えたら SIGTERM → 10秒待って kill、 status=stopped の行を台帳に足す ・落ちた回は status=failed の行を足す ・止まった・落ちた回は **その夜のうちに1度だけ** やり直す(フォルダに _try2、 実行ファイルには -ssTry 2 を渡す) ・KIOXIA が外れたら、新しい回を始めずに走っている回を待ち、終わったら止まる ・時刻では止めない ・記録は service_sim/unity/night/{night}/runner_log.txt と logs/{回}.log ・全部終わったら judge_night.py を呼ぶ(service_sim/unity/ で) ・終了コード 0=ぜんぶ completed/2=止まった・落ちた回があった/1=始められなかった 実行ファイルの呼び方(依頼 2 章の形のまま): {実行ファイル} -batchmode -nographics -logFile {その回のログ} -ssCondition fam_p1_s4_r1_a42 -ssSeed 3 -ssLabel night -ssNight 20261026 -ssParallel 2 [-ssTry 2] ### ledger.py C# の ServiceSimLedger と同じ決まりにしました。 ・**追記だけ**。前の行は読むだけ ・同じ run_folder の行は2度書かない ・**列の並びは実体の1行め(ヘッダ)が正**。 C# 側が「ヘッダとコードの列が1字でも違えば書かない」を守っているので、 実体のヘッダを信じれば C# と Python の列がずれません (列の一覧を Python にもう1つ持たせると、そこがずれる元になるので持たせていません) ・そのうえで、頭の並び(timestamp,run_folder,status,unity_cs,…)と ledger_schema_version があることだけ確かめる ・ヘッダに無い列名を渡したら例外(打ち間違いを通さない) ・値のカンマ・引用符・改行は落とす(C# の Clean と同じ) ・最後が改行で終わっていない台帳に足すときは、先に改行を入れる ・書いたら fsync する 鍵:unity_ledger_v1.lock を O_EXCL で作れたら持ち主、閉じるときに消す。 取れなければ 0.25 秒おきに最大60秒試す。 C# から new FileStream(lock, FileMode.CreateNew) で取るのと同じやり方なので、 依頼 3 章の Unity 側と同じ鍵を取り合えます。 持ち主が落ちて鍵が残ったら、120 秒より古ければ1度だけ壊します。 ==================================================================== 2. 確かめ A(Unity 抜きでやれた所) ==================================================================== (1) 構文とライブラリ 4本とも py_compile を通る。import は argparse / csv / datetime / errno / glob / json / os / re / signal / socket / statistics / subprocess / sys / time / collections(ぜんぶ標準)。judge_night.py は元のファイルと **cmp で同一**。 (2) make_queue.py 60 回(6条件 × 種0〜9)。試算の版 v2.8・店の形 8a5b2f6a016a を queue.json に写した。 --conditions / --seeds で絞れることも確かめた。 (3) ledger.py(本物の台帳は読むだけ。書いたのは写しに対してだけ) 23 件ぜんぶ OK。 ・59 列のヘッダを読める/ledger_schema_version がある ・1行足せて、書いた値(status・seed・store)が読み直せる。測った値の列は空のまま ・同じ run_folder は2度書かない ・ヘッダに無い列名は例外で止まる ・run_folder が空なら書かない ・値のカンマ・改行を落とすので、足した行はどれも 59 列 ・ヘッダが違う台帳には書かない(追記ガード) ・鍵は同時に2つ持てない/離せば取れる/離すとファイルが消える ・**10本から同時に足しても10行ぜんぶ入り、行が混ざらず、ヘッダも壊れない** ※ 台帳の行の列数は {49列: 36行, 59列: 新しい行} です。 49 列は依頼 v10b で schema 2 にしたときに書き換えなかった古い行で、仕様どおりです。 ※ 本物の台帳は sha256(頭12桁)2e0580691ee1 のまま変わっていません。 (4) night_runner.py(偽の実行ファイルで通しの試験) 実行ファイルの代わりに、終了コードと待ち時間を変えられる偽物を作り、 台帳も写しに向けて1通り流しました(4回・同時2本・上限0.2分)。 種0・種1 終了コード0 → completed(偽物が自分で台帳に行を書く=本物と同じ) 種7 終了コード1 → failed。実行係が行を足し、_try2 でやり直し、 2回めも failed(**3回めはやらない**) 種8 終わらない → 上限で SIGTERM → stopped。行を足し、_try2 でやり直し、 2回めも stopped まとめ completed 2 / failed 2 / stopped 2。終了コード 2 判定 service_sim/unity/ で judge_night.py --runs '20261026_night_*' --out night/20261026 を呼び、judge.md を書いた できた台帳(写し)を確かめた結果: 足された6行はぜんぶ 59 列・unity_cs は ServiceSim/cs:3・seed と wall_seconds が入る ヘッダは無事・鍵は残っていない (5) 空回し(--dry-run) 実行ファイルが無くても、打つコマンドだけ見られます。 版は cm status から ServiceSim/cs:3 を拾い、フォルダの字は cs3 になりました。 やれなかった確かめ(1〜3 章が済んでから) 依頼 5 章 A の「実行ファイルが作れる」「画面なしで短い1回が回る」「2本同時で 台帳に2行」は、実行ファイルがまだ無いのでできません。 いまできる範囲は、偽の実行ファイルで (4) まで見た形です。 5 章 B(画面なしでも同じ結果か)・C(何本同時に回せるか)も 1〜3 章のあとです。 ==================================================================== 3. judge_night.py について(変えていません。直した方がよい所の報告) ==================================================================== glob の確かめ(本物のフォルダで・読むだけ) 20261025_stageB_cs144_* → 18 件 ← 基準データ v2。合う 20261025_det_check_* → 4 件 20261025_split_check_* → 2 件 20261026_night_* → 0 件(まだ回していない) 20261025_stageB_cs3_* → 0 件(6 章を見てください) → 新しい名前({night}_{ラベル}_cs{N}_{店}_r{台数}_s{種})でも `{night}_{ラベル}_*` でちゃんと拾えます。**glob は直す必要なし**です。 直した方がよいと思う所(**直していません**。別の課題か、v12 の続きで決めてください) ア. **落ちた回・止まった回を拾えません**(いちばん大事) judge は `glob` で **フォルダがある回** だけを見ます(collect の isdir)。 出力フォルダを作る前に落ちた回は、台帳に failed の行があっても judge からは見えず、「回の失敗 … なし」と出ます。 偽の実行ファイルの試験でも、6回のうち judge が見たのは **2回だけ**でした (completed の2回。failed 2・stopped 2 は見えていない)。 → 直すなら「--runs に合うフォルダ」+「台帳でその夜・そのラベルの行」の 両方を見て、フォルダが無い行を「回の失敗」に入れる形です。 イ. **基準データの既定が、前のプロジェクトのままです** BASELINE_DEFAULT = '20261025_stageB_cs144_*'(Robotics_UX_New の cs:144)。 これから基準にするのは ServiceSim の18回なので、 夜に呼ぶときは --baseline を明示する必要があります。 いまの実行係は --baseline を渡さなければ既定のままにします (--baseline で渡せるようにしてあります)。 ウ. **基準データが0件のとき、全部「Unity の作り」になります** 試験で基準が0件だったとき、completed の2回がどちらも 「Unity の作り」に振り分けられました(比べる範囲が無いので外れ扱いになる)。 → 基準が0件なら、警告して止まる方が安全だと思います。 エ. **_try2 の回と、元の回の両方が judge に入ります** `{night}_{ラベル}_*` は _try2 も拾います。 元の回(stopped)と やり直し(completed)が両方入るので、 元の回は「回の失敗」に数えられます。 記録としては正しいのですが、「60回のうち何回が正常か」を見るときに 分母が増えます。どう数えるかを決めてください。 ==================================================================== 4. 決めてほしいこと(1つだけ) ==================================================================== 出力フォルダに入る「版の字」 依頼 2 章の例 20261026_night_**ss12**_fam_p1_r1_s3 いまの Unity 側 20261025_stageB_**cs144**_…/20261025_det_check_**cs2**_… (ServiceSimStageB.FolderName が "cs{N}" にしている) いまは **cs{N}** にそろえてあります(service_sim/unity/ の中の名前が ぜんぶ同じ形になるので、台帳の名札の読み分けもそのまま使えます)。 ss{N} にしたいなら、実行係は --cs-token 'ss{N}' で合わせられますが、 **1〜3 章の実行ファイル側も同じにそろえる**必要があります。 私は cs{N} のままが良いと思いますが、決めてください。 ==================================================================== 5. 最初の夜のコマンド(実行ファイルができてから) ==================================================================== cd /Users/shimazueiichi/Robotics_UX/ServiceSim python3 tools/make_queue.py --out queue.json python3 tools/night_runner.py --queue queue.json --parallel 2 --night 20261026 \ --baseline '20261025_stageB_cs3_*' ・--parallel は 5 章 C の実測で決める値です(いまは仮に 2) ・--baseline は基準にする18回の glob(6 章のとおり、まだ回り切っていません) ・上限を変えるなら --limit-min 90 ・先に打つコマンドだけ見たいなら --dry-run を足す ★ 依頼 5 章 D のとおり、最初の夜の前に台帳を写します(コピーだけ): mkdir -p /Volumes/KIOXIA/r2r2r-data/service_sim/unity/archive cp /Volumes/KIOXIA/r2r2r-data/service_sim/unity/unity_ledger_v1.csv \ /Volumes/KIOXIA/r2r2r-data/service_sim/unity/archive/unity_ledger_v1_prenight_20261026.csv これは夜を始める直前に私がやります(いまやると18回の行が入りません)。 ==================================================================== 6. ★ 見ておいてほしいこと(私の分ではありません) ==================================================================== (1) Assets の Robot まわりが、いま書き換わっています cm status(19:45 時点) PR Assets/ServiceSim/Robot/RobotPassBy.cs 19:42 に作られた(新しい) CH Assets/ServiceSim/Robot/ServingRobotController.cs 19:43 CH Assets/ServiceSim/Robot/RobotSpec.cs 19:41 CH Assets/ServiceSim/Experiment/ExperimentRunner.cs 19:45 ごろ CH Assets/ServiceSim/Experiment/TripLogger.cs 19:45 ごろ 中身に「依頼 v13 の 依頼1」「すれ違い(実店舗の動画に合わせた)」と書かれており、 RobotSpec に passByEnabled / passByDistanceM 2.0 / passBySpeedMps 0.3 / passBySeparationM 0.1 が足されています。 前回私が「こう変える」と報告した すれ違いの実装そのものです。 **私は Assets を1つも触っていません**(ご指示どおり)。 別の手(エイイチか、別のセッション)で進んでいるのだと思います。 ただ、ご指示の理由そのまま、**スクリプトの読み込み直しが起きるので、 回している途中の回が壊れます**。心当たりがなければ確かめてください。 (2) 段階Bの18回が進んでいないようです 台帳 ServiceSim/cs:3 の行が **0 件** (内訳は cs:140 18・cs:143 18・cs:144 18・ServiceSim/cs:2 6) 出力フォルダ 20261025_stageB_cs3_* が **0 件** 出力先 ここ30分で書かれたファイルが **0 件** run_all_log 最後の記録は det_check の2回(19時前) Unity 動いてはいる。Editor.log の最後はアセットの解放とライセンス (=読み込み直しの後のような見え方) 18回が始まっていないのか、(1) の読み込み直しで止まったのかは、 Unity の Console と「ServiceSim/Stage B/押す前の確かめ」で分かります。 cs:3 の18回をやり直すことになっても、台帳は名札+版で照合するので 「まだ」の回から続けられます(行が残っていないので18回とも「まだ」のままです)。 ==================================================================== 7. check-in ==================================================================== cs:4 tools/make_queue.py・night_runner.py・ledger.py・judge_night.py を足した cs:5 ignore.conf に __pycache__ と *.pyc を足した(Python の中間ファイルを入れない) ★ Assets の5本(6 章 (1))は **入れていません**。私の分ではないので触っていません。 ★ 試験に使った偽の実行ファイル・台帳の写しは scratchpad の中だけで、 プロジェクトにも KIOXIA にも残していません。 から回しが作った service_sim/unity/night/20261026/ も消しました (本番の夜に作り直されます)。 作ったファイル tools/make_queue.py 174 行 tools/night_runner.py 440 行 tools/ledger.py 230 行 tools/judge_night.py 291 行(judge_night_v0.py と同一) ignore.conf 2 行足した 次(18回が終わってから) ・1〜3 章:BuildHeadless.cs・実行ファイルの引数の受け取り・台帳の鍵(C# 側) ・5 章 A の残り・B・C ・5 章 D:ledger.py と C# 側の台帳まわりに codex のレビュー(依頼文は私が作ります)