#!/usr/bin/env python3 """ A script to run the project in Webots. Largely just a shortcut to running the arena world in Webots. """ # ruff: noqa: E501 from __future__ import annotations import sys import traceback from os.path import expandvars from pathlib import Path from shutil import which from subprocess import Popen BOLD_RED = '\x1b[31;1m' RESET_COLOUR = '\x1b[0m' if sys.platform == "win32": from subprocess import CREATE_NEW_PROCESS_GROUP, DETACHED_PROCESS if (Path(__file__).parent / 'simulator/VERSION').exists(): print("Running in release mode") SIM_BASE = Path(__file__).parent.resolve() else: print("Running in development mode") # Assume the script is in the scripts directory SIM_BASE = Path(__file__).parents[1].resolve() POSSIBLE_WEBOTS_PATHS = [ ("darwin", "/Applications/Webots.app/Contents/MacOS/webots"), ("win32", "C:\\Program Files\\Webots\\msys64\\mingw64\\bin\\webotsw.exe"), ("win32", expandvars("%LOCALAPPDATA%\\Programs\\Webots\\msys64\\mingw64\\bin\\webotsw.exe")), # Attempt to use the start menu shortcut ("win32", expandvars("%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\Cyberbotics\\Webots.lnk")), ("win32", expandvars("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Cyberbotics\\Webots.lnk")), ("linux", "/usr/local/bin/webots"), ("linux", "/usr/bin/webots"), ] def get_webots_parameters() -> tuple[Path, Path]: """ Get the paths to the Webots executable and the arena world file. :return: The paths to the Webots executable and the arena world file """ world_file = SIM_BASE / "simulator/worlds/arena.wbt" if not world_file.exists(): raise RuntimeError("World file not found.") if not (SIM_BASE / "venv").exists(): raise RuntimeError("Please run the setup.py script before running the simulator.") # Check setup finish successfully if not (SIM_BASE / "venv/setup_success").exists(): raise RuntimeError("Setup has not completed successfully. Please re-run the setup.py script.") # Check if Webots is in the PATH webots = which("webots") # Find the webots executable, if it is not in the PATH if webots is None: for system_filter, path in POSSIBLE_WEBOTS_PATHS: if sys.platform.startswith(system_filter): print(f"Checking {path}") if Path(path).exists(): webots = path break if webots is None or not Path(webots).exists(): raise RuntimeError("Webots executable not found.") return Path(webots), world_file def main() -> None: """Run the project in Webots.""" try: webots, world_file = get_webots_parameters() # Run the world file in Webots, # detaching the process so it does not close when this script does if sys.platform == "win32": Popen( [str(webots), str(world_file)], creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, # shell=True is needed to run from shortcuts shell=(webots.suffix == ".lnk"), ) else: Popen([str(webots), str(world_file)], start_new_session=True) except RuntimeError as e: print(BOLD_RED) print(f"An error occurred: \n{e}") input(f"Press enter to continue...{RESET_COLOUR}") exit(1) except Exception as e: print(BOLD_RED) print(f"An error occurred: {e}") print(traceback.format_exc()) input(f"Press enter to continue...{RESET_COLOUR}") exit(1) if __name__ == "__main__": main()