You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.6 KiB
111 lines
3.6 KiB
"""
|
|
scenarios/obstacle.py
|
|
---------------------
|
|
Static Obstacle Scenario.
|
|
|
|
A traffic cone (or configurable static prop) is placed on the ego lane
|
|
ahead of the vehicle. The ego autopilot must detect and react to the
|
|
obstruction. No per-frame logic is needed — this is a purely static scene.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from scenarios.base import ScenarioBase
|
|
|
|
|
|
class ObstacleScenario(ScenarioBase):
|
|
"""
|
|
Scenario: Static obstacle on the ego lane.
|
|
|
|
A prop is spawned on the road ahead. The ego continues under
|
|
autopilot and must navigate around or brake for the obstacle.
|
|
"""
|
|
|
|
OBSTACLE_DISTANCE_M = 30 # metres ahead of ego for static prop
|
|
# CARLA blueprint name for the static prop
|
|
PROP_BLUEPRINT = "static.prop.trafficcone01"
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._obstacle = None
|
|
|
|
# ------------------------------------------------------------------
|
|
# ScenarioBase interface
|
|
# ------------------------------------------------------------------
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
return "obstacle"
|
|
|
|
@property
|
|
def ego_spawn_point(self):
|
|
# Working Town10 intersection point (Southbound)
|
|
import carla
|
|
return carla.Transform(carla.Location(x=107.412, y=45.309, z=0.5), carla.Rotation(yaw=-87.7))
|
|
|
|
def setup(self, world, ego_vehicle, traffic_manager) -> None:
|
|
self._world = world
|
|
self._ego = ego_vehicle
|
|
self._tm = traffic_manager
|
|
|
|
bp_lib = world.get_blueprint_library()
|
|
|
|
# Locate prop blueprint
|
|
prop_bps = bp_lib.filter(self.PROP_BLUEPRINT)
|
|
if not prop_bps:
|
|
# Fallback to any traffic cone available
|
|
prop_bps = bp_lib.filter("static.prop.trafficcone*")
|
|
if not prop_bps:
|
|
raise RuntimeError(
|
|
f"[ObstacleScenario] Blueprint '{self.PROP_BLUEPRINT}' not found. "
|
|
"Check CARLA content pack."
|
|
)
|
|
prop_bp = prop_bps[0]
|
|
|
|
# Place obstacle on the ego lane ahead
|
|
spawn_wp = self._get_waypoint_ahead(self.OBSTACLE_DISTANCE_M, lane_offset=0)
|
|
if spawn_wp is None:
|
|
raise RuntimeError(
|
|
"[ObstacleScenario] Could not find waypoint ahead — "
|
|
"ensure ego is on a driveable road."
|
|
)
|
|
|
|
# Offset slightly to lane centre to avoid collision with road mesh
|
|
obstacle_transform = spawn_wp.transform
|
|
obstacle_transform.location.z += 0.1 # tiny Z lift avoids clipping
|
|
|
|
self._obstacle = world.try_spawn_actor(prop_bp, obstacle_transform)
|
|
if self._obstacle is None:
|
|
raise RuntimeError(
|
|
"[ObstacleScenario] Failed to spawn obstacle at "
|
|
f"{obstacle_transform.location}."
|
|
)
|
|
|
|
self._actors.append(self._obstacle)
|
|
|
|
print(
|
|
f"[{self.name}] '{self.PROP_BLUEPRINT}' placed "
|
|
f"{self.OBSTACLE_DISTANCE_M} m ahead of ego."
|
|
)
|
|
|
|
def step(self, frame_count: int, ego_vehicle, pbar=None) -> None:
|
|
# Static scenario — no per-frame logic required
|
|
pass
|
|
|
|
def cleanup(self) -> None:
|
|
self._destroy_actors()
|
|
print(f"[{self.name}] Cleanup complete.")
|
|
|
|
# ------------------------------------------------------------------
|
|
# Optional overrides
|
|
# ------------------------------------------------------------------
|
|
|
|
def get_scenario_metadata(self) -> dict:
|
|
return {
|
|
"scenario": self.name,
|
|
"obstacle_prop": self.PROP_BLUEPRINT,
|
|
"obstacle_distance_m": self.OBSTACLE_DISTANCE_M,
|
|
}
|