--- /sessions/rcw-01levexvnksg51fwlydnyzff/mnt/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_8/haizen_sim.py 2026-10-24 23:58:07.432138539 +0000 +++ /sessions/rcw-01levexvnksg51fwlydnyzff/mnt/PixelstoMotors/デジタルツイン学習R2R2R/サービスロボット導入シミュレーション/simulation/v2_9/haizen_sim.py 2026-10-30 00:13:52.903726056 +0000 @@ -1,5 +1,16 @@ """ -サービスロボット導入シミュレーション #1 配膳ロボット(試作 v2.4) +サービスロボット導入シミュレーション #1 配膳ロボット(試作 v2.9) + +v2.9 で直したこと(2026-10-30。エイイチと決めた:フロントの実感では、レジと案内を優先して仕事をしていた) + 会計のスタッフを頼む時刻を「客が食べ終えてレジに並んだとき」にした。v2.8 までは、レジの順番が来てから + スタッフを頼んだので、ほかの優先1の仕事(案内・料理・呼び出し)の後ろに並び、そのあいだレジが止まっていた。 + v2.9 では、会計の頼みはレジに並んだ時刻の古さで並ぶ(優先は1のまま)。スタッフが会計に付くのは、 + これまでどおりレジが空いてから(レジ1つにつき1組ずつ・pay_s 秒)。会計が終わると先にレジを空け、 + 次の組の会計の頼みが並んでからスタッフの手を放すので、レジに並ぶ組がいれば会計の係がそのまま次を取る。 + Unity(ServiceSim)の頼み方と同じ(依頼31の調べ。Unity は会計のスタッフがほぼいつも1人レジにいる)。 + 会計が速く回るぶん、片付けの仕事が速く入ってくる。乱数の使い方は変えていない。 + +(以下、v2.4 の説明) v2.4 で直したこと(2026-10-22。動画の台本を codex で検証したときに見つかった2点。直し方はエイイチと決めた) 1. 入店待ちの終わりを「案内されて卓に着いたとき」にした。v2.3 までは、案内したスタッフが説明(guide_s)を @@ -95,7 +106,7 @@ "util_sample_s": 10, # 手がふさがっている人数・台数を数える間隔(秒) "max_extra_min": 600, # 数える時間のあと、追いかけるのを打ち切る上限(分)。店が回らない条件の保険 "robot_first_wait_s": 120, # v2.7 ロボット優先:料理はロボットを待つ。これだけ待っても来なければスタッフが運ぶ(秒) - "model": "v2.8", # モデルの版(前の版の結果を使い回さないための印) + "model": "v2.9", # モデルの版(前の版の結果を使い回さないための印) } # --------------------------------------------------------------- @@ -203,6 +214,17 @@ return rng.triangular(lo, hi, mode) +class _AgedRequest(simpy.resources.resource.PriorityRequest): + """v2.9:頼んだ時刻を since にさかのぼらせたスタッフの頼み(同じ優先の中で、since の古い順に並ぶ)""" + def __init__(self, resource, priority, since): + self.priority = priority + self.preempt = False + self.time = since + self.usage_since = None + self.key = (self.priority, self.time, not self.preempt) + simpy.resources.resource.Request.__init__(self, resource) + + class Store: def __init__(self, env, rng, p): self.env, self.rng, self.p = env, rng, p @@ -276,9 +298,11 @@ self.finished.succeed() # ---- スタッフの仕事(priority 0=ロボット救出, 1=配膳・案内・会計, 2=下げ膳) - def staff_job(self, priority, walk_m, work_s, waited=None): + def staff_job(self, priority, walk_m, work_s, waited=None, since=None): t0 = self.env.now - with self.staff.request(priority=priority) as req: + # v2.9:since があれば、その時刻に頼んだものとして並ぶ(会計は、レジに並んだ時刻の古さで並ぶ) + req0 = _AgedRequest(self.staff, priority, since) if since is not None else self.staff.request(priority=priority) + with req0 as req: yield req if waited is not None: waited.append(self.env.now - t0) # 手が空くのを待った時間(案内待ち) @@ -525,10 +549,18 @@ if extras: yield simpy.AllOf(env, extras) # v2.8 会計:卓に座ったままレジの順番を待ち、順番が来たらスタッフの手が空くのを待って会計する + # v2.9 会計のスタッフの頼みは、レジに並んだ時刻(p0)の古さで並ぶ。会計が終わったら先にレジを空け、 + # 次にレジに入った組の頼みが並んでからスタッフの手を放す(会計の係がそのまま次の会計を取れる。Unity と同じ) p0 = env.now - with self.register.request() as rq: - yield rq - yield env.process(self.staff_job(1, 0, p["pay_s"])) + rq = self.register.request() + yield rq + sreq = _AgedRequest(self.staff, 1, p0) + yield sreq + self.staff_busy_s += p["pay_s"] + yield env.timeout(p["pay_s"]) + yield self.register.release(rq) # レジを空ける(次の組がレジに入る) + yield env.timeout(0) # 次の組の会計の頼みが並ぶのを待ってから + self.staff.release(sreq) # スタッフの手を放す if counted: self.pay_waits.append((env.now - p0 - p["pay_s"]) / 60) self._acc()