From e29d3421072eb96937d22cb7da3b2e40e31bdec9 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Tue, 7 May 2024 19:01:48 +0000 Subject: [PATCH 01/10] started building client for mission --- spot_wrapper/spot_mission_wrapper | 198 ++++++++++++++++++++++++++++++ spot_wrapper/wrapper.py | 1 + 2 files changed, 199 insertions(+) create mode 100644 spot_wrapper/spot_mission_wrapper diff --git a/spot_wrapper/spot_mission_wrapper b/spot_wrapper/spot_mission_wrapper new file mode 100644 index 0000000..6375bae --- /dev/null +++ b/spot_wrapper/spot_mission_wrapper @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 +import logging +import time +import typing + +from bosdyn.api import header_pb2 +from bosdyn.client import robot_command +from bosdyn.client.lease import Lease, LeaseClient, LeaseWallet +from bosdyn.client.robot import Robot +from bosdyn.client.spot_check import SpotCheckClient, run_spot_check, spot_check_pb2 +from google.protobuf.timestamp_pb2 import Timestamp + +from bosdyn.mission.client import MissionClient + +from spot_wrapper.wrapper_helpers import RobotState + + +class SpotMission: + """ + Allow access to mission functionality through the SDK + """ + + def __init__( + self, + robot: Robot, + logger: logging.Logger, + robot_state: RobotState, + mission_client: MissionClient, + robot_command_client: robot_command.RobotCommandClient, + lease_client: LeaseClient, + ) -> None: + self._robot = robot + self._logger = logger + self._mission_client: MissionClient = mission_client + self._robot_command_client = robot_command_client + self._lease_client = lease_client + self._robot_state = robot_state + self._spot_check_resp = None + self._lease = None + self._lease_wallet: LeaseWallet = self._lease_client.lease_wallet + + def _get_lease(self) -> Lease: + self._lease = self._lease_wallet.get_lease() + return self._lease + + def _load_mission(self, root, leases=[]): + """Load a mission""" + return + + def _play_mission(self, pause_time_secs, leases=[], settings=None,): + """Play loaded mission""" + return + + def _get_mission_state(self, upper_tick_bound=None, lower_tick_bound=None, past_ticks=None): + """Get the state of the current mission""" + return + + def _pause_mission(self): + """Pause mission""" + return + + def _restart_mission(self, pause_time_secs, leases=[], settings=None): + """Restart mission after pause""" + return + + def _stop_mission(self): + """Stop the current mission""" + return + + + def _spot_check_cmd(self, command: spot_check_pb2.SpotCheckCommandRequest): + """Send a Spot Check command""" + start_time_seconds, start_time_ns = int(time.time()), int(time.time_ns() % 1e9) + req = spot_check_pb2.SpotCheckCommandRequest( + header=header_pb2.RequestHeader( + request_timestamp=Timestamp(seconds=start_time_seconds, nanos=start_time_ns), + client_name="spot-check", + disable_rpc_logging=False, + ), + lease=self._get_lease().lease_proto, + command=command, + ) + self._spot_check_client.spot_check_command(req) + + def stop_check(self) -> typing.Tuple[bool, str]: + """Stop the Spot Check + Note: This may cause the robot to enter a FaultState. Use only in emergencies. + """ + self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_ABORT) + + # Get feedback + resp = self._req_feedback() + + # Check for errors + success, status = self._feedback_error_check(resp) + + if success: + status = "Successfully stopped Spot Check" + self._logger.info(status) + else: + self._logger.error("Failed to stop Spot Check") + + return success, status + + def revert_calibration(self) -> typing.Tuple[bool, str]: + """Revert calibration for Spot Check""" + self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_REVERT_CAL) + + # Get feedback + resp = self._req_feedback() + + # Check for errors + success, status = self._feedback_error_check(resp) + + if success: + status = "Successfully reverted calibration" + self._logger.info(status) + else: + status = "Failed to revert calibration" + self._logger.error(status) + + return success, status + + def start_check(self) -> typing.Tuple[bool, str]: + """Start the Spot Check""" + # Make sure we're powered on and sitting + try: + self._robot.power_on() + if not self._robot_state.is_sitting: + robot_command.blocking_sit(command_client=self._robot_command_client, timeout_sec=10) + self._logger.info("Spot is sitting") + else: + self._logger.info("Spot is already sitting") + + self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_START) + + # Get feedback + resp = self._req_feedback() + + # Check for errors + success, status = self._feedback_error_check(resp) + + if success: + status = "Successfully started Spot Check" + self._logger.info(status) + else: + self._logger.error("Failed to start Spot Check") + return success, status + + except Exception as e: + return False, f"Exception running start_check from spot check: {str(e)}" + + def blocking_check( + self, + timeout_sec: int = 360, + update_freq: float = 0.25, + verbose: bool = False, + ) -> typing.Tuple[bool, str]: + """Check the robot + Args: + timeout_sec: Timeout for the blocking check + update_freq: Frequency to update the check + verbose: Whether to print the check status + Returns: + Tuple of (success, message) + """ + try: + # Make sure we're powered on and sitting + self._robot.power_on() + if not self._robot_state.is_sitting: + robot_command.blocking_sit(command_client=self._robot_command_client, timeout_sec=10) + self._logger.info("Spot is sitting") + else: + self._logger.info("Spot is already sitting") + + # Check the robot and block for timeout_sec + self._logger.info("Blocking Spot Check is starting!") + resp: spot_check_pb2.SpotCheckFeedbackResponse = run_spot_check( + self._spot_check_client, + self._get_lease(), + timeout_sec, + update_freq, + verbose, + ) + + self._logger.info("Blocking Spot Check ran successfully!") + success, status = self._feedback_error_check(resp) + + return success, status + + except Exception as e: + self._logger.error("Exception thrown during blocking spot check: {}".format(e)) + return False, str(e) + + def get_feedback(self) -> spot_check_pb2.SpotCheckFeedbackResponse: + """Get feedback from Spot Check""" + resp = self._req_feedback() + return resp[0], "Got only feedback from Spot Check" diff --git a/spot_wrapper/wrapper.py b/spot_wrapper/wrapper.py index 65e1bbd..bdb72fe 100644 --- a/spot_wrapper/wrapper.py +++ b/spot_wrapper/wrapper.py @@ -54,6 +54,7 @@ from bosdyn.client.spot_check import SpotCheckClient from bosdyn.client.time_sync import TimeSyncEndpoint from bosdyn.client.world_object import WorldObjectClient +from bosdyn.mission.client import MissionClient from bosdyn.geometry import EulerZXY from bosdyn.mission.client import MissionClient from google.protobuf.timestamp_pb2 import Timestamp From 477872eac9f9953e12ac246c2a979043effcc850 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Wed, 8 May 2024 16:41:16 +0000 Subject: [PATCH 02/10] filled in spot_mission wrapper --- spot_wrapper/spot_mission_wrapper | 284 ++++++++++++++---------------- spot_wrapper/wrapper.py | 6 + 2 files changed, 143 insertions(+), 147 deletions(-) diff --git a/spot_wrapper/spot_mission_wrapper b/spot_wrapper/spot_mission_wrapper index 6375bae..9da36f1 100644 --- a/spot_wrapper/spot_mission_wrapper +++ b/spot_wrapper/spot_mission_wrapper @@ -1,17 +1,20 @@ #!/usr/bin/env python3 import logging import time -import typing +from typing import Optional -from bosdyn.api import header_pb2 from bosdyn.client import robot_command from bosdyn.client.lease import Lease, LeaseClient, LeaseWallet from bosdyn.client.robot import Robot -from bosdyn.client.spot_check import SpotCheckClient, run_spot_check, spot_check_pb2 -from google.protobuf.timestamp_pb2 import Timestamp - -from bosdyn.mission.client import MissionClient +from bosdyn.mission.client import ( + MissionClient, + CompilationError, + ValidationError, + NoMissionError, + NoMissionPlayingError +) +from bosdyn.client import RpcError from spot_wrapper.wrapper_helpers import RobotState @@ -43,156 +46,143 @@ class SpotMission: self._lease = self._lease_wallet.get_lease() return self._lease - def _load_mission(self, root, leases=[]): - """Load a mission""" - return + def _load_mission(self, root, leases=[], data_chunk_byte_size: Optional[int]=None): + """Load a mission + Args: + root: Root node in a mission. + leases: All leases necessary to initialize a mission. + data_chunk_byte_size: Optional max size of each streamed message + Raises: + RpcError: Problem communicating with the robot. + bosdyn.mission.client.CompilationError: The mission failed to compile. + bosdyn.mission.client.ValidationError: The mission failed to validate. + """ + if data_chunk_byte_size: + return self._load_mission_as_chunks(root, leases, data_chunk_byte_size) + try: + resp = self._mission_client.load_mission_async(root, leases) + except RpcError: + resp = (False, "Could not communicate with the robot") + except CompilationError as e: + resp = (False, f"The mission failed to compile: {e}") + except ValidationError as e: + resp = (False, f"The mission could not be validated: {e}") + return resp + + + def _load_mission_as_chunks(self, root, leases=[], data_chunk_byte_size=1000 * 1000): + """Load a mission onto the robot. + Args: + root: Root node in a mission. + leases: All leases necessary to initialize a mission. + data_chunk_byte_size: max size of each streamed message + Raises: + RpcError: Problem communicating with the robot. + bosdyn.mission.client.CompilationError: The mission failed to compile. + bosdyn.mission.client.ValidationError: The mission failed to validate. + """ + try: + resp = self._mission_client.load_mission_as_chunks2(root, leases, data_chunk_byte_size) + except RpcError: + resp = (False, "Could not communicate with the robot") + except CompilationError as e: + resp = (False, f"The mission failed to compile: {e}") + except ValidationError as e: + resp = (False, f"The mission could not be validated: {e}") + return resp + + def get_mission_info(self): + """Get static information about the loaded mission. + + Raises: + RpcError: Problem communicating with the robot. + """ + try: + return self._mission_client.get_info() + except RpcError: + return False, "Could not communicate with the robot" def _play_mission(self, pause_time_secs, leases=[], settings=None,): - """Play loaded mission""" - return + """Play loaded mission + Args: + pause_time_secs: Absolute time when the mission should pause execution. Subsequent RPCs + will override this value, so you can use this to say "if you don't hear from me again, + stop running the mission at this time." + leases: Leases the mission service will need to use. Unlike other clients, these MUST + be specified. + Raises: + RpcError: Problem communicating with the robot. + NoMissionError: No mission Loaded. + """ + try: + resp = self._mission_client.play_mission_async(pause_time_secs, leases, settings) + except RpcError: + resp = (False, "Could not communicate with the robot") + except NoMissionError: + resp = (False, "No mission loaded") + return resp def _get_mission_state(self, upper_tick_bound=None, lower_tick_bound=None, past_ticks=None): - """Get the state of the current mission""" - return + """Get the state of the current playing mission + Raises: + RpcError: Problem communicating with the robot. + NoMissionPlayingError: No mission playing. + """ + try: + resp = self._mission_client.get_state_async(upper_tick_bound, lower_tick_bound, past_ticks) + except RpcError: + resp = (False, "Could not communicate with the robot") + except NoMissionPlayingError: + resp = (False, "No mission playing") + return resp def _pause_mission(self): - """Pause mission""" - return + """Pause mission + Raises: + RpcError: Problem communicating with the robot. + NoMissionPlayingError: No mission playing. + """ + try: + resp = self._mission_client.pause_mission_async() + except RpcError: + resp = (False, "Could not communicate with the robot") + except NoMissionPlayingError: + resp = (False, "No mission playing") + return resp def _restart_mission(self, pause_time_secs, leases=[], settings=None): - """Restart mission after pause""" - return - - def _stop_mission(self): - """Stop the current mission""" - return - - - def _spot_check_cmd(self, command: spot_check_pb2.SpotCheckCommandRequest): - """Send a Spot Check command""" - start_time_seconds, start_time_ns = int(time.time()), int(time.time_ns() % 1e9) - req = spot_check_pb2.SpotCheckCommandRequest( - header=header_pb2.RequestHeader( - request_timestamp=Timestamp(seconds=start_time_seconds, nanos=start_time_ns), - client_name="spot-check", - disable_rpc_logging=False, - ), - lease=self._get_lease().lease_proto, - command=command, - ) - self._spot_check_client.spot_check_command(req) - - def stop_check(self) -> typing.Tuple[bool, str]: - """Stop the Spot Check - Note: This may cause the robot to enter a FaultState. Use only in emergencies. + """Restart mission after pause + Args: + pause_time_secs: Absolute time when the mission should pause execution. Subsequent RPCs + to RestartMission will override this value, so you can use this to say "if you don't hear + from me again, stop running the mission at this time." + leases: Leases the mission service will need to use. Unlike other clients, these MUST + be specified. + Raises: + RpcError: Problem communicating with the robot. + NoMissionError: No Mission Loaded. + bosdyn.mission.client.ValidationError: The mission failed to validate. """ - self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_ABORT) - - # Get feedback - resp = self._req_feedback() - - # Check for errors - success, status = self._feedback_error_check(resp) - - if success: - status = "Successfully stopped Spot Check" - self._logger.info(status) - else: - self._logger.error("Failed to stop Spot Check") - - return success, status - - def revert_calibration(self) -> typing.Tuple[bool, str]: - """Revert calibration for Spot Check""" - self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_REVERT_CAL) - - # Get feedback - resp = self._req_feedback() - - # Check for errors - success, status = self._feedback_error_check(resp) - - if success: - status = "Successfully reverted calibration" - self._logger.info(status) - else: - status = "Failed to revert calibration" - self._logger.error(status) - - return success, status - - def start_check(self) -> typing.Tuple[bool, str]: - """Start the Spot Check""" - # Make sure we're powered on and sitting try: - self._robot.power_on() - if not self._robot_state.is_sitting: - robot_command.blocking_sit(command_client=self._robot_command_client, timeout_sec=10) - self._logger.info("Spot is sitting") - else: - self._logger.info("Spot is already sitting") - - self._spot_check_cmd(spot_check_pb2.SpotCheckCommandRequest.COMMAND_START) - - # Get feedback - resp = self._req_feedback() - - # Check for errors - success, status = self._feedback_error_check(resp) - - if success: - status = "Successfully started Spot Check" - self._logger.info(status) - else: - self._logger.error("Failed to start Spot Check") - return success, status - - except Exception as e: - return False, f"Exception running start_check from spot check: {str(e)}" - - def blocking_check( - self, - timeout_sec: int = 360, - update_freq: float = 0.25, - verbose: bool = False, - ) -> typing.Tuple[bool, str]: - """Check the robot - Args: - timeout_sec: Timeout for the blocking check - update_freq: Frequency to update the check - verbose: Whether to print the check status - Returns: - Tuple of (success, message) + resp = self._mission_client.restart_mission_async(pause_time_secs, leases, settings) + except RpcError: + resp = (False, "Could not communicate with the robot") + except NoMissionError: + resp = (False, "No mission loaded") + except ValidationError as e: + resp = (False, f"The mission could not be validated: {e}") + return resp + + def _stop_mission(self): + """Stop the current mission + Raises: + RpcError: Problem communicating with the robot. + NoMissionPlayingError: No mission playing. """ try: - # Make sure we're powered on and sitting - self._robot.power_on() - if not self._robot_state.is_sitting: - robot_command.blocking_sit(command_client=self._robot_command_client, timeout_sec=10) - self._logger.info("Spot is sitting") - else: - self._logger.info("Spot is already sitting") - - # Check the robot and block for timeout_sec - self._logger.info("Blocking Spot Check is starting!") - resp: spot_check_pb2.SpotCheckFeedbackResponse = run_spot_check( - self._spot_check_client, - self._get_lease(), - timeout_sec, - update_freq, - verbose, - ) - - self._logger.info("Blocking Spot Check ran successfully!") - success, status = self._feedback_error_check(resp) - - return success, status - - except Exception as e: - self._logger.error("Exception thrown during blocking spot check: {}".format(e)) - return False, str(e) - - def get_feedback(self) -> spot_check_pb2.SpotCheckFeedbackResponse: - """Get feedback from Spot Check""" - resp = self._req_feedback() - return resp[0], "Got only feedback from Spot Check" + resp = self._mission_client.stop_mission_async() + except RpcError: + resp = (False, "Could not communicate with the robot") + except NoMissionPlayingError: + resp = (False, "No mission playing") + return resp diff --git a/spot_wrapper/wrapper.py b/spot_wrapper/wrapper.py index bdb72fe..e49ff23 100644 --- a/spot_wrapper/wrapper.py +++ b/spot_wrapper/wrapper.py @@ -68,6 +68,7 @@ from .spot_images import SpotImages from .spot_mission_wrapper import SpotMission from .spot_world_objects import SpotWorldObjects +from .spot_mission_wrapper import SpotMission from .wrapper_helpers import ClaimAndPowerDecorator, RobotCommandData, RobotState SPOT_CLIENT_NAME = "ros_spot" @@ -740,6 +741,11 @@ def spot_arm(self) -> SpotArm: def spot_check(self) -> SpotCheck: """Return SpotCheck instance""" return self._spot_check + + @property + def spot_mission(self) -> SpotMission: + """Return SpotMission instance""" + return self._spot_mission @property def spot_mission(self) -> SpotMission: From 3264e0e5e5ee882402740f79448bf14619b92ebf Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Thu, 9 May 2024 17:44:18 +0000 Subject: [PATCH 03/10] mission client wrapper done; testing/debugging --- spot_wrapper/spot_mission_wrapper | 188 ------------------------------ 1 file changed, 188 deletions(-) delete mode 100644 spot_wrapper/spot_mission_wrapper diff --git a/spot_wrapper/spot_mission_wrapper b/spot_wrapper/spot_mission_wrapper deleted file mode 100644 index 9da36f1..0000000 --- a/spot_wrapper/spot_mission_wrapper +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -import logging -import time -from typing import Optional - -from bosdyn.client import robot_command -from bosdyn.client.lease import Lease, LeaseClient, LeaseWallet -from bosdyn.client.robot import Robot - -from bosdyn.mission.client import ( - MissionClient, - CompilationError, - ValidationError, - NoMissionError, - NoMissionPlayingError -) -from bosdyn.client import RpcError -from spot_wrapper.wrapper_helpers import RobotState - - -class SpotMission: - """ - Allow access to mission functionality through the SDK - """ - - def __init__( - self, - robot: Robot, - logger: logging.Logger, - robot_state: RobotState, - mission_client: MissionClient, - robot_command_client: robot_command.RobotCommandClient, - lease_client: LeaseClient, - ) -> None: - self._robot = robot - self._logger = logger - self._mission_client: MissionClient = mission_client - self._robot_command_client = robot_command_client - self._lease_client = lease_client - self._robot_state = robot_state - self._spot_check_resp = None - self._lease = None - self._lease_wallet: LeaseWallet = self._lease_client.lease_wallet - - def _get_lease(self) -> Lease: - self._lease = self._lease_wallet.get_lease() - return self._lease - - def _load_mission(self, root, leases=[], data_chunk_byte_size: Optional[int]=None): - """Load a mission - Args: - root: Root node in a mission. - leases: All leases necessary to initialize a mission. - data_chunk_byte_size: Optional max size of each streamed message - Raises: - RpcError: Problem communicating with the robot. - bosdyn.mission.client.CompilationError: The mission failed to compile. - bosdyn.mission.client.ValidationError: The mission failed to validate. - """ - if data_chunk_byte_size: - return self._load_mission_as_chunks(root, leases, data_chunk_byte_size) - try: - resp = self._mission_client.load_mission_async(root, leases) - except RpcError: - resp = (False, "Could not communicate with the robot") - except CompilationError as e: - resp = (False, f"The mission failed to compile: {e}") - except ValidationError as e: - resp = (False, f"The mission could not be validated: {e}") - return resp - - - def _load_mission_as_chunks(self, root, leases=[], data_chunk_byte_size=1000 * 1000): - """Load a mission onto the robot. - Args: - root: Root node in a mission. - leases: All leases necessary to initialize a mission. - data_chunk_byte_size: max size of each streamed message - Raises: - RpcError: Problem communicating with the robot. - bosdyn.mission.client.CompilationError: The mission failed to compile. - bosdyn.mission.client.ValidationError: The mission failed to validate. - """ - try: - resp = self._mission_client.load_mission_as_chunks2(root, leases, data_chunk_byte_size) - except RpcError: - resp = (False, "Could not communicate with the robot") - except CompilationError as e: - resp = (False, f"The mission failed to compile: {e}") - except ValidationError as e: - resp = (False, f"The mission could not be validated: {e}") - return resp - - def get_mission_info(self): - """Get static information about the loaded mission. - - Raises: - RpcError: Problem communicating with the robot. - """ - try: - return self._mission_client.get_info() - except RpcError: - return False, "Could not communicate with the robot" - - def _play_mission(self, pause_time_secs, leases=[], settings=None,): - """Play loaded mission - Args: - pause_time_secs: Absolute time when the mission should pause execution. Subsequent RPCs - will override this value, so you can use this to say "if you don't hear from me again, - stop running the mission at this time." - leases: Leases the mission service will need to use. Unlike other clients, these MUST - be specified. - Raises: - RpcError: Problem communicating with the robot. - NoMissionError: No mission Loaded. - """ - try: - resp = self._mission_client.play_mission_async(pause_time_secs, leases, settings) - except RpcError: - resp = (False, "Could not communicate with the robot") - except NoMissionError: - resp = (False, "No mission loaded") - return resp - - def _get_mission_state(self, upper_tick_bound=None, lower_tick_bound=None, past_ticks=None): - """Get the state of the current playing mission - Raises: - RpcError: Problem communicating with the robot. - NoMissionPlayingError: No mission playing. - """ - try: - resp = self._mission_client.get_state_async(upper_tick_bound, lower_tick_bound, past_ticks) - except RpcError: - resp = (False, "Could not communicate with the robot") - except NoMissionPlayingError: - resp = (False, "No mission playing") - return resp - - def _pause_mission(self): - """Pause mission - Raises: - RpcError: Problem communicating with the robot. - NoMissionPlayingError: No mission playing. - """ - try: - resp = self._mission_client.pause_mission_async() - except RpcError: - resp = (False, "Could not communicate with the robot") - except NoMissionPlayingError: - resp = (False, "No mission playing") - return resp - - def _restart_mission(self, pause_time_secs, leases=[], settings=None): - """Restart mission after pause - Args: - pause_time_secs: Absolute time when the mission should pause execution. Subsequent RPCs - to RestartMission will override this value, so you can use this to say "if you don't hear - from me again, stop running the mission at this time." - leases: Leases the mission service will need to use. Unlike other clients, these MUST - be specified. - Raises: - RpcError: Problem communicating with the robot. - NoMissionError: No Mission Loaded. - bosdyn.mission.client.ValidationError: The mission failed to validate. - """ - try: - resp = self._mission_client.restart_mission_async(pause_time_secs, leases, settings) - except RpcError: - resp = (False, "Could not communicate with the robot") - except NoMissionError: - resp = (False, "No mission loaded") - except ValidationError as e: - resp = (False, f"The mission could not be validated: {e}") - return resp - - def _stop_mission(self): - """Stop the current mission - Raises: - RpcError: Problem communicating with the robot. - NoMissionPlayingError: No mission playing. - """ - try: - resp = self._mission_client.stop_mission_async() - except RpcError: - resp = (False, "Could not communicate with the robot") - except NoMissionPlayingError: - resp = (False, "No mission playing") - return resp From e29a2413d0f58414ede1624fba02f9cebccc6931 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Fri, 10 May 2024 14:27:54 +0000 Subject: [PATCH 04/10] linting and bug fixes --- spot_wrapper/wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spot_wrapper/wrapper.py b/spot_wrapper/wrapper.py index e49ff23..cabca30 100644 --- a/spot_wrapper/wrapper.py +++ b/spot_wrapper/wrapper.py @@ -54,7 +54,6 @@ from bosdyn.client.spot_check import SpotCheckClient from bosdyn.client.time_sync import TimeSyncEndpoint from bosdyn.client.world_object import WorldObjectClient -from bosdyn.mission.client import MissionClient from bosdyn.geometry import EulerZXY from bosdyn.mission.client import MissionClient from google.protobuf.timestamp_pb2 import Timestamp @@ -69,6 +68,7 @@ from .spot_mission_wrapper import SpotMission from .spot_world_objects import SpotWorldObjects from .spot_mission_wrapper import SpotMission +from .spot_world_objects import SpotWorldObjects from .wrapper_helpers import ClaimAndPowerDecorator, RobotCommandData, RobotState SPOT_CLIENT_NAME = "ros_spot" From 9d3b1c864d9c94a17e71a5c38f32515e9fc4b4d6 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Fri, 10 May 2024 15:13:06 +0000 Subject: [PATCH 05/10] linting --- spot_wrapper/spot_mission_wrapper.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spot_wrapper/spot_mission_wrapper.py b/spot_wrapper/spot_mission_wrapper.py index cd4b967..d5670fe 100644 --- a/spot_wrapper/spot_mission_wrapper.py +++ b/spot_wrapper/spot_mission_wrapper.py @@ -1,5 +1,4 @@ import logging -from typing import Optional from bosdyn.api.mission import nodes_pb2 from bosdyn.client import RpcError, robot_command From 1263694122ae20ddf56e00824e6e419c763d68a9 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Fri, 10 May 2024 19:37:33 +0000 Subject: [PATCH 06/10] minor typo fix --- spot_wrapper/spot_mission_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spot_wrapper/spot_mission_wrapper.py b/spot_wrapper/spot_mission_wrapper.py index d5670fe..abf94da 100644 --- a/spot_wrapper/spot_mission_wrapper.py +++ b/spot_wrapper/spot_mission_wrapper.py @@ -85,7 +85,7 @@ def _load_mission_as_chunks(self, root: nodes_pb2.Node, leases=None, data_chunk_ except ValidationError as e: return False, f"The mission could not be validated: {e}" - def get_mission_info(self): + def _get_mission_info(self): """Get static information about the loaded mission. Raises: From ab2e32590fde0735b052f2f3537ec1ed0fbf752e Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Mon, 13 May 2024 18:13:54 +0000 Subject: [PATCH 07/10] PR comments edits --- spot_wrapper/spot_mission_wrapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spot_wrapper/spot_mission_wrapper.py b/spot_wrapper/spot_mission_wrapper.py index abf94da..cd4b967 100644 --- a/spot_wrapper/spot_mission_wrapper.py +++ b/spot_wrapper/spot_mission_wrapper.py @@ -1,4 +1,5 @@ import logging +from typing import Optional from bosdyn.api.mission import nodes_pb2 from bosdyn.client import RpcError, robot_command @@ -85,7 +86,7 @@ def _load_mission_as_chunks(self, root: nodes_pb2.Node, leases=None, data_chunk_ except ValidationError as e: return False, f"The mission could not be validated: {e}" - def _get_mission_info(self): + def get_mission_info(self): """Get static information about the loaded mission. Raises: From 2a975f2518f572a60a7c767d59fb3c809b6c563c Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Wed, 15 May 2024 21:00:22 +0000 Subject: [PATCH 08/10] added mission service to mock spot directory --- spot_wrapper/testing/mocks/directory.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spot_wrapper/testing/mocks/directory.py b/spot_wrapper/testing/mocks/directory.py index 67ed12c..6749fc5 100644 --- a/spot_wrapper/testing/mocks/directory.py +++ b/spot_wrapper/testing/mocks/directory.py @@ -124,6 +124,11 @@ class MockDirectoryService(DirectoryServiceServicer): type="bosdyn.api.spot_cam.VersionService", authority="api.spot.robot", ), + ServiceEntry( + name="robot-mission", + type = "bosdyn.api.mission.MissionService", + authority="api.spot.robot", + ), ] } From 9a1781d94cac7d196dc7728772208d2c2af2cb56 Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Wed, 15 May 2024 21:04:37 +0000 Subject: [PATCH 09/10] lint --- spot_wrapper/testing/mocks/directory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spot_wrapper/testing/mocks/directory.py b/spot_wrapper/testing/mocks/directory.py index 6749fc5..6ae1669 100644 --- a/spot_wrapper/testing/mocks/directory.py +++ b/spot_wrapper/testing/mocks/directory.py @@ -126,7 +126,7 @@ class MockDirectoryService(DirectoryServiceServicer): ), ServiceEntry( name="robot-mission", - type = "bosdyn.api.mission.MissionService", + type="bosdyn.api.mission.MissionService", authority="api.spot.robot", ), ] From 4542ec437223e4d6708e453b5fdc6ff7cdf0bbbd Mon Sep 17 00:00:00 2001 From: Tiffany Cappellari Date: Wed, 15 May 2024 21:12:50 +0000 Subject: [PATCH 10/10] rebase error --- spot_wrapper/wrapper.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/spot_wrapper/wrapper.py b/spot_wrapper/wrapper.py index cabca30..65e1bbd 100644 --- a/spot_wrapper/wrapper.py +++ b/spot_wrapper/wrapper.py @@ -67,8 +67,6 @@ from .spot_images import SpotImages from .spot_mission_wrapper import SpotMission from .spot_world_objects import SpotWorldObjects -from .spot_mission_wrapper import SpotMission -from .spot_world_objects import SpotWorldObjects from .wrapper_helpers import ClaimAndPowerDecorator, RobotCommandData, RobotState SPOT_CLIENT_NAME = "ros_spot" @@ -741,11 +739,6 @@ def spot_arm(self) -> SpotArm: def spot_check(self) -> SpotCheck: """Return SpotCheck instance""" return self._spot_check - - @property - def spot_mission(self) -> SpotMission: - """Return SpotMission instance""" - return self._spot_mission @property def spot_mission(self) -> SpotMission: