diff --git a/scenarios/base.py b/scenarios/base.py index 48176df..da84b4e 100644 --- a/scenarios/base.py +++ b/scenarios/base.py @@ -86,6 +86,29 @@ class ScenarioBase(ABC): Always call this in a finally block so CARLA stays clean. """ + # ------------------------------------------------------------------ + # Logging Utilities + # ------------------------------------------------------------------ + + def log_frame(self, frame: int, ego_vehicle, extra_msg: str = "", pbar=None) -> None: + """ + Unified 1:1 logging for all scenarios. + This method ensures clean console output by manually managing tqdm state + to avoid redundant bar updates in redirected log files. + """ + import math + vel = ego_vehicle.get_velocity() + speed = 3.6 * math.sqrt(vel.x**2 + vel.y**2 + vel.z**2) + + msg = f"[FRAME {frame:03d}] EGO (spd={speed:.1f}kph) {extra_msg}" + + if pbar: + # We assume pbar.n has been updated by the orchestrator (main.py) + # pbar.write prints the msg and refreshes the bar on a new line. + pbar.write(msg) + else: + print(msg) + # ------------------------------------------------------------------ # Optional hooks & Properties (default no-ops — override as needed) # ------------------------------------------------------------------ diff --git a/scenarios/braking.py b/scenarios/braking.py index fff9597..35b947d 100644 --- a/scenarios/braking.py +++ b/scenarios/braking.py @@ -111,19 +111,13 @@ class BrakingScenario(ScenarioBase): self._braked = True print(f"[{self.name}] EMERGENCY BRAKE applied at frame {frame_count}.") - # Verbose Logging (Full frequency for 1:1 log mirroring) - e_vel = ego_vehicle.get_velocity() - e_speed = 3.6 * math.sqrt(e_vel.x**2 + e_vel.y**2 + e_vel.z**2) - + # Unified Verbose Logging l_dist = -1.0 if self._lead_vehicle and self._lead_vehicle.is_alive: l_dist = ego_vehicle.get_location().distance(self._lead_vehicle.get_location()) - msg = f"[FRAME {frame_count:03d}] EGO (spd={e_speed:.1f}kph) | LEAD DIST: {l_dist:.1f}m {'(BRAKING)' if self._braked else ''}" - if pbar: - pbar.write(msg) - else: - print(msg) + extra = f"| LEAD DIST: {l_dist:.1f}m {'(BRAKING)' if self._braked else ''}" + self.log_frame(frame_count, ego_vehicle, extra_msg=extra, pbar=pbar) def cleanup(self) -> None: self._destroy_actors() diff --git a/scenarios/cutin.py b/scenarios/cutin.py index 0035ed7..5225e38 100644 --- a/scenarios/cutin.py +++ b/scenarios/cutin.py @@ -103,19 +103,13 @@ class CutInScenario(ScenarioBase): self._cut_triggered = True print(f"[{self.name}] Lane change triggered at frame {frame_count}.") - # Verbose Logging (Full frequency for 1:1 log mirroring) - e_vel = ego_vehicle.get_velocity() - e_speed = 3.6 * math.sqrt(e_vel.x**2 + e_vel.y**2 + e_vel.z**2) - + # Unified Verbose Logging n_dist = -1.0 if self._npc and self._npc.is_alive: n_dist = ego_vehicle.get_location().distance(self._npc.get_location()) - msg = f"[FRAME {frame_count:03d}] EGO (spd={e_speed:.1f}kph) | NPC DIST: {n_dist:.1f}m {'(CUT-IN)' if self._cut_triggered else ''}" - if pbar: - pbar.write(msg) - else: - print(msg) + extra = f"| NPC DIST: {n_dist:.1f}m {'(CUT-IN)' if self._cut_triggered else ''}" + self.log_frame(frame_count, ego_vehicle, extra_msg=extra, pbar=pbar) def cleanup(self) -> None: self._destroy_actors() diff --git a/scenarios/obstacle.py b/scenarios/obstacle.py index 6b51b3e..8feadd3 100644 --- a/scenarios/obstacle.py +++ b/scenarios/obstacle.py @@ -92,8 +92,8 @@ class ObstacleScenario(ScenarioBase): ) def step(self, frame_count: int, ego_vehicle, pbar=None) -> None: - # Static scenario — no per-frame logic required - pass + # Static scenario — minimal logging every frame + self.log_frame(frame_count, ego_vehicle, extra_msg="(STATIC OBSTACLE)", pbar=pbar) def cleanup(self) -> None: self._destroy_actors() diff --git a/scenarios/showcase.py b/scenarios/showcase.py index 8e4cbfd..3b5a879 100644 --- a/scenarios/showcase.py +++ b/scenarios/showcase.py @@ -122,14 +122,9 @@ class ShowcaseScenario(ScenarioBase): self._npc.set_target_velocity(fwd * 9.72) self._npc.apply_control(carla.VehicleControl(throttle=1.0, steer=n_steer)) - # Verbose Logging (Full frequency for 1:1 log mirroring) - e_vel = ego_vehicle.get_velocity() - e_speed = 3.6 * math.sqrt(e_vel.x**2 + e_vel.y**2 + e_vel.z**2) - msg = f"[FRAME {frame:03d}] EGO (spd={e_speed:.1f}kph) target={'MID' if not self._ego_reached_mid else 'P3'} | NPC target={'MID' if not self._npc_reached_mid else 'P3'}" - if pbar: - pbar.write(msg) - else: - print(msg) + # Unified Verbose Logging + extra = f"target={'MID' if not self._ego_reached_mid else 'P3'} | NPC target={'MID' if not self._npc_reached_mid else 'P3'}" + self.log_frame(frame, ego_vehicle, extra_msg=extra, pbar=pbar) def cleanup(self): self._destroy_actors() diff --git a/src/main.py b/src/main.py index cc8590d..0a9eee2 100644 --- a/src/main.py +++ b/src/main.py @@ -246,7 +246,9 @@ def main(): world.tick() frame_count += 1 - pbar.update(1) + # Synchronize progress bar counter WITHOUT refreshing (which causes double-prints in logs) + if pbar: + pbar.n = frame_count cam, cam_tpp, radar, lidar = sensor_manager.get_data()