Browse Source

refactor: generic orchestrator with CLI param injection

- Added --params CLI flag for dynamic scenario tuning
- Implemented orchestration priority chain: CLI > Scenario > Global Config
- Added world.tick() before setup to ensure physics synchronization
- Implemented robust ego 'Spawn-and-Move' strategy for absolute coordinates
- Cleaned up config.py from scenario-specific constants
1843_integration
RUSHIL AMBARISH KADU 2 months ago
parent
commit
7089c35d09
  1. 18
      config.py
  2. 109
      src/main.py

18
config.py

@ -22,18 +22,8 @@ LIDAR_ROTATION_FREQUENCY = FPS
MAX_FRAMES = 200
# -----------------------------------------------------------------------
# Scenario defaults (scenarios read these via getattr(config, KEY, default))
# Global Defaults
# -----------------------------------------------------------------------
DEFAULT_SCENARIO = "braking"
# BrakingScenario
SCENARIO_LEAD_DISTANCE = 25 # metres ahead of ego for lead vehicle
SCENARIO_BRAKE_FRAME = 80 # frame on which the lead vehicle emergency-brakes
# CutInScenario
SCENARIO_CUTIN_DISTANCE = 15 # metres ahead of ego for NPC in adjacent lane
SCENARIO_CUTIN_FRAME = 60 # frame on which NPC is forced to change lane
# ObstacleScenario
SCENARIO_OBSTACLE_DISTANCE = 30 # metres ahead of ego for static prop
SCENARIO_OBSTACLE_PROP = "static.prop.trafficcone01"
DEFAULT_SCENARIO = "braking"
DEFAULT_EGO_MODEL = "vehicle.tesla.model3"
DEFAULT_WEATHER = "ClearNoon"

109
src/main.py

@ -59,8 +59,14 @@ def parse_args():
parser.add_argument(
"--weather", "-w",
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(
"--list-scenarios", "-l",
@ -88,12 +94,31 @@ def main():
from sensors import SensorManager
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)
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
@ -101,26 +126,19 @@ def main():
client = carla.Client("localhost", 2000)
client.set_timeout(10.0)
world = client.get_world()
world = client.get_world()
# Apply Weather (CLI > Scenario > Config)
from utils import get_weather_preset
# 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}")
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()
map_ = world.get_map()
@ -148,32 +166,46 @@ def main():
# ------------------------------------------------------------------
# 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()
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:
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})")
# Fallback to searching if not specified or failed
print(f"[INFO] Ego spawned at requested absolute transform: {sp_req.location}")
# Fallback search if no request was made
if ego_vehicle is None:
for i, sp in enumerate(spawn_points):
ego_vehicle = world.try_spawn_actor(vehicle_bp, sp)
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
if ego_vehicle is None:
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())
# Notify scenario of ego spawn (optional hook)
@ -194,6 +226,9 @@ def main():
# ------------------------------------------------------------------
# 6. Scenario setup
# ------------------------------------------------------------------
# Tick once to settle ego physics before scenario setup starts calculating waypoints
world.tick()
scenario.setup(world, ego_vehicle, traffic_manager)
print(f"[INFO] Running scenario: '{scenario.name}' for {max_frames} frames")

Loading…
Cancel
Save