def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) options = parser.parse_args() # Create robot object. sdk = create_standard_sdk('FiducialFollowClient') sdk.load_app_token(options.app_token) robot = sdk.create_robot(options.hostname) print("Authenticate robot") image_viewer = None fiducial_follower = None try: with Exit(): robot.authenticate(options.username, options.password) robot.start_time_sync() fiducial_follower = FiducialFollow(robot) time.sleep(.1) if fiducial_follower.display_images: image_viewer = DisplayImagesAsync(fiducial_follower) image_viewer.start() fiducial_follower.start() except RpcError as err: LOGGER.error("Failed to communicate with robot: %s", err) finally: if image_viewer is not None: image_viewer.stop() if fiducial_follower is not None: fiducial_follower.stop() return False
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) parser.add_argument("--distance-margin", default=.5, help="Distance [meters] that the robot should stop from the fiducial.") parser.add_argument("--limit-speed", default=True, type=lambda x: (str(x).lower() == 'true'), help="If the robot should limit its maximum speed.") parser.add_argument("--avoid-obstacles", default=False, type=lambda x: (str(x).lower() == 'true'), help="If the robot should have obstacle avoidance enabled.") parser.add_argument( "--use-world-objects", default=True, type=lambda x: (str(x).lower() == 'true'), help="If fiducials should be from the world object service or the apriltag library.") options = parser.parse_args() # If requested, attempt import of Apriltag library if not options.use_world_objects: try: global apriltag from apriltag import apriltag except ImportError as e: print("Could not import the AprilTag library. Aborting. Exception: ", str(e)) return False # Create robot object. sdk = create_standard_sdk('FollowFiducialClient') robot = sdk.create_robot(options.hostname) fiducial_follower = None image_viewer = None try: with Exit(): robot.authenticate(options.username, options.password) robot.start_time_sync() # Verify the robot is not estopped. assert not robot.is_estopped(), "Robot is estopped. " \ "Please use an external E-Stop client, " \ "such as the estop SDK example, to configure E-Stop." fiducial_follower = FollowFiducial(robot, options) time.sleep(.1) if not options.use_world_objects and str.lower(sys.platform) != "darwin": # Display the detected bounding boxes on the images when using the april tag library. # This is disabled for MacOS-X operating systems. image_viewer = DisplayImagesAsync(fiducial_follower) image_viewer.start() fiducial_follower.start() except RpcError as err: LOGGER.error("Failed to communicate with robot: %s", err) finally: if image_viewer is not None: image_viewer.stop() if fiducial_follower is not None: fiducial_follower.stop() return False
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) parser.add_argument( "--distance-margin", default=.5, help="Distance [meters] that the robot should stop from the fiducial.") parser.add_argument("--limit-speed", default=True, type=lambda x: (str(x).lower() == 'true'), help="If the robot should limit its maximum speed.") parser.add_argument( "--avoid-obstacles", default=False, type=lambda x: (str(x).lower() == 'true'), help="If the robot should have obstacle avoidance enabled.") parser.add_argument( "--use-world-objects", default=True, type=lambda x: (str(x).lower() == 'true'), help= "If fiducials should be from the world object service or the apriltag library." ) options = parser.parse_args() # Create robot object. sdk = create_standard_sdk('FollowFiducialClient') sdk.load_app_token(options.app_token) robot = sdk.create_robot(options.hostname) fiducial_follower = None image_viewer = None try: with Exit(): robot.authenticate(options.username, options.password) robot.start_time_sync() # Verify the robot is not estopped. verify_estop(robot) fiducial_follower = FollowFiducial(robot, options) time.sleep(.1) if not options.use_world_objects: # Display the detected bounding boxes on the images when using the april tag library. image_viewer = DisplayImagesAsync(fiducial_follower) image_viewer.start() fiducial_follower.start() except RpcError as err: LOGGER.error("Failed to communicate with robot: %s", err) finally: if image_viewer is not None: image_viewer.stop() if fiducial_follower is not None: fiducial_follower.stop() return False
def initialize_robot(options): """Generate a Robot objects, then authenticate and timesync. Returns: Robot """ sdk = create_standard_sdk('DoorExample') robot = sdk.create_robot(options.hostname) robot.authenticate(options.username, options.password) robot.time_sync.wait_for_sync() return robot
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) parser.add_argument( '--time-sync-interval-sec', help= 'The interval (seconds) that time-sync estimate should be updated.', type=float) options = parser.parse_args() stream_handler = _setup_logging(options.verbose) # Create robot object. sdk = create_standard_sdk('WASDClient') robot = sdk.create_robot(options.hostname) try: robot.authenticate(options.username, options.password) robot.start_time_sync(options.time_sync_interval_sec) except RpcError as err: LOGGER.error("Failed to communicate with robot: %s" % err) return False wasd_interface = WasdInterface(robot) try: wasd_interface.start() except (ResponseError, RpcError) as err: LOGGER.error("Failed to initialize robot communication: %s" % err) return False LOGGER.removeHandler( stream_handler) # Don't use stream handler in curses mode. try: try: # Prevent curses from introducing a 1 second delay for ESC key os.environ.setdefault('ESCDELAY', '0') # Run wasd interface in curses mode, then restore terminal config. curses.wrapper(wasd_interface.drive) finally: # Restore stream handler to show any exceptions or final messages. LOGGER.addHandler(stream_handler) except Exception as e: LOGGER.error("WASD has thrown an error: [%r] %s", e, e) finally: # Do any final cleanup steps. wasd_interface.shutdown() return True
def main(): """Command-line interface""" # pylint: disable=import-outside-toplevel import argparse from bosdyn.client import create_standard_sdk, InvalidLoginError from bosdyn.client.util import add_common_arguments parser = argparse.ArgumentParser() parser.add_argument('-T', '--timespan', default='5m', help='Time span (default last 5 minutes)') parser.add_argument('--help-timespan', action='store_true', help='Print time span formating options') parser.add_argument('-c', '--channel', help='Specify channel for data (default=all)') parser.add_argument('-t', '--type', help='Specify message type (default=all)') parser.add_argument('-s', '--service', help='Specify service name (default=all)') parser.add_argument('-o', '--output', help='Output file name (default is "download.bddf"') parser.add_argument('-R', '--robot-time', action='store_true', help='Specified timespan is in robot time') add_common_arguments(parser) options = parser.parse_args() if options.verbose: LOGGER.setLevel(logging.DEBUG) if options.help_timespan: _print_help_timespan() return 0 # Create a robot object. sdk = create_standard_sdk('bddf') robot = sdk.create_robot(options.hostname) # Use the robot object to authenticate to the robot. # A JWT Token is required to download log data. try: robot.authenticate(options.username, options.password) except InvalidLoginError as err: LOGGER.error("Cannot authenticate to robot to obtain token: %s", err) return 1 output_filename = download_data(robot, options.hostname, options.timespan, robot_time=options.robot_time, channel=options.channel, message_type=options.type, grpc_service=options.service, show_progress=True) if not output_filename: return 1 LOGGER.info("Wrote '%s'.", output_filename) return 0
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) parser.add_argument( 'directory', help='Output directory for graph map and mission file.') parser.add_argument( '--time-sync-interval-sec', help= 'The interval (seconds) that time-sync estimate should be updated.', type=float) options = parser.parse_args() stream_handler = setup_logging(options.verbose) # Create robot object. sdk = create_standard_sdk('MissionRecorderClient') robot = sdk.create_robot(options.hostname) try: robot.authenticate(options.username, options.password) robot.start_time_sync(options.time_sync_interval_sec) except RpcError as err: LOGGER.error("Failed to communicate with robot: %s" % err) return False recorder_interface = RecorderInterface(robot, options.directory) try: recorder_interface.start() except (ResponseError, RpcError) as err: LOGGER.error("Failed to initialize robot communication: %s" % err) return False try: # Run recorder interface in curses mode, then restore terminal config. curses.wrapper(recorder_interface.drive) except Exception as e: LOGGER.error("Mission recorder has thrown an error: %s" % repr(e)) finally: # Restore stream handler after curses mode. LOGGER.addHandler(stream_handler) return True
def prepare_download(hostname, username, password, timespan, channel, message_type, service): """Prepares all arguments for http get request.""" # Create a robot object. sdk = create_standard_sdk('bddf') robot = sdk.create_robot(hostname) # Use the robot object to authenticate to the robot. # A JWT Token is required to download log data. try: robot.authenticate(username, password) except RpcError as err: LOGGER.error("Cannot authenticate to robot to obtain token: %s", err) return 1 # Establish time sync with robot to obtain skew. time_sync_client = robot.ensure_client(TimeSyncClient.default_service_name) time_sync_endpoint = TimeSyncEndpoint(time_sync_client) did_establish = time_sync_endpoint.establish_timesync() if did_establish: LOGGER.debug("Established timesync, skew of sec:%d nanosec:%d", time_sync_endpoint.clock_skew.seconds, time_sync_endpoint.clock_skew.nanos) # Now assemble the query to obtain a bddf file. url = 'https://{}/v1/data-buffer/bddf/'.format(hostname) headers = {"Authorization": "Bearer {}".format(robot.user_token)} # Get the parameters for limiting the timespan of the response. get_params = request_timespan(timespan, time_sync_endpoint) # Optional parameters for limiting the messages if channel: get_params['channel'] = channel if message_type: get_params['type'] = message_type if service: get_params['grpc_service'] = service return url, headers, get_params
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) options = parser.parse_args() stream_handler = _setup_logging(options.verbose) # Create robot object. sdk = create_standard_sdk('WASDClient') sdk.load_app_token(options.app_token) robot = sdk.create_robot(options.hostname) try: robot.authenticate(options.username, options.password) robot.start_time_sync() except RpcError as err: LOGGER.error("Failed to communicate with robot: %s" % err) return False wasd_interface = WasdInterface(robot) try: wasd_interface.start() except (ResponseError, RpcError) as err: LOGGER.error("Failed to initialize robot communication: %s" % err) return False LOGGER.removeHandler(stream_handler) # Don't use stream handler in curses mode. try: # Run wasd interface in curses mode, then restore terminal config. curses.wrapper(wasd_interface.drive) except Exception as e: LOGGER.error("WASD has thrown an error: %s" % repr(e)) finally: # Restore stream handler after curses mode. LOGGER.addHandler(stream_handler) # Do any final cleanup steps. wasd_interface.shutdown() return True
def connect(self, cb=None, retry=False): self.__sdk = create_standard_sdk(self.app_name) try: self.__robot = self.__sdk.create_robot(self.hostname) logging.info(f"Authenticating payload with guid {self.guid}") self.__robot.authenticate_from_payload_credentials( guid=self.guid, secret=self.secret) logging.info("Starting time sync") self.__robot.start_time_sync() self.__preflight() if cb is not None: cb() except RpcError: logging.error( f"Could not connect with robot using {self.hostname}") if retry: logging.info(f"Retrying using {self.hostname}") self.connect(cb, retry) except InvalidPayloadCredentialsError: logging.error(f"Invalid guid '{self.guid}' or secret") except Exception as exc: logging.error(exc)
def __init__(self, username, password, hostname, logger, rates={}, callbacks={}): self._username = username self._password = password self._hostname = hostname self._logger = logger self._rates = rates self._callbacks = callbacks self._keep_alive = True self._valid = True self._mobility_params = RobotCommandBuilder.mobility_params() self._is_standing = False self._is_sitting = True self._is_moving = False self._last_stand_command = None self._last_sit_command = None self._last_motion_command = None self._last_motion_command_time = None self._front_image_requests = [] for source in front_image_sources: self._front_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) self._side_image_requests = [] for source in side_image_sources: self._side_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) self._rear_image_requests = [] for source in rear_image_sources: self._rear_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) try: self._sdk = create_standard_sdk('ros_spot') except Exception as e: self._logger.error("Error creating SDK object: %s", e) self._valid = False return self._robot = self._sdk.create_robot(self._hostname) try: self._robot.authenticate(self._username, self._password) self._robot.start_time_sync() except RpcError as err: self._logger.error("Failed to communicate with robot: %s", err) self._valid = False return if self._robot: # Clients try: self._robot_state_client = self._robot.ensure_client( RobotStateClient.default_service_name) self._robot_command_client = self._robot.ensure_client( RobotCommandClient.default_service_name) self._graph_nav_client = self._robot.ensure_client( GraphNavClient.default_service_name) self._power_client = self._robot.ensure_client( PowerClient.default_service_name) self._lease_client = self._robot.ensure_client( LeaseClient.default_service_name) self._lease_wallet = self._lease_client.lease_wallet self._image_client = self._robot.ensure_client( ImageClient.default_service_name) self._estop_client = self._robot.ensure_client( EstopClient.default_service_name) except Exception as e: self._logger.error("Unable to create client service: %s", e) self._valid = False return # Store the most recent knowledge of the state of the robot based on rpc calls. self._current_graph = None self._current_edges = dict( ) #maps to_waypoint to list(from_waypoint) self._current_waypoint_snapshots = dict( ) # maps id to waypoint snapshot self._current_edge_snapshots = dict() # maps id to edge snapshot self._current_annotation_name_to_wp_id = dict() # Async Tasks self._async_task_list = [] self._robot_state_task = AsyncRobotState( self._robot_state_client, self._logger, max(0.0, self._rates.get("robot_state", 0.0)), self._callbacks.get("robot_state", lambda: None)) self._robot_metrics_task = AsyncMetrics( self._robot_state_client, self._logger, max(0.0, self._rates.get("metrics", 0.0)), self._callbacks.get("metrics", lambda: None)) self._lease_task = AsyncLease( self._lease_client, self._logger, max(0.0, self._rates.get("lease", 0.0)), self._callbacks.get("lease", lambda: None)) self._front_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("front_image", 0.0)), self._callbacks.get("front_image", lambda: None), self._front_image_requests) self._side_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("side_image", 0.0)), self._callbacks.get("side_image", lambda: None), self._side_image_requests) self._rear_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("rear_image", 0.0)), self._callbacks.get("rear_image", lambda: None), self._rear_image_requests) self._idle_task = AsyncIdle(self._robot_command_client, self._logger, 10.0, self) self._estop_endpoint = None self._async_tasks = AsyncTasks([ self._robot_state_task, self._robot_metrics_task, self._lease_task, self._front_image_task, self._side_image_task, self._rear_image_task, self._idle_task ]) self._robot_id = None self._lease = None
def main(): # pylint: disable=too-many-locals """Command-line interface""" import argparse # pylint: disable=import-outside-toplevel parser = argparse.ArgumentParser() parser.add_argument('-T', '--timespan', help='Time span (default last 5 minutes)') parser.add_argument('--help-timespan', action='store_true', help='Print time span formatting options') parser.add_argument('-c', '--channel', help='Specify channel for data (default=all)') parser.add_argument('-t', '--type', help='Specify message type (default=all)') parser.add_argument('-s', '--service', help='Specify service name (default=all)') parser.add_argument('-o', '--output', help='Output file name (default is "download.bddf"') bosdyn.client.util.add_common_arguments(parser) options = parser.parse_args() if options.verbose: LOGGER.setLevel(logging.DEBUG) if options.help_timespan: _print_help_timespan() return 0 # Create a robot object. sdk = create_standard_sdk('bddf') robot = sdk.create_robot(options.hostname) # Use the robot object to authenticate to the robot. # A JWT Token is required to download log data. try: robot.authenticate(options.username, options.password) except RpcError as err: LOGGER.error("Cannot authenticate to robot to obtain token: %s", err) return 1 # Establish time sync with robot to obtain skew. time_sync_client = robot.ensure_client(TimeSyncClient.default_service_name) time_sync_endpoint = TimeSyncEndpoint(time_sync_client) did_establish = time_sync_endpoint.establish_timesync() if did_establish: LOGGER.debug("Established timesync, skew of sec:%d nanosec:%d", time_sync_endpoint.clock_skew.seconds, time_sync_endpoint.clock_skew.nanos) # Now assemble the query to obtain a bddf file. url = 'https://{}/v1/data-buffer/bddf/'.format(options.hostname) headers = {"Authorization": "Bearer {}".format(robot.user_token)} # Get the parameters for limiting the timespan of the response. get_params = request_timespan(options.timespan, time_sync_endpoint) # Optional parameters for limiting the messages if options.channel: get_params['channel'] = options.channel if options.type: get_params['type'] = options.type if options.service: get_params['grpc_service'] = options.service # Request the data. with requests.get(url, headers=headers, verify=False, stream=True, params=get_params) as resp: if resp.status_code != 200: LOGGER.error("https response: %d", resp.status_code) sys.exit(1) outfile = output_filename(options, resp) with open(outfile, 'wb') as fid: for chunk in resp.iter_content(chunk_size=REQUEST_CHUNK_SIZE): print('.', end='', flush=True) fid.write(chunk) print() LOGGER.info("Wrote '%s'.", outfile) return 0
def __init__(self, username, password, token, hostname, logger, rates={}, callbacks={}): self._username = username self._password = password self._token = token self._hostname = hostname self._logger = logger self._rates = rates self._callbacks = callbacks self._keep_alive = True self._valid = True self._mobility_params = RobotCommandBuilder.mobility_params() self._is_standing = False self._is_sitting = True self._is_moving = False self._last_stand_command = None self._last_sit_command = None self._last_motion_command = None self._last_motion_command_time = None self._front_image_requests = [] for source in front_image_sources: self._front_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) self._side_image_requests = [] for source in side_image_sources: self._side_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) self._rear_image_requests = [] for source in rear_image_sources: self._rear_image_requests.append( build_image_request( source, image_format=image_pb2.Image.Format.FORMAT_RAW)) try: self._sdk = create_standard_sdk('ros_spot') except Exception as e: self._logger.error("Error creating SDK object: %s", e) self._valid = False return try: self._sdk.load_app_token(self._token) except Exception as e: self._logger.error("Error loading developer token: %s", e) self._valid = False return self._robot = self._sdk.create_robot(self._hostname) try: self._robot.authenticate(self._username, self._password) self._robot.start_time_sync() except RpcError as err: self._logger.error("Failed to communicate with robot: %s", err) self._valid = False return if self._robot: # Clients try: self._robot_state_client = self._robot.ensure_client( RobotStateClient.default_service_name) self._robot_command_client = self._robot.ensure_client( RobotCommandClient.default_service_name) self._power_client = self._robot.ensure_client( PowerClient.default_service_name) self._lease_client = self._robot.ensure_client( LeaseClient.default_service_name) self._image_client = self._robot.ensure_client( ImageClient.default_service_name) self._estop_client = self._robot.ensure_client( EstopClient.default_service_name) except Exception as e: self._logger.error("Unable to create client service: %s", e) self._valid = False return # Async Tasks self._async_task_list = [] self._robot_state_task = AsyncRobotState( self._robot_state_client, self._logger, max(0.0, self._rates.get("robot_state", 0.0)), self._callbacks.get("robot_state", lambda: None)) self._robot_metrics_task = AsyncMetrics( self._robot_state_client, self._logger, max(0.0, self._rates.get("metrics", 0.0)), self._callbacks.get("metrics", lambda: None)) self._lease_task = AsyncLease( self._lease_client, self._logger, max(0.0, self._rates.get("lease", 0.0)), self._callbacks.get("lease", lambda: None)) self._front_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("front_image", 0.0)), self._callbacks.get("front_image", lambda: None), self._front_image_requests) self._side_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("side_image", 0.0)), self._callbacks.get("side_image", lambda: None), self._side_image_requests) self._rear_image_task = AsyncImageService( self._image_client, self._logger, max(0.0, self._rates.get("rear_image", 0.0)), self._callbacks.get("rear_image", lambda: None), self._rear_image_requests) self._idle_task = AsyncIdle(self._robot_command_client, self._logger, 10.0, self) self._estop_endpoint = EstopEndpoint(self._estop_client, 'ros', 9.0) self._async_tasks = AsyncTasks([ self._robot_state_task, self._robot_metrics_task, self._lease_task, self._front_image_task, self._side_image_task, self._rear_image_task, self._idle_task ]) self._robot_id = None self._lease = None
def main(): """Command-line interface.""" import argparse parser = argparse.ArgumentParser() bosdyn.client.util.add_common_arguments(parser) parser.add_argument( 'directory', help='Output directory for graph map and mission file.') parser.add_argument( '--time-sync-interval-sec', help= 'The interval (seconds) that time-sync estimate should be updated.', type=float) parser.add_argument( '--waypoint-commands-only', nargs='+', help= 'Build a mission from the graph on-robot, specifying these commands') options = parser.parse_args() if os.path.exists(options.directory): LOGGER.error("ERROR: Directory %s already exists." % options.directory) return False stream_handler = setup_logging(options.verbose) # Create robot object. sdk = create_standard_sdk('MissionRecorderClient') robot = sdk.create_robot(options.hostname) try: robot.authenticate(options.username, options.password) robot.start_time_sync(options.time_sync_interval_sec) except RpcError as err: LOGGER.error("Failed to communicate with robot: %s" % err) return False recorder_interface = RecorderInterface(robot, options.directory) if options.waypoint_commands_only is not None: recorder_interface._waypoint_commands = options.waypoint_commands_only # Save graph map os.mkdir(recorder_interface._download_filepath) if not recorder_interface._download_full_graph( overwrite_desert_flag=[]): recorder_interface.add_message("ERROR: Error downloading graph.") return LOGGER.info(recorder_interface._all_graph_wps_in_order) # Generate mission mission = recorder_interface._make_mission() # Save mission file os.mkdir(recorder_interface._download_filepath + "/missions") mission_filepath = recorder_interface._download_filepath + "/missions/autogenerated" write_mission(mission, mission_filepath) return True try: recorder_interface.start() except (ResponseError, RpcError) as err: LOGGER.error("Failed to initialize robot communication: %s" % err) return False try: # Prevent curses from introducing a 1 second delay for ESC key os.environ.setdefault('ESCDELAY', '0') # Run recorder interface in curses mode, then restore terminal config. curses.wrapper(recorder_interface.drive) except Exception as e: LOGGER.error("Mission recorder has thrown an error: %s" % repr(e)) LOGGER.error(traceback.format_exc()) finally: # Restore stream handler after curses mode. LOGGER.addHandler(stream_handler) return True