diff --git a/flight/odlc_boundaries/search_path.py b/flight/odlc_boundaries/search_path.py index daea496f..42ced9b7 100644 --- a/flight/odlc_boundaries/search_path.py +++ b/flight/odlc_boundaries/search_path.py @@ -117,7 +117,7 @@ async def run() -> None: try: # create a drone object logging.info("Waiting for drone to connect...") - drone: dronekit.Vehicle = dronekit.connect(sitl.connection_string()) + drone: dronekit.Vehicle = dronekit.connect("tcp:127.0.0.1:5762") drone.wait_ready(True) logging.info("Waiting for pre-arm checks to pass...") @@ -210,7 +210,9 @@ async def run() -> None: ) # Generate search path - BUFFER_DISTANCE: int = -40 # use height/2 of camera image area on ground as buffer distance + BUFFER_DISTANCE: int = ( + -40 + ) # use height/2 of camera image area on ground as buffer distance search_paths: list[tuple[float, float]] = generate_search_paths( data_search_area_boundary_utm, BUFFER_DISTANCE ) diff --git a/flight/waypoint/goto.py b/flight/waypoint/goto.py index 3b0bf060..80be78f6 100644 --- a/flight/waypoint/goto.py +++ b/flight/waypoint/goto.py @@ -39,9 +39,9 @@ async def move_to( a float containing the requested longitude to move to altitude: float a float containing the requested altitude to go to in meters - airspeed: float, optional - a float containing the requested airspeed in meters per second; - if not specified, lets DroneKit decide the airspeed + airspeed: float, default None + a float containing the requested airspeed in meters per second, + or None to let DroneKit decide the airspeed """ drone.simple_goto( dronekit.LocationGlobalRelative(latitude, longitude, altitude), diff --git a/state_machine/drone.py b/state_machine/drone.py index ac75ab6a..1968896c 100644 --- a/state_machine/drone.py +++ b/state_machine/drone.py @@ -14,6 +14,8 @@ class Drone: ---------- address : str The address used to connect to the drone. + baud : int | None + The baud rate, or None to use the default. is_connected odlc_scan : bool A boolean to tell if the odlc zone needs to be scanned, used the @@ -27,15 +29,17 @@ class Drone: ------- __init__(connection_string: str) -> None Initialize a new Drone object, but do not connect to a drone. - connect_drone(self) -> Awaitable[None] - Connect to a drone. - is_connected(self) -> bool - Checks if a drone has been connected to. vehicle(self) -> dronekit.Vehicle Get the Dronekit Vehicle object owned by this Drone object. + is_connected(self) -> bool + Checks if a drone has been connected to. + connect_drone(self) -> Awaitable[None] + Connect to a drone. + close(self) -> Awaitable[none] + Close the owned DroneKit Vehicle object. """ - def __init__(self, address: str = "") -> None: + def __init__(self, address: str = "", baud: int | None = None) -> None: """ Initialize a new Drone object, but do not connect to a drone. @@ -44,29 +48,14 @@ def __init__(self, address: str = "") -> None: address : str, default "" The address of the drone to connect to when the `connect_drone()` method is called. + baud : int, default None + The baud rate, or None to use the default. """ self._vehicle: dronekit.Vehicle | None = None self.address: str = address + self.baud: int | None = baud self.odlc_scan: bool = True - async def connect_drone(self) -> None: - """Connect to a drone. This operation is idempotent. - - Raises - ------ - RuntimeError - If no connection address has been set. - """ - if self.is_connected: - return - - if len(self.address) == 0: - raise RuntimeError("no connection address specified") - - vehicle: dronekit.Vehicle = dronekit.connect(self.address) - vehicle.wait_ready(True) # this doesn't run asynchronously - self._vehicle = vehicle - @property def is_connected(self) -> bool: """Checks if a drone has been connected to. @@ -80,7 +69,7 @@ def is_connected(self) -> bool: @property def vehicle(self) -> dronekit.Vehicle: - """Get the Dronekit Vehicle object owned by this Drone object. + """Get the DroneKit Vehicle object owned by this Drone object. Returns ------- @@ -94,5 +83,29 @@ def vehicle(self) -> dronekit.Vehicle: """ vehicle: dronekit.Vehicle | None = self._vehicle if vehicle is None: - raise AttributeError("we haven't connected to the drone yet") + raise RuntimeError("we haven't connected to the drone yet") return vehicle + + async def connect_drone(self) -> None: + """Connect to a drone. This operation is idempotent. + + Raises + ------ + RuntimeError + If no connection address has been set. + """ + if self.is_connected: + return + + if len(self.address) == 0: + raise RuntimeError("no connection address specified") + + vehicle: dronekit.Vehicle = ( + dronekit.connect(self.address, wait_ready=True) + if self.baud is None + else dronekit.connect(self.address, wait_ready=True, baud=self.baud) + ) + + async def close(self) -> None: + """Close the owned DroneKit Vehicle object.""" + self.vehicle.close() diff --git a/state_machine/flight_manager.py b/state_machine/flight_manager.py index b2d3ebe8..a4914a97 100644 --- a/state_machine/flight_manager.py +++ b/state_machine/flight_manager.py @@ -60,13 +60,13 @@ async def run_manager( standard_object_count : int, default DEFAULT_STANDARD_OBJECT_COUNT The number of standard objects to attempt to find. """ - sitl: dronekit_sitl.SITL | None = None if sim_flag: sitl = dronekit_sitl.start_default() - self.drone.address = sitl.connection_string() + self.drone.address = "tcp:127.0.0.1:5762" else: - self.drone.address = "serial:///dev/ttyFTDI:921600" + self.drone.address = "/dev/ttyFTDI" + self.drone.baud = 921600 try: flight_settings_obj: FlightSettings = FlightSettings( @@ -103,6 +103,7 @@ async def run_manager( state_machine_task.cancel() await self._graceful_exit() finally: + await self.drone.close() if sitl is not None: sitl.stop()