サービスロボット導入シミュレーション Log#12 | ロボットに地図を渡したら、詰まりが減った
配膳ロボットを2台入れたファミレスを Unity(建物や人を3Dで置いて動かせるソフト)の中で動かすと、2台が通路で向かい合ったまま止まる場面が何度も出ていました。原因は、ロボットに1本の線の上しか走らせない作りでした。そこで、実際の配膳ロボットと同じように、ロボットに店の地図を渡し、行き先までの道を自分で引かせ、前がふさがったら回り込ませる形に変えると、60秒以上止まった回数は57回から20回に減りました。 料理ができてから卓に届くまでの待ちも、2.90分から1.17分になり、サイトの試算の1.01分に近づきました。
この Unity の店は、サイトに置いている配膳ロボットの試算( https://pixelstomotors.com/series8 )と比べるために作っています。試算は、ロボットや人を点として動かす計算です。Unity は、同じ店の形・同じ人数・同じ客の数を、床・卓・人の体がある3Dの店で動かします。試算では見えない「通路で起きること」(すれ違い・立ち止まり・詰まり)を Unity で測り、試算の仮の値を本物に近づけるのが目的です。
道の引き方を変えたあと、3Dの画面を見てもう1つ分かったことがあります。右下の2人席の前の通路は、ドリンクバーと6人席の間が0.4mしかなく、ロボットにとって行き止まりでした。入った道を戻るしかないので、行きのロボットと帰りのロボットがそこで出会います。残った詰まりの7割がこの場所に集まっていました。ドリンクバーを上へ0.5m・左へ0.8m動かして抜け道を作ると、ここでの詰まりはなくなりました。
| やったこと | なぜ | 結果 |
|---|---|---|
サイトから、店の床を2.5cmのマス目に分けた地図を書き出した | ロボットが自分で道を引くには、走れる範囲が要るため | 地図だけで、試算と同じ「狭い道でしか行けない卓」の分け方になる |
Unity のロボットが、地図の上で道を自分で引き、ふさがったら3秒で回り込む形にした | 実際の配膳ロボットはそう動くため | 60秒の止まり 57回 → 59回(行き止まりに集中) |
ドリンクバーを動かして、右下の行き止まりをなくした | 3Dの画面で、行き止まりの通路で2台が出会っていたため | 60秒の止まり 59回 → 20回、ロボットが運んだ皿 76% → 99% |
試算 v2.7(料理はロボット優先)を、店の形の直しと一緒に公開した | 店の形が変わったら、その店の試算も計算し直す決まりのため | ③⑦だけ計算し直し。差は小さい |
2つの店 × ロボット0・1・2台 × 3回の18回を回し直した | 1回だけでは偶然と区別できないため | ロボットがいる回は大きく良くなった。入店待ちのずれは残った |
一方で、残ったずれもあります。客が店に来てから席に着くまでの待ち(入店待ち)は、試算ではロボットを入れるほど短くなりますが、Unity ではロボットの台数で変わりませんでした。ロボット0台でもスタッフの手が足りていて、試算より人の仕事が軽く見えます。これはロボットではなく、人の動かし方の側のずれです。
下の図で、同じ条件で回した3回(線に縛っていた版・地図で道を引く版・ドリンクバーを動かした版)と、18回の条件ごとの数字を切り替えて見られます。
作業ログ ― この記事で扱う範囲と、Unity・店の形・試算の版
前の記事(LOG370)で、ロボットどうしの詰まりの根本は、ロボットを決まった線の上しか走らせない作りだと分かりました。この記事は、その動き方を変えるところから、18回を回し直して基準のデータとして区切るところまでです。
| もの | 始め | 終わり |
|---|---|---|
Unity のコード(Unity Version Control) | cs:141 | cs:143(v9 の本体が cs:142、NavMesh の種類の掃除が cs:143) |
店の形(p2m-site の public/sim/layouts/) | 82023936eb99 | 2fa10547a2b7(地図を足しただけ)→ 8a5b2f6a016a(ドリンクバーを動かした) |
試算(serving-robot.html) | v2.6 を公開・v2.7 は作業用の枝 | v2.7 を公開(③⑦だけ新しい店の形で計算し直し) |
| Unity で回した回 | v8b の確かめ(1004) | ③2台・種0 を2回(1304・1559)+段階Bの18回(cs:143) |
効果の数字は、どれも回した記録から数えた値です。見込みのところは、見込みと書きます。
動き方を変える前に決めた3つ
動き方を変える依頼を Claude Code(Unity のコードを書く AI)に出す前に、決めておく必要があることが3つありました。どれも、実際のファミレスと配膳ロボットの動きに照らして決めました。
| 決めること | 選んだ案 | 理由 |
|---|---|---|
ロボットどうしが出会ったとき、どちらが先に行くか | 料理を載せているロボットが先に行き、空で戻るロボットがよける。同じ状態なら1号機が先 | 料理を待っている客がいる方を優先する |
前がふさがってから、回り込む道を探し始めるまで | 3秒 | 人は数秒でよけることが多い。すぐ回り込むと、人がよけたあとも遠回りする |
| 通路のどこを走るか | 真ん中寄り(壁や卓のそばを道探しで重くする) | 実機は通路のぎりぎりを通らない、という見立てに合わせる |
前の版では、サイトが渡す道の線が、通れる範囲の中の最短の線でした。最短の線は通路の端に寄った1本になるので、行きと帰りが同じ線を走ります。真ん中寄りを走らせるのは、この重なりを避けるためでもあります。
サイト:ロボットが道を引くための地図を書き出した(版 2fa10547a2b7)
店の形はサイトが正、という決まりがあります。Unity は、サイトが書き出したデータを読んで店を建てています。Unity の中で走れる範囲を勝手に作ると、サイトと Unity で「走れる所」の決め方が別々になります。そこで、サイトの試算が卓までの距離を測るときに使っている2.5cmのマス目を、そのまま地図として書き出しました。
| 項目 | 中身 |
|---|---|
| ファイル | public/sim/layouts/unity/{店の名前}_map.json(6店) |
| free_class | マスごとに 2=ふだん走らせる幅(1.0m)の道が通れる/1=通れる幅(0.8m)の道だけ通れる/0=通れない |
| clear_mm | マスの中心から、いちばん近い障害物(壁・部屋・卓・会計の列)までの距離(mm) |
| 待機場所 | 床として入れる。止まっているロボットは、Unity の中で動くものとして扱う |
| 大きさ | ③は 960×640=614,400マス。gzip で縮めて base64 にし、1店40〜100KB |
確かめに、地図だけを使って「受け渡し口からふだんの道で行ける卓」と「狭い道でしか行けない卓」を数え、試算の分け方と同じになることをテストに足しました(③は全42卓がふだんの道、⑦は24卓が狭い道)。確かめは135件すべて通りました。店の形・試算の数字は変わらず、変わったのは版の番号だけです。
1つだけ、確かめを書き直しました。ロボットの待機場所は、真ん中が壁から0.45mの位置にあります。ふだんの道(1.0m)の真ん中は壁から0.5m以上離れている必要があるので、待機場所は「狭い道(1)」のマスになります。実際の配膳ロボットも壁に寄せて止めるので、確かめを「狭い道で行ければよい」に直しました。
v9:ロボットが地図の上で自分で道を引く(cs:142)
依頼文(claude_code_request_v9_map_planner.md)は、後ろに全文を載せます。中身は次のとおりです。
| 前(cs:141) | v9(cs:142) | |
|---|---|---|
| 道 | サイトの道の線の点を順にたどる(点と点の間は NavMesh) | サイトの地図の上で、行き先までの道をその都度自分で引く(NavMesh は使わない) |
| ふだんの道と狭い道 | 線で決まっている | 行き先まで2のマスだけで行けるなら2だけ、行けなければ1のマスを3倍重くして使う |
| 人やロボットに出会ったら | 止まって待つ。10秒ごとに同じ線を引き直す | 止まる → 3秒空かなければ、近く3mの人とロボットを通れないマスとして置いて回り込む道を引く |
| ロボットどうし | 番号の小さい台が先。横へどく点を探す | 料理を載せている方が先。低い方は相手の先の道(4m分)を重くして道を引き、引けなければ2.5m以内の離れたマスへ動いて待つ(最大20秒) |
線のために足した決まり(戻りの線・横へどく・角の箱) | 使う | 新しい動き方では使わない。pathMode=SiteRoutes で前の動き方に戻せる |
| 記録 | — | 引き直した回数・回り込んだ回数・よけた回数・延びた距離・道探しの時間などを足した |
変えなかったものも決めてあります。ロボットの速さ・加速・前のセンサー・卓での25秒・60秒で立ち往生・600秒で打ち切り・人のよけ方(ロボット>スタッフ>客)・料理はロボット優先、はそのままです。
人のいない店で道を引く確かめ(確かめ A)
Claude Code は、Unity がプロジェクトを開いたままでも、同じコードを Unity の外で組み立てて、受け渡し口から全卓への道を引きました。
| ③ 効率重視・入口が角 | ⑦ ③の通路を95cmに | |
|---|---|---|
| 狭い道を使った卓(サイト) | 0卓(0卓) | 24卓(24卓) |
| 道が引けない卓 | 0 / 42 | 0 / 42 |
道の長さ ÷ サイトの道の長さ(最小 / 平均 / 最大) | 0.959 / 1.019 / 1.057 | 0.959 / 1.037 / 1.227 |
1回の道探しの時間(平均 / 中央 / 最大) | 13.2 / 11.2 / 35.5 ms | 30.3 / 22.6 / 79.4 ms |
真ん中寄りにした分、道は平均で2〜4%延びます。サイトより短い卓が出るのは2つの理由です。T34・T35・T28 の1〜4cmは、道の端をマス目の真ん中にそろえた誤差です。T42 の22cmは、地図で待機場所を床にしたためで、サイトの道の線は待機場所を障害物として下へよけていました。
Claude Code が決めて、報告で知らせてきたこと
依頼に決まりがなかった所を、Claude Code が決めて報告に書いてきました。どれも今の状態のまま回しています。
| 項目 | いまの決め方 | 決め直すかどうか |
|---|---|---|
ロボットが、地図では通れないマスに立っているとき | 1.0m以内のいちばん近い通れるマスへ、出発点だけ寄せて道を引く | 前の版で60秒止まった51回のうち36回は、NavMesh には乗るが地図では通れない所だった。寄せた回数は記録に出る |
受け渡し口と客席の間の角の箱(止まった所が角の中かを数えるだけ) | 新しい動き方では数えない | 前の版の「止まった時間の3分の1がこの角」と並べられなくなる |
何もしていないロボットが待機場所へ動く処理 | 手を入れていない | 行き先を渡しているだけで、実際には動いていない疑い(あとで効いてくる) |
1回目(ドリンクバーを動かす前):詰まりは減らず、右下の行き止まりに集まった
③・ロボット2台・種0 を回すと、最後まで回り切り、来た組も前と同じ64組でした。ロボットが運んだ皿は64%から76%に、料理の待ちは2.90分から2.12分になりました。ところが、60秒の止まりは57回から59回で、減っていません。場所を見ると、59回のうち43回が右下の2人席の前の通路(x 17〜20m・z 2m)に集まっていました。
回している画面を見て、すぐに理由が分かりました。
前より全然いいね。ただドリンクバーの位置を上に上げて、少し左寄せにして、右側のブースの回遊性を作らないと詰まるね

ドリンクバーの右端(x 20.8m)と6人席(x 21.2m)の間は0.4mで、ロボットは通れません。右下の8つの2人席へは、左から入って左へ戻るしかありませんでした。道の引き方を変えても、道が1本しかない所では、正面から出会うのは変わりません。
もう1つ、1往復のあいだに「よける」を156回くり返したロボットがいました。行き止まりで、よけては戻るをくり返していたと見ています。
ドリンクバーを上へ0.5m・左へ0.8m:右下を一周できるようにした(版 8a5b2f6a016a)
ドリンクバーの位置を2案、図で比べました。青い所が、ロボットのふだんの道が通れる所です。

A 上へ0.5m・左へ0.8m(選んだ案) | B 上へ0.3m・左へ0.8m | |
|---|---|---|
| 右の抜け道 | 1.2m(ふだんの道が通れる) | 1.2m |
| 下の通路 | 1.4m → 1.9m。卓の前にロボットが1台止まっていても、もう1台が狭い道として横を抜けられる | 1.7m。卓の前にロボットが止まると抜けられない |
ドリンクバーの前に立つ人と待機場所の間 | 1.05m | 1.25m |
| ドリンクバーに並ぶ点 | 2つ → 1つ(2つめが待機場所に近すぎる) | 1つ |
卓までの距離が変わったのは、右下の6卓だけです。左寄りの T36〜T38 は0.18mずつ延び、右の T40・T41 は0.67mずつ近くなりました。卓の数・席の数・ふだんの道で行ける卓は変わりません。⑦は③の店をもとに作っているので、⑦も同じように変わります。

試算 v2.7 を、店の形の直しと一緒に公開した
店の形の直しで卓までの距離が変わったら、その店の試算も計算し直して、店の形と一緒に公開する決まりです。公開中の試算は v2.6(料理は、ロボットとスタッフのうち先に空いた方が運ぶ)で、作業用の枝に v2.7(料理はまずロボットを待ち、2分たっても来なければスタッフも運ぶ)を置いたままでした。Unity は v2.7 を読んでいます。どちらを公開するかを聞き、v2.7 を公開すると決めました。
- ③⑦の3,066条件だけを、新しい店の形と v2.7 で計算し直した(クラウドの作業環境で2つ並べて19分)。ほかの店の13,359条件は v2.7 の結果のまま
- 計算し直した差は小さい:入店待ちの差の平均は ③−0.05分・⑦−0.06分、店が回らない条件は ③203→203・⑦202→203
- ページの前提の一覧に「配膳の分担:先に空いた方が運ぶ」が残っていたので、v2.7 の決まりに書き直した
- ⑦の名前が「③の通路を80cmに」のままだった(0.95mに広げる前の名前)ので、「95cmに」に直した
- 試算から数字を読んでいる導入前ガイドの LP も、v2.7 の数字に変わる。ビルドして、文と数字が食い違わないことを確かめた(数字はどれも試算から計算して出している)
2回目(ドリンクバーを動かした後):60秒の止まりは20回、料理の待ちは試算に近づいた
1回目と同じ条件で、もう一度回しました。来た組は64組で同じです。
| ③・ロボット2台・種0 | v8b(線に縛る) | v9・ドリンクバーを動かす前 | v9・ドリンクバーを動かした後 | 試算 v2.7 |
|---|---|---|---|---|
60秒の止まり(うちロボットどうし) | 57(51) | 59(36) | 20(15) | — |
| 1往復で止まった秒(平均) | 109.9 | 83.4 | 33.4 | — |
| 往復 / 打ち切り(600秒) | 72 / 11 | 92 / 10 | 114 / 1 | — |
| ロボットが運んだ皿の割合 | 64.4% | 76.2% | 99.4% | 99.2% |
| 料理の待ち | 2.90分 | 2.12分 | 1.17分 | 1.01分 |
| 入店待ち | 1.67分 | 1.61分 | 1.47分 | 1.08分 |
回り込んだ回数 / よけた回数(1往復の平均) | — | 1.04 / 4.54 | 0.65 / 1.41 | — |
| 1往復でよけた最大の回数 | — | 156 | 21 | — |
逃がし弁(あきらめた / 移した / 卓を空けた) | 61 / 54 / 19 | 71 / 78 / 5 | 31 / 59 / 2 | — |
- ねらい:ロボットに地図を渡して道を自分で引かせ、右下の行き止まりをなくして、ロボットどうしが正面から出会う場所を減らす
- 変わったこと:道は地図の上でその都度引き、ふさがったら3秒で回り込む。ドリンクバーを動かし、右下を一周できるようにした
- 見込める効果:測った値で、60秒の止まりは57回から20回、1往復で止まった秒は110秒から33秒、打ち切りは11回から1回。ロボットが運んだ割合と料理の待ちは、試算とほぼ同じ大きさになった
止まった回数そのものは490回から2,090回に増えました。1回ずつは短く止まって、回り込んで動き出しています。長く固まる止まり方から、短く止まって回り込む止まり方に変わりました。
残った20回の60秒の止まり
| 場所 | 回数 | 中身 |
|---|---|---|
受け渡し口の左下(x 14.3m・z 5.3m) | 10 | 店が終わりに近い152〜160分に、1号機が2号機に7回続けて止められた。何もしていないロボットが待機場所へ動かず、受け渡し口の近くに立っていた疑い(Claude Code が報告で書いていた「待機場所へ実際には動いていない」と合う) |
右の抜け道の入口(x 20.0m・z 2.7m) | 4 | スタッフ1人が4分以上立ち止まり、2号機が通れなかった |
通路の入口の手前(x 11m・z 4m) | 3 | ロボットどうし |
| ほか | 3 | ロボットどうし2・スタッフ1 |
逃がし弁(動けなくなった人やロボットを、決めた時間で先に進める仕組み)は92回のうち70回が、ドリンクバーで並べずに移された客、またはあきらめた客でした。ドリンクバーを動かす前も72回あったので、人の動きの側の問題です。
③で、回り込みのときに狭い所を通った往復が114回中8回あった
人のいない店では、③の卓はどれも狭い道を使いません。狭い道を通ったのは、人やもう1台でふだんの道がふさがったときに、0.8mのすき間を抜けて回り込んだ場面です。Claude Code から、狭いマスをもっと重くするか、ふさがったら待つかを聞かれました。
このままにしました。実機の BellaBot も0.8mあれば通れるので、ふさがったときにすき間を抜けるのは現実の動きに近いと考えます。サイトの「狭い道を使う卓」は店の形だけで決まる分け方で、混雑の中で狭い所を抜けるのは、Unity が測る「通路で起きること」の側に入ります。サイトの分け方に数字を合わせるために値を動かすと、帳尻合わせになります。比べるときは「店の形で狭い道を使う」と「回り込みで狭い所を通った」を分けて数えます。
段階Bの18回を回し直した(cs:143)
2つの店(③・⑦)× ロボット0・1・2台 × 乱数の種3つの18回を、Stage B の Run All でまとめて回しました(16時33分ごろ〜23時13分)。18回とも全員が店を出るまで回り切りました。来る客は種ごとに、ロボットの台数に関係なくそろっています(種0は64組、種1は83組、種2は102組。平均83組で、試算の約84組とほぼ同じ)。
前の18回(cs:140)とは来る客の作り方が違うので、比べるときは向きと大きさで見ます。
| 3回の平均 | 前の18回(cs:140) | 今回(cs:143) | 試算 v2.7 |
|---|---|---|---|
| ③2台・料理の待ち | 4.46分 | 1.51分 | 1.01分 |
| ⑦2台・料理の待ち | 3.53分 | 1.38分 | 1.01分 |
| ③2台・ロボットが運んだ割合 | 67.8% | 89.9% | 99.2% |
| ⑦2台・ロボットが運んだ割合 | 76.6% | 94.7% | 99.2% |
③2台・打ち切り(3回の合計) | 24 | 7 | — |
⑦2台・打ち切り(3回の合計) | 21 | 6 | — |
③2台・ロボットどうしの60秒の止まり(3回の合計) | 94 | 61 | — |
⑦2台・ロボットどうしの60秒の止まり(3回の合計) | 111 | 35 | — |
| ③1台・料理の待ち | 3.61分 | 2.41分 | 2.03分 |
| ⑦1台・料理の待ち | 3.74分 | 2.53分 | 2.16分 |
| ③1台・ロボットが運んだ割合 | 63.7% | 72.3% | 72.8% |
| ⑦1台・ロボットが運んだ割合 | 62.2% | 69.0% | 70.8% |
⑦(通路を0.95mに詰めた店)は、新しい動き方で回すのはこれが初めてでした。前の18回では⑦2台の入店待ちが9.84分まで延びていましたが、今回は3.81分です。
残ったずれ:入店待ちがロボットの台数で変わらない
| 入店待ち(3回の平均) | ロボット0台 | 1台 | 2台 |
|---|---|---|---|
| ③ Unity | 3.48分 | 3.53分 | 3.66分 |
| ③ 試算 | 3.99分 | 1.82分 | 1.08分 |
| ⑦ Unity | 3.91分 | 3.97分 | 3.81分 |
| ⑦ 試算 | 4.78分 | 2.14分 | 1.14分 |
入店待ちは、試算ではロボットを入れるほど短くなるのに、Unity ではロボットの台数で変わりませんでした。 中身を分けると、2つのことが重なっています。
1つめは、種2(102組)の回です。どの台数でも入店待ちが7〜8.5分になり、3回の平均はこの1回で決まります。種0・1では1.4〜2.0分です。3回では、ロボットの効果と偶然の差が見分けられません。
2つめは、ロボット0台でもスタッフの手が足りていることです。席は空いているのに片付けや案内が追いつかずに待った時間は、種0・1で0.3〜0.7分しかありません。試算では、ロボット0台だとスタッフが足りず、③で3.36分・⑦で3.95分待ちます。Unity のスタッフの仕事が試算より軽い疑いがあります。疑っているのは、片付けが試算より短いことと、逃がし弁の「卓を空けた」が片付けを飛ばしていること(ロボット0台で ③61回・⑦92回)です。前のずれの一覧の5番(ロボットなしで卓が空くまでが短い)と同じ根です。
もう1つ、ドリンクバーの逃がし弁が増えました。⑦のロボット0台では、移された・あきらめた客が3回の合計で69人から148人に増えています。ドリンクバーを動かしたときに、並ぶ点が2つから1つに減ったのが疑いです。店の形の決まりで、並ぶ点を横に並べれば戻せる見込みです。
基準データ v1 と、夜のあいだも回すための改良
別の会話で、研究室が寝ている間もシミュレーションを回し続けるには何が要るかを話し、4つの改良を、区切り → 2 → 4 → 1 → 3 の順で進めると決めていました。
| # | 改良 | 中身 |
|---|---|---|
| 1 | ケースを部品の組み合わせで書ける型 | 店の形 × ロボット機種 × 運用の決まり × 来客の波を別々の部品にする |
| 2 | 夜の結果を自動で振り分ける判定 | 立ち往生・向かい合い・サイトとのずれを自動で見つけ、「正常」「Unity の作りの問題」「サイト側を見直す候補」に分ける |
| 3 | 次に回す条件を選ぶ仕組み | 回る・回らないが切り替わる境目の近くを重点的に回す。境目を探すのは速い試算(SimPy)、Unity は見つかった条件だけ |
| 4 | 画面なしで回す実行環境 | Unity を画面を出さずに起動し、条件と乱数の種を外から渡す |
その区切りを、この18回にしました。Unity の版 cs:143・店の形 8a5b2f6a016a・試算 v2.7 の組を「基準データ v1」とし、KIOXIA の service_sim/unity/stageB_cs143/ に、版・出力の場所・判定に使う事実・分かっている作りの問題をまとめた README を置きました。改良を入れたあとの回は、この18回と比べます。
この18回から、自動の判定を決めるときの材料が出ています。
- 判定に使うのは、ばらつきの小さい料理の待ちとロボットが運んだ割合。どの条件も試算と同じ向きで、大きさの比は2倍未満(いちばん離れているのは⑦0台の料理の待ちで1.72倍)
- 入店待ちは、種3つでは判断に使えない。使うなら種を増やす
- ロボット0台の回が試算とずれていたら、ロボットの回は比べずに「人の動かし方の問題」として分ける
- 改良の最初に直す候補:待機場所へ動かないロボット、片付けを飛ばす「卓を空けた」、台帳の pause_rate・stuck_rate が空、ドリンクバーの並ぶ点が1つ
夜に回すときの実際も分かりました。1回の実時間は、店の中の3時間ほどを10.6〜20.9分で回します。18回の通しは、途中でふたを閉じた分を含めて約6時間40分でした。ふたを閉じると Mac はスリープし、回している1回はそこで止まります。開けると続きから動き、店の中の時間は実際の時間と別に進むので、結果は変わりません。1回の上限は40分で、3回目はふたを閉じた分を含めて32分で終わり、台帳にも書かれました。終わった回は1回ごとに台帳に書かれ、もう一度押すと同じ版で終わった回は飛ばします。回している間はスリープを止める仕組みが入っていますが、ふたを閉じたときのスリープまでは止められません。画面なしで回す改良(4)でも、この点は残ります。
データとコードの置き場所
| もの | 場所 |
|---|---|
Unity の出力(③2台・種0 の2回) | KIOXIA r2r2r-data/service_sim/unity/20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1304・…_1559 |
| 段階Bの18回の出力 | KIOXIA r2r2r-data/service_sim/unity/20261024_stageB_cs143_{fam_p1・fam_p5}_r{0・1・2}_s{0・1・2} |
| 台帳 | KIOXIA r2r2r-data/service_sim/unity/unity_ledger_v1.csv(unity_cs が cs:143 の18行) |
基準データ v1 の説明と、集計のコードと出力 | KIOXIA r2r2r-data/service_sim/unity/stageB_cs143/(README.md・b1〜b4) |
依頼文・報告・確かめ A の出力・ずれの一覧・設計書 | iCloud サービスロボット導入シミュレーション/unity/(claude_code_request_v9_map_planner.md・claude_code_reports/20261024_1155_v9_map_planner.txt・screens/20261024_1150_v9_*・unity_stageC_gaps_v1.md・unity_design_v0.md) |
Unity が読んだ店の形と試算の写し | iCloud サービスロボット導入シミュレーション/unity/site_copy_2fa10547a2b7/・site_copy_8a5b2f6a016a/ |
| Unity のコード | /Users/shimazueiichi/Robotics_UX/Robotics_UX_New/Assets/ServiceSim/(Unity Version Control cs:143) |
| 店の形と地図 | GitHub PixelstoMotors/p2m-site の tools/sim_layouts/・public/sim/layouts/(commit 1ee9d8e・a33aefd) |
| 試算 v2.7 の計算し直し | iCloud サービスロボット導入シミュレーション/simulation/v2_7/(run_p1p5.py・merge_v27.py・rows_v27_p1p5.json・compare_v27_drinkbar.txt・README.md) |
Unity のコードは、Unity Version Control の差分を取り出せる環境が手元にないので、この記事で直したファイルの cs:143 の全文を載せます。新しく作った4つのファイルは、Claude Code の報告の後ろにも全文が入っています。回した記録のうち、人どうしの詰まりの記録(people_jams.csv)と、1回ずつの CSV は KIOXIA の同じフォルダにあります。
Claude Code への依頼文
この記事のコード・ログ・データは、1ファイルずつ下に置いています。全文はリンク先にあります。
ファイルの一覧(25本)
01_sec11.md ― 依頼 v9:claude_code_request_v9_map_planner.md・5,429字
02_sec12.txt ― 11:55 v9 を入れた報告(claude_code_reports/20261024_1155_v9_map_planner.txt)・65,465字
03_sec12.txt ― 12:49 確かめ A の報告(チャットに貼られたもの)・5,310字
04_sec12.txt ― 16:31 確かめ B と Check-in(cs:143)の報告(チャットに貼られたもの)・4,913字
05_Assets_ServiceSim_Robot_GridPlanner.cs.txt ― Assets/ServiceSim/Robot/GridPlanner.cs・33,405字
06_Assets_ServiceSim_Robot_MapPlanCheck.cs.txt ― Assets/ServiceSim/Robot/MapPlanCheck.cs・10,169字
07_Assets_ServiceSim_Robot_RobotPathLine.cs.txt ― Assets/ServiceSim/Robot/RobotPathLine.cs・4,314字
08_Assets_ServiceSim_Editor_ServiceSimMapPlanner.cs.txt ― Assets/ServiceSim/Editor/ServiceSimMapPlanner.cs・4,184字
09_Assets_ServiceSim_Robot_ServingRobotController.cs.txt ― Assets/ServiceSim/Robot/ServingRobotController.cs・102,189字
10_Assets_ServiceSim_Robot_RobotSpec.cs.txt ― Assets/ServiceSim/Robot/RobotSpec.cs・12,013字
11_Assets_ServiceSim_Store_JsonStoreLayout.cs.txt ― Assets/ServiceSim/Store/JsonStoreLayout.cs・36,517字
12_Assets_ServiceSim_Store_StorePlan.cs.txt ― Assets/ServiceSim/Store/StorePlan.cs・11,943字
13_Assets_ServiceSim_Store_StoreBuilder.cs.txt ― Assets/ServiceSim/Store/StoreBuilder.cs・21,843字
14_Assets_ServiceSim_Experiment_TripLogger.cs.txt ― Assets/ServiceSim/Experiment/TripLogger.cs・76,771字
15_Assets_ServiceSim_Experiment_ExperimentRunner.cs.txt ― Assets/ServiceSim/Experiment/ExperimentRunner.cs・50,357字
16_Assets_ServiceSim_Store_KitchenMonitor.cs.txt ― Assets/ServiceSim/Store/KitchenMonitor.cs・9,188字
17_Assets_ServiceSim_Service_ServiceOps.cs.txt ― Assets/ServiceSim/Service/ServiceOps.cs・61,323字
18_1ee9d8e.txt ― commit 1ee9d8e:ロボットの地図を書き出す(tools/ の差分)・8,519字
19_sec15.txt ― tools/sim_layouts/test_famires_v3.py の出力(版 8a5b2f6a016a)・5,617字
20_a33aefd.txt ― commit a33aefd:ドリンクバー・README・試算の条件ファイルの差分・10,032字
21_simulation_v2_7_merge_v27.py.txt ― simulation/v2_7/merge_v27.py・4,282字
22_stageB_cs143_runs.txt ― stageB_cs143/runs.txt・10,290字
23_stageB_cs143_b2_three_runs_output.txt ― stageB_cs143/b2_three_runs_output.txt・3,976字
24_unity_ledger_v1.csv ― unity_ledger_v1.csv(見出しと cs:143 の18行)・5,602字
25_unity_unity_stageC_gaps_v1.md ― unity/unity_stageC_gaps_v1.md(この記事の時点の全文)・5,520字
長い依頼文はファイルにして Mac に置き、Claude Code には「unity/claude_code_request_v9_map_planner.md を読んで、書いてある依頼を進めてください」とだけ送りました。
依頼 v9:claude_code_request_v9_map_planner.md
# 依頼 v9:ロボットが地図の上で自分で道を引く(2026-10-24)
いまのロボットは、サイトの道順(routes)の点を順にたどっている。道順は通れる範囲の中の最短の線なので、通路の端に寄った1本になり、行きと帰りが同じ線を走る。広い所でも2台が正面から出会い、回り込めずに60秒止まる(v8b の確かめの③2台・種0:60秒の止まり57回のうち51回がロボットどうし)。戻りの線・横へどく・角の決まりは、これを後から補うために足したもの。
現実の配膳ロボットは、動ける範囲を地図で持ち、道はその都度自分で引き、人や障害物にはセンサーで止まる・回り込む・引き直す。v9 でこの形に変える。サイトは地図を正として渡し(版 2fa10547a2b7 で公開済み)、道は Unity のロボットが地図の上で引く。NavMesh はロボットの道探しには使わない。
## 変えないもの
Claude Code の報告
報告は3つです。1つめはファイルに書かれた報告で、新しく作った4つのファイルの全文も入っています。2つめと3つめは、チャットに貼られた報告です。
11:55 v9 を入れた報告(claude_code_reports/20261024_1155_v9_map_planner.txt)
# 依頼 v9 の報告:ロボットが地図の上で自分で道を引く(2026-10-24)
書いた日時: 2026-10-24 11:55
依頼: unity/claude_code_request_v9_map_planner.md
やったこと: 0〜6 章を入れて、7 章 A(人のいない店で道を引く確かめ)を回した。
7 章 B(③ ロボット2台・種0 を1回)はエイイチが押す。
**先に「決めた値」と「気になる所」を書きます(6 章のあと)。読んでから B を押してください。**12:49 確かめ A の報告(チャットに貼られたもの)
v9 の実装は揃っていて、確かめ A は③⑦とも通りました。B(回す確認)はエイイチに押
していただく必要があるので、そこで止めます。
0章 版の突き合わせ ✅
summary.json 6店すべて 2fa10547a2b7
p1 / p5 の店の JSON 2fa10547a2b7
p1 / p5 の _map.json 2fa10547a2b716:31 確かめ B と Check-in(cs:143)の報告(チャットに貼られたもの)
新しい固定版は cs:143 です。(v9 本体が cs:142、NavMesh の掃除が cs:143。保留は
Mat_MonitorBoard の Private 2件だけ)
出力フォルダ
20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1559
path_mode = MapPlanner / map_generation = 8a5b2f6a016a / stopped_early = False
確かめ A の出力(unity/screens/)
screens/20261024_1150_v9_checkA_map_planner.txt
# 確かめ A:人のいない店で、受け渡し口から全卓へ道を引く(依頼 v9 の 7 章 A)
回した所: Unity の外(mono)。
Unity Editor がプロジェクトを押さえているので、Assets の
MapPlanCheck.cs / GridPlanner.cs / SimpleJson.cs をそのまま組み立てて回した。
Unity のメニュー ServiceSim/Map Planner が呼ぶのと同じ MapPlanCheck.Run。
回した日時: 2026-10-24 11:55:20
道の引き方は RobotSpec.asset と同じ既定の値(narrowCellCost 3 / centerWeight 2 /
preferClearM 0.6 / maxExpand 200000 / snapM 1 / simplifyMaxM 6)
## ③ 効率重視型・入口が左下の角(p1_efficient_corner)
地図 (map.json): 版 2fa10547a2b7 / マス 960 × 640 = 614400 / 1 マス 0.025 m
ふだんの道の幅 1 m / 通れる幅 0.8 m
マスの数: 2(ふだんの道)148223 / 1(通れる幅だけ)30397 / 0(通れない)435780 … JSON の counts と 一致
道の引き方: narrowCellCost 3 / centerWeight 2 / preferClearM 0.6 / maxExpand 200000 / snapM 1 / simplifyMaxM 6
受け渡し口の前 (15.3, 5.95) → マスの種類 2
狭い道を使った卓: 引いた道 0 卓 / サイトの routes の use 0 卓 → 一致
道が引けない卓: 0 / 42
長さの比(引いた道 ÷ サイトの length): 最小 0.959 / 平均 1.019 / 最大 1.057(真ん中寄りにした分だけ延びる)
道探しの時間: 平均 13.177 ms / 中央 11.113 ms / 最大 35.921 ms
出発点・行き先が地図で通れないマス(0)だったので寄せた卓: 0 / 42
待機場所1 (16.9, 6.05) マスの種類 1 → 引けた(1.605 m・0.508 ms・狭い道を使った)
待機場所2 (17.7, 6.05) マスの種類 1 → 引けた(2.403 m・0.822 ms・狭い道を使った)
待機場所3 (18.5, 6.05) マスの種類 1 → 引けた(3.202 m・1.064 ms・狭い道を使った)
→ 確かめ A は通った
CSV: /private/tmp/claude-501/-Users-shimazueiichi/c8678a42-0b89-4f0f-8750-cfda10b0d91e/scratchpad/harness/checkA_p1_efficient_corner.csv
## ⑦ ぎっしり型(p5_crammed)
地図 (map.json): 版 2fa10547a2b7 / マス 960 × 640 = 614400 / 1 マス 0.025 m
ふだんの道の幅 1 m / 通れる幅 0.8 m
マスの数: 2(ふだんの道)148223 / 1(通れる幅だけ)30397 / 0(通れない)435780 … JSON の counts と 一致
道の引き方: narrowCellCost 3 / centerWeight 2 / preferClearM 0.6 / maxExpand 200000 / snapM 1 / simplifyMaxM 6
受け渡し口の前 (15.3, 5.95) → マスの種類 2
狭い道を使った卓: 引いた道 24 卓 / サイトの routes の use 24 卓 → 一致
道が引けない卓: 0 / 42
長さの比(引いた道 ÷ サイトの length): 最小 0.959 / 平均 1.037 / 最大 1.227(真ん中寄りにした分だけ延びる)
道探しの時間: 平均 30.359 ms / 中央 23.372 ms / 最大 80.214 ms
出発点・行き先が地図で通れないマス(0)だったので寄せた卓: 0 / 42
待機場所1 (16.9, 6.05) マスの種類 1 → 引けた(1.605 m・0.502 ms・狭い道を使った)
待機場所2 (17.7, 6.05) マスの種類 1 → 引けた(2.403 m・0.817 ms・狭い道を使った)
待機場所3 (18.5, 6.05) マスの種類 1 → 引けた(3.202 m・1.124 ms・狭い道を使った)
→ 確かめ A は通った
CSV: /private/tmp/claude-501/-Users-shimazueiichi/c8678a42-0b89-4f0f-8750-cfda10b0d91e/scratchpad/harness/checkA_p5_crammed.csv
→ ③⑦ ともに確かめ A は通った
screens/20261024_1150_v9_planner_unit_checks.txt
行き先 T20 (9.312, 8.662) マスの種類 2
○ 1. 同じ条件なら毎回同じ道 … 点 9 個・10.825 m を 2 回引いて 同じ
○ 2. 人を通れないマスにすると道が変わる … 結果 引けた / 長さ 10.825 m → 11.697 m
○ 3. 重いマスを差し込んでも引ける … 結果 引けた / 長さ 16.145 m(もとは 10.825 m)
○ 4. 行き先をふさぐと引けない … 結果 つながっていない
出発点 (10, 4.5) マスの種類 0(0 なら地図では通れない所)
○ 5. 出発点が 0 のマスでも寄せて引ける … 結果 引けた(狭い道) / 寄せた はい 0.088 m / 長さ 4.917 m
○ 6. 曲がり角の点がすべて通れるマスの上 … はみ出し 0 点
○ 7. 曲がり角だけにしても長さが暴れない … マスをたどった 11.122 m → 縮めた 10.825 m
→ ぜんぶ通った
screens/20261024_1150_v9_map_plan_p1_efficient_corner.csv
table,site_use,plan_use,site_length_m,plan_length_m,ratio,corners,plan_ms,status
T01,normal,normal,14.114,14.284,1.012,10,12.644,ok
T02,normal,normal,15.961,16.176,1.013,10,27.164,ok
T03,normal,normal,17.81,18.026,1.012,10,31.586,ok
T04,normal,normal,19.664,19.875,1.011,10,35.034,ok
T05,normal,normal,14.31,14.531,1.015,10,13.03,ok
T06,normal,normal,16.16,16.376,1.013,10,27.927,ok
T07,normal,normal,18.014,18.225,1.012,10,31.409,ok
T08,normal,normal,19.861,20.075,1.011,10,35.921,ok
T09,normal,normal,10.61,10.831,1.021,10,10.373,ok
T10,normal,normal,12.464,12.676,1.017,10,18.678,ok
T11,normal,normal,14.31,14.525,1.015,10,21.566,ok
T12,normal,normal,16.161,16.375,1.013,10,25.509,ok
T13,normal,normal,10.61,10.831,1.021,10,10.106,ok
T14,normal,normal,12.464,12.676,1.017,10,19.638,ok
T15,normal,normal,14.31,14.525,1.015,10,21.039,ok
T16,normal,normal,16.161,16.375,1.013,10,25.851,ok
T17,normal,normal,16.277,16.872,1.037,23,22.54,ok
T18,normal,normal,6.915,7.131,1.031,9,7.324,ok
T19,normal,normal,8.761,8.976,1.025,9,11.182,ok
T20,normal,normal,10.611,10.825,1.02,9,13.553,ok
T21,normal,normal,12.139,12.7,1.046,25,11.046,ok
T22,normal,normal,11.576,11.988,1.036,22,7.262,ok
T23,normal,normal,6.915,7.131,1.031,9,7.335,ok
T24,normal,normal,8.761,8.976,1.025,9,11.113,ok
T25,normal,normal,10.611,10.825,1.02,9,13.286,ok
T26,normal,normal,12.139,12.7,1.046,25,10.816,ok
T27,normal,normal,2.212,2.235,1.01,3,0.127,ok
T28,normal,normal,2.584,2.714,1.05,7,0.439,ok
T29,normal,normal,4.315,4.56,1.057,7,1.015,ok
T30,normal,normal,6.149,6.398,1.04,8,1.422,ok
T31,normal,normal,7.609,7.711,1.013,3,6.19,ok
T32,normal,normal,5.994,5.998,1.001,2,3.896,ok
T33,normal,normal,4.581,4.581,1,2,0.583,ok
T34,normal,normal,3.763,3.751,0.997,2,0.321,ok
T35,normal,normal,3.804,3.79,0.996,2,1.195,ok
T36,normal,normal,4.291,4.386,1.022,7,4.116,ok
T37,normal,normal,5.371,5.485,1.021,5,6.36,ok
T38,normal,normal,6.468,6.585,1.018,5,7.361,ok
T39,normal,normal,7.568,7.685,1.015,5,10.418,ok
T40,normal,normal,8.667,8.794,1.015,6,11.907,ok
T41,normal,normal,9.767,9.894,1.013,6,12.977,ok
T42,normal,normal,5.379,5.159,0.959,2,2.187,ok
screens/20261024_1150_v9_map_plan_p5_crammed.csv
table,site_use,plan_use,site_length_m,plan_length_m,ratio,corners,plan_ms,status
T01,narrow,narrow,14.066,14.379,1.022,9,23.372,ok
T02,narrow,narrow,15.917,16.229,1.02,9,50.99,ok
T03,narrow,narrow,17.766,18.079,1.018,9,78.034,ok
T04,narrow,narrow,19.616,22.376,1.141,31,80.214,ok
T05,narrow,narrow,14.266,14.579,1.022,9,30.275,ok
T06,narrow,narrow,16.116,16.429,1.019,9,54.934,ok
T07,narrow,narrow,17.966,18.279,1.017,9,78.396,ok
T08,narrow,narrow,19.817,22.158,1.118,30,79.807,ok
T09,narrow,narrow,10.815,11.137,1.03,8,24.795,ok
T10,narrow,narrow,12.666,12.987,1.025,8,46.28,ok
T11,narrow,narrow,14.516,14.837,1.022,8,68.644,ok
T12,narrow,narrow,16.367,20.082,1.227,28,72.066,ok
T13,narrow,narrow,10.815,11.137,1.03,8,24.696,ok
T14,narrow,narrow,12.666,12.987,1.025,8,47.216,ok
T15,narrow,narrow,14.516,14.837,1.022,8,69.505,ok
T16,narrow,narrow,16.367,20.082,1.227,28,71.806,ok
T17,normal,normal,16.199,16.718,1.032,24,26.189,ok
T18,narrow,narrow,7.365,7.687,1.044,9,17.502,ok
T19,narrow,narrow,9.215,9.537,1.035,9,36.312,ok
T20,narrow,narrow,11.066,11.387,1.029,9,55.642,ok
T21,narrow,narrow,11.827,12.64,1.069,21,21.916,ok
T22,normal,normal,11.463,11.984,1.045,20,11.278,ok
T23,narrow,narrow,7.365,7.687,1.044,9,17.235,ok
T24,narrow,narrow,9.215,9.537,1.035,9,37.039,ok
T25,narrow,narrow,11.066,11.387,1.029,9,55.772,ok
T26,narrow,narrow,11.827,12.64,1.069,21,22.423,ok
T27,normal,normal,2.962,2.975,1.004,2,0.163,ok
T28,normal,normal,3.275,3.23,0.986,3,0.299,ok
T29,normal,normal,4.557,4.705,1.032,7,1.258,ok
T30,normal,normal,6.291,6.599,1.049,8,2.593,ok
T31,normal,normal,7.596,7.62,1.003,3,7.306,ok
T32,normal,normal,5.994,5.998,1.001,2,4.068,ok
T33,normal,normal,4.581,4.581,1,2,0.58,ok
T34,normal,normal,3.763,3.751,0.997,2,0.343,ok
T35,normal,normal,3.804,3.79,0.996,2,1.208,ok
T36,normal,normal,4.291,4.386,1.022,7,4.118,ok
T37,normal,normal,5.371,5.485,1.021,5,6.041,ok
T38,normal,normal,6.468,6.585,1.018,5,7.774,ok
T39,normal,normal,7.568,7.685,1.015,5,10.109,ok
T40,normal,normal,8.667,8.794,1.015,6,11.739,ok
T41,normal,normal,9.767,9.894,1.013,6,12.952,ok
T42,normal,normal,5.379,5.159,0.959,2,2.173,ok
Unity のコード(cs:143)の全文
新しく作った4つと、直した9つのファイルです。パスは /Users/shimazueiichi/Robotics_UX/Robotics_UX_New/ から。
Assets/ServiceSim/Robot/GridPlanner.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Text;
using UnityEngine;Assets/ServiceSim/Robot/MapPlanCheck.cs
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEngine;
namespace ServiceSim
{
/// <summary>Assets/ServiceSim/Robot/RobotPathLine.cs
using System.Collections.Generic;
using UnityEngine;
namespace ServiceSim
{
/// <summary>
/// ロボットがいま引いている道を、床の上に細い線で出す(依頼 v9 の 6 章)。
///Assets/ServiceSim/Editor/ServiceSimMapPlanner.cs
using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace ServiceSim.EditorTools
{Assets/ServiceSim/Robot/ServingRobotController.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
namespace ServiceSim
{
/// <summary>Assets/ServiceSim/Robot/RobotSpec.cs
using UnityEngine;
namespace ServiceSim
{
/// <summary>
/// 道の決め方(依頼 v9 の 2 章)。
/// MapPlanner … ロボットが地図(サイトの {名前}_map.json)の上で自分で道を引く。NavMesh は使わない
/// SiteRoutes … サイトの routes の点を順にたどる(v5b〜v8b と同じ。比べるために残す)Assets/ServiceSim/Store/JsonStoreLayout.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEngine;
namespace ServiceSim
{Assets/ServiceSim/Store/StorePlan.cs
using System.Collections.Generic;
using UnityEngine;
namespace ServiceSim
{
/// <summary>席の種類</summary>
public enum SeatKind
{Assets/ServiceSim/Store/StoreBuilder.cs
using System;
using System.Collections.Generic;
using UnityEngine;
namespace ServiceSim
{
/// <summary>
/// StoreLayout が作った部品の一覧(StorePlan)を見て、床・壁・卓・椅子・ベンチ・Assets/ServiceSim/Experiment/TripLogger.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using UnityEngine;
namespace ServiceSimAssets/ServiceSim/Experiment/ExperimentRunner.cs
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace ServiceSim
{
/// <summary>
/// 条件を回して記録する。1回の Play の中で、条件を順に通せる(段階3の Run All)。Assets/ServiceSim/Store/KitchenMonitor.cs
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace ServiceSim
{
/// <summary>
/// キッチンのモニター(2026-10-23 エイイチと決めた。設計書 v0 の 0 章)。Assets/ServiceSim/Service/ServiceOps.cs
using System.Collections.Generic;
using UnityEngine;
namespace ServiceSim
{
/// <summary>料理1皿</summary>
public class DishOrder
{サイトの店の形の変更(p2m-site)
commit 1ee9d8e:ロボットの地図を書き出す(tools/ の差分)
店の形・解析・Unity 用の JSON は、版の番号と規則の説明文だけが変わったので、tools/ の差分だけを載せます。地図の JSON(public/sim/layouts/unity/*_map.json)はサイトにあります。
commit 1ee9d8e8590c9391280774c292ee266b918d26cc
店の形:Unity のロボットが自分で道を引くための地図を書き出す(版 2fa10547a2b7)
diff --git a/tools/sim_layouts/README.md b/tools/sim_layouts/README.md
index 22d2ece..1aa11e9 100644
--- a/tools/sim_layouts/README.md
+++ b/tools/sim_layouts/README.mdtools/sim_layouts/famires_v3.py の出力(版 8a5b2f6a016a)
[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.6, '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': '⑦ ③の列の間の通路を95cmに(卓と席数は③と同じ)', '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': 10.8, 'robot_dist_max': 20.17, 'human_walk_total': 0.0, 'human_walk_max': None} マス目の差: []
tools/sim_layouts/test_famires_v3.py の出力(版 8a5b2f6a016a)
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)
OK 80cmの通路はBellaBotで通れる(マス目0.025・ずらし0.031)
OK 77cmの通路はBellaBotで通れない(マス目0.025・ずらし0.031)ドリンクバーの案を比べたコード(drink_variants.py)
tools/sim_layouts/ で python3 drink_variants.py <出力先> として動かし、今・A・B の図(LOG374_02_drinkbar_options.png のもと)と、卓までの距離の変わり方を出しました。
import sys, copy, json
sys.path.insert(0, '.')
import numpy as np, matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib import font_manager
font_manager.fontManager.addfont('/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc')
plt.rcParams['font.family'] = 'Noto Sans CJK JP'
import famires_v3 as v, famires_gen2 as gen, unity_export as ux
OUT = sys.argv[1]
VARS = [("今", None), ("A 上へ0.5m・左へ0.8m", [16.0, 3.3, 20.0, 4.0]), ("B 上へ0.3m・左へ0.8m", [16.0, 3.1, 20.0, 3.8])]
base = {}
for name, rect in VARS:
L = gen.p1_efficient_corner()
if rect:
for r in L["rooms"]:
if r["label"] == "ドリンクバー": r["rect"] = rect
L = v.prepare(L)
viol = v.check_rules(L)
ctx = {}
res, err = v.analyze(L, v.SETTINGS["res"], ctx)
meta = dict(settings=v.SETTINGS, robot_model=dict(name="BellaBot", **v.ROBOT_MODELS["BellaBot"]))
U = ux.build(dict(L, robot_keepout=v.checkout_keepout(L)), res, ctx["grid"], ctx["d_norm"], ctx["d_pass"], ctx["sides"], v.standby_slots(L["robot_standby"]), v.FURNITURE_TYPES, {})
gm = v.Grid(L, v.SETTINGS["res"], standby=[])
cls = np.where(gm.free(1.0), 2, np.where(gm.free(0.8), 1, 0))
d = {a["id"]: a.get("dist") for a in res}
if not rect: base = d
print(name, "違反", viol, err, "robot卓", sum(a["category"] == "robot" for a in res))
print(" 距離の変わった卓", {k: (base[k], d[k]) for k in d if base.get(k) != d[k]})
pts = [p for p in U["places"] if p["kind"] in ("DrinkBarStand", "DrinkBarQueue")]
print(" 立つ点・並ぶ点", [(p["kind"][9:], p["point"]) for p in pts])
fig, ax = plt.subplots(figsize=(9, 6.2), dpi=130)
summ = v.summarize(L, res)
v.draw(ax, L, res, summ, [])
ext = [0, gm.nx * gm.res, 0, gm.ny * gm.res]
ov = np.zeros(cls.shape + (4,)); ov[cls == 2] = (0.2, 0.6, 1.0, 0.28); ov[cls == 1] = (1.0, 0.6, 0.1, 0.35)
ax.imshow(ov, origin='lower', extent=ext, zorder=5, interpolation='nearest')
for p in pts:
ax.plot(*p["point"], 'o', color='#d33' if 'Queue' in p["kind"] else '#a0a', ms=6, zorder=6)
ax.set_xlim(12.5, 24.2); ax.set_ylim(-0.2, 7.2); ax.set_title(name + "(青=ロボットのふだんの道が通れる所/橙=狭い道だけ/赤紫・赤=ドリンクバーに立つ・並ぶ人)", fontsize=8)
for t in ax.texts:
if not (12.5 <= t.get_position()[0] <= 24.2 and -0.2 <= t.get_position()[1] <= 7.2): t.set_visible(False)
fig.savefig(f"{OUT}/{name[0]}.png", bbox_inches='tight', facecolor='white'); plt.close(fig)
drink_variants.py の出力
今 違反 [] [] robot卓 42
距離の変わった卓 {}
立つ点・並ぶ点 [('tand', [17.3, 3.9]), ('tand', [18.3, 3.9]), ('tand', [19.3, 3.9]), ('tand', [20.3, 3.9]), ('ueue', [18.8, 4.8]), ('ueue', [18.8, 5.3])]
A 上へ0.5m・左へ0.8m 違反 [] [] robot卓 42
距離の変わった卓 {'T36': (4.62, 4.8), 'T37': (5.72, 5.9), 'T38': (6.82, 7.0), 'T39': (7.92, 7.94), 'T40': (9.02, 8.35), 'T41': (10.12, 9.45)}
立つ点・並ぶ点 [('tand', [16.5, 4.4]), ('tand', [17.5, 4.4]), ('tand', [18.5, 4.4]), ('tand', [19.5, 4.4]), ('ueue', [18.0, 5.3])]
B 上へ0.3m・左へ0.8m 違反 [] [] robot卓 42
距離の変わった卓 {'T36': (4.62, 4.91), 'T37': (5.72, 6.01), 'T38': (6.82, 7.11), 'T39': (7.92, 7.82), 'T40': (9.02, 8.23), 'T41': (10.12, 9.33)}
立つ点・並ぶ点 [('tand', [16.5, 4.2]), ('tand', [17.5, 4.2]), ('tand', [18.5, 4.2]), ('tand', [19.5, 4.2]), ('ueue', [18.0, 5.1])]
commit a33aefd:ドリンクバー・README・試算の条件ファイルの差分
commit a33aefdcca1dc9c15a0cb6b83c5984bff18d2767
配膳ロボット:③⑦のドリンクバーを動かして右下の行き止まりをなくし、試算 v2.7(料理はロボット優先)を公開(店の形の版 8a5b2f6a016a)
diff --git a/public/sim/serving-robot-params.json b/public/sim/serving-robot-params.json
index 3f3cb45..23f2350 100644
--- a/public/sim/serving-robot-params.json
+++ b/public/sim/serving-robot-params.jsoncommit a33aefd:試算のページ serving-robot.html の差分(const D の行を除く)
const D の行は、16,425条件の結果が入った約2.2MBの1行なので、差分から外しました。中身は下の merge_v27.py で作っています。
diff --git a/public/sim/serving-robot.html b/public/sim/serving-robot.html
index c45f387..3495feb 100644
--- a/public/sim/serving-robot.html
+++ b/public/sim/serving-robot.html
@@ -198,7 +198,7 @@ footer { color: var(--ink-3); font-size: 11px; }
<span class="series">サービスロボット導入シミュレーション #1</span>
<h1>配膳ロボット、何台入れたら店は変わる?</h1>
<p class="lead">飲食店のピーク時間を SimPy で再現しました。店のタイプ・ロボットの使い方・運び方を選ぶと、各条件40回ずつ回した平均が表示されます。</p>
- <span class="tag">数字はすべて仮置き(試作 v2.6)</span>
+ <span class="tag">数字はすべて仮置き(試作 v2.7)</span>
</header>
<section>
@@ -403,7 +403,7 @@ footer { color: var(--ink-3); font-size: 11px; }
</div>
<script>
const ROWS = D.r.map(r => Object.fromEntries(D.k.map((k, i) => [k, r[i]])));
const STORES = D.stores;
const STORE_KEYS = ["small", "family", "large", "hotel", "buffet"];
@@ -748,7 +748,7 @@ function renderAssume() {
["立ち往生(スタッフが動かす)", `1往復の${Math.round(c.stuck_rate * 100)}%で、スタッフが動かしに行く(${c.rescue_s}秒+歩く時間)`],
["1往復で複数卓を回るとき", `近い卓から順に回り、卓から卓へ${c.hop_m}mの寄り道`],
["仕事の優先順", "ロボットの救出 → 配膳・案内・会計・呼び出し → 下げ膳"],
- ["配膳の分担", "ロボットとスタッフのうち先に空いた方が運ぶ"],
+ ["配膳の分担", `ロボットが配膳するときは、料理はまずロボットを待つ。${Math.round(c.robot_first_wait_s / 60)}分たってもロボットが空かなければ、そこからはロボットとスタッフのうち先に空いた方が運ぶ。割れ物を人だけが運ぶ設定と、ロボットなしはスタッフが運ぶ(v2.7 から。それまでは、はじめから先に空いた方が運んでいた)`],
["下げ膳にも使う場合", "スタッフが片付けに向かうとき、空いているロボットがいれば一緒に卓へ向かう。ロボットはスタッフが皿を載せ終えるまで卓で待ち、洗い場へ戻る。いなければ人だけで下げる(v2.4)"],
];
document.getElementById("assume").innerHTML = list.map(([k, v]) => `<li>${k}:${v}</li>`).join("");
試算 v2.7 の③⑦の計算し直し(simulation/v2_7/)
③⑦の結果の rows_v27_p1p5.json(約1.8MB)は、iCloud の同じフォルダにあります。
simulation/v2_7/README.md
# 配膳ロボットの試算 v2.7(2026-10-23 回す・2026-10-24 公開)
試算のモデルを v2.7 にした版。料理はロボット優先(料理ができたらまずロボットを待ち、2分たってもロボットが空かなければ、そこからはロボットとスタッフのうち先に空いた方が運ぶ。2026-10-23 エイイチと決めた)。
## 公開までの流れ
- 2026-10-23:全16,425条件を v2.7 で回した(Mac と作業用の計算機で分けて回した。run_shard.py・shard_a.json)。結果のページは p2m-site の枝 wip/robot-first-v27 に置き、公開しなかった
- 2026-10-24:③⑦のドリンクバーを動かした(上へ0.5m・左へ0.8m。右の6人席との間に1.2mの抜け道を作り、右下の2人席の前の通路を行き止まりにしない。店の形の版 82023936eb99 → 2fa10547a2b7(地図の書き出しを足しただけ)→ 8a5b2f6a016a)。距離が変わったのは③⑦の6卓だけなので、③⑦の3,066条件だけを回し直し(run_p1p5.py → rows_v27_p1p5.json)、枝のページの③⑦の行と店の情報・平面図を入れ替えて公開した(merge_v27.py)
- 前提の「配膳の分担」を v2.7 の決まりに直した。⑦の名前を「③の通路を95cmに」に直した(haizen_sim.py の LAYOUT_LABELS。80cmのままだった)
## ③⑦の回し直しの差(compare_v27_drinkbar.txt)
- 入店待ちの差の平均 ③ −0.05分・⑦ −0.06分。店が回らない ③ 203→203・⑦ 202→203。全体 2,956 / 16,425 条件
## 作り方
```
python3 run_p1p5.py rows_v27_p1p5.json # ③⑦だけ回す(layouts/ は p2m-site の public/sim/layouts/ の写し)
python3 merge_v27.py <枝の v2.7 のページ> rows_v27_p1p5.json <公開中のページ> serving-robot.v27.html compare_v27_drinkbar.txt
python3 ../v2_6/export_params.py rows_v27_p1p5.json serving-robot-params.json
node ../v2_6/test_page_v26.js serving-robot.v27.html # 全部の組み合わせを描いて例外がないか
```
- `serving-robot.v27.html` は p2m-site の `public/sim/serving-robot.html`、`serving-robot-params.json` は `public/sim/serving-robot-params.json` に入れた(commit a33aefd)
- 公開済みの記事の数字は前の版のまま
simulation/v2_7/run_p1p5.py
"""③⑦(fam_p1・fam_p5)の条件だけを回す。出力は rows の JSON(haizen_sim.run_condition の戻り値の並び。条件の並びは conditions() と同じ)"""
import json, sys, time
from multiprocessing import Pool
import haizen_sim as h
out = sys.argv[1]
conds = [c for c in h.conditions() if c["store"] in ("fam_p1", "fam_p5")]
t0 = time.time()
with Pool(2) as p:
rows = p.map(h.run_condition, conds, chunksize=4)
json.dump({"common": h.COMMON, "reps": h.REPS, "stores": {k: h.STORES[k] for k in ("fam_p1", "fam_p5")}, "rows": rows}, open(out, "w"), ensure_ascii=False)
print(len(rows), "rows", round(time.time() - t0), "s", flush=True)
simulation/v2_7/merge_v27.py
"""v2.7 の試算ページのデータ(const D)の③⑦(fam_p1・fam_p5)だけを、ドリンクバーを直した店の形で回し直した結果に入れ替える(2026-10-24)。
使い方: python3 merge_v27.py <枝の v2.7 のページ> <③⑦の結果 rows_v27_p1p5.json> <公開中のページ> <出力するページ> <比べた結果.txt>
- ほかの店の行は枝の v2.7 のまま(同じモデル・同じ店の形なので回し直さない)
- 公開中のページの const D の1行・見出しの版・前提の「配膳の分担」だけを入れ替える(費用の欄・LP 用の色は残す)"""
import json, os, re, sys
import haizen_sim as h
br, newp, live, out, cmp_out = sys.argv[1:6]
STO = ("fam_p1", "fam_p5")simulation/v2_7/compare_v27_drinkbar.txt
v2.7(枝・店の形 82023936eb99)と、③⑦をドリンクバーを直した店の形(8a5b2f6a016a)で回し直したものの比較
fam_p1 entry_wait_mean: 差の平均 -0.048 最小 -5.296 最大 +5.255
fam_p1 staff_wait_mean: 差の平均 +0.005 最小 -1.694 最大 +2.083
fam_p1 dish_wait_mean: 差の平均 -0.003 最小 -0.118 最大 +0.071
fam_p1 robot_share: 差の平均 +0.000 最小 -0.019 最大 +0.022
fam_p1 店が回らない 203 -> 203 卓までの平均 10.6
fam_p5 entry_wait_mean: 差の平均 -0.055 最小 -4.029 最大 +4.419
fam_p5 staff_wait_mean: 差の平均 -0.015 最小 -2.239 最大 +2.024
fam_p5 dish_wait_mean: 差の平均 -0.002 最小 -0.132 最大 +0.085
fam_p5 robot_share: 差の平均 +0.000 最小 -0.023 最大 +0.018
fam_p5 店が回らない 202 -> 203 卓までの平均 10.8
全体の店が回らない 2956 / 16425 条件
Unity の出力の集計(KIOXIA stageB_cs143/)
stageB_cs143/README.md
# 基準データ v1(段階Bの18回・cs:143)
2026-10-24 の別の会話(「研究室の夜間AI稼働」)で決めた「区切り」の印。夜に回す改良(自動の判定・画面なしで回す・ケースの型・次の条件を選ぶ仕組み)は、ここを答え合わせの材料にする。改良を入れたあとの回は、この18回と比べる。
## 何の版か
- Unity: Unity Version Control cs:143(v9:ロボットがサイトの地図の上で自分で道を引く。NavMesh はロボットの道探しに使わない。人は NavMesh のまま)
- 店の形: p2m-site の public/sim/layouts/ 版 8a5b2f6a016a(③⑦のドリンクバーを上へ0.5m・左へ0.8m。地図 unity/{名前}_map.json つき)
- 試算: v2.7(料理はロボット優先・2分で人も運ぶ)。Unity が読む条件は serving-robot-params.json(layout_generation 8a5b2f6a016a)
- 回した日時: 2026-10-24 16:33ごろ〜23:13(Stage B / Run All(18回))。台帳 unity_ledger_v1.csv の unity_cs = cs:143 の18行
- 出力フォルダ: ../20261024_stageB_cs143_{fam_p1|fam_p5}_r{0|1|2}_s{0|1|2}
- 比べる前の版: cs:140 の18回(../20261023_stageB_*)。来る客の乱数の作り方が cs:141 で変わったので、cs:140 とは来る客が違う
## このフォルダのファイル
- b1_collect.py → runs.txt:36回(cs:140 と cs:143)を1回1行にまとめる
- b2_three_runs.py → b2_three_runs_output.txt:③ロボット2台・種0 の3回(v8b・v9 ドリンクバー前・後)
- b3_stageB_compare.py → b3_stageB_compare_output.txt:条件ごとに cs:140 → cs:143 と試算を並べる
- b4_giveups_by_job.py → b4_giveups_by_job_output.txt:逃がし弁を仕事ごとに数える
## 自動の判定を決めるときに使う事実(この18回から)
- 1条件3回(種0・1・2)。来る客は種ごとに台数に関係なく同じ(64・83・102組。平均83組で試算の約84組とほぼ同じ)
- ばらつきが小さいのは、料理の待ちとロボットが運んだ割合。試算との比はどれも同じ向きで2倍未満(料理の待ち ③0台 0.93/0.65・1台 2.41/2.03・2台 1.51/1.01、⑦0台 1.12/0.65・1台 2.53/2.16・2台 1.38/1.01。割合 ③1台 0.72/0.73・2台 0.90/0.99、⑦1台 0.69/0.71・2台 0.95/0.99)
- 入店待ちは種2(102組)で7〜8.5分、種0・1で1.4〜2.0分。平均は種2で決まり、ロボットの台数で変わらない。3回では判断に使えない
- ロボット0台でも、席が空いているのに待った時間が試算より短い(種0・1で0.3〜0.7分、試算 ③3.36・⑦3.95分)。人の動かし方の側のずれ
- 60秒の止まり(3回の合計):2台 ③90(うちロボットどうし61)・⑦64(35)、1台 ③13・⑦22、0台 0
- 逃がし弁の半分ほどはドリンクバーの客(移した・あきらめた)。⑦0台で cs:140 の69から148に増えた。ドリンクバーを動かして並ぶ点が2つから1つに減ったのが疑い
- 1回の実時間(run_info の wall_seconds)は10.6〜20.9分。18回の通しは、外出でふたを閉じた分を含めて約6時間40分
## この版で分かっている Unity の作りの問題(改良の最初に直す候補)
- 何もしていないロボットが待機場所へ実際には動かない(GoStandby は NavMeshAgent に行き先を渡すだけで、位置を動かしていない。Claude Code の v9 報告の (6))。受け渡し口の左下で1号機が2号機に7回続けて止められたのは、これの疑い
- 逃がし弁「卓を空けた」が片付けを飛ばしている(ロボット0台で ③61・⑦92回)。スタッフの仕事が試算より軽く見える一因の疑い
- 台帳の pause_rate・stuck_rate が空
- まだ決めていないこと(v9 報告):(2) 通れないマスから道を引くときの寄せ方(いまは1.0m以内の通れるマスへ寄せる)、(4) 角の箱(corner_stops)を新しい動き方で数えるか(いまは数えない)
stageB_cs143/b1_collect.py
"""段階Bの18回(cs:140 線に縛る版 と cs:143 地図の上で自分で道を引く版)を1回1行にまとめる(2026-10-24)。使い方: python3 b1_collect.py <service_sim/unity> > runs.jsonl"""
import csv,sys,json,os,statistics as st
B=sys.argv[1]
for cs in ('cs140','cs143'):
for store in ('fam_p1','fam_p5'):
for rb in (0,1,2):
for sd in (0,1,2):
name=f"20261023_stageB_{store}_r{rb}_s{sd}" if cs=='cs140' else f"20261024_stageB_cs143_{store}_r{rb}_s{sd}"
d=os.path.join(B,name)
s=json.load(open(d+'/summary.json')); r=s['site_run']; m=s['site_metrics']; ri=json.load(open(d+'/run_info.json'))
T=list(csv.DictReader(open(d+'/trips.csv'))); S=list(csv.DictReader(open(d+'/stops.csv')))
L=[x for x in S if float(x['duration_s'])>=59.5]
print(json.dumps(dict(cs=cs,store=store,rb=rb,sd=sd,left=r['everyone_left'],early=ri.get('stopped_early'),wall_min=round(ri.get('wall_seconds',0)/60,1),groups=m['groups'],entry=m['entry_wait_mean'],staffw=m.get('staff_wait_mean'),dish=m['dish_wait_mean'],share=m.get('robot_share') or 0,
trips=len(T),timeout=sum(t.get('timeout')=='1' for t in T),stop_trip=st.mean(float(t['stopped_s']) for t in T) if T else 0,
s60=len(L),s60r=sum(x['cause']=='もう1台のロボット' for x in L),gu=r['gave_up'],wp=r['warped'],tf=r['table_freed']),ensure_ascii=False))
stageB_cs143/runs.txt
{"cs": "cs140", "store": "fam_p1", "rb": 0, "sd": 0, "left": true, "early": false, "wall_min": 11.6, "groups": 81, "entry": 1.9311, "staffw": 0.7289, "dish": 0.9608, "share": 0, "trips": 0, "timeout": 0, "stop_trip": 0, "s60": 0, "s60r": 0, "gu": 10, "wp": 11, "tf": 22}
{"cs": "cs140", "store": "fam_p1", "rb": 0, "sd": 1, "left": true, "early": false, "wall_min": 8.5, "groups": 80, "entry": 2.2816, "staffw": 1.0721, "dish": 0.8046, "share": 0, "trips": 0, "timeout": 0, "stop_trip": 0, "s60": 0, "s60r": 0, "gu": 9, "wp": 11, "tf": 22}
{"cs": "cs140", "store": "fam_p1", "rb": 0, "sd": 2, "left": true, "early": false, "wall_min": 9.3, "groups": 86, "entry": 3.9575, "staffw": 2.1577, "dish": 0.913, "share": 0, "trips": 0, "timeout": 0, "stop_trip": 0, "s60": 0, "s60r": 0, "gu": 7, "wp": 14, "tf": 22}
{"cs": "cs140", "store": "fam_p1", "rb": 1, "sd": 0, "left": true, "early": false, "wall_min": 9.7, "groups": 88, "entry": 3.5292, "staffw": 1.6372, "dish": 3.8528, "share": 0.5688, "trips": 57, "timeout": 1, "stop_trip": 47.78437543859649, "s60": 21, "s60r": 0, "gu": 58, "wp": 43, "tf": 23}
{"cs": "cs140", "store": "fam_p1", "rb": 1, "sd": 1, "left": true, "early": false, "wall_min": 9.0, "groups": 73, "entry": 1.5759, "staffw": 0.3513, "dish": 3.1393, "share": 0.75, "trips": 70, "timeout": 0, "stop_trip": 18.069758571428572, "s60": 5, "s60r": 0, "gu": 37, "wp": 37, "tf": 6}
{"cs": "cs140", "store": "fam_p1", "rb": 1, "sd": 2, "left": true, "early": false, "wall_min": 9.1, "groups": 85, "entry": 5.9371, "staffw": 2.3347, "dish": 3.8241, "share": 0.5935, "trips": 61, "timeout": 1, "stop_trip": 31.854624590163937, "s60": 16, "s60r": 0, "gu": 36, "wp": 36, "tf": 23}
{"cs": "cs140", "store": "fam_p1", "rb": 2, "sd": 0, "left": true, "early": false, "wall_min": 13.1, "groups": 83, "entry": 2.892, "staffw": 1.6328, "dish": 4.2197, "share": 0.7053, "trips": 99, "timeout": 7, "stop_trip": 72.43318787878788, "s60": 56, "s60r": 24, "gu": 100, "wp": 59, "tf": 35}
{"cs": "cs140", "store": "fam_p1", "rb": 2, "sd": 1, "left": true, "early": false, "wall_min": 9.0, "groups": 74, "entry": 2.3919, "staffw": 1.1051, "dish": 4.4348, "share": 0.6448, "trips": 82, "timeout": 10, "stop_trip": 93.59512195121951, "s60": 62, "s60r": 36, "gu": 74, "wp": 46, "tf": 21}stageB_cs143/b2_three_runs.py
"""③ロボット2台・種0 の3回を並べる(2026-10-24)。v8b(線に縛る・1004)/v9 ドリンクバー前(1304)/v9 ドリンクバー後(1559)。
使い方: python3 b2_three_runs.py <service_sim/unity>"""
import csv, json, os, sys, statistics as st, collections as C
B = sys.argv[1]
RUNS = [("v8b 線に縛る", "20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1004"),
("v9 ドリンクバー前", "20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1304"),
("v9 ドリンクバー後", "20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1559")]
for label, name in RUNS:
d = os.path.join(B, name)
s = json.load(open(d + "/summary.json")); r = s["site_run"]; m = s["site_metrics"]
ri = json.load(open(d + "/run_info.json"))
T = list(csv.DictReader(open(d + "/trips.csv"))); S = list(csv.DictReader(open(d + "/stops.csv")))
G = list(csv.DictReader(open(d + "/give_ups.csv")))
L = [x for x in S if float(x["duration_s"]) >= 59.5]
print(f"== {label} {name}")
print(f" path_mode={ri.get('path_mode')} map_generation={ri.get('map_generation')} 書いた時刻={ri.get('written_at')} 実時間={ri.get('wall_seconds', 0)/60:.1f}分")
print(f" 全員が店を出た={r['everyone_left']} 店の中の時間={r['total_minutes']:.1f}分 組={m['groups']}")
print(f" 入店待ち={m['entry_wait_mean']:.2f}分 料理の待ち={m['dish_wait_mean']:.2f}分 ロボットが運んだ割合={(m.get('robot_share') or 0):.3f}")
print(f" 往復={len(T)} 打ち切り={sum(t.get('timeout') == '1' for t in T)} 1往復で止まった秒(平均)={st.mean(float(t['stopped_s']) for t in T):.1f}")
for c in ("detours", "robot_yields", "detour_extra_m", "replans", "narrow_used", "plan_ms_max"):
if T and c in T[0]:
v = [float(t[c]) for t in T if t[c] != ""]
print(f" {c}: 平均 {st.mean(v):.2f} 最大 {max(v):.1f}")
print(f" 止まり={len(S)} 60秒の止まり={len(L)} 原因={C.Counter(x['cause'] for x in L).most_common()}")
print(f" 60秒の止まりの場所(1m刻み)={C.Counter((round(float(x['x'])), round(float(x['z']))) for x in L).most_common(8)}")
print(f" 止まりの解け方={C.Counter(x['resolved'] for x in S).most_common()}")
print(f" 逃がし弁 あきらめた={r['gave_up']} 移した={r['warped']} 卓を空けた={r['table_freed']}")
print(f" 逃がし弁の内訳={C.Counter((g['job'], g['action']) for g in G).most_common(8)}")
if label.endswith("後"):
print(" 60秒の止まりの1件ずつ(ロボット・往復・店の中の時刻・x・z・原因・相手・解け方):")
for x in L:
print(f" {x['robot_id']} {x['trip_id']} {float(x['t_s']):.0f} {float(x['x']):.2f} {float(x['z']):.2f} {x['cause']} {x['cause_detail']} {x['resolved']}")
stageB_cs143/b2_three_runs_output.txt
== v8b 線に縛る 20261024_p1_efficient_corner_fam_p1_s4_r2_a42_s0_1004
path_mode=None map_generation=None 書いた時刻=2026-10-24 10:18:23 実時間=13.8分
全員が店を出た=True 店の中の時間=180.4分 組=64
入店待ち=1.67分 料理の待ち=2.90分 ロボットが運んだ割合=0.644
往復=72 打ち切り=11 1往復で止まった秒(平均)=109.9
止まり=490 60秒の止まり=57 原因=[('もう1台のロボット', 51), ('お客さんとすれ違った', 4), ('人が立ち止まっていた', 1), ('スタッフとすれ違った', 1)]
60秒の止まりの場所(1m刻み)=[((10, 5), 11), ((10, 4), 10), ((17, 2), 9), ((13, 7), 7), ((19, 2), 6), ((13, 8), 5), ((13, 10), 5), ((16, 4), 1)]
止まりの解け方=[('自分で動き出した', 395), ('動けなくなった', 57), ('経路を引き直した', 38)]stageB_cs143/b3_stageB_compare.py
"""段階Bの18回を、条件(店・ロボットの台数)ごとに cs:140 と cs:143 で並べ、試算 v2.7 の値も添える(2026-10-24)。
使い方: python3 b3_stageB_compare.py <runs.txt(b1_collect.py の出力)> <serving-robot-params.json>"""
import json, sys, statistics as st, collections as C
R = [json.loads(l) for l in open(sys.argv[1])]
P = json.load(open(sys.argv[2]))
site = {(c["condition"]["store"], c["condition"]["robots"]): c["site_result"] for c in P["unity_conditions"]}
print("試算", P["meta"]["model"], "店の形", P["meta"]["layout_generation"])
print("全員が店を出た(cs:143)", all(r["left"] for r in R if r["cs"] == "cs143"), " 途中で止めた回", [(r["cs"], r["store"], r["rb"], r["sd"]) for r in R if r["early"]])
gs = C.defaultdict(set)
for r in R:
gs[(r["cs"], r["store"], r["sd"])].add(r["groups"])
print("来た組(種ごと)", dict(sorted((k, sorted(v)) for k, v in gs.items())))
f = lambda L, k: st.mean(x[k] for x in L)
for store in ("fam_p1", "fam_p5"):
for rb in (0, 1, 2):
a = [r for r in R if r["cs"] == "cs140" and r["store"] == store and r["rb"] == rb]
b = [r for r in R if r["cs"] == "cs143" and r["store"] == store and r["rb"] == rb]
s = site[(store, rb)]
print(f"\n== {store} ロボット{rb}台(3回平均。cs:140 → cs:143 / 試算)")
print(f" 入店待ち {f(a,'entry'):.2f} → {f(b,'entry'):.2f} / {s['entry_wait_mean']:.2f} 種ごと {[round(x['entry'],2) for x in b]}")
print(f" 席は空いているのに待った {f(a,'staffw'):.2f} → {f(b,'staffw'):.2f} / {s['staff_wait_mean']:.2f} 種ごと {[round(x['staffw'],2) for x in b]}")
print(f" 料理の待ち {f(a,'dish'):.2f} → {f(b,'dish'):.2f} / {s['dish_wait_mean']:.2f}")
print(f" ロボットが運んだ割合 {f(a,'share'):.3f} → {f(b,'share'):.3f} / {s['robot_share']:.3f}")
print(f" 1往復で止まった秒 {f(a,'stop_trip'):.1f} → {f(b,'stop_trip'):.1f} 往復(3回の合計) {sum(x['trips'] for x in a)} → {sum(x['trips'] for x in b)} 打ち切り {sum(x['timeout'] for x in a)} → {sum(x['timeout'] for x in b)}")
print(f" 60秒の止まり(3回の合計) {sum(x['s60'] for x in a)} → {sum(x['s60'] for x in b)} うちロボットどうし {sum(x['s60r'] for x in a)} → {sum(x['s60r'] for x in b)}")
print(f" 逃がし弁(あきらめた/移した/卓を空けた・3回の合計) {[sum(x[k] for x in a) for k in ('gu','wp','tf')]} → {[sum(x[k] for x in b) for k in ('gu','wp','tf')]}")
print(f" 実時間(分) {[x['wall_min'] for x in b]}")
stageB_cs143/b3_stageB_compare_output.txt
試算 v2.7 店の形 8a5b2f6a016a
全員が店を出た(cs:143) True 途中で止めた回 []
来た組(種ごと) {('cs140', 'fam_p1', 0): [81, 83, 88], ('cs140', 'fam_p1', 1): [73, 74, 80], ('cs140', 'fam_p1', 2): [85, 86], ('cs140', 'fam_p5', 0): [85, 86, 106], ('cs140', 'fam_p5', 1): [69, 71, 95], ('cs140', 'fam_p5', 2): [74, 99, 102], ('cs143', 'fam_p1', 0): [64], ('cs143', 'fam_p1', 1): [83], ('cs143', 'fam_p1', 2): [102], ('cs143', 'fam_p5', 0): [64], ('cs143', 'fam_p5', 1): [83], ('cs143', 'fam_p5', 2): [102]}
== fam_p1 ロボット0台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 2.72 → 3.48 / 3.99 種ごと [1.51, 1.74, 7.17]
席は空いているのに待った 1.32 → 1.70 / 3.36 種ごと [0.32, 0.55, 4.22]
料理の待ち 0.89 → 0.93 / 0.65
ロボットが運んだ割合 0.000 → 0.000 / 0.000
1往復で止まった秒 0.0 → 0.0 往復(3回の合計) 0 → 0 打ち切り 0 → 0
60秒の止まり(3回の合計) 0 → 0 うちロボットどうし 0 → 0
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [26, 36, 66] → [39, 31, 61]
実時間(分) [18.2, 12.8, 12.5]
== fam_p1 ロボット1台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 3.68 → 3.53 / 1.82 種ごと [1.41, 1.67, 7.5]
席は空いているのに待った 1.44 → 1.37 / 1.22 種ごと [0.18, 0.44, 3.49]
料理の待ち 3.61 → 2.41 / 2.03
ロボットが運んだ割合 0.637 → 0.723 / 0.728
1往復で止まった秒 32.6 → 15.7 往復(3回の合計) 188 → 204 打ち切り 2 → 1
60秒の止まり(3回の合計) 42 → 13 うちロボットどうし 0 → 0
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [131, 116, 52] → [136, 115, 37]
実時間(分) [15.6, 13.8, 16.5]
== fam_p1 ロボット2台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 4.77 → 3.66 / 1.08 種ごと [1.6, 2.01, 7.37]
席は空いているのに待った 2.54 → 1.48 / 0.75 種ごと [0.3, 0.74, 3.4]
料理の待ち 4.46 → 1.51 / 1.01
ロボットが運んだ割合 0.678 → 0.899 / 0.992
1往復で止まった秒 85.5 → 39.4 往復(3回の合計) 272 → 379 打ち切り 24 → 7
60秒の止まり(3回の合計) 174 → 90 うちロボットどうし 94 → 61
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [287, 178, 89] → [184, 188, 57]
実時間(分) [11.7, 13.5, 20.9]
== fam_p5 ロボット0台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 2.69 → 3.91 / 4.78 種ごと [1.8, 1.87, 8.07]
席は空いているのに待った 0.99 → 1.94 / 3.95 種ごと [0.6, 0.67, 4.54]
料理の待ち 1.08 → 1.12 / 0.65
ロボットが運んだ割合 0.000 → 0.000 / 0.000
1往復で止まった秒 0.0 → 0.0 往復(3回の合計) 0 → 0 打ち切り 0 → 0
60秒の止まり(3回の合計) 0 → 0 うちロボットどうし 0 → 0
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [25, 54, 69] → [129, 103, 92]
実時間(分) [16.1, 15.9, 16.9]
== fam_p5 ロボット1台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 7.86 → 3.97 / 2.14 種ごと [1.65, 1.75, 8.49]
席は空いているのに待った 3.27 → 1.85 / 1.36 種ごと [0.42, 0.53, 4.59]
料理の待ち 3.74 → 2.53 / 2.16
ロボットが運んだ割合 0.622 → 0.690 / 0.708
1往復で止まった秒 22.2 → 20.6 往復(3回の合計) 199 → 191 打ち切り 2 → 0
60秒の止まり(3回の合計) 20 → 22 うちロボットどうし 0 → 0
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [139, 165, 80] → [207, 196, 68]
実時間(分) [13.9, 12.0, 18.4]
== fam_p5 ロボット2台(3回平均。cs:140 → cs:143 / 試算)
入店待ち 9.84 → 3.81 / 1.14 種ごと [1.58, 2.04, 7.81]
席は空いているのに待った 2.92 → 1.80 / 0.80 種ごと [0.3, 0.72, 4.38]
料理の待ち 3.53 → 1.38 / 1.01
ロボットが運んだ割合 0.766 → 0.947 / 0.992
1往復で止まった秒 58.2 → 30.5 往復(3回の合計) 336 → 409 打ち切り 21 → 6
60秒の止まり(3回の合計) 143 → 64 うちロボットどうし 111 → 35
逃がし弁(あきらめた/移した/卓を空けた・3回の合計) [232, 237, 82] → [274, 275, 66]
実時間(分) [11.8, 11.1, 10.6]
stageB_cs143/b4_giveups_by_job.py
"""逃がし弁を仕事ごとに数える(3回の合計。cs:140 と cs:143)(2026-10-24)。使い方: python3 b4_giveups_by_job.py <service_sim/unity>"""
import csv, os, sys, collections as C
B = sys.argv[1]
for store in ("fam_p1", "fam_p5"):
for rb in (0, 1, 2):
for cs, pre in (("cs:140", f"20261023_stageB_{store}_r{rb}_s"), ("cs:143", f"20261024_stageB_cs143_{store}_r{rb}_s")):
c = C.Counter()
for sd in (0, 1, 2):
for g in csv.DictReader(open(os.path.join(B, pre + str(sd), "give_ups.csv"))):
c[(g["job"], g["action"])] += 1
drink = sum(v for (j, _), v in c.items() if j == "ドリンクバー")
print(f"{store} r{rb} {cs} 合計{sum(c.values())} うちドリンクバー{drink} {c.most_common(8)}")
stageB_cs143/b4_giveups_by_job_output.txt
fam_p1 r0 cs:140 合計128 うちドリンクバー56 [(('片付け', '卓を空けた'), 44), (('ドリンクバー', '移した'), 30), (('ドリンクバー', 'あきらめた'), 26), (('会計', '卓を空けた'), 22), (('トイレ', '移した'), 6)]
fam_p1 r0 cs:143 合計131 うちドリンクバー63 [(('片付け', '卓を空けた'), 46), (('ドリンクバー', 'あきらめた'), 39), (('ドリンクバー', '移した'), 24), (('会計', '卓を空けた'), 15), (('トイレ', '移した'), 7)]
fam_p1 r1 cs:140 合計299 うちドリンクバー128 [(('ドリンクバー', '移した'), 87), (('ドリンクバー', 'あきらめた'), 41), (('料理を運ぶ', 'あきらめた'), 39), (('片付け', '卓を空けた'), 30), (('会計', '卓を空けた'), 22), (('片付け', 'あきらめた'), 19), (('案内', 'あきらめた'), 16), (('トイレ', '移した'), 14)]
fam_p1 r1 cs:143 合計288 うちドリンクバー192 [(('ドリンクバー', '移した'), 105), (('ドリンクバー', 'あきらめた'), 87), (('会計', '卓を空けた'), 21), (('料理を運ぶ', 'あきらめた'), 20), (('片付け', 'あきらめた'), 19), (('片付け', '卓を空けた'), 16), (('トイレ', '移した'), 5), (('立ち往生を動かす', 'あきらめた'), 4)]
fam_p1 r2 cs:140 合計554 うちドリンクバー184 [(('ドリンクバー', '移した'), 118), (('料理を運ぶ', 'あきらめた'), 81), (('ドリンクバー', 'あきらめた'), 66), (('片付け', '卓を空けた'), 61), (('片付け', 'あきらめた'), 55), (('案内', 'あきらめた'), 39), (('会計', '卓を空けた'), 28), (('立ち往生を動かす', 'あきらめた'), 21)]
fam_p1 r2 cs:143 合計429 うちドリンクバー237 [(('ドリンクバー', '移した'), 155), (('ドリンクバー', 'あきらめた'), 82), (('片付け', '卓を空けた'), 33), (('片付け', 'あきらめた'), 30), (('料理を運ぶ', 'あきらめた'), 27), (('会計', '卓を空けた'), 24), (('トイレ', '移した'), 15), (('呼び出し', 'あきらめた'), 14)]
fam_p5 r0 cs:140 合計148 うちドリンクバー69 [(('片付け', '卓を空けた'), 55), (('ドリンクバー', '移した'), 48), (('ドリンクバー', 'あきらめた'), 21), (('会計', '卓を空けた'), 14), (('トイレ', '移した'), 4), (('料理を運ぶ', 'あきらめた'), 3), (('退店', '移した'), 2), (('片付け', 'あきらめた'), 1)]
fam_p5 r0 cs:143 合計324 うちドリンクバー148 [(('片付け', '卓を空けた'), 77), (('ドリンクバー', '移した'), 75), (('ドリンクバー', 'あきらめた'), 73), (('料理を運ぶ', 'あきらめた'), 20), (('片付け', 'あきらめた'), 19), (('会計', '卓を空けた'), 15), (('退店', '移した'), 13), (('トイレ', '移した'), 7)]
fam_p5 r1 cs:140 合計384 うちドリンクバー203 [(('ドリンクバー', '移した'), 141), (('ドリンクバー', 'あきらめた'), 62), (('片付け', '卓を空けた'), 56), (('会計', '卓を空けた'), 24), (('料理を運ぶ', 'あきらめた'), 19), (('片付け', 'あきらめた'), 19), (('トイレ', '移した'), 17), (('案内', 'あきらめた'), 17)]
fam_p5 r1 cs:143 合計471 うちドリンクバー235 [(('ドリンクバー', '移した'), 147), (('ドリンクバー', 'あきらめた'), 88), (('片付け', '卓を空けた'), 51), (('片付け', 'あきらめた'), 43), (('料理を運ぶ', 'あきらめた'), 42), (('会計', '卓を空けた'), 17), (('案内', 'あきらめた'), 13), (('退店', '移した'), 13)]
fam_p5 r2 cs:140 合計551 うちドリンクバー269 [(('ドリンクバー', '移した'), 177), (('ドリンクバー', 'あきらめた'), 92), (('片付け', '卓を空けた'), 45), (('片付け', 'あきらめた'), 37), (('会計', '卓を空けた'), 37), (('料理を運ぶ', 'あきらめた'), 30), (('呼び出し', 'あきらめた'), 30), (('退店', '移した'), 20)]
fam_p5 r2 cs:143 合計615 うちドリンクバー322 [(('ドリンクバー', '移した'), 197), (('ドリンクバー', 'あきらめた'), 125), (('片付け', 'あきらめた'), 63), (('片付け', '卓を空けた'), 46), (('退店', '移した'), 33), (('案内', 'あきらめた'), 32), (('料理を運ぶ', 'あきらめた'), 22), (('会計', '卓を空けた'), 20)]
run_all_log.txt(段階B cs:143 の分)
=== 2026-10-24 23:13:42 段階B(Unity cs:143)===
[ServiceSim] 段階B:ぜんぶ終わりました
回した: 18 / 18 回
台帳: /Volumes/KIOXIA/r2r2r-data/service_sim/unity/unity_ledger_v1.csv
一覧(出力フォルダ / status / 実時間 / 入店待ち / ロボットが運んだ割合):
1. 20261024_stageB_cs143_fam_p1_r2_s0 / completed / 実時間 11.9 分 / 入店待ち 1.5964 分 / ロボットが運んだ割合 0.975
2. 20261024_stageB_cs143_fam_p5_r2_s0 / completed / 実時間 19.1 分 / 入店待ち 1.5844 分 / ロボットが運んだ割合 0.975
3. 20261024_stageB_cs143_fam_p1_r0_s0 / completed / 実時間 32.1 分 / 入店待ち 1.5149 分 / ロボットが運んだ割合 0
4. 20261024_stageB_cs143_fam_p1_r0_s1 / completed / 実時間 24.4 分 / 入店待ち 1.7438 分 / ロボットが運んだ割合 0
5. 20261024_stageB_cs143_fam_p1_r0_s2 / completed / 実時間 18.1 分 / 入店待ち 7.1696 分 / ロボットが運んだ割合 0
6. 20261024_stageB_cs143_fam_p1_r1_s0 / completed / 実時間 17.3 分 / 入店待ち 1.4148 分 / ロボットが運んだ割合 0.8188
7. 20261024_stageB_cs143_fam_p1_r1_s1 / completed / 実時間 28.1 分 / 入店待ち 1.665 分 / ロボットが運んだ割合 0.6893
8. 20261024_stageB_cs143_fam_p1_r1_s2 / completed / 実時間 17.4 分 / 入店待ち 7.5011 分 / ロボットが運んだ割合 0.6614
9. 20261024_stageB_cs143_fam_p1_r2_s1 / completed / 実時間 43.6 分 / 入店待ち 2.0113 分 / ロボットが運んだ割合 0.9029
10. 20261024_stageB_cs143_fam_p1_r2_s2 / completed / 実時間 21.4 分 / 入店待ち 7.372 分 / ロボットが運んだ割合 0.8189
11. 20261024_stageB_cs143_fam_p5_r0_s0 / completed / 実時間 22.5 分 / 入店待ち 1.7959 分 / ロボットが運んだ割合 0
12. 20261024_stageB_cs143_fam_p5_r0_s1 / completed / 実時間 15.9 分 / 入店待ち 1.8685 分 / ロボットが運んだ割合 0
13. 20261024_stageB_cs143_fam_p5_r0_s2 / completed / 実時間 16.9 分 / 入店待ち 8.0689 分 / ロボットが運んだ割合 0
14. 20261024_stageB_cs143_fam_p5_r1_s0 / completed / 実時間 38.0 分 / 入店待ち 1.6539 分 / ロボットが運んだ割合 0.8125
15. 20261024_stageB_cs143_fam_p5_r1_s1 / completed / 実時間 12.1 分 / 入店待ち 1.7516 分 / ロボットが運んだ割合 0.6262
16. 20261024_stageB_cs143_fam_p5_r1_s2 / completed / 実時間 40.0 分 / 入店待ち 8.4937 分 / ロボットが運んだ割合 0.6299
17. 20261024_stageB_cs143_fam_p5_r2_s1 / completed / 実時間 11.2 分 / 入店待ち 2.0392 分 / ロボットが運んだ割合 0.9223
18. 20261024_stageB_cs143_fam_p5_r2_s2 / completed / 実時間 10.7 分 / 入店待ち 7.8111 分 / ロボットが運んだ割合 0.9449
unity_ledger_v1.csv(見出しと cs:143 の18行)
timestamp,run_folder,status,unity_cs,layout_generation,params_model,store,staff,robots,arrivals_per_h,mode,trays,fragile_by,seed,staff_first_yield,yield_order_enabled,one_robot_per_aisle,robot_first_wait_s,everyone_left,total_minutes,wall_seconds,entry_wait_mean,staff_wait_mean,dish_wait_mean,cold_share,robot_share,staff_util,robot_util,walk_km_per_staff,site_entry_wait_mean,site_staff_wait_mean,site_dish_wait_mean,site_robot_share,robot_speed_mps,pause_rate,pause_s_mean,stuck_rate,trips,timeouts,stuck_count,stop_s_total,corner_stop_time_share,gave_up,warped,table_freed,rescues,late_staff_dishes,staff_yield_share_of_staff_time,ledger_schema_version
2026-10-24T16:44:48,20261024_stageB_cs143_fam_p1_r2_s0,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,2,42,serve,3,any,0,1,1,1,120,1,174.2833,699.3919,1.5964,0.2997,1.1661,0.0313,0.975,0.6221,0.6511,2.1231,1.0758,0.7468,1.0095,0.9918,0.5676,,1.8264,,120,2,24,3610.899,0,45,73,5,24,4,0.0752,1
2026-10-24T17:03:52,20261024_stageB_cs143_fam_p5_r2_s0,completed,cs:143,8a5b2f6a016a,v2.7,fam_p5,4,2,42,serve,3,any,0,1,1,1,120,1,174.2858,709.9011,1.5844,0.305,1.0312,0.0375,0.975,0.6431,0.6478,2.1893,1.1434,0.8016,1.0105,0.9917,0.5696,,1.5677,,128,2,25,3449.849,0,58,83,4,25,4,0.0313,1
2026-10-24T17:36:01,20261024_stageB_cs143_fam_p1_r0_s0,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,0,42,serve,1,any,0,1,1,1,120,1,172.3251,1094.92,1.5149,0.3214,0.846,0,0,0.6674,0,2.8311,3.99,3.3554,0.6466,0,0,,0,,0,0,0,0,0,8,6,0,0,0,0,1
2026-10-24T18:00:23,20261024_stageB_cs143_fam_p1_r0_s1,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,0,42,serve,1,any,1,1,1,1,120,1,173.3096,765.7284,1.7438,0.5525,0.9386,0,0,0.7728,0,3.1201,3.99,3.3554,0.6466,0,0,,0,,0,0,0,0,0,7,13,24,0,0,0,1
2026-10-24T18:18:27,20261024_stageB_cs143_fam_p1_r0_s2,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,0,42,serve,1,any,2,1,1,1,120,1,197.7529,751.3111,7.1696,4.2236,1.0143,0.0039,0,0.8091,0,3.6539,3.99,3.3554,0.6466,0,0,,0,,0,0,0,0,0,24,12,37,0,0,0,1
2026-10-24T18:35:45,20261024_stageB_cs143_fam_p1_r1_s0,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,1,42,serve,3,any,0,1,1,1,120,1,172.8132,934.1382,1.4148,0.1777,2.2135,0.2438,0.8188,0.5981,0.7368,2.1527,1.8213,1.2201,2.0323,0.7275,0.5829,,2.9667,,65,0,5,763.0456,0,42,34,1,5,29,0.0337,1
2026-10-24T19:03:53,20261024_stageB_cs143_fam_p1_r1_s1,completed,cs:143,8a5b2f6a016a,v2.7,fam_p1,4,1,42,serve,3,any,1,1,1,1,120,1,180.7106,826.8843,1.665,0.4383,2.5071,0.2816,0.6893,0.7113,0.7452,2.5239,1.8213,1.2201,2.0323,0.7275,0.5781,,3.2266,,64,1,4,846.7955,0,33,31,8,4,64,0.0351,1ずれの一覧と設計書
unity/unity_stageC_gaps_v1.md(この記事の時点の全文)
# 段階C:サイトの試算と Unity のずれの一覧 v1(2026-10-24)
元のデータ:段階Bの18回(cs:140・店の形 82023936eb99・試算 v2.7)。③⑦ × ロボット0・1・2台 × 種0・1・2。
分析のコードと結果:KIOXIA `r2r2r-data/service_sim/unity/stageC_v1/`(a1〜a4.py・rows.json・carry.json・*_output.txt)。
理由の分け方は設計書 0.5 章:1 数え方の違い/2 サイトにない動き(すれ違い・混雑)/3 Unity の作りの問題。
対処を実際に入れるのは次の版。この一覧では決めるところまで。
## 1. 合っていたものunity/unity_design_v0.md(この記事で足した行)
- 地図の上で自分で道を引く形の決定(2026-10-24 エイイチ):(1) ロボットどうしは料理を載せている方が先、空で戻る方がよける(同じなら1号機が先)(2) 前がふさがって3秒空かなければ回り込む道を探す (3) 通路の真ん中寄りを走る(壁や卓のそばを道探しで重くする)。サイトは地図(unity/{名前}_map.json:2.5cmのマス目ごとに 2=ふだんの道・1=狭い道だけ・0=通れない、と障害物までの距離。試算と同じ式。待機場所は床)を版 2fa10547a2b7 で公開。店の形の中身は前の版と同じ。行き先まで2だけで行けるなら2だけ、行けなければ1も重くして使う(試算と同じ規則)。前の動き方(routes をたどる・戻りの線・横へどく・角の決まり)は pathMode=SiteRoutes の切り替えで残す。依頼は claude_code_request_v9_map_planner.md。写す元は site_copy_2fa10547a2b7/
- v9 の確かめ B の1回目(2026-10-24 13:06、店の形 2fa10547a2b7)を見たエイイチの指摘:右下の2人席の前の通路が行き止まり(ドリンクバーと6人席の間が0.4m)で詰まる。ドリンクバーを上へ0.5m・左へ0.8m動かし、右に1.2mの抜け道を作って一周できるようにした(A を選択)。店の形の版 8a5b2f6a016a。距離が変わったのは③⑦の6卓だけで、③⑦だけ試算を回し直し、試算 v2.7(料理はロボット優先)を公開した(p2m-site a33aefd)。Unity の Layouts と params は site_copy_8a5b2f6a016a/ から写した。1回目の記録は動かす前の比べる元として残す
- 夜間に回す改良とのつなぎ(2026-10-24 23時。別の会話「研究室の夜間AI稼働」で、区切り → 自動の判定 → 画面なしで回す → ケースの型 → 次の条件を選ぶ仕組み、の順と決めた):区切りは cs:143 の段階B18回(2026-10-24 16:33ごろ〜23:13)とし、「基準データ v1」として KIOXIA service_sim/unity/stageB_cs143/README.md に版・出力・判定に使う事実・既知の作りの問題をまとめた。自動の判定は、ばらつきの小さい料理の待ちとロボットが運んだ割合で見る(どれも試算と同じ向きで2倍未満)。入店待ちは種3つでは判断に使えない。ロボット0台のずれは人の動かし方の側。改良の最初に直す候補:待機場所へ動かないロボット(GoStandby)・「卓を空けた」が片付けを飛ばす・台帳の pause_rate と stuck_rate が空・ドリンクバーの並ぶ点が1つ。改良を入れたあとの回は v1 と比べる。記事は LOG374