サービスロボット導入シミュレーション Log#7 | Unity の店をサイトの図面から建てた

配膳ロボットを入れると、ファミレスの入店待ちや料理が届くまでの時間がどう変わるか。それを計算する試算ページをサイトに置いています( https://pixelstomotors.com/series8 )。ただ、この計算には仮の数字が4つ入っています。ロボットが人とすれ違いながら実際に何m/秒で走れるか、何回止まるか、止まったら何秒動けないか、人に助けてもらわないと動けなくなるのは何回に1回か。どれも、店の中で客とスタッフとロボットを一緒に動かしてみないと分かりません。そこで、Unity(建物や人を3Dで置いて動かせるソフト)の中にファミレスを建てて、測ろうとしています。

これまで Unity の店は、Unity の中で形を組み立てていました。そのため、サイトの試算が使っている店とは、卓の数も通路の幅も違っていました。違う店で測った数字は、サイトの計算に戻せません。そこで、サイトの試算が使っている店の図面(卓・壁・通路の位置を座標で並べたデータ)を、Unity がそのまま読んで店を建てるように変えました。Unity は自分で店の形を作りません。建てた2つの店(通路1.2mの店と、同じ店の通路を80cmに詰めた店)は、どちらも卓42・席160・ロボットが止まる位置42か所がサイトと一致しました。

途中で一度、おかしな結果が出ました。通路80cmの店で、ロボットどころか人も、42卓のうち21卓の席にたどり着けないと出たのです。図面は1mmも変わっていませんでした。原因は店ではなく、Unity の中に、前の作り方で計算した「通れる床」が消えずに残っていたことでした。 Unity は、人やロボットが歩ける床を NavMesh(三角形をつないだ面)として計算して持っています。プログラムを書き換えると Unity は読み込み直しをしますが、そのとき古い面を消す手がかりが失われ、新しい面と重なって残っていました。重なった2枚の面はつながっていないので、道を探すと途中で止まります。Unity を開き直すと21卓すべてに入れるようになり、面を計算する前に必ず全部消す1行を入れて直しました。

もう1つ、作業の終わり方を決めました。Unity をサイトに完全に合わせようとすると、ズレが見つかるたびに直す作業が続き、いつ何が達成できるのかが分かりません。そこで、Unity は Unity の作りのまま回し切って記録し、サイトとのズレは直す対象ではなく、調べる対象として扱うことにしました。

やったことなぜどうなったか
店の図面の確かめを codex にもう2回検証してもらい、穴をふさいだ
図面を作った側が確かめると同じ所を見落とすため
L字席の受け取る側・待機場所の大きさ・トイレの囲みなどを直した。テストは30件から107件に
記憶の店(②)に、パントリーから客席へ出る扉のない出入り口を2つ開けた
従業員が通る口がなかった
②だけ卓までの距離が変わり、試算を v2.5 として②だけ回し直した
Unity が建てるための細かい形(ベンチ・椅子・座る位置・並ぶ点など)をサイトの JSON に足した
Unity で形を作らないため
Unity が JSON から店を建て、卓・席・止まる位置がサイトと一致した
ロボットの道順をサイトが決めて JSON で渡した
80cmの通路を Unity の中で扱おうとしたら、通れる床が割れた
受け渡し口から42本・卓から卓へ861本。全部つながった
21卓に入れない原因を突き止めた
図面は同じなのに結果が変わった
古い通れる床が残っていた。消してから計算する形に直した
ゴールを3段階で決めた
ズレを直す作業に終わりがなかった
店を作る → 回して台帳に記録する → ズレを調べる。まず③⑦で一度通す

下の図で、ボタンを押すと、古い通れる床が残っていると道探しがどこで止まるかが見られます。

作業ログ ― 店の番号と、この記事で扱う範囲

店の番号は、試算ページの番号(②〜⑦)で書きます。codex の検証結果やコードの一部には、作業中の番号(⓪〜⑤)が残っています。

ページの番号作業中の番号名前コードの名前
②⓪
定番の郊外型(記憶の店を決まりに合わせた版)
p0_memory
③①効率重視型・入口が左下の角
p1_efficient_corner
④②
効率重視型・狭い店・入口が右の壁
p2_efficient_narrow
⑤③ゆったり型・入口が正面の中央
p3_relaxed_center
⑥④ゆったり型・入口が左の壁
p4_relaxed_side
⑦⑤
③の列の間の通路を80cmに(卓と席数は③と同じ)
p5_crammed

この記事は、LOG360(6つの店の図面を作って試算に入れた回)のあと、codex の2回目の検証結果を受け取ったところから始まります。Unity の作業は Claude Code(Unity のコードを書く AI)が実装し、ここでは Claude がサイト側の図面と依頼文を作り、Unity での確かめは、Unity のメニューを手で押して行いました。Unity の版は、Unity Version Control の Check-in の番号(cs:112〜cs:116)で書きます。

codex の2回目の検証:数字は再現できるが、L字席と②の待機場所と確かめのすり抜けが残っていた

LOG360 の終わりに頼んだ2回目の検証(依頼文は LOG360 に全量)の結果は、「数字は再現できる。ただし、客が受け取れる卓の割合を試算する材料として、このまま採用するのは不可」でした。全文は後ろの「codex の2回目の検証結果」に載せています。

大きな指摘は3つです。

指摘中身
L字席のソファ側に止まった位置を「届く」と数えている
L字の6人席は、卓の外側の4辺すべてを止まってよい辺にしていた。②の T02 では、止まる位置がソファの側面の前にあり、天板の中心から約2.8m離れていた
②の待機場所が1台0.8m×0.8mを満たさない
3台分の場所が2.2m×0.7mしかなかった。1台ずつ出られるかも調べていなかった
確かめをすり抜ける置き方がある
トイレの囲み・レジの有無・建物の輪郭などで、決まりに反した店でも確かめが通る反例が7つあった

L字席で止まってよい所は、案を2つ出して選んでもらいました。a は「天板のある内側の角の、開いた2辺だけ」。b は「a に加えて、そこからソファの端に沿って0.6mまで」。

b. a に加えて、端の席の人が受け取れる通路の端も含める / 3台のまま場所を広げる

b にしたのは、L字ソファの端に座った人は、内側の角まで手を伸ばさなくても、ソファの端の前の通路で料理を受け取れるためです。②の待機場所は、台数を減らさずに場所を広げることにしました。

L字席・2人席で止まってよい辺を決め直し、②の待機場所を2.4m×0.8mに広げた

決まりは次の3つにしました(tools/sim_layouts/README.md の「2026-10-22 codex の2回目の検証を受けて」に書いた)。

  • L字席で止まってよいのは、テーブルのある内側の角の開いた2辺と、そこからソファの端に沿って0.6mまで。ソファの横は使わない
  • 2人席で止まってよいのは、椅子の側とテーブルの横。ベンチの側・ベンチの横は使わない
  • 待機場所は1台分0.8m×0.8m以上、台数は正の整数。1台ずつ、ほかの台が止まったままで受け渡し口の前まで出られること

コードでは、lsofa_sides(L字席の止まってよい区間)と t2_sides(2人席)を足し、standby_slots で待機場所を1台分ずつの区画に分けました。1台ずつ出られるかは、出ようとする1台だけを障害物から外し、残りの台を障害物にしたまま、受け渡し口の前まで道があるかで確かめます。テストは30件から49件になりました。

②のパントリーの上の通路に、扉のない出入り口を2つ開けた

②(記憶の店)の図を見直すと、パントリーから客席へ出る口がありませんでした。

この形だとパントリから右上のブースに出入りするための出入り口がないよ。緑の線の上に出入り口を開けて(従業員もここから出入りします)

②の図のパントリーの上の部分。トイレの右の通路と洗い場の下の間に、出入り口を開けてほしい所が緑の線で引かれている
②の図のパントリーの上の端。洗い場の下の左の壁ぎわに、もう1か所の出入り口の位置が緑の線で引かれている

出入り口を2つ開けました。A はパントリーの壁に1m、客席側とつながる口。B はパントリーの上の端の口です。最初は扉を付けていましたが、扉は要らないと言われました。

Bのラインは扉とかはないからね。

A も扉ないよ!(あったら誰か扉開けないとダメでしょ!)扉は洗い場とキッチンの出入り口のところだね

料理を持ったスタッフやロボットが通る口に扉があると、誰かが開けないと通れません。扉があるのは、上の通路から洗い場とキッチンへ入る所だけです。JSON の layout.doors に、出入り口ごとに扉の有無(door)を書くようにしました。doors は図と Unity のための情報で、ロボットの道の計算には使いません(パントリーなどの部屋の中は障害物のまま)。

同じ図で、仕切り壁の上の4人席2つにも指摘がありました。

②の図の左の部分。真ん中の灰色の仕切り壁の上に4人席が2つあり、ロボットの道(オレンジの線)が卓と壁のすき間から卓に近づいている

ロボットが壁側から入っていくのはNGだね。机をもっと壁に寄せてください。

卓と仕切り壁の間が空いていたので、ロボットの道が壁側から卓に近づいていました。4人席2つを y=10.0m から 9.6m に下げ、壁との間を0.6mにしました。0.6mはロボット(BellaBot は幅80cmの通路が要る)が入れない幅です。

直したあとの②の図。パントリーの左の壁と上の端に緑の出入り口が2つあり、仕切り壁の上の4人席は壁に寄って、ロボットの道は卓の下側から入る

直したあとの②は19卓88席で、19卓すべてにふだんの1.0mの道で届きます。卓までの平均は8.49mから8.56mに、最長は14.01mから13.78mに変わりました。

確かめの穴を7つふさいだ(トイレ・レジ・仕切り・輪郭・線の当たり・候補の打ち切り・違反時の出力)

codex が反例として出した7つの置き方を、全部テストにしてから直しました。

穴直した形
トイレの入口とトイレの対応を見ていなかった
トイレの4辺を、外壁・裏の部屋・建物の外・厚さ30cm以上の壁・入口のどれかで、すきまなく囲むこと(辺を区間として計算で確かめる)
トイレの入口の前が、名前によっては空いていなくても通った
入口の前と入口そのものは、名前に関係なく何も置かない
トイレから1m以内の席の目隠しを確かめていなかった
席のトイレ側の辺の両端からトイレの入口の両端へ引いた4本の線が、全部壁に当たること
レジとレジ内がなくても通った
レジ(2.5m以上)とレジ内(店員の立つ所)が両方あり、接していること
仕切りが卓に食い込んでいても通った
食い込んでよいのは、ボックス席のベンチの背の辺の上で深さ8cm以内のときだけ
建物の輪郭と「建物の外」がずれていても通った
輪郭は縦と横の辺だけの形にし、座標で区切ったマスごとに建物の外と照合する
決まりに違反しても、出力先に途中の結果が残った
出力はいったん作業用のフォルダに出し、6つ全部が通ったときだけ入れ替える

あわせて、点を並べて当たりを確かめていた所を、線と矩形の交わりの計算に変えました(点の間隔より薄い壁を見逃していた)。止まる位置の候補を200点で打ち切っていたのもやめました。出力には版の番号(generation。作り方のコード・記憶の店の原本・設定から決まる12桁)を入れ、読む側が同じ版の一式かを確かめられるようにしました。テストは73件になり、6つの店の数字は前と同じでした。

4本の線の目隠しの決まりは、近似です。目隠しの壁に切れ目があると、4本は壁に当たっても間から入口が見える置き方を見落とし得ます。README に「目隠しは1枚の続いた壁で作る」と書きました。

codex の3回目の検証と、どこまで直すかの線引き

3回目の検証も「正式に採用する前に直すことがある」という結論でした。指摘を受けて、出力の入れ替えを途中で失敗したら元に戻す形に変えました(summary.json は最後に入れ替える)。ほかに、トイレの4辺と入口を区間として確かめる、入口の前の奥行き1.2m以上を確かめる、輪郭を縦と横の辺だけの形に限る、出入り口に壁を重ねない、を直しました。テストは80件で、6つの店の数字はまた同じでした。

ここで、どこまでやるかの線引きを問い直しました。

サイトの試算 v2.5は必要?どこまでやればいいかの線引きしてる?

codex の指摘は、回を重ねるごとに「確かめの仕組みにすり抜ける穴がある」という種類が中心になっていました。そうした穴をふさいでも、6つの店の数字は3回続けて変わっていません。そこで、次の線を引きました。

  • 6つの店の数字(卓の分け方・距離・止まる位置)が変わらない指摘は、これ以上 codex とやり取りしてふさがない
  • 数字が変わった店だけ、試算を回し直す。今回は②だけ

試算 v2.5:卓までの距離が変わった②だけを回し直した

16,425条件(店・スタッフ数・ロボット台数・来客のペースなどの組み合わせ)のうち、②の1,314条件だけを40回ずつ回し直しました。ほかの15,111条件は v2.4 の結果をそのまま使い、数字が1つも変わっていないことを確かめました。

比べたものv2.4 → v2.5
②の卓の数19 → 19
②の卓までの平均8.49m → 8.56m
②の「店が回らない」条件の数124 → 124
全体の「店が回らない」条件の数
3,007 → 3,007
②の入店待ちの差
平均 −0.09分(−4.3〜+3.9分)

入店待ちの差の幅が±4分あるのは、距離が変わると乱数の出方も変わるためで、平均はほぼ同じです。比べた結果の全量は、後ろの「実行したコマンドと出力」に載せています。

サイトを正にしたときの問題と、「何について正か」の表

ここから Unity の作業です。これまでの方針は「サイトの試算が正で、Unity はそれに合わせる」でした。その方針で何が困るのかを、先に整理しました。

サイトを正にした時に問題はどんなところですか?整理して教えてください。

一番大きな問題は、サイトの数字の一部が、Unity で測るための仮の値だということです。ロボットの速さ(0.5m/秒)、止まる割合(往復の30%)、止まる長さ、動けなくなる割合(1%)は、Unity で測ってサイトに戻すはずの値です。全部をサイトに合わせると、測るはずの値を Unity に読み込ませることになり、話が逆になります。もう1つは、Unity にしかないもの(組の人数・2人席・ドリンクバー・トイレ・椅子を引く)がサイトにはないことです。

そこで、何について正かを分けました。

何について正扱い
店の形(卓・壁・部屋・止まる位置)
サイト
サイトの JSON を読んで建てる。Unity で形を作らない
条件(スタッフ・来客・ロボットの台数)
サイト
図面のある店の値をそのまま使う
店の回し方の決まりと時間、数字の定義
サイト比べる物差しをそろえる
通路で起きること(実際の速さ・止まる回数と長さ・立ち往生)
Unity が測る
測った値は、サイトを先に直して入れる
Unity が建てるための細かい形(通路の区画・椅子・座る位置・並ぶ点など)
サイトの店の形から、決まった規則で作る
規則はサイト側に置き、JSON に書き出す
Unity にしかないものUnity
「Unity だけの値」として残し、サイトとは比べない

距離の測り方も違います。サイトは通路の真ん中に50cmの余裕を取った道のり、Unity は半径25cmの円が家具に寄って走る道のりです。そのため、Unity とサイトの数字は完全には合いません。合っているかは、向き(どちらが大きいか)と大きさで見ることにしました。この表は、あとで段階A〜Cを決めたときに、店の形と条件をそろえるところまでに絞っています(最後の節)。

Unity が店を建てるための細かい形を、サイトの JSON に書き出した(unity_export.py)

サイトの図面の JSON には、卓の外形と止まる位置はあっても、Unity が店を建てるのに要る細かい形がありません。それを決まった規則で作る unity_export.py を書き、public/sim/layouts/unity/{名前}.json に書き出しました。公開されているので、誰でも同じ店を建てられます( https://pixelstomotors.com/sim/layouts/unity/p5_crammed.json など)。

書き出すもの規則
床・外壁・壁
建物の外を除いた床。外壁は輪郭から作り、入口の所だけ空ける。壁には高さを付ける
部屋
通れない箱。ただしレジ内は通れる部屋(スタッフだけ)
細い通路
同じ向きのボックス席がすき間なく並んだ列の、隣り合う列のすき間(0.5〜1.5m)。両端の0.8m外に入口の点を置き、受け渡し口に近いほうを entrance にする。③⑦は3本(③1.2m、⑦0.8m)
卓の部品
天板・ベンチ・椅子(2人席の通路側の椅子だけ引ける。引く向きつき)・座る位置(席数ぶん)・席に着くために立つ点(障害物から0.2m以上離れた所だけ)
場所の点
受け渡し口の前・下げ膳の返却・入口・待合・レジとレジに並ぶ点・レジ内・トイレの入口の前・ドリンクバーの前と並ぶ点・ロボットの待機場所(1台ずつ)・スタッフが待つ点

卓の数・止まる位置・卓までの距離は、試算が使う解析結果(analysis)と同じであることをテストで確かめます。Claude Code が最初に建てたときの報告で、レジ内が通れない箱になっていてスタッフが立てない、席に着く点の一部が障害物に近すぎる、の2点が出たので、規則を直しました(テスト99件)。

Unity が JSON から③⑦を建てた:卓42・席160・止まる位置42がサイトと一致した(cs:112)

Claude Code への依頼文(v4)は後ろに全量で載せています。Unity の中に JsonStoreLayout という店の形の種類を足し、JSON の座標を Unity の座標に置き換えて建てます(JSON の x → Unity の X、JSON の y → Unity の Z)。

Unity で建てた③を真上から見た画面。左に4列のボックス席の島、右上に厨房、ロボットが入れる床が水色で塗られ、席の列の間の通路は1.2m
Unity で建てた⑦を真上から見た画面。③と同じ卓の並びで、列の間の通路だけが0.8mに狭まっている

確かめの結果です(Claude Code の報告から)。

確かめたこと③(通路1.2m)⑦(通路0.8m)
卓・席
42・160(JSON・summary と一致)
42・160(同)
止まる位置が通れる床の上42 / 4242 / 42
席に着く点・場所の点が通れる床の上
45 / 45・26 / 2645 / 45・26 / 26
受け渡し口から卓までの道のり(Unity − JSON)
平均 −0.71m・最大 1.86m 短い
平均 −0.67m・最大 1.86m 短い
入口から席に入れない卓00

42卓すべてで、Unity の道のりのほうが短く出ました。サイトは通路の真ん中に余裕を取り、Unity は家具に寄って走るので、向きは見込みどおりです。

1つ、サイトと答えが違う所がありました。⑦では、サイトの決まりで「1.0mの道では届かず、0.8mの道なら届く」卓が24あります。サイトは、ロボットをふだん1.0m以上の道で走らせ、それで届かない卓だけ0.8mの道を使います。Unity は半径25cmの円が通れればどこでも走るので、1.0m以上の道で行ける卓にも、近道の0.8mの通路を通って行っていました。

試算の条件と店の回し方の値を Unity 用に書き出した(serving-robot-params.json)

Unity がサイトの条件で回せるように、条件と回し方の値を public/sim/serving-robot-params.json に書き出しました。手で写すと写し間違えるので、Unity はこのファイルを読みます。

  • common:案内45秒・会計90秒・片付け40秒+40秒など。値ごとに role を付けた。site_rule は Unity が使う値、unity_measures(robot_speed・pause_rate・pause_s・stuck_rate)は Unity が測る値で読まない、site_only は試算の中だけの値
  • stores:③⑦の卓の数・来客のペース・スタッフの人数・食事の長さなど
  • unity_conditions:Unity で回す6条件(③⑦ × ロボット0・1・2台。スタッフ4人・1時間42組・上げ膳だけ・1往復で3卓まで)と、同じ条件の試算の結果(site_result)
条件試算の入店待ち(平均・分)料理が届くまで(平均・分)ロボットが運んだ割合
③ ロボット0台3.180.650%
③ ロボット1台1.960.5547%
③ ロボット2台1.020.4673%
⑦ ロボット0台3.500.660%
⑦ ロボット1台2.100.5546%
⑦ ロボット2台1.230.4973%

⑦の0.8m通路をサイトの決まりにそろえようとして、通れる床が割れた

「ふだんは1.0m以上の道、届かない卓だけ0.8mの道」をサイトにそろえるため、Claude Code は⑦の0.8mの通路3本を NavMesh の別の区画(area 4)にし、そこを通る道に20倍の重み(コスト)を付けました。結果は、21卓で道が途中までしか引けない、でした。重みを使わず、すべての区画を通ってよいことにして探しても、11卓がつながりませんでした。

区画を書き込まなかった段階1では、42卓すべてにつながっていました。区画の箱の位置は JSON の通路と小数点以下まで同じでした。このときは、区画を書き込むと同じ床が細かく割れ、道がつながらない所が出る、と考えました。あとで分かった「古い床が残る」こと(2つ先の節)が、このときの結果にも効いていた可能性がありますが、確かめていません。

ここで、2つの案を比べました。Unity の中で狭い道を扱い続ける案と、ロボットの道順をサイトが決めて JSON で渡す案です。

道順をサイトから渡す案

サイトの試算は、卓ごとの道(1.0mの道か、届かなければ0.8mの道)をもう持っています。それを Unity に渡せば、Unity の中で同じ規則を作り直さずに済みます。人をよける・止まる・動けなくなる、は Unity の中で起きることなので、Unity で測る値はそのままです。

ロボットの道順はサイトが決めて渡す形にした(routes)

unity_export.py に build_routes を足しました。やっていることは3つです。

  1. 受け渡し口の前と各卓の止まる位置から、マス目(2.5cm)の上で最短の道を探す。ふだんの幅(1.0m)で通れるマスだけで行けるならその道、行けなければ通れる幅(0.8m)のマスで探す
  2. マス目の道は細かい階段の形なので、通れる範囲でまっすぐにつなぎ、曲がり角の点だけを残す(点と点の間の見通しは、1/4マスおきに確かめる)
  3. 受け渡し口の前→各卓(from_pass、42本)と、卓→卓(between、861本)を書き出す。逆向きは点を逆にたどる
⑦の道順の図。受け渡し口の前(黒い四角)から、青い線がふだんの1.0mの道、オレンジの線が0.8mの道。T17・T22 は青い線で店の上を回り、T21 はオレンジの線で狭い通路に上の口から入る。緑の点線は T09 から T21 への卓から卓の道

③は42本すべてふだんの道、⑦は24本が0.8mの道で、どちらもサイトの卓の分け方と全卓で一致しました(テスト107件)。⑦の T17・T22 は、近道の0.8mの通路を通らずに、1.0mの道で店の上を回ります。

Claude Code への依頼文(v5b)では、次を頼みました。

  • 狭い通路の区画を NavMesh に書き込む作りを外し、段階1と同じ床に戻す
  • ロボットは、受け取った道順の点を1つずつ行き先にしてたどる。止まる位置は寄せない
  • 人にふさがれて道を引き直すときは、次の点までの区間だけを引き直す。全体の道順は変えない
  • 確かめでは、点から点の区間がすべてつながるか、区間の道のりがまっすぐの1.05倍を超えていないか(店の形と NavMesh が合っていない印)を見る

⑦で人まで21卓に入れない:原因は Unity に残っていた古い通れる床だった

v5b を入れて、③⑦を続けて確かめました。③は全部通りました。⑦は通りませんでした。

確かめたこと③⑦
すべての区間がつながった卓42 / 4221 / 42
つながらない区間025
まっすぐの1.05倍を超えた区間
02(T17・T22)
0.8mの道を通る卓024
入口から席に入れない卓(人)021

最後の行が手がかりでした。人の歩きは、サイトの道順を使いません。その人まで入れないので、道順ではなく、⑦の通れる床そのものが途切れていることになります。

まず、図面が変わっていないかを確かめました。段階1で全卓つながったときの⑦の JSON(版 e624bdf4bdd4)と、今の JSON(版 9628954a582f)を項目ごとに比べると、違うのは道順(routes)を足したことだけで、床・壁・部屋・卓・通路・場所の点は同じでした。図面が同じなら、段階1のあとに Unity の側で何かが変わっています。

次の疑いは、③を建てた直後に⑦を建てるときの片付け漏れでした。⑦だけを建てて確かめてもらうと、結果は同じでした(21卓に入れない)。片付け漏れではありません。

そこで、落ちた卓の並びを見直しました。落ちたのは2本目の通路の卓・3本目の通路の卓・T27〜T30で、1本目の通路の卓は通っていました。この並びは、狭い通路の区画を書き込んでいたときに落ちた卓の並びと同じです。区画を書き込む作りは外したのに、同じ並びで落ちています。

Unity は、焼いた(計算した)NavMesh を覚えておくために、プログラムの中に目印を持っています。プログラムを書き換えると Unity は読み込み直しをし、そのときこの目印が空になります。目印がないと、次に焼き直すときに古い面を消せません。古い面は Unity の中に残り、新しい面と重なります。重なった2枚の面はつながっていないので、道探しが古い面の上の点から始まると、区画で割れた所で止まります。段階1は、まだ何も重なっていない状態で確かめていました。

確かめ方は、コードを変えずにできました。Unity を一度終了して開き直すと、残っていた面はすべて消えます。開き直して⑦だけを確かめると、通りました。

確かめたこと⑦(開き直す前・20:50)
⑦(開き直した後・20:52)
すべての区間がつながった卓21 / 4242 / 42
つながらない区間250
まっすぐの1.05倍を超えた区間
20
入口から席に入れない卓210
Unity を開き直して⑦を確かめた画面。⑦の店が真上から写り、Console に「Build Store おわり」と「JSON Store の確かめ おわり(p5_crammed)」の2行が出ている

Claude Code に、焼く前に入っている NavMesh を全部外す1行(NavMesh.RemoveAllNavMeshData())を、焼く所と三角形を読む所の2か所に入れてもらいました。あわせて、狭い通路の印(hardToPass)を Unity から外しました。狭いかどうかを決めるのはサイトの道順の use だけにするためです。プログラムを書き換えたあと、開き直さずに③⑦を続けて確かめると、両方通りました(cs:114)。

確かめたこと③(通路1.2m)⑦(通路0.8m)
区間がつながった卓42 / 4242 / 42
つながらない区間00
1.05倍を超えた区間00
0.8mの道を通る卓024
入口から席に入れない卓00
サイトの距離との差(平均/最大)
0.28m/0.67m 短い0.37m/0.87m 短い

道順をたどると、サイトの距離より平均0.3m前後短くなります。サイトの距離はマス目の道の長さで、Unity は曲がり角を直線で結んで走るためです。サイトと比べるときは、Unity のほうがこの分だけ少し速く着くことになります。

回し方をサイトにそろえる作業(v5の3章)を入れた:まだ回していない

続けて Claude Code が、回し方をサイトにそろえる作業を入れました(cs:116。報告は後ろに全量)。

  • サイトと同じ6条件を Unity のメニューから選べる。数字は serving-robot-params.json から読む
  • 空の店から始め、120分だけ客が来て、全員が帰ったら終わる(客が来なくなってから600分で打ち切り)
  • ロボットが60秒動けなくなったら、受け渡し口へ移す(warp)のをやめ、スタッフが歩いて行って15秒動かす。止まっていた所から道順の続きを走る
  • あきらめた・移した・卓を空けた、の回数(逃がし弁)を記録する
  • 往復ごとに、実際に走れた速さ・動けなくなった回数・スタッフを待った秒数・0.8mの道を使ったか・狭い通路の中と外で止まった回数と秒数を出す

報告には「サイトと定義が違うもの」が並んでいたので、試算のコード(haizen_sim.py)と1行ずつ照らし合わせました。

報告にあった違い試算のコードを見た結果
「席はあるのに待った時間」(staff_wait_mean)。Unity は案内の人が来るまでだけを測る
違う。サイトは「卓は空いたが片付けが終わらず待った時間」+「案内の人の手が空かず待った時間」。Unity は前半を「席が埋まっていて待った時間」に入れていた
片付けの時間(turn_mean)。サイトは片付けと拭く時間だけ
読み違い。サイトもスタッフの手が空くのを待つ時間・卓まで歩く時間・皿を戻す往復を含む。同じ定義
ロボットに料理を載せる15秒(load_s)を Unity は形にしていない
15秒は下げ膳のときだけ使う値。上げ膳だけの条件では、サイトは載せる時間を0秒にしている

「席はあるのに待った時間」は、サイトがこの値が10分以上の条件を「店が回らない」と判定する数字です。Claude Code は、サイトと同じ数え方に変え、上げ膳のときの待ち時間を0秒にしていました。どちらも記録する数字か、もともと使われていない値の変更で、店の中の動きは変わりません。そのまま使うことにしました。

Unity をサイトに合わせ続けるのをやめ、3段階のゴールを決めた

ここで、作業の終わりを先に決めることにしました。

最終的にはUnityのシミュレーションをサイトの「配膳ロボット導入シミュレーション」に完全に合わせることは難しいと思います。 なのでどこまでズレを直せばゴールなのかあらかじめ決めてください。 このままだと延々と作業を繰り返しているだけで、いつまで経っても何が達成できるのか分かりません。

最初に出した案は、「4つの値(速さ・止まる割合・止まる長さ・動けなくなる割合)を測ってサイトに戻すことをゴールにし、ズレは、ロボットのまわりを動く人やロボットの数・通る場所が変わるものだけ直す」でした。これに対して、進め方そのものの案が返ってきました。

最終的にはこういう手順でサイトとUnityのシミュレーションを擦り合わせする必要があると思ってはいます。

まずはUnityでファミレス店舗で図面があるもののシミュレーションを大方作ってしまいます。 実際にUnityでシミュレーションで回してみて、どのようなことが店舗で起こるかをデータを記録します(実際に動くシミュレーションデータを取得する)

そのデータを元に台帳にデータをまとめてUnity特有のロボット導入シミュレーションデータとして確率されます。この時にサイトのデータとUnityのデータが揃っていれば良いですが実際には難しいと思います。

つまりサイトの導入シミュレーションとUnityシミュレーションのギャップが生まれるはずです。 その差をどう埋めていくかを観察して、データの取得項目や部屋の構成の見直しなどを測る必要があります。

最初の案は「Unity を先にサイトに合わせ、ズレたら直す」の延長でした。これだと、ズレが見つかるたびに直す作業が続きます。返ってきた進め方では、サイトとのズレは直す対象ではなく、Unity を回し切ったあとに調べる対象(結果)になります。 この進め方を3つの段階に分け、それぞれの終わりを決めました。

段階やること終わり
A. 店を作る
図面のある店を Unity で建てる。店の形と条件(1時間の組数・スタッフ数・ロボット台数)だけはサイトと同じにする。仕事の決まりや数え方は Unity のままでよく、違いは一覧に書くだけ
どの店・どの条件でも最後まで回り切り、逃がし弁がほぼ0
B. 回して台帳にまとめる
1回回すごとに台帳に1行足す(店・条件・乱数の種・結果の数字・ロボットの4つの値・逃がし弁の回数)。台帳の置き場所は先に MASTER の保存先の表に足す
決めた条件と回数が全部台帳に入る
C. ズレを調べる
同じ店・同じ条件でサイトと Unity の数字を並べ、ズレごとに理由を分ける(数え方の違い/サイトにない動き=すれ違い・混雑/Unity の作りの問題)。何を直すかを決める
ズレの一覧と、それぞれの理由・対処が書ける。対処を入れるのは次の版

店と条件だけをそろえるのは、そこが違うと、あとでズレの理由を読めなくなるからです。店の順番は、③⑦で A〜C を一度通してから、ほかの店(②④⑤⑥)を足すことにしました。③⑦で一度ズレの出方を見れば、ほかの店で何を記録すべきかが分かるためです。問題が出たときに直すのは1回だけにし、それでも直らなければ制約として書いて先へ進みます。この表は、設計書(unity_design_v0.md)の0.5章に書きました。

次は、③のロボット2台の条件を乱数の種1つで1回だけ回し、最後まで回り切るか、逃がし弁がほぼ0か、往復ごとの値が記録されるかを見ます。1回にかかる実時間を見て、何回ずつ回すかを決めます。

データとコードの置き場所

もの場所
店の形の作り方・確かめ・Unity 用の書き出し
GitHub PixelstoMotors/p2m-site の tools/sim_layouts/(famires_v3.py・famires_p0.py・unity_export.py・test_famires_v3.py・README.md)
店の形のデータ(試算用・Unity 用)
p2m-site の public/sim/layouts/・public/sim/layouts/unity/(版 9628954a582f)
試算の条件と店の回し方の値
p2m-site の public/sim/serving-robot-params.json
試算 v2.5
iCloud サービスロボット導入シミュレーション/simulation/v2_5/(haizen_sim.py は v2.4 と同じ)
Unity の設計書・Claude Code への依頼文・Claude Code の報告
iCloud サービスロボット導入シミュレーション/unity/(unity_design_v0.md・claude_code_request_v4/v5/v5b・claude_code_reports/)
Unity の確かめの出力
iCloud サービスロボット導入シミュレーション/unity/screens/
Unity のコード
/Users/shimazueiichi/Robotics_UX/Robotics_UX_New/Assets/ServiceSim/(Unity Version Control cs:112〜cs:116)

実行したコマンドと出力

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

ファイルの一覧(26本)

01_sec18.txt ― 確かめの仕組みのテスト(tools/sim_layouts/test_famires_v3.py・107件)・4,694字

02_sec18.txt ― ⑦の確かめ:開き直す前(2026-10-22 20:50、⑦だけで建てた。20:33 に③⑦を続けて建てたときも、作った日時以外は同じ出力)・4,421字

03_sec19.md ― v4:サイトの店の形(JSON)から店を建てる(claude_code_request_v4_json_store.md)・3,280字

04_sec19.md ― v5:回し方をサイトの試算にそろえる(claude_code_request_v5_align.md)・3,037字

05_20261022_1830_json_store_v4.txt ― 20261022_1830_json_store_v4.txt・6,612字

06_20261022_1900_json_store_v4_regen.txt ― 20261022_1900_json_store_v4_regen.txt・4,660字

07_20261022_1920_json_store_v4_result.txt ― 20261022_1920_json_store_v4_result.txt・5,608字

08_20261022_1935_align_v5_step0_1_2.txt ― 20261022_1935_align_v5_step0_1_2.txt・8,357字

09_20261022_2010_narrow_aisle_fix.txt ― 20261022_2010_narrow_aisle_fix.txt・4,489字

10_20261022_2040_routes_v5b.txt ― 20261022_2040_routes_v5b.txt・4,948字

11_20261022_2140_align_v5_step3.txt ― 20261022_2140_align_v5_step3.txt・11,885字

12_sec21.md ― 2回目の検証の結果(review_result_v3.md・codex が書いたもの)・8,207字

13_tools_sim_layouts_famires_v3.py.txt ― tools/sim_layouts/famires_v3.py・46,705字

14_tools_sim_layouts_famires_p0.py.txt ― tools/sim_layouts/famires_p0.py・4,728字

15_tools_sim_layouts_unity_export.py.txt ― tools/sim_layouts/unity_export.py・24,289字

16_tools_sim_layouts_test_famires_v3.py.txt ― tools/sim_layouts/test_famires_v3.py・19,078字

17_tools_sim_layouts_README.md ― tools/sim_layouts/README.md・5,853字

18_simulation_v2_5_export_params.py.txt ― simulation/v2_5/export_params.py・3,380字

19_simulation_v2_5_build_page_v25.py.txt ― simulation/v2_5/build_page_v25.py・3,839字

20_Assets_ServiceSim_Store_JsonStoreLayout.cs.txt ― Assets/ServiceSim/Store/JsonStoreLayout.cs・28,013字

21_Assets_ServiceSim_Store_RouteBook.cs.txt ― Assets/ServiceSim/Store/RouteBook.cs・4,340字

22_Assets_ServiceSim_Store_NavMeshBaker.cs.txt ― Assets/ServiceSim/Store/NavMeshBaker.cs・13,470字

23_Assets_ServiceSim_Store_SimpleJson.cs.txt ― Assets/ServiceSim/Store/SimpleJson.cs・8,813字

24_Assets_ServiceSim_Editor_ServiceSimJsonStore.cs.txt ― Assets/ServiceSim/Editor/ServiceSimJsonStore.cs・25,950字

25_Assets_ServiceSim_Experiment_SimParams.cs.txt ― Assets/ServiceSim/Experiment/SimParams.cs・11,248字

26_Assets_ServiceSim_Robot_ServingRobotController.cs.txt ― Assets/ServiceSim/Robot/ServingRobotController.cs・47,881字

確かめの仕組みのテスト(tools/sim_layouts/test_famires_v3.py・107件)

01_sec18.txt4,694字・123行・text
$ cd tools/sim_layouts
$ time python3 test_famires_v3.py
OK  80cmの通路はBellaBotで通れる(マス目0.025・ずらし0.0)
OK  77cmの通路はBellaBotで通れない(マス目0.025・ずらし0.0)
OK  75cmの通路はServiで通れる(マス目0.025・ずらし0.0)
OK  80cmの通路はBellaBotで通れる(マス目0.025・ずらし0.013)
OK  77cmの通路はBellaBotで通れない(マス目0.025・ずらし0.013)
OK  75cmの通路はServiで通れる(マス目0.025・ずらし0.013)
別のタブで開く保存

6つの店を確かめて書き出す(famires_v3.py)。出力は公開中のデータとすべて同じだった

$ time python3 famires_v3.py --out /tmp/claude-0/runout/layouts
[OK] p0_memory: {'name': '② 定番の郊外型', 'seats': 88, 'tables': 19, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 19, 'robot_seats': 88, 'narrow_tables': 0, 'narrow_seats': 0, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 8.6, 'robot_dist_max': 13.78, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []
[OK] p1_efficient_corner: {'name': '③ 効率重視型・入口が左下の角', 'seats': 160, 'tables': 42, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 42, 'robot_seats': 160, 'narrow_tables': 0, 'narrow_seats': 0, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 10.7, 'robot_dist_max': 20.14, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []
[OK] p2_efficient_narrow: {'name': '④ 効率重視型・狭い店・入口が右の壁', 'seats': 88, 'tables': 28, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 28, 'robot_seats': 88, 'narrow_tables': 0, 'narrow_seats': 0, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 8.4, 'robot_dist_max': 14.02, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []
[OK] p3_relaxed_center: {'name': '⑤ ゆったり型・入口が正面の中央', 'seats': 200, 'tables': 46, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 46, 'robot_seats': 200, 'narrow_tables': 0, 'narrow_seats': 0, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 13.7, 'robot_dist_max': 23.17, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []
[OK] p4_relaxed_side: {'name': '⑥ ゆったり型・入口が左の壁', 'seats': 158, 'tables': 38, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 38, 'robot_seats': 158, 'narrow_tables': 0, 'narrow_seats': 0, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 10.7, 'robot_dist_max': 18.38, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []
[OK] p5_crammed: {'name': '⑦ ③の列の間の通路を80cmに(卓と席数は③と同じ)', 'seats': 160, 'tables': 42, 'model': 'BellaBot', 'pass_width': 0.8, 'normal_width': 1.0, 'robot_tables': 18, 'robot_seats': 64, 'narrow_tables': 24, 'narrow_seats': 96, 'human_tables': 0, 'human_seats': 0, 'robot_dist_mean': 11.0, 'robot_dist_max': 20.32, 'human_walk_total': 0.0, 'human_walk_max': None}  マス目の差: []

real	2m55.063s
user	2m42.507s
sys	0m9.891s
$ for f in *.json unity/*.json; do cmp -s $f <p2m-site>/public/sim/layouts/$f && echo "same $f" || echo "DIFF $f"; done
same p0_memory.json
same p0_memory_analysis.json
same p1_efficient_corner.json
same p1_efficient_corner_analysis.json
same p2_efficient_narrow.json
same p2_efficient_narrow_analysis.json
same p3_relaxed_center.json
same p3_relaxed_center_analysis.json
same p4_relaxed_side.json
same p4_relaxed_side_analysis.json
same p5_crammed.json
same p5_crammed_analysis.json
same summary.json
same unity/p0_memory.json
same unity/p1_efficient_corner.json
same unity/p2_efficient_narrow.json
same unity/p3_relaxed_center.json
same unity/p4_relaxed_side.json
same unity/p5_crammed.json

試算 v2.4 と v2.5 の比較(compare_v24_v25.txt)

v2.4 と v2.5 の比較(店の形の直しで ② 定番の郊外型(fam_p0)の卓までの距離が変わったため、② だけ回し直した)
条件の数 16425 16425 並びが同じ True
② 以外で数字が変わった条件 0 / 15111
② の条件 1314 変わった条件 1314
② の卓の数 19 -> 19  卓までの平均 8.49 -> 8.56
② の店が回らない 124 -> 124  全体 3007 -> 3007
② entry_wait_mean: 差の平均 -0.087  最小 -4.315  最大 +3.916
② staff_wait_mean: 差の平均 -0.020  最小 -2.310  最大 +2.848
② dish_wait_mean: 差の平均 +0.002  最小 -0.041  最大 +0.051
② walk_km_per_staff: 差の平均 +0.005  最小 -0.126  最大 +0.201
代表 ('fam_p0', 4, 2, 19, 'serve', 3, 'any') {'entry_wait_mean': (0.93, 0.53), 'staff_wait_mean': (0.21, 0.14), 'dish_wait_mean': (0.3, 0.3), 'walk_km_per_staff': (0.62, 0.62)}

⑦の確かめ:開き直す前(2026-10-22 20:50、⑦だけで建てた。20:33 に③⑦を続けて建てたときも、作った日時以外は同じ出力)

02_sec18.txt4,421字・112行・text
[ServiceSim] JSON Store の確かめ おわり(p5_crammed)
# JSON から建てた店の確かめ(段階1・回していない)
店の形: StoreLayout_p5_crammed / JsonStoreLayout(p5_crammed)
作った日時: 2026-10-22 20:50:17

JSON から建てた店(Unity では形を作っていない)
  ファイル: p5_crammed / 名前: ⑦ ③の列の間の通路を80cmに(卓と席数は③と同じ)
  版の番号 (meta.generation): 9628954a582f
別のタブで開く保存

③⑦の確かめ:NavMesh を消してから焼く直しのあと(2026-10-22 21:04、③⑦を続けて建てた)

20261022_p1_efficient_corner_json_check.txt

# JSON から建てた店の確かめ(段階1・回していない)
店の形: StoreLayout_p1_efficient_corner / JsonStoreLayout(p1_efficient_corner)
作った日時: 2026-10-22 21:04:49

JSON から建てた店(Unity では形を作っていない)
  ファイル: p1_efficient_corner / 名前: ③ 効率重視型・入口が左下の角
  版の番号 (meta.generation): 9628954a582f
  写した日時: 2026-10-22 20:23:50 JST(版 9628954a582f)
  写し元: https://pixelstomotors.com/sim/layouts/unity/p1_efficient_corner.json
  卓 42 / 席 160 / 細い通路 3 本(幅 1.2 m)
  通れない部屋 9 / 通れる部屋 1(うちスタッフだけ 1)
  場所の点 26 / 壁 9 / 仕切り 0 / 椅子 8 / 席に着く点 45 / 座る位置 160
  道順 (routes): 受け渡し口から 42 本 / 卓から卓 861 本(狭い道を使うかは routes の use が正。Unity では印を持たない)
  doors: 0(壁の切れ目として、もう空いている)
  refuges(よけ場所): 0(JSON にまだ無い。空のまま)
  止まる位置は JSON の stop をそのまま使う(deliveryOffsetFromAisleCenter と aisleEntranceSetback は使わない)
  合わないもの: なし

## 1. 数
  卓: Unity 42 / JSON 42 / summary.json 42  一致
  席: Unity 160 / JSON 160 / summary.json 160  一致
  細い通路: 3 本(A01 1.2 m / A02 1.2 m / A03 1.2 m)
  組み立てた幅 (plan.aisleWidth): 1.2 m
  外寸: 24 × 16 m / JSON outer 24 × 16 m

## 2. 点が NavMesh の上に乗るか(乗らないものだけ並べる)
  止まる位置 (deliveryPoint, ロボット用): 乗らない 0 / 42
  席に着く点 (spots, 人用): 乗らない 0
  座る位置 (seatPoints, 人用): 乗らない 160  ※ 座面やベンチの上の点は NavMesh に乗らないのがふつう(見た目に使う点)
    - T01#1 (0.3, 4.88)
    - T01#2 (0.9, 4.88)
    - T01#3 (0.3, 6.18)
    - T01#4 (0.9, 6.18)
    - T02#1 (0.3, 6.73)
    - T02#2 (0.9, 6.73)
    - T02#3 (0.3, 8.03)
    - T02#4 (0.9, 8.03)
    - ほか 152 件
  場所の点 (places): 乗らない 0

## 3. 道順の照合(受け渡し口の前 → 止まる位置。サイトの routes をたどる)
  道順: 受け渡し口から 42 本(うち 0.8 m の道 0 本)/ 卓から卓 861 本
  止まる位置を面へ寄せる半径: 1 m
  すべての区間がつながった卓: 42 / 42
  差(Unity − JSON)の平均: -0.28 m
  差の大きさの平均: 0.28 m / 最大: 0.67 m(T17)
  差が 30% を超えた卓: 0
  via_narrow(use=narrow)の卓: 0 / 42
  つながらない区間: 0
  まっすぐの 1.05 倍を超えた区間: 0
  CSV: /Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/unity/screens/20261022_p1_efficient_corner_table_dist.csv

## 4. 席に入れない卓(入口から、席に着く点まで歩けるか)
  出発点 (Entrance): (1.8, 0.5)
  確かめた点: 42 / 卓 42
  入れない卓: 0

20261022_p1_efficient_corner_table_dist.csv

table,category,aisle,use,json_dist_m,route_len_m,unity_path_m,diff_m,diff_pct,via_narrow,segments,bad_segments,status
T01,robot,A01,normal,14.39,14.11,14.11,-0.28,-1.92,0,5,0,ok
T02,robot,A01,normal,16.24,15.96,15.96,-0.28,-1.72,0,6,0,ok
T03,robot,A01,normal,18.09,17.81,17.81,-0.28,-1.55,0,6,0,ok
T04,robot,A01,normal,19.94,19.66,19.66,-0.28,-1.38,0,5,0,ok
T05,robot,A01,normal,14.59,14.31,14.31,-0.28,-1.92,0,6,0,ok
T06,robot,A01,normal,16.44,16.16,16.16,-0.28,-1.7,0,6,0,ok
T07,robot,A01,normal,18.29,18.01,18.01,-0.28,-1.51,0,5,0,ok
T08,robot,A01,normal,20.14,19.86,19.86,-0.28,-1.38,0,6,0,ok
T09,robot,A02,normal,10.89,10.61,10.61,-0.28,-2.57,0,6,0,ok
T10,robot,A02,normal,12.74,12.46,12.46,-0.28,-2.17,0,5,0,ok
T11,robot,A02,normal,14.59,14.31,14.31,-0.28,-1.92,0,6,0,ok
T12,robot,A02,normal,16.44,16.16,16.16,-0.28,-1.69,0,6,0,ok
T13,robot,A02,normal,10.89,10.61,10.61,-0.28,-2.57,0,6,0,ok
T14,robot,A02,normal,12.74,12.46,12.46,-0.28,-2.17,0,5,0,ok
T15,robot,A02,normal,14.59,14.31,14.31,-0.28,-1.92,0,6,0,ok
T16,robot,A02,normal,16.44,16.16,16.16,-0.28,-1.69,0,6,0,ok
T17,robot,A02,normal,16.95,16.28,16.28,-0.67,-3.97,0,10,0,ok
T18,robot,A03,normal,7.19,6.91,6.91,-0.28,-3.83,0,5,0,ok
T19,robot,A03,normal,9.04,8.76,8.76,-0.28,-3.09,0,6,0,ok
T20,robot,A03,normal,10.89,10.61,10.61,-0.28,-2.56,0,6,0,ok
T21,robot,A03,normal,12.48,12.14,12.14,-0.34,-2.73,0,10,0,ok
T22,robot,A03,normal,11.9,11.58,11.58,-0.32,-2.72,0,7,0,ok
T23,robot,A03,normal,7.19,6.91,6.91,-0.28,-3.83,0,5,0,ok
T24,robot,A03,normal,9.04,8.76,8.76,-0.28,-3.09,0,6,0,ok
T25,robot,A03,normal,10.89,10.61,10.61,-0.28,-2.56,0,6,0,ok
T26,robot,A03,normal,12.48,12.14,12.14,-0.34,-2.73,0,10,0,ok
T27,robot,,normal,2.22,2.21,2.21,-0.01,-0.36,0,1,0,ok
T28,robot,,normal,2.65,2.58,2.58,-0.07,-2.47,0,3,0,ok
T29,robot,,normal,4.5,4.32,4.32,-0.18,-4.1,0,3,0,ok
T30,robot,,normal,6.35,6.15,6.15,-0.2,-3.17,0,4,0,ok
T31,robot,,normal,8.22,7.61,7.61,-0.61,-7.44,0,2,0,ok
T32,robot,,normal,6.37,5.99,5.99,-0.38,-5.91,0,1,0,ok
T33,robot,,normal,4.67,4.58,4.58,-0.09,-1.9,0,1,0,ok
T34,robot,,normal,3.81,3.76,3.76,-0.05,-1.25,0,1,0,ok
T35,robot,,normal,4,3.8,3.8,-0.2,-4.91,0,1,0,ok
T36,robot,,normal,4.62,4.29,4.29,-0.33,-7.12,0,3,0,ok
T37,robot,,normal,5.72,5.37,5.37,-0.35,-6.1,0,4,0,ok
T38,robot,,normal,6.82,6.47,6.47,-0.35,-5.16,0,4,0,ok
T39,robot,,normal,7.92,7.57,7.57,-0.35,-4.44,0,4,0,ok
T40,robot,,normal,9.02,8.67,8.67,-0.35,-3.92,0,4,0,ok
T41,robot,,normal,10.12,9.77,9.77,-0.35,-3.48,0,4,0,ok
T42,robot,,normal,5.43,5.38,5.38,-0.05,-0.93,0,3,0,ok

20261022_p5_crammed_json_check.txt

# JSON から建てた店の確かめ(段階1・回していない)
店の形: StoreLayout_p5_crammed / JsonStoreLayout(p5_crammed)
作った日時: 2026-10-22 21:04:50

JSON から建てた店(Unity では形を作っていない)
  ファイル: p5_crammed / 名前: ⑦ ③の列の間の通路を80cmに(卓と席数は③と同じ)
  版の番号 (meta.generation): 9628954a582f
  写した日時: 2026-10-22 20:23:50 JST(版 9628954a582f)
  写し元: https://pixelstomotors.com/sim/layouts/unity/p5_crammed.json
  卓 42 / 席 160 / 細い通路 3 本(幅 0.8 m)
  通れない部屋 9 / 通れる部屋 1(うちスタッフだけ 1)
  場所の点 26 / 壁 9 / 仕切り 0 / 椅子 8 / 席に着く点 45 / 座る位置 160
  道順 (routes): 受け渡し口から 42 本 / 卓から卓 861 本(狭い道を使うかは routes の use が正。Unity では印を持たない)
  doors: 0(壁の切れ目として、もう空いている)
  refuges(よけ場所): 0(JSON にまだ無い。空のまま)
  止まる位置は JSON の stop をそのまま使う(deliveryOffsetFromAisleCenter と aisleEntranceSetback は使わない)
  合わないもの: なし

## 1. 数
  卓: Unity 42 / JSON 42 / summary.json 42  一致
  席: Unity 160 / JSON 160 / summary.json 160  一致
  細い通路: 3 本(A01 0.8 m / A02 0.8 m / A03 0.8 m)
  組み立てた幅 (plan.aisleWidth): 0.8 m
  外寸: 24 × 16 m / JSON outer 24 × 16 m

## 2. 点が NavMesh の上に乗るか(乗らないものだけ並べる)
  止まる位置 (deliveryPoint, ロボット用): 乗らない 0 / 42
  席に着く点 (spots, 人用): 乗らない 0
  座る位置 (seatPoints, 人用): 乗らない 160  ※ 座面やベンチの上の点は NavMesh に乗らないのがふつう(見た目に使う点)
    - T01#1 (0.3, 4.88)
    - T01#2 (0.9, 4.88)
    - T01#3 (0.3, 6.18)
    - T01#4 (0.9, 6.18)
    - T02#1 (0.3, 6.73)
    - T02#2 (0.9, 6.73)
    - T02#3 (0.3, 8.03)
    - T02#4 (0.9, 8.03)
    - ほか 152 件
  場所の点 (places): 乗らない 0

## 3. 道順の照合(受け渡し口の前 → 止まる位置。サイトの routes をたどる)
  道順: 受け渡し口から 42 本(うち 0.8 m の道 24 本)/ 卓から卓 861 本
  止まる位置を面へ寄せる半径: 1 m
  すべての区間がつながった卓: 42 / 42
  差(Unity − JSON)の平均: -0.37 m
  差の大きさの平均: 0.37 m / 最大: 0.87 m(T17)
  差が 30% を超えた卓: 0
  via_narrow(use=narrow)の卓: 24 / 42
  つながらない区間: 0
  まっすぐの 1.05 倍を超えた区間: 0
  CSV: /Users/shimazueiichi/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/unity/screens/20261022_p5_crammed_table_dist.csv

## 4. 席に入れない卓(入口から、席に着く点まで歩けるか)
  出発点 (Entrance): (1.8, 0.5)
  確かめた点: 42 / 卓 42
  入れない卓: 0

20261022_p5_crammed_table_dist.csv

table,category,aisle,use,json_dist_m,route_len_m,unity_path_m,diff_m,diff_pct,via_narrow,segments,bad_segments,status
T01,narrow,A01,narrow,14.57,14.18,14.18,-0.39,-2.65,1,5,0,ok
T02,narrow,A01,narrow,16.42,16.04,16.04,-0.38,-2.34,1,5,0,ok
T03,narrow,A01,narrow,18.27,17.88,17.88,-0.39,-2.12,1,6,0,ok
T04,narrow,A01,narrow,20.12,19.73,19.73,-0.39,-1.92,1,5,0,ok
T05,narrow,A01,narrow,14.77,14.38,14.38,-0.39,-2.62,1,6,0,ok
T06,narrow,A01,narrow,16.62,16.23,16.23,-0.39,-2.32,1,5,0,ok
T07,narrow,A01,narrow,18.47,18.08,18.08,-0.39,-2.09,1,5,0,ok
T08,narrow,A01,narrow,20.32,19.93,19.93,-0.39,-1.9,1,6,0,ok
T09,narrow,A02,narrow,11.47,11.08,11.08,-0.39,-3.37,1,5,0,ok
T10,narrow,A02,narrow,13.32,12.93,12.93,-0.39,-2.9,1,5,0,ok
T11,narrow,A02,narrow,15.17,14.78,14.78,-0.39,-2.54,1,5,0,ok
T12,narrow,A02,narrow,17.02,16.63,16.63,-0.39,-2.26,1,5,0,ok
T13,narrow,A02,narrow,11.47,11.08,11.08,-0.39,-3.37,1,5,0,ok
T14,narrow,A02,narrow,13.32,12.93,12.93,-0.39,-2.9,1,5,0,ok
T15,narrow,A02,narrow,15.17,14.78,14.78,-0.39,-2.54,1,5,0,ok
T16,narrow,A02,narrow,17.02,16.63,16.63,-0.39,-2.26,1,5,0,ok
T17,robot,A02,normal,17.05,16.18,16.18,-0.87,-5.12,0,11,0,ok
T18,narrow,A03,narrow,8.17,7.78,7.78,-0.39,-4.74,1,6,0,ok
T19,narrow,A03,narrow,10.02,9.63,9.63,-0.39,-3.86,1,6,0,ok
T20,narrow,A03,narrow,11.87,11.48,11.48,-0.39,-3.25,1,5,0,ok
T21,narrow,A03,narrow,12.59,11.96,11.96,-0.63,-4.99,1,10,0,ok
T22,robot,A03,normal,12,11.43,11.43,-0.57,-4.73,0,7,0,ok
T23,narrow,A03,narrow,8.17,7.78,7.78,-0.39,-4.74,1,6,0,ok
T24,narrow,A03,narrow,10.02,9.63,9.63,-0.39,-3.86,1,6,0,ok
T25,narrow,A03,narrow,11.87,11.48,11.48,-0.39,-3.25,1,5,0,ok
T26,narrow,A03,narrow,12.59,11.96,11.96,-0.63,-4.99,1,10,0,ok
T27,robot,,normal,3.42,3.41,3.41,-0.01,-0.23,0,1,0,ok
T28,robot,,normal,3.78,3.72,3.72,-0.06,-1.72,0,2,0,ok
T29,robot,,normal,5,4.79,4.79,-0.21,-4.27,0,3,0,ok
T30,robot,,normal,6.85,6.43,6.43,-0.42,-6.08,0,3,0,ok
T31,robot,,normal,8.22,7.6,7.6,-0.62,-7.59,0,1,0,ok
T32,robot,,normal,6.37,5.99,5.99,-0.38,-5.91,0,1,0,ok
T33,robot,,normal,4.67,4.58,4.58,-0.09,-1.9,0,1,0,ok
T34,robot,,normal,3.81,3.76,3.76,-0.05,-1.25,0,1,0,ok
T35,robot,,normal,4,3.8,3.8,-0.2,-4.91,0,1,0,ok
T36,robot,,normal,4.62,4.29,4.29,-0.33,-7.12,0,3,0,ok
T37,robot,,normal,5.72,5.37,5.37,-0.35,-6.1,0,4,0,ok
T38,robot,,normal,6.82,6.47,6.47,-0.35,-5.16,0,4,0,ok
T39,robot,,normal,7.92,7.57,7.57,-0.35,-4.44,0,4,0,ok
T40,robot,,normal,9.02,8.67,8.67,-0.35,-3.92,0,4,0,ok
T41,robot,,normal,10.12,9.77,9.77,-0.35,-3.48,0,4,0,ok
T42,robot,,normal,5.43,5.38,5.38,-0.05,-0.93,0,3,0,ok

試算の値を Unity で読んで確かめた出力(20261022_sim_params_check.txt)

# 試算の値の読み込み(v5・回していない)
作った日時: 2026-10-22 19:40:30

## p1_efficient_corner と突き合わせ → 合っている
  店の形の版 (meta.generation): e624bdf4bdd4
サイトの試算の値(serving-robot-params.json)
  ファイル: serving-robot-params
  写した日時: 2026-10-22 19:26:39 JST
  写し元: https://pixelstomotors.com/sim/serving-robot-params.json
  試算の版 (meta.model): v2.4 / 店の形の版 (meta.layout_generation): e624bdf4bdd4
  条件: 6 件
    fam_p1_s4_r0_a42  スタッフ 4 / ロボット 0 / 42 組毎時 / serve / 1往復 1 卓 / 倒れやすい物 any
    fam_p1_s4_r1_a42  スタッフ 4 / ロボット 1 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p1_s4_r2_a42  スタッフ 4 / ロボット 2 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p5_s4_r0_a42  スタッフ 4 / ロボット 0 / 42 組毎時 / serve / 1往復 1 卓 / 倒れやすい物 any
    fam_p5_s4_r1_a42  スタッフ 4 / ロボット 1 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p5_s4_r2_a42  スタッフ 4 / ロボット 2 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
  Unity が読まない値 (unity_measures): robot_speed / pause_rate / pause_s / stuck_rate
  合わないもの: なし

## p5_crammed と突き合わせ → 合っている
  店の形の版 (meta.generation): e624bdf4bdd4
サイトの試算の値(serving-robot-params.json)
  ファイル: serving-robot-params
  写した日時: 2026-10-22 19:26:39 JST
  写し元: https://pixelstomotors.com/sim/serving-robot-params.json
  試算の版 (meta.model): v2.4 / 店の形の版 (meta.layout_generation): e624bdf4bdd4
  条件: 6 件
    fam_p1_s4_r0_a42  スタッフ 4 / ロボット 0 / 42 組毎時 / serve / 1往復 1 卓 / 倒れやすい物 any
    fam_p1_s4_r1_a42  スタッフ 4 / ロボット 1 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p1_s4_r2_a42  スタッフ 4 / ロボット 2 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p5_s4_r0_a42  スタッフ 4 / ロボット 0 / 42 組毎時 / serve / 1往復 1 卓 / 倒れやすい物 any
    fam_p5_s4_r1_a42  スタッフ 4 / ロボット 1 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
    fam_p5_s4_r2_a42  スタッフ 4 / ロボット 2 / 42 組毎時 / serve / 1往復 3 卓 / 倒れやすい物 any
  Unity が読まない値 (unity_measures): robot_speed / pause_rate / pause_s / stuck_rate
  合わないもの: なし

## Unity が使う値(role=site_rule)
  guide_s = 45
  pay_s = 90
  call_s = 30
  staff_place_s = 10
  robot_handoff_s = 25
  clear_s = 40
  wipe_s = 40
  load_s = 15
  guest_load_s = 20
  rescue_s = 15
  staff_speed = 1
  cold_min = 3
  dish_extra_m = 0
  max_extra_min = 600
  fragile_cook = 2 / 4 / 7

## 店ごとの値(stores)
  fam_p1: 卓 42 / peak_min 120 / 来客(真ん中)42 組毎時 / スタッフ(真ん中)4 人 / eat_min (20.00, 30.00, 45.00) / call_rate 0.6 / bus_trips 2 / fragile 0.5
  fam_p5: 卓 42 / peak_min 120 / 来客(真ん中)42 組毎時 / スタッフ(真ん中)4 人 / eat_min (20.00, 30.00, 45.00) / call_rate 0.6 / bus_trips 2 / fragile 0.5

## 出す数字の名前と意味(meta.metrics)
  entry_wait_mean: 入店待ち:店に来てから案内されて卓に着くまで(分)
  full_wait_mean: そのうち満席で待った時間(分)
  staff_wait_mean: そのうち席は空いているのに片付け・案内が追いつかず待った時間(分)。ng_min 以上なら「店が回らない」
  dish_wait_mean: 料理ができてから卓に届くまで(分)
  dish_wait_p90: 同じく上位10%の境目(分)
  cold_share: cold_min 分を超えて届いた皿の割合
  turn_mean: 客が帰ってから卓が使えるまで(分)
  walk_km_per_staff: スタッフ1人が歩いた距離(km)
  staff_util: スタッフの手がふさがっている割合
  robot_util: ロボットがふさがっている割合
  robot_share: ロボットが運んだ皿の割合
  rescues: 立ち往生でスタッフが動かしに行った回数
  pauses: 一時停止の回数
  groups: 入れた組の数

Claude Code への依頼文

v4:サイトの店の形(JSON)から店を建てる(claude_code_request_v4_json_store.md)

03_sec19.md3,280字・64行・markdown
# Claude Code への依頼:サイトの店の形(JSON)から店を建てる(v4・段階1)

設計書:同じフォルダの unity_design_v0.md(「0. 何について正か」を 2026-10-22 に足した)
回している途中にスクリプトを変えない。Assets/ServiceSim/ の中だけで作る。ServiceSim の外は変えない。

## 0. 何をするか

いまの店(StoreLayout_Family の帯の組み立て)は、Unity で形を作っている。これを、サイトの店の形の JSON を読んで建てる形に変える。
別のタブで開く保存

v5:回し方をサイトの試算にそろえる(claude_code_request_v5_align.md)

04_sec19.md3,037字・58行・markdown
# Claude Code への依頼:回し方をサイトの試算にそろえる(v5・段階2)

設計書:同じフォルダの unity_design_v0.md(0 章「何について正か」)
前の依頼:claude_code_request_v4_json_store.md(段階1。③⑦を JSON から建てた。cs:112)
回している途中にスクリプトを変えない。Assets/ServiceSim/ の中だけで作る。

## 0. 先にやること
別のタブで開く保存

v5b:ロボットの道順をサイトから受け取る(claude_code_request_v5b_routes.md)

# Claude Code への依頼:ロボットの道順をサイトから受け取る(v5b)

前の依頼:claude_code_request_v5_align.md(段階2)。報告 20261022_2010_narrow_aisle_fix.txt のあと。
回している途中にスクリプトを変えない。Assets/ServiceSim/ の中だけで作る。

## 0. 何があったか・どうするか(2026-10-22 エイイチと決めた)

⑦の確かめで、コストを使わず全区画で探しても 11 卓がつながらなかった(all_status が「途中まで」)。原因はコストではなく、**狭い通路の区画を NavMesh に書き込んだこと**(段階1の区画なしでは 42 卓すべてつながっていた)。止まる位置を 0.29〜0.69 m 寄せて「着いた」ことにした卓も 8 卓あった。

そこで、**Unity で道を決めるのをやめ、ロボットの道順はサイトが決めて渡す**。サイトの試算は卓ごとの道(ふだん走らせる 1.0 m の道、届かなければ 0.8 m の道)をもう持っているので、それを曲がり角の点の並びにして JSON に入れた。Unity のロボットはその点を順にたどる。人をよける・止まる・立ち往生は今までどおり Unity の中で起きる(それを測るのが Unity の役目)。

## 1. 読むもの

- `https://pixelstomotors.com/sim/layouts/unity/{名前}.json` と `summary.json`、`https://pixelstomotors.com/sim/serving-robot-params.json` を写し直す。版の番号は **9628954a582f**(3つともそろっていること)
- 新しく `routes` がある(作り方は JSON の `meta.rules`)
  - `routes.from_pass["T05"]`:受け渡し口の前 → T05 の止まる位置。`points`(曲がり角の点。最初が受け渡し口の前、最後が止まる位置そのもの)、`use`(normal=1.0 m の道 / narrow=0.8 m の道)、`length`
  - `routes.between["T05|T12"]`:T05 の止まる位置 → T12 の止まる位置。逆向き(T12 → T05)は点を逆にたどる
  - 卓 → 受け渡し口は `from_pass` を逆にたどる
  - ③⑦とも、受け渡し口から 42 本・卓から卓 861 本。つながらない道は無い。use はサイトの卓の分け方(category)と全卓で一致(サイトのテストで確かめた)

## 2. 直すこと

1. **v5 で足した狭い通路の区画(NavMeshBaker の AddNarrowAisleAreas・ModifierBox・avoidNarrowAisles・2段の道探し)を外す**。NavMesh は段階1と同じにする(レジの内側の区画はそのまま)
2. ロボットの走り方:行き先の卓が決まったら、`routes` の点を1つずつ行き先にしてたどる(受け渡し口 → 1卓目 → 2卓目 → 3卓目 → 受け渡し口)。最後の点は止まる位置そのもので、寄せない(寄せる半径は 0.1 m 以下)
   - 点と点の間は、サイト側でまっすぐ通れることを確かめてある(0.8〜1.0 m の幅の道の真ん中)。NavMesh の道探しは、次の点までの短い区間だけに使う
   - 人にふさがれたときの止まる・待つ・よける・立ち往生は今のまま。道を引き直すとき(replanAfterStoppedSec)は、**次の点までの区間だけ**引き直す。全体の道順は変えない
   - 待機場所 ↔ 受け渡し口の前は、今までどおり Unity の道でよい(短いため)
3. 確かめ(JSON Store のメニュー)も同じにする
   - 卓ごとに、道順の長さ(点を結んだ長さ)・JSON の dist・Unity で点から点を NavMesh でつないだ長さ・`use` を CSV に出す
   - 点から点の区間が NavMesh で完全につながるか(つながらない区間の一覧)。区間の NavMesh の道のりが、まっすぐの長さの 1.05 倍を超える区間の一覧(店の形と NavMesh が合っていない印)
   - via_narrow は `use == "narrow"` の卓(⑦で 24 卓・③で 0 卓になるはず)
4. v5 の 3章(条件・始め方・立ち往生でスタッフを呼ぶ・逃がし弁の記録・出す数字・往復ごとの4つの値)は、このあとそのまま続ける

## 3. お願い(Unity で押してもらう)

③⑦ を続けて確かめる。見るのは、42 卓すべての区間がつながること、1.05 倍を超える区間がないこと、via_narrow が⑦ 24 卓・③ 0 卓。
通ったら VCS Check-in して、v5 の 3章に進む。

Claude Code の報告(claude_code_reports/)

20261022_1830_json_store_v4.txt

05_20261022_1830_json_store_v4.txt6,612字・160行・text
v4(段階1)サイトの店の形の JSON から店を建てる — コードを書き終えました。Unity は押していません。

依頼:unity/claude_code_request_v4_json_store.md
設計:unity/unity_design_v0.md の 0 章「何について正か」(店の形はサイトが正。Unity は形を作らない)

────────────────────────────────────────────────────────
1. 作ったもの(Assets/ServiceSim/ の中だけ。外は触っていません)
────────────────────────────────────────────────────────
別のタブで開く保存

20261022_1900_json_store_v4_regen.txt

v4(段階1)版 e624bdf4bdd4 を写し直して、walkable / staff_only を入れました。
建てるところで止まっています(Unity Editor が開いたままで、こちらから動かせません)。

────────────────────────────────────────────────────────
1. 写し直し(依頼 1)
────────────────────────────────────────────────────────

写した日時:2026-10-22 18:51:26 JST
別のタブで開く保存

20261022_1920_json_store_v4_result.txt

v4(段階1)③⑦の結果を読みました。確かめはすべて通っています。VCS Check-in しました(cs:112)。

読んだもの(screens/)
  20261022_p1_efficient_corner_json_check.txt / _table_dist.csv
  20261022_p5_crammed_json_check.txt / _table_dist.csv
  20261022_family_v0_store_report.txt(③のもの。下の「気づいたこと 2」)
  20261022_family_v0_top_w120_people.png(③)/ _top_w080.png(⑦)
別のタブで開く保存

20261022_1935_align_v5_step0_1_2.txt

v5(段階2)0 章と、1 章の狭い通路・2 章の値の読み込みまで入れました。
3 章(回し方そのもの)はこれからです。Unity は押していません(Editor が開いたままのため)。

────────────────────────────────────────────────────────
0. 先にやること(両方おわり)
────────────────────────────────────────────────────────

(1) 10/21 までの変更を、今回の作業と分けて Check-in しました
別のタブで開く保存

20261022_2010_narrow_aisle_fix.txt

⑦で 21 卓が「経路がつながらない」になった件。原因しらべと、コストをやめて手順に直した分です。
Unity は押していません(Editor が開いたままのため)。

────────────────────────────────────────────────────────
1. 原因しらべ(私の側でできたところまで)
────────────────────────────────────────────────────────

(1) 区画の箱の位置は、通路の区画どおりでした ← 原因ではない
別のタブで開く保存

20261022_2040_routes_v5b.txt

10_20261022_2040_routes_v5b.txt4,948字・127行・text
v5b(ロボットの道順をサイトから受け取る)を入れました。Unity は押していません(Editor が開いたまま)。

────────────────────────────────────────────────────────
1. 写し直し
────────────────────────────────────────────────────────

写した日時:2026-10-22 20:23:50 JST
版の番号:**9628954a582f**(③・⑦・summary.json・serving-robot-params.json の 4 つとも同じ)
別のタブで開く保存

20261022_2055_navmesh_clear.txt

⑦が通った件、ありがとうございます。ご指示の 1・2 を入れました。押していただく前の報告です。

────────────────────────────────────────────────────────
1. 焼く前に、入っている NavMesh を全部外す
────────────────────────────────────────────────────────

原因(エイイチのご指摘):スクリプトの読み込み直し(ドメインリロード)をまたぐと、
前に焼いた NavMesh がシステムに残ったままになる。baker の _instance / _peopleInstance は
読み込み直しで空になるので、Remove() では外せない。
⑦でつながらなかったのは、v5 の「狭い通路の区画」入りの面が残っていたためでした。

直した場所は 2 か所です。

  Bake()
    NavMesh.RemoveAllNavMeshData();   ← 足した
    Remove();                          ← これまでどおり(この baker の分を片付ける)
    …ロボット用を焼く
    BakePeople(...)                    ← **人用はこのあと焼き直す**(元のまま)

  TriangulateFor(agentRadius)
    これまで:自分の 2 つの instance だけ外す → 一時の面を焼いて三角形を読む → 元に戻す
    これから:**NavMesh.RemoveAllNavMeshData()** で全部外す → 一時の面を焼いて読む →
              元に戻す(_data / _peopleData の参照は持っているので、そのまま AddNavMeshData で戻す)

  どちらも、焼き直しのたびに「入っている面はこの baker が今つくったものだけ」になります。
  塗り分け(FloorPaint)と「焼いた NavMesh のしらべ」も TriangulateFor を通るので、
  残った面が混ざった三角形を読むことはなくなります。

────────────────────────────────────────────────────────
2. hardToPass の印を外した
────────────────────────────────────────────────────────

  StorePlan.PlanAisle.hardToPass     削除
  StoreBuilder.AisleInfo.hardToPass  削除
  JsonStoreLayout                    normal_width と比べて印を付ける処理を削除。
                                     報告の「狭い通路 N 本」の行も消し、
                                     代わりに道順の本数を出すようにしました

  報告に出る行(JSON から建てた店…の節)
    道順 (routes): 受け渡し口から 42 本 / 卓から卓 861 本
    (狭い道を使うかは routes の use が正。Unity では印を持たない)

  これで「狭いかどうか」を持っているのは、サイトの routes の use だけになりました。
  Unity 側(NavMesh・通路の区画・ロボットの設定)には、狭い道の概念がありません。

────────────────────────────────────────────────────────
3. お願い
────────────────────────────────────────────────────────

  **ServiceSim/JSON Store/③⑦ を続けて確かめる** を、もう一度押してください。

  前回と同じ 3 点が出れば通りです(前回は焼き直しの前の面が混ざっていた可能性があるので、
  今回はきれいな状態での確かめになります)。

    1. 42 卓すべての区間がつながる(つながらない区間 0)
    2. まっすぐの 1.05 倍を超える区間 0
    3. via_narrow が ⑦ 24 卓・③ 0 卓

  通ったら、こちらで VCS Check-in して(v5 の 0 章の直し 2 つ・v5b の道順・今回の 2 つを
  まとめて入れます)、v5 の 3 章に進みます。

  今回触ったファイル
    Store/NavMeshBaker.cs   Bake() と TriangulateFor() で RemoveAllNavMeshData
    Store/StorePlan.cs      PlanAisle.hardToPass 削除
    Store/StoreBuilder.cs   AisleInfo.hardToPass 削除
    Store/JsonStoreLayout.cs 印を付ける処理と報告の行を削除(道順の本数に差し替え)

20261022_2140_align_v5_step3.txt

11_20261022_2140_align_v5_step3.txt11,885字・286行・text
cs:114 で Check-in しました(v5b の道順・v5 の0章の直し2つ・NavMesh の焼き直し・hardToPass 削除)。
そのあと v5 の 3 章(回し方をサイトにそろえる)を入れました。Unity は押していません(Editor が開いたまま)。

────────────────────────────────────────────────────────
0. cs:114 の中身(21 項目)
────────────────────────────────────────────────────────

  新規  Store/RouteBook.cs(+.meta)
別のタブで開く保存

codex の検証

2回目の検証の結果(review_result_v3.md・codex が書いたもの)

12_sec21.md8,207字・166行・markdown
# 第3版・敵対的検証結果

2026-10-22再検証(初回2026-10-21)。対象は指定フォルダの依頼書、README、生成・解析・テストコード、6配置のJSON/analysis/summaryと図。行番号は今回の原本。添付の前回レビューや「対応済み」の説明は証拠として信用せず、コードと反例で確認した。

**総合:❌ 現状のまま「客が受け取れる卓の割合」を試算する材料として採用するのは不可。** 数値は再現できるが、L字席の受取側、⓪の駐機寸法、検査のすり抜けが残る。静的な幾何モデルの開発用データとしては利用可能。

依頼で対象外とされた厨房内部の人の動き、すれ違い・複数台運用・旋回、一時的な狭まり、壁高、サイトとUnityの共通スキーマは今回の不合格理由に含めない。
別のタブで開く保存

3回目の依頼文(codex_review_request_v4.md)

# 敵対的検証の依頼(3回目):ファミレスの店の形 第3版

前回の検証結果(`review_result_v3.md`)を受けて直しました。前回と同じく、反例を探す立場で見てください。
決まりと計算の約束は `tools/sim_layouts/README.md` にまとめています(2026-10-22 の節が今回の変更)。

再現:`cd tools/sim_layouts && python3 test_famires_v3.py && python3 famires_v3.py`(出力は `public/sim/layouts/`。依存の版は README)

店の呼び方:ファイル名の p0〜p5 で書いてください。前回の結果の ⓪〜⑤ は p0〜p5 と同じです(サイトの画面では ②〜⑦ と表示しています)。

## 前回の指摘への対応

| 指摘 | 対応 |
|---|---|
| [P1] L字席でソファ側への停止を「届く」とする | L字席で止まってよい辺を、テーブルのある内側の角の開いた2辺と、そこからソファの端に沿って0.6m(端の席の人が受け取れる所)までに限った(`lsofa_sides`。flip・mirror の4通りをテストで確かめる)。p0 T02 は角の正面(右の辺の開いた部分)に止まるようになった |
| t2 の全4辺 | 椅子の側とテーブルの横だけにした。ベンチの側・ベンチの横は使わない(`t2_sides`) |
| [P1] p0 の待機場所 2.2×0.7m | 2.4×0.8m(3台)にした。1台分0.8×0.8m以上・台数が正の整数かを確かめる。1台ずつ、その台の区画だけを障害物から外し、ほかの台が止まったままで出発点までつながるかを確かめる(つながりは上下左右)。前だけふさぐと真ん中の台だけ、前と両横をふさぐと3台とも見つかることをテストで確かめる |
| 検査をすり抜ける7つの配置 | 7つとも違反として見つかることをテストで確かめる。レジとレジ内の有無と接していること/トイレの4辺がすきまなく囲まれていること(外壁・裏の部屋・建物の外・厚さ30cm以上の壁・入口のどれか)/入口の前は名前で免除しない・入口そのものを壁がふさがない/仕切りの接合はボックスのベンチの背の辺で深さ8cm以内だけ/台数/輪郭と建物の外の一致(5cmのマス目で照合)・輪郭の外に壁・待機場所・受け渡し口・出発点を置かない |
| [P2] トイレ遮蔽が中心の1本 | 入口の情報とトイレを「接しているか」で対応させ、トイレ1つに入口1つ。席のトイレ側の辺の両端から、入口(入口の前の矩形とトイレの境目の線分)の両端へ引いた4本の線が、全部壁(接合でない壁)に当たることにした |
| [P2] 1cmサンプリングが薄い壁を見逃す | 線と矩形の交わりを計算で求める(`seg_rect_hit`)。見通し(`sight`)も同じ |
| [P2] best_stop が201番目以降を捨てる | 打ち切りをなくした。201番目だけ見通せる偽のマス目でテストする |
| [P2] NG 時も過去の出力が残る | いったん作業用のフォルダに出し、6つ全部が通ったときだけ出力先へ入れ替える。違反があれば出力先には何も書かない(前の版の一式がそのまま残る)。決まりに違反があれば重い計算に進まない。layout・analysis・summary に同じ版の番号(`generation`)を入れる |
| ⚠️ 2解像度は分類一致だけ | 図の文言を「卓の分け方が同じ」に改め、README に「距離や止まる位置が同じとは限らない」「narrowest が 0.97m のように 1.0m をわずかに下回ることがある」と書いた |

## エイイチの指摘で直したこと(p0 の店の形)

- パントリーの上の通路に出入りできなかったので、出入り口を2つ開けた。A=パントリーの壁に1m(客席側のトイレへの通路とつながる)、B=パントリーの上の端。どちらも扉はない。扉は上の通路から洗い場とキッチンへ入る所(位置は仮)。JSON の `layout.doors`(`door` が扉の有無)
- 仕切り壁の上の4人席2つ(T07・T08)を、壁との間1.0mから0.6mに寄せた(ロボットが壁側から入っていたため)

数字が変わったのは p0 だけです(T01・T02・T03・T05・T06・T07・T08・T18 の距離。平均8.5→8.6m、最長14.01→13.78m)。p1〜p5 は卓・距離・止まる位置が前と同じです。

## まだ対応していないこと(今回の検証の対象外)

厨房の中の人の動き、すれ違い・複数台・旋回、通路の一時的な狭まり、壁の高さ(仮の値)、サイトと Unity の共通のデータの形、p0 の一般卓(t4・r4・long6)の椅子と着席位置(前回の ⚠️。次の段階で扱う)、公表通過幅を円の半径として使う仮定と機種の一次資料(前回の ⚠️)、human_walk の意味(全配置で0のため)。

## 見てほしいこと

1. 上の対応で、前回の指摘が本当に直っているか。直ったように見えて別の抜けが出ていないか
2. 新しく足した確かめ(トイレの囲み・4本の線・輪郭・接合・待機場所の発車・出力の入れ替え)を、すり抜ける置き方を作れるか
3. L字席の「開いた2辺+ソファの端0.6m」と、2人席の「椅子の側とテーブルの横」の決め方に、止まれるが客が受け取れない反例があるか
4. 6つの数字(`public/sim/layouts/summary.json`)が、決まりと計算の約束から見て正しいか
5. p0 の出入り口 A・B と、寄せた4人席で、決まりやロボットの計算に抜けがないか

結果の書き方は前回と同じ(✅/⚠️/❌、最後に「試算の材料に使ってよいか」)。結果は `review_result_v4.md` に書いてください。

コード全量

サイト側(GitHub PixelstoMotors/p2m-site、commit 298de98 の時点)と試算 v2.5 のコードです。

tools/sim_layouts/famires_v3.py

13_tools_sim_layouts_famires_v3.py.txt46,705字・1,068行・python
"""ファミレスの店の形 第3版:決まりの確かめ方とロボットの届き方を作り直した版。

codex の敵対的検証(review_result.md)を受けて直したこと
- ロボットの通れる幅は機種の公表値(初期値 BellaBot 80cm)。本体の幅とは別に扱う
- 「ふだん走らせる幅」(初期値 1.0m)を別に持ち、卓を3つに分ける
    ロボットが届く卓/狭い道なら届く卓/人が運ぶ卓(ロボットから受け取って人が運ぶ)
- 届くかは、卓の「座る側(開いた側)」の前で止まれるかで判定する。背中側・壁側・仕切り越しは数えない
- 幅の判定は、マス目の中心から障害物までの距離で行い、2つの細かさで同じ結果になるかを毎回確かめる
別のタブで開く保存

tools/sim_layouts/famires_p0.py

"""記憶の店(昔働いていたファミレスを記憶から起こした店・layout_v11)を、5パターンと同じ決まりに合わせた版。

layout_v11.json(記憶のまま)は変えずに残し、ここで直した版を作る。
直したこと(2026-10-21 エイイチと決めたこと)
- 建物の形:客席の奥の壁はそのまま。トイレ・パントリーの出入り口・洗い場・物置の並びが、その外へ約2.2m出っ張る
- 空いた所は厨房が広がる(キッチンと冷蔵庫を奥へ延ばし、出っ張りとの間に裏の通路)
- トイレへは、パントリーの壁ぞいの通路を奥へ進んで入る。元のトイレの場所は通路。トイレの手前に短い仕切り壁(約2.6m)
- トイレの客席側(通路側)に厚い壁(30cm)、入口は下向き(通路の突き当たり)
別のタブで開く保存

tools/sim_layouts/unity_export.py

15_tools_sim_layouts_unity_export.py.txt24,289字・517行・python
"""Unity が店を建てるための細かい形を、店の形(layout)と解析(analysis)から決まった規則で作る。

2026-10-22 エイイチと決めた「何について正か」による(README)。Unity は店の形を自分で作らず、ここで書き出したものを読む。
サイトの試算(haizen_sim.py)はこれを使わない。数字(卓の数・卓までの距離・止まる位置)は analysis と同じものをそのまま渡す。

書き出すもの(public/sim/layouts/unity/{名前}.json)
- outer_walls:外壁(入口を空けた矩形の並び。外形の外側に壁の厚みぶん)
- floor:床を敷く矩形(建物の外を除く)
別のタブで開く保存

tools/sim_layouts/test_famires_v3.py

"""famires_v3 の確かめ(codex の反例を含む)。使い方: python3 test_famires_v3.py"""
import copy
import famires_v3 as v
import famires_gen2 as gen

ok = True

別のタブで開く保存

tools/sim_layouts/README.md

17_tools_sim_layouts_README.md5,853字・112行・markdown
# ファミレスの店の形(サービスロボット導入シミュレーション・配膳ロボットの試算用)

このフォルダの店の形が、サイトの試算と Unity の共通の元になる。Unity は `public/sim/layouts/` の JSON を読んで店を建てる。直すときは、ここ(サイト側)を先に直す。

## 何について正か(2026-10-22 エイイチと決めた)

| 何について | 正 | 扱い |
|---|---|---|
別のタブで開く保存

simulation/v2_5/export_params.py

"""試算(haizen_sim.py)の条件と店の回し方の値を、Unity が読む JSON に書き出す(2026-10-22)。

「何について正か」(unity_design_v0.md の 0 章)で、条件と店の回し方の決まり・時間・数字の定義はサイトが正。
Unity はこの JSON を読み、値を手で写さない(LOG359 のずれ9「値の手写し」をなくすため)。

使い方: python3 export_params.py results.json <出力先>   (出力先は p2m-site の public/sim/serving-robot-params.json)
- common:店に共通の値。role が "unity_measures" の値は Unity で測ってサイトに戻すための仮の値なので、Unity は読まない
- stores:Unity で回す店(fam_p1・fam_p5)の値
別のタブで開く保存

simulation/v2_5/build_page_v25.py

"""試算の結果(results.json)から、公開用の試算ページ(serving-robot.html)を作る(v2.5)。

使い方: python3 build_page_v25.py results.json page_v25.template.html <出力先>
  v2.5:試算のモデルは v2.4 のまま、店の形(layouts/)を直した版に入れ替え、② 定番の郊外型だけ回し直した。
  店の形の版(generation)がそろっているか、試算に使った卓までの距離が店の形の距離と同じかを確かめてから作る。
  results.json は haizen_sim.py(v2.4)を総当たりで回した結果。v2.4 で入店待ちの終わりを卓に着いたときにし、
  「下げ膳にも使う」でロボットがスタッフと一緒に卓へ向かい、載せ終えるまで待つ形に直した。
  v2.3 で足したのは、標準ファミレスの中の「図面のある店」(fam_p0〜fam_p5)と、その平面図(D.plans)。
別のタブで開く保存

simulation/v2_5/README.md

# 配膳ロボットの試算 v2.5(2026-10-22)

試算のモデルは v2.4 のまま(`haizen_sim.py` は v2.4 と同じ。COMMON の `model` も "v2.4")。
店の形(`layouts/`)を、codex の2回目・3回目の検証とエイイチの指摘で直した版に入れ替え、② 定番の郊外型(fam_p0)だけ回し直した版。

## 店の形で変わったこと(正は p2m-site の `public/sim/layouts/`。版の番号 generation = 78359abbe188 → 9628954a582f)

- L字席で止まってよい所を、テーブルのある内側の角の開いた2辺と、そこからソファの端に沿って0.6mまでにした
- 2人席で止まってよい所を、椅子の側とテーブルの横にした(ベンチの側・横は使わない)
- ② の待機場所を2.2×0.7mから2.4×0.8m(3台)に広げた
- ② のパントリーの上の通路に出入り口を2つ開けた(A=パントリーの壁に1m、B=パントリーの上の端。どちらも扉なし)。扉は洗い場とキッチンの入口
- ② の仕切り壁の上の4人席2つを、壁との間0.6mまで寄せた(ロボットが壁側から入らないように)

同じ日の夕方、店の形の書き出しに Unity 用の細かい形(`unity/`)を足して直したため、版の番号が b700048057af → e624bdf4bdd4 → 9628954a582f(ロボットの道順を足した)に変わった。卓・距離・止まる位置は同じなので、試算は回し直さず、ページだけ作り直した(`layouts/` もこの版の写し)。これからも、数字が同じまま版の番号だけ変わったときは、ページだけ作り直す(いまの版は summary.json とページの `layout_generation` で見る)。

距離が変わったのは ② だけ(T01・T02・T03・T05・T06・T07・T08・T18。卓までの平均 8.49m → 8.56m、最長 14.01m → 13.78m)。③〜⑦は卓・距離・止まる位置が前と同じ。

## v2.4 と比べた結果(compare_v24_v25.txt)

- 16,425条件の並びは同じ。② 以外の15,111条件は、数字がすべて v2.4 と同じ(前の結果をそのまま使った)
- ② の1,314条件は、卓までの距離が変わったので全部回し直した(乱数の出方も変わる)。入店待ちの差は平均 −0.09分(−4.3〜+3.9分)
- 店が回らないの数は、② が124 → 124、全体が3,007 → 3,007 で変わらない

## ファイル

- `haizen_sim.py`:試算のモデル(v2.4 と同じ)
- `results.json`:総当たりの結果(16,425条件×40回)
- `layouts/`:店の形と解析結果と summary(p2m-site の public/sim/layouts/ の写し)
- `build_page_v25.py`:`python3 build_page_v25.py results.json page_v25.template.html serving-robot.html`。店の形の版(generation)がそろっているか、試算に使った卓までの距離がいまの店の形と同じかを確かめてから作る(違えば止まる)
- `page_v25.template.html`:v2.4 から、見出しの「試作 v2.4」を「試作 v2.5」にしただけ
- `test_page_v25.js`:`node test_page_v25.js serving-robot.v25.html`(全部の組み合わせを描いて例外がないか確かめる)
- `serving-robot.v25.html`:作ったページ(p2m-site の `public/sim/serving-robot.html` に入れた)
- `compare_v24_v25.txt`:v2.4 と比べた結果
- `export_params.py`:`python3 export_params.py results.json serving-robot-params.json`。条件と店の回し方の値、Unity で回す6条件と同じ条件の試算の結果を、Unity が読む JSON に書き出す(p2m-site の `public/sim/serving-robot-params.json` に入れた)。Unity で測る値(robot_speed・pause_rate・pause_s・stuck_rate)は role が unity_measures で、Unity は読まない

v2_4/・v2_3/ は前の版。公開済みの記事(LOG359・LOG360 など)の数字は前の版のまま(LOG は直さない)。

Unity 側(Claude Code が書いたもの。Unity Version Control cs:116 の時点。SimParams.cs と ServingRobotController.cs には、まだ回していない v5 の3章の変更も入っている)

Assets/ServiceSim/Store/JsonStoreLayout.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEngine;

namespace ServiceSim
{
別のタブで開く保存

Assets/ServiceSim/Store/RouteBook.cs

using System.Collections.Generic;
using UnityEngine;

namespace ServiceSim
{
    /// <summary>
    /// ロボットの道順(v5b)。サイトが決めた曲がり角の点の並びを持つ。
    ///
別のタブで開く保存

Assets/ServiceSim/Store/NavMeshBaker.cs

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

namespace ServiceSim
{
    /// <summary>
    /// 店の形から NavMesh を焼く。com.unity.ai.navigation を入れずに、
別のタブで開く保存

Assets/ServiceSim/Store/SimpleJson.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace ServiceSim
{
    /// <summary>
別のタブで開く保存

Assets/ServiceSim/Editor/ServiceSimJsonStore.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
別のタブで開く保存

Assets/ServiceSim/Experiment/SimParams.cs

using System.Collections.Generic;
using UnityEngine;

namespace ServiceSim
{
    /// <summary>
    /// サイトの試算の値(serving-robot-params.json)を読む .asset。
    ///
別のタブで開く保存

Assets/ServiceSim/Robot/ServingRobotController.cs

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

namespace ServiceSim
{
    /// <summary>
別のタブで開く保存