Fix/e stop#10
Conversation
ratheron
left a comment
There was a problem hiding this comment.
I think this PR can be made significantly cleaner by removing all the extra checks.
| self._preset: None | str = None | ||
| self._strict_processing = strict_processing | ||
| self._strict_drone_match = strict_drone_match | ||
| self._active_swarm: Any | None = None |
There was a problem hiding this comment.
| self._active_swarm: Any | None = None | |
| self._active_swarm: DroneSwarm | None = None |
| self.music_manager.stop() | ||
| swarm.goto(final_pos_dict, duration=2.0) # Transition from ideal point to hover pos | ||
| if self.settings["land_on_docks"]: # Commented out for demo | ||
| if self.settings["land_on_docks"]: # Commented out for demo |
There was a problem hiding this comment.
Extra space from linting. The comment should be removed though
| server = uvicorn.Server(uvicorn.Config(app, host=host, port=port)) | ||
| # uvicorn captures SIGINT/SIGTERM itself (Server.capture_signals installs self.handle_exit) | ||
| # and only starts a graceful shutdown, which waits on the open events WebSocket while the | ||
| # deploy thread keeps flying. Wrap handle_exit so the first Ctrl+C cuts the motors before | ||
| # uvicorn begins draining. capture_signals installs whatever self.handle_exit is at call time. |
There was a problem hiding this comment.
I think we should only have the button. This CTRL+C handling seems like unnecessary overhead, since we are inside the frontend only anyway
| # In-flight loop coroutines self-cut on the latch; this also sends the packet directly | ||
| # to cover idle windows. Bounded so the caller never blocks on a loop that has stopped. | ||
| coro = self._parallel_by_uri("Emergency stop", uris, self._emergency_stop, timeout=0.5) | ||
| try: | ||
| if self._loop_thread is not None or self._loop.is_running(): | ||
| asyncio.run_coroutine_threadsafe(coro, self._loop).result(timeout=1.0) | ||
| else: | ||
| self._loop.run_until_complete(coro) | ||
| except Exception as exc: | ||
| logger.error(f"Emergency stop encountered errors: {exc}") |
There was a problem hiding this comment.
Isn't this essentially the same as just doing run?
| Sets a latch that halts the choreography stream and blocks further motion | ||
| commands so fresh setpoints cannot override the motor cut. | ||
| """ | ||
| self._estop.set() |
There was a problem hiding this comment.
Shouldn't really matter what other threads do. Not sure if we need this
| def emergency_stop_active_swarm(self) -> None: | ||
| """Emergency-stop the currently active deployment swarm, if one exists.""" | ||
| swarm = self._active_swarm | ||
| if swarm is None: | ||
| raise RuntimeError("No active deployment swarm to emergency stop.") | ||
| swarm.emergency_stop() | ||
| self.music_manager.stop() | ||
|
|
There was a problem hiding this comment.
Why are we not simply closing the swarm? This will also trigger an estop and reduces the number of changes significantly.
| class EmergencyStopActive(RuntimeError): | ||
| """Raised when a motion command is issued after the emergency-stop latch is set.""" | ||
|
|
||
|
|
| if await self._estop_guarded_sleep(uri, duration): | ||
| return |
There was a problem hiding this comment.
There are no continuous commands here -> we should be able to do a regular sleep in this thread. This is also true for all other sleeps
| if self._estop.is_set(): | ||
| await self._emergency_stop(uri) | ||
| return |
There was a problem hiding this comment.
This is the only point where checking for the estop makes sense, since the commands might overwrite the estop. However, emergency stop sets the estop, so calling emergency stop when estop is set doesn't make sense? Further, I think sending a command won't overwrite an estop, so we should be able to remove this.
now drones will immediately drop when pressing ctrl + c or pressing the e-stop button on the front end