From 03602baaa07af4630fbb415b2fc85a87d88ed1ab Mon Sep 17 00:00:00 2001 From: servinar Date: Tue, 5 May 2026 20:09:38 +0100 Subject: [PATCH 1/5] Allow Ubuntu's apport_python_hook in excepthook check Ubuntu's apport_python_hook installs an excepthook on system Python by default, which previously triggered a warning and prevented Scenic from formatting its backtraces on Ubuntu. Treat it the same as exceptiongroup and allow overwriting it. --- src/scenic/core/errors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scenic/core/errors.py b/src/scenic/core/errors.py index 6cca51d8a..56e1d0723 100644 --- a/src/scenic/core/errors.py +++ b/src/scenic/core/errors.py @@ -265,8 +265,9 @@ def includeFrame(frame): # we specially allow overwriting excepthooks from the following modules, # which are known to not cause problems: # - exceptiongroup (PEP 654 backport for pre-3.11) +# - apport_python_hook (Ubuntu crash reporting system) if sys.excepthook is not sys.__excepthook__ and not sys.excepthook.__module__.startswith( - "exceptiongroup" + ("exceptiongroup", "apport_python_hook") ): warnings.warn("unable to install sys.excepthook to format Scenic backtraces") else: From 8f7f8191e7179d24aecc6740b48f32afdc200ba4 Mon Sep 17 00:00:00 2001 From: servinar Date: Tue, 5 May 2026 20:10:29 +0100 Subject: [PATCH 2/5] Wire up HUD tick and render in CARLA simulator The HUD object was constructed but never updated or rendered, leaving it permanently blank. Register the HUD's on_world_tick callback so the server FPS counter and frame number stay current, and call hud.tick() and hud.render() each step alongside the camera render. --- src/scenic/simulators/carla/simulator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/scenic/simulators/carla/simulator.py b/src/scenic/simulators/carla/simulator.py index e69b4f860..066172c8a 100644 --- a/src/scenic/simulators/carla/simulator.py +++ b/src/scenic/simulators/carla/simulator.py @@ -135,6 +135,7 @@ def setup(self): self.displayDim, pygame.HWSURFACE | pygame.DOUBLEBUF ) self.cameraManager = None + self.world.on_tick(self.hud.on_world_tick) if self.record: if not os.path.exists(self.record): @@ -301,6 +302,9 @@ def step(self): # Run simulation for one timestep self.current_frame = self.world.tick() + if self.render: + self.displayClock.tick() + # Wait for sensors to get updates for obj in self.objects: if obj.sensors: @@ -310,7 +314,9 @@ def step(self): # Render simulation if self.render: + self.hud.tick(self.world, self.objects[0], self.displayClock) self.cameraManager.render(self.display) + self.hud.render(self.display) pygame.display.flip() def getProperties(self, obj, properties): From ae99c4ecb49a62b9a1c7a977fe87cd5b6a0c1d9e Mon Sep 17 00:00:00 2001 From: servinar Date: Tue, 5 May 2026 20:11:09 +0100 Subject: [PATCH 3/5] Clean up residual CARLA actors before each simulation When a previous simulation crashed or left actors behind in the CARLA world, the next run could see stale walkers, vehicles, controllers, or sensors and behave unpredictably. Add _cleanupWorld() which destroys any leftover actors and call it at the start of createSimulation(). --- src/scenic/simulators/carla/simulator.py | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/scenic/simulators/carla/simulator.py b/src/scenic/simulators/carla/simulator.py index 066172c8a..ba133b644 100644 --- a/src/scenic/simulators/carla/simulator.py +++ b/src/scenic/simulators/carla/simulator.py @@ -79,6 +79,8 @@ def createSimulation(self, scene, *, timestep, **kwargs): "set timestep when creating the CarlaSimulator instead" ) + self._cleanupWorld() + self.scenario_number += 1 return CarlaSimulation( scene, @@ -91,6 +93,31 @@ def createSimulation(self, scene, *, timestep, **kwargs): **kwargs, ) + def _cleanupWorld(self): + """Destroy any actors left over in the CARLA world from a prior run.""" + verbosePrint("Cleaning up existing actors in CARLA world...") + actor_list = self.world.get_actors() + + for actor in actor_list.filter("walker.*"): + if actor.is_alive: + actor.destroy() + + for actor in actor_list.filter("controller.ai.walker"): + if actor.is_alive: + actor.destroy() + + for actor in actor_list.filter("vehicle.*"): + if actor.is_alive: + actor.set_autopilot(False, self.tm.get_port()) + actor.destroy() + + for actor in actor_list.filter("sensor.*"): + if actor.is_alive: + actor.destroy() + + self.world.tick() + verbosePrint("Cleanup complete.") + def destroy(self): super().destroy() settings = self.world.get_settings() From 083369b0c34d37266c043db9edf7a6c7bbf2f159 Mon Sep 17 00:00:00 2001 From: servinar Date: Tue, 5 May 2026 20:11:32 +0100 Subject: [PATCH 4/5] Enable CARLA physics substepping for higher simulation fidelity CARLA's physics integrator can become unstable at the default fixed_delta_seconds when objects move quickly, leading to tunnelling and incorrect collision behavior. Enable substepping with a 10ms cap on substep delta and up to 10 substeps per tick, the configuration recommended by CARLA's docs for synchronous mode. --- src/scenic/simulators/carla/simulator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/scenic/simulators/carla/simulator.py b/src/scenic/simulators/carla/simulator.py index ba133b644..847620633 100644 --- a/src/scenic/simulators/carla/simulator.py +++ b/src/scenic/simulators/carla/simulator.py @@ -63,6 +63,9 @@ def __init__( # Set to synchronous with fixed timestep settings = self.world.get_settings() + settings.substepping = True + settings.max_substep_delta_time = 0.01 + settings.max_substeps = 10 settings.synchronous_mode = True settings.fixed_delta_seconds = timestep # NOTE: Should not exceed 0.1 self.world.apply_settings(settings) From ebdac5d6d56c087fa92e75ca47fd1122550a1656 Mon Sep 17 00:00:00 2001 From: servinar Date: Tue, 5 May 2026 20:15:04 +0100 Subject: [PATCH 5/5] Fix: Default to 2D compatibility mode --- src/scenic/__main__.py | 2 +- src/scenic/syntax/translator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scenic/__main__.py b/src/scenic/__main__.py index 05f527fba..082450368 100644 --- a/src/scenic/__main__.py +++ b/src/scenic/__main__.py @@ -63,7 +63,7 @@ "--scenario", default=None, help="name of scenario to run (if file contains multiple)" ) mainOptions.add_argument( - "--2d", action="store_true", help="run Scenic in 2D compatibility mode" + "--2d", default=True, action="store_true", help="run Scenic in 2D compatibility mode" ) # Simulation options diff --git a/src/scenic/syntax/translator.py b/src/scenic/syntax/translator.py index 58e856607..cfc817c38 100644 --- a/src/scenic/syntax/translator.py +++ b/src/scenic/syntax/translator.py @@ -102,7 +102,7 @@ def scenarioFromString( def scenarioFromFile( - path, params={}, model=None, scenario=None, *, mode2D=False, **kwargs + path, params={}, model=None, scenario=None, *, mode2D=True, **kwargs ): """Compile a Scenic file into a `Scenario`.