Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
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
Ejemplo n.º 13
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
Ejemplo n.º 14
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)
    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