|
|
@ -59,8 +59,14 @@ def parse_args(): |
|
|
parser.add_argument( |
|
|
parser.add_argument( |
|
|
"--weather", "-w", |
|
|
"--weather", "-w", |
|
|
type=str, |
|
|
type=str, |
|
|
default="ClearNoon", |
|
|
|
|
|
help="Weather preset (ClearNoon, SoftRain, Rain, Sunset, Night, Wet, etc.)" |
|
|
|
|
|
|
|
|
default=None, |
|
|
|
|
|
help="Weather preset (ClearNoon, Rain, etc.). If omitted, scenario or config default is used." |
|
|
|
|
|
) |
|
|
|
|
|
parser.add_argument( |
|
|
|
|
|
"--params", |
|
|
|
|
|
type=str, |
|
|
|
|
|
default=None, |
|
|
|
|
|
help="Scenario parameters as key=val pairs, e.g. 'BRAKE_FRAME=100,SPEED=50'" |
|
|
) |
|
|
) |
|
|
parser.add_argument( |
|
|
parser.add_argument( |
|
|
"--list-scenarios", "-l", |
|
|
"--list-scenarios", "-l", |
|
|
@ -88,39 +94,51 @@ def main(): |
|
|
from sensors import SensorManager |
|
|
from sensors import SensorManager |
|
|
from recorder import Recorder |
|
|
from recorder import Recorder |
|
|
|
|
|
|
|
|
max_frames = args.frames if args.frames is not None else config.MAX_FRAMES |
|
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
# 1. Load scenario (no CARLA needed yet) |
|
|
|
|
|
|
|
|
# 1. Load & Parameterize scenario |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
scenario = load_scenario(args.scenario) |
|
|
scenario = load_scenario(args.scenario) |
|
|
|
|
|
|
|
|
|
|
|
if args.params: |
|
|
|
|
|
# Parse "KEY=VAL,KEY2=VAL2" |
|
|
|
|
|
try: |
|
|
|
|
|
# Strip outer quotes and spaces before split-processing |
|
|
|
|
|
p_str = args.params.strip().strip('"').strip("'") |
|
|
|
|
|
p_dict = {} |
|
|
|
|
|
for item in p_str.split(","): |
|
|
|
|
|
if "=" in item: |
|
|
|
|
|
k, v = item.split("=", 1) |
|
|
|
|
|
p_dict[k.strip().strip('"').strip("'")] = v.strip().strip('"').strip("'") |
|
|
|
|
|
scenario.apply_parameters(p_dict) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
print(f"[ERROR] Failed to parse --params '{args.params}': {e}") |
|
|
|
|
|
|
|
|
|
|
|
# Determine simulation duration (CLI > Scenario > Config) |
|
|
|
|
|
max_frames = args.frames |
|
|
|
|
|
if max_frames is None: |
|
|
|
|
|
max_frames = scenario.max_frames |
|
|
|
|
|
if max_frames is None: |
|
|
|
|
|
max_frames = config.MAX_FRAMES |
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
# 2. Connect to CARLA |
|
|
# 2. Connect to CARLA |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
client = carla.Client("localhost", 2000) |
|
|
client = carla.Client("localhost", 2000) |
|
|
client.set_timeout(10.0) |
|
|
client.set_timeout(10.0) |
|
|
|
|
|
|
|
|
world = client.get_world() |
|
|
|
|
|
|
|
|
|
|
|
# Apply Weather |
|
|
|
|
|
weather_presets = { |
|
|
|
|
|
"Clear": carla.WeatherParameters.ClearNoon, |
|
|
|
|
|
"Cloudy": carla.WeatherParameters.CloudyNoon, |
|
|
|
|
|
"Wet": carla.WeatherParameters.WetNoon, |
|
|
|
|
|
"SoftRain": carla.WeatherParameters.SoftRainNoon, |
|
|
|
|
|
"Rain": carla.WeatherParameters.HardRainNoon, |
|
|
|
|
|
"Sunset": carla.WeatherParameters.ClearSunset, |
|
|
|
|
|
"Night": carla.WeatherParameters(sun_altitude_angle=-90.0, cloudiness=0.0, precipitation=10.0, precipitation_deposits=10.0, wind_intensity=0.0, fog_density=0.0, fog_distance=0.0, wetness=0.0) |
|
|
|
|
|
} |
|
|
|
|
|
# Match partial string (e.g. "Rain" matches "HardRainNoon") |
|
|
|
|
|
chosen_weather = carla.WeatherParameters.ClearNoon |
|
|
|
|
|
for k, v in weather_presets.items(): |
|
|
|
|
|
if k.lower() in args.weather.lower(): |
|
|
|
|
|
chosen_weather = v |
|
|
|
|
|
break |
|
|
|
|
|
world.set_weather(chosen_weather) |
|
|
|
|
|
print(f"[INFO] Applied weather: {args.weather}") |
|
|
|
|
|
|
|
|
world = client.get_world() |
|
|
|
|
|
|
|
|
|
|
|
# Apply Weather (CLI > Scenario > Config) |
|
|
|
|
|
from utils import get_weather_preset |
|
|
|
|
|
|
|
|
|
|
|
weather_name = args.weather |
|
|
|
|
|
if weather_name is None: |
|
|
|
|
|
weather_name = scenario.weather |
|
|
|
|
|
if weather_name is None: |
|
|
|
|
|
weather_name = config.DEFAULT_WEATHER |
|
|
|
|
|
|
|
|
|
|
|
world.set_weather(get_weather_preset(weather_name)) |
|
|
|
|
|
print(f"[INFO] Applied weather: {weather_name}") |
|
|
|
|
|
|
|
|
blueprint_library = world.get_blueprint_library() |
|
|
blueprint_library = world.get_blueprint_library() |
|
|
map_ = world.get_map() |
|
|
map_ = world.get_map() |
|
|
@ -148,32 +166,46 @@ def main(): |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
# 4. Spawn ego vehicle |
|
|
# 4. Spawn ego vehicle |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
vehicle_bp = blueprint_library.filter("model3")[0] |
|
|
|
|
|
|
|
|
vehicle_bp = blueprint_library.filter(config.DEFAULT_EGO_MODEL)[0] |
|
|
spawn_points = map_.get_spawn_points() |
|
|
spawn_points = map_.get_spawn_points() |
|
|
|
|
|
|
|
|
ego_vehicle = None |
|
|
ego_vehicle = None |
|
|
|
|
|
|
|
|
# Try specified spawn point first if provided |
|
|
|
|
|
if args.spawn_point is not None: |
|
|
|
|
|
if args.spawn_point < len(spawn_points): |
|
|
|
|
|
sp = spawn_points[args.spawn_point] |
|
|
|
|
|
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp) |
|
|
|
|
|
|
|
|
# Priority: CLI Argument > Scenario Preference |
|
|
|
|
|
sp_req = args.spawn_point |
|
|
|
|
|
if sp_req is None: |
|
|
|
|
|
sp_req = scenario.ego_spawn_point |
|
|
|
|
|
|
|
|
|
|
|
if sp_req is not None: |
|
|
|
|
|
if isinstance(sp_req, int): |
|
|
|
|
|
if sp_req < len(spawn_points): |
|
|
|
|
|
sp = spawn_points[sp_req] |
|
|
|
|
|
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp) |
|
|
|
|
|
if ego_vehicle: |
|
|
|
|
|
print(f"[INFO] Ego spawned at requested point index {sp_req}") |
|
|
|
|
|
else: |
|
|
|
|
|
print(f"[WARN] Spawn index {sp_req} out of range (max {len(spawn_points)-1})") |
|
|
|
|
|
elif isinstance(sp_req, carla.Transform): |
|
|
|
|
|
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp_req) |
|
|
if ego_vehicle: |
|
|
if ego_vehicle: |
|
|
print(f"[INFO] Ego spawned at requested spawn point index {args.spawn_point}") |
|
|
|
|
|
else: |
|
|
|
|
|
print(f"[WARN] Spawn point index {args.spawn_point} out of range (max {len(spawn_points)-1})") |
|
|
|
|
|
|
|
|
print(f"[INFO] Ego spawned at requested absolute transform: {sp_req.location}") |
|
|
|
|
|
|
|
|
# Fallback to searching if not specified or failed |
|
|
|
|
|
|
|
|
# Fallback search if no request was made |
|
|
if ego_vehicle is None: |
|
|
if ego_vehicle is None: |
|
|
for i, sp in enumerate(spawn_points): |
|
|
for i, sp in enumerate(spawn_points): |
|
|
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp) |
|
|
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp) |
|
|
if ego_vehicle: |
|
|
if ego_vehicle: |
|
|
print(f"[INFO] Ego spawned at spawn point index {i}") |
|
|
|
|
|
|
|
|
print(f"[INFO] Ego spawned at fallback spawn point index {i}") |
|
|
break |
|
|
break |
|
|
|
|
|
|
|
|
if ego_vehicle is None: |
|
|
if ego_vehicle is None: |
|
|
raise RuntimeError("Failed to spawn ego vehicle") |
|
|
raise RuntimeError("Failed to spawn ego vehicle") |
|
|
|
|
|
|
|
|
|
|
|
# If scenario requested a specific absolute transform, move the spawned vehicle there |
|
|
|
|
|
if sp_req is not None and isinstance(sp_req, carla.Transform): |
|
|
|
|
|
ego_vehicle.set_transform(sp_req) |
|
|
|
|
|
print(f"[INFO] Ego moved to requested absolute transform: {sp_req.location}") |
|
|
|
|
|
|
|
|
ego_vehicle.set_autopilot(True, traffic_manager.get_port()) |
|
|
ego_vehicle.set_autopilot(True, traffic_manager.get_port()) |
|
|
|
|
|
|
|
|
# Notify scenario of ego spawn (optional hook) |
|
|
# Notify scenario of ego spawn (optional hook) |
|
|
@ -194,6 +226,9 @@ def main(): |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
# 6. Scenario setup |
|
|
# 6. Scenario setup |
|
|
# ------------------------------------------------------------------ |
|
|
# ------------------------------------------------------------------ |
|
|
|
|
|
# Tick once to settle ego physics before scenario setup starts calculating waypoints |
|
|
|
|
|
world.tick() |
|
|
|
|
|
|
|
|
scenario.setup(world, ego_vehicle, traffic_manager) |
|
|
scenario.setup(world, ego_vehicle, traffic_manager) |
|
|
print(f"[INFO] Running scenario: '{scenario.name}' for {max_frames} frames") |
|
|
print(f"[INFO] Running scenario: '{scenario.name}' for {max_frames} frames") |
|
|
|
|
|
|
|
|
|