|
98 | 98 | # Functions |
99 | 99 | ################################################################################ |
100 | 100 |
|
| 101 | +def _abort_missing_slot(protocol, ip, robot_name): |
| 102 | + """Check the robot has an extern slot in Webots, print a clear error and exit if not.""" |
| 103 | + import socket |
| 104 | + |
| 105 | + if protocol == "tcp": |
| 106 | + try: |
| 107 | + s = socket.create_connection((ip, 1234), timeout=2) |
| 108 | + s.close() |
| 109 | + except OSError: |
| 110 | + print(f"Error: Cannot reach Webots at {ip}:1234 via TCP. Is Webots running?") |
| 111 | + raise SystemExit(1) |
| 112 | + print(f"Warning: Cannot verify extern slot for '{robot_name}' over TCP — " |
| 113 | + "make sure the correct world is loaded.") |
| 114 | + return |
| 115 | + |
| 116 | + import getpass |
| 117 | + ipc_dir = f"/tmp/webots/{getpass.getuser()}/1234/ipc" |
| 118 | + if not os.path.isdir(ipc_dir): |
| 119 | + print("Error: Webots is not running or no world is loaded.") |
| 120 | + raise SystemExit(1) |
| 121 | + |
| 122 | + ipc_socket = f"{ipc_dir}/{robot_name}/extern" |
| 123 | + if not os.path.exists(ipc_socket): |
| 124 | + available = [n for n in os.listdir(ipc_dir) |
| 125 | + if os.path.exists(os.path.join(ipc_dir, n, "extern"))] |
| 126 | + slots = ", ".join(available) if available else "(none)" |
| 127 | + print(f"Error: Robot '{robot_name}' has no extern controller slot in the loaded world.") |
| 128 | + print(f" Available extern slots: {slots}") |
| 129 | + print(" Load a world where the robot has controller \"<extern>\".") |
| 130 | + raise SystemExit(1) |
| 131 | + |
| 132 | + try: |
| 133 | + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
| 134 | + s.settimeout(1) |
| 135 | + s.connect(ipc_socket) |
| 136 | + s.close() |
| 137 | + except OSError: |
| 138 | + print(f"Error: Extern slot for '{robot_name}' exists but is already claimed by another controller.") |
| 139 | + raise SystemExit(1) |
| 140 | + |
| 141 | + |
| 142 | +def check_webots_ready(source, target, env): # pylint: disable=unused-argument |
| 143 | + """Check that Webots is running and the robot has a free extern controller slot.""" |
| 144 | + protocol = env.GetProjectOption("custom_webots_protocol") |
| 145 | + ip = env.GetProjectOption("custom_webots_ip_address") |
| 146 | + robot_name = env.GetProjectOption("custom_webots_robot_name") |
| 147 | + _abort_missing_slot(protocol, ip, robot_name) |
| 148 | + |
| 149 | + |
101 | 150 | ################################################################################ |
102 | 151 | # Main |
103 | 152 | ################################################################################ |
|
107 | 156 | name="webots_launcher", |
108 | 157 | dependencies=PROGRAM_PATH + PROGRAM_NAME, |
109 | 158 | actions=[ |
| 159 | + check_webots_ready, |
110 | 160 | WEBOTS_LAUNCHER_ACTION |
111 | 161 | ], |
112 | 162 | title="Launch", |
|
0 commit comments