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.
207 lines
6.1 KiB
207 lines
6.1 KiB
"""
|
|
src/main.py
|
|
-----------
|
|
Entry point for the Fox CARLA ADAS simulation pipeline.
|
|
|
|
This file is now a thin CLI wrapper around the PipelineManager.
|
|
It parses arguments, builds a PipelineContext, and executes the
|
|
stage sequence: Simulation → Shenron → MCAP.
|
|
|
|
Usage
|
|
-----
|
|
python src/main.py --scenario braking
|
|
python src/main.py --scenario cutin --frames 120
|
|
python src/main.py --list-scenarios
|
|
python src/main.py --only-mcap --session data/braking_20260423_093000
|
|
python src/main.py --skip-shenron
|
|
|
|
This file never changes when new scenarios are added.
|
|
All scenario logic lives in scenarios/<name>.py.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
import argparse
|
|
|
|
# Add project root to sys.path
|
|
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
|
|
|
import config
|
|
from scenario_loader import list_scenarios
|
|
|
|
|
|
# -----------------------------------------------------------------------
|
|
# CLI
|
|
# -----------------------------------------------------------------------
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(
|
|
description="CARLA ADAS Simulation — stage-based pipeline runner"
|
|
)
|
|
parser.add_argument(
|
|
"--scenario", "-s",
|
|
type=str,
|
|
default=getattr(config, "DEFAULT_SCENARIO", "braking"),
|
|
help="Scenario name to run (e.g. braking, cutin, obstacle)"
|
|
)
|
|
parser.add_argument(
|
|
"--frames", "-f",
|
|
type=int,
|
|
default=None,
|
|
help="Override config.MAX_FRAMES for this run"
|
|
)
|
|
parser.add_argument(
|
|
"--spawn-point", "-p",
|
|
type=int,
|
|
default=None,
|
|
help="Index of the spawn point to use for ego vehicle"
|
|
)
|
|
parser.add_argument(
|
|
"--no-record",
|
|
action="store_true",
|
|
help="Disable image and metadata recording for faster iteration"
|
|
)
|
|
parser.add_argument(
|
|
"--weather", "-w",
|
|
type=str,
|
|
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",
|
|
action="store_true",
|
|
help="Print available scenarios and exit"
|
|
)
|
|
|
|
# --- Pipeline Stage Control ---
|
|
parser.add_argument(
|
|
"--skip-sim",
|
|
action="store_true",
|
|
help="Skip the simulation stage (requires --session)"
|
|
)
|
|
parser.add_argument(
|
|
"--skip-shenron",
|
|
action="store_true",
|
|
help="Skip the Shenron radar synthesis stage"
|
|
)
|
|
parser.add_argument(
|
|
"--skip-mcap",
|
|
action="store_true",
|
|
help="Skip the MCAP conversion stage"
|
|
)
|
|
parser.add_argument(
|
|
"--only-mcap",
|
|
action="store_true",
|
|
help="Run only the MCAP stage (requires --session)"
|
|
)
|
|
parser.add_argument(
|
|
"--only-shenron",
|
|
action="store_true",
|
|
help="Run only the Shenron stage (requires --session)"
|
|
)
|
|
parser.add_argument(
|
|
"--session",
|
|
type=str,
|
|
default=None,
|
|
help="Path to an existing session folder. Required when "
|
|
"skipping the simulation stage."
|
|
)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Main
|
|
# -----------------------------------------------------------------------
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
# ------------------------------------------------------------------
|
|
# 0. Clean up stale stop flags
|
|
# ------------------------------------------------------------------
|
|
flag_path = os.path.join(os.path.dirname(__file__), "..", "tmp", "stop.flag")
|
|
if os.path.exists(flag_path):
|
|
try:
|
|
os.remove(flag_path)
|
|
print("[INFO] Cleaned up stale stop.flag")
|
|
except Exception:
|
|
pass
|
|
|
|
if args.list_scenarios:
|
|
print("Available scenarios:")
|
|
for s in list_scenarios():
|
|
print(f" - {s}")
|
|
return
|
|
|
|
# ------------------------------------------------------------------
|
|
# 1. Build PipelineContext
|
|
# ------------------------------------------------------------------
|
|
from pipeline.base import PipelineContext
|
|
|
|
ctx = PipelineContext(
|
|
scenario_name=args.scenario,
|
|
args=args,
|
|
)
|
|
|
|
# Populate session_path if provided via CLI (for --skip-sim modes)
|
|
if args.session:
|
|
session = Path(args.session)
|
|
if session.exists():
|
|
ctx.session_path = session
|
|
print(f"[INFO] Using existing session: {session}")
|
|
else:
|
|
print(f"[ERROR] Session path does not exist: {args.session}")
|
|
return
|
|
|
|
# Determine which stages to skip
|
|
if args.only_mcap:
|
|
ctx.skip_stages = ["simulation", "shenron"]
|
|
elif args.only_shenron:
|
|
ctx.skip_stages = ["simulation", "mcap"]
|
|
else:
|
|
if args.skip_sim:
|
|
ctx.skip_stages.append("simulation")
|
|
if args.skip_shenron:
|
|
ctx.skip_stages.append("shenron")
|
|
if args.skip_mcap:
|
|
ctx.skip_stages.append("mcap")
|
|
|
|
# Validate: if sim is skipped, session_path must be provided
|
|
if "simulation" in ctx.skip_stages and ctx.session_path is None:
|
|
print("[ERROR] --session is required when skipping the simulation "
|
|
"stage (--skip-sim, --only-mcap, --only-shenron).")
|
|
return
|
|
|
|
# ------------------------------------------------------------------
|
|
# 2. Build & Execute Pipeline
|
|
# ------------------------------------------------------------------
|
|
from pipeline.manager import PipelineManager
|
|
from pipeline.stages.sim_stage import SimulationStage
|
|
from pipeline.stages.shenron_stage import ShenronStage
|
|
from pipeline.stages.mcap_stage import McapStage
|
|
from pipeline.stages.video_stage import VideoStage
|
|
|
|
manager = PipelineManager([
|
|
SimulationStage(),
|
|
ShenronStage(),
|
|
McapStage(),
|
|
VideoStage(),
|
|
])
|
|
|
|
manager.execute(ctx)
|
|
|
|
print("[INFO] Done")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|