"""Unified CLI for system identification tools. Usage: python scripts/sysid.py capture --robot-path assets/rotary_cartpole --duration 20 python scripts/sysid.py optimize --robot-path assets/rotary_cartpole --recording .npz python scripts/sysid.py visualize --recording .npz python scripts/sysid.py export --robot-path assets/rotary_cartpole --result .json """ from __future__ import annotations import sys from pathlib import Path # Ensure project root is on sys.path _PROJECT_ROOT = str(Path(__file__).resolve().parent.parent) if _PROJECT_ROOT not in sys.path: sys.path.insert(0, _PROJECT_ROOT) def main() -> None: if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"): print( "Usage: python scripts/sysid.py [options]\n" "\n" "Commands:\n" " capture Record real robot trajectory under PRBS excitation\n" " optimize Run CMA-ES parameter optimization\n" " visualize Plot real vs simulated trajectories\n" " export Write tuned URDF + robot.yaml files\n" "\n" "Run 'python scripts/sysid.py --help' for command-specific options." ) sys.exit(0) command = sys.argv[1] # Remove the subcommand from argv so the module's argparse works normally sys.argv = [f"sysid {command}"] + sys.argv[2:] if command == "capture": from src.sysid.capture import main as cmd_main elif command == "optimize": from src.sysid.optimize import main as cmd_main elif command == "visualize": from src.sysid.visualize import main as cmd_main elif command == "export": from src.sysid.export import main as cmd_main else: print(f"Unknown command: {command}") print("Available commands: capture, optimize, visualize, export") sys.exit(1) cmd_main() if __name__ == "__main__": main()