Esempio n. 1
0
    def acquire_data_async(self,
                           acquisition_requests,
                           action_name,
                           group_name,
                           data_timestamp=None,
                           metadata=None,
                           **kwargs):
        """Async version of the acquire_data() RPC."""
        if data_timestamp is None:
            if not self._timesync_endpoint:
                data_timestamp = now_timestamp()
            else:
                data_timestamp = self._timesync_endpoint.robot_timestamp_from_local_secs(
                    time.time())
        action_id = data_acquisition.CaptureActionId(action_name=action_name,
                                                     group_name=group_name,
                                                     timestamp=data_timestamp)

        metadata_proto = metadata_to_proto(metadata)
        request = data_acquisition.AcquireDataRequest(
            metadata=metadata_proto,
            acquisition_requests=acquisition_requests,
            action_id=action_id)
        return self.call_async(self._stub.AcquireData,
                               request,
                               value_from_response=get_request_id,
                               error_from_response=acquire_data_error,
                               **kwargs)
def issue_acquire_data_request(data_acq_client,
                               acquisition_requests,
                               group_name,
                               action_name,
                               metadata=None):
    """Sends the data acquisition request without blocking until the acquisition completes.

    Args:
        data_acq_client: DataAcquisition client for send the acquisition requests.
        acquisition_requests: Acquisition requests to include in request message.
        group_name: Group name for the acquitions.
        action_name: Action name for the acquitions.
        metadata: Metadata to include in the request message.

    Returns:
        The request id (int) and the action id (CaptureActionId). A request id set as None
        indicates the AcquireData rpc failed.
    """
    # Create action id for the query for this request.
    action_id = data_acquisition_pb2.CaptureActionId(action_name=action_name,
                                                     group_name=group_name)

    # Send an AquireData request
    request_id = None
    try:
        request_id = data_acq_client.acquire_data(
            acquisition_requests=acquisition_requests,
            action_name=action_name,
            group_name=action_id.group_name,
            metadata=metadata)
    except ResponseError as err:
        print("Exception raised by issue_acquire_data_request: " + str(err))

    return request_id, action_id
Esempio n. 3
0
def acquire_data_and_check_errors(acquisition_request, data_acq_client,
                                  capability_name, action_name, group_name,
                                  verbose):
    """Helper function which makes the acquisition request for this data source and checks for errors.

    Args:
        acquisition_request (AcquisitionRequestList): The acquisition request for the capability_name.
        data_acq_client (DataAcquisitionClient): The client for the on-robot data acquisition service.
        capability_name (string): The data source name being acquired.
        action_name (string): The action name for saving in the CaptureActionId of the AcquireData request.
        group_name (string): The group name for saving in the CaptureActionId of the AcquireData request.
        verbose (boolean): Print additional logging information on failure.

    Returns:
        A tuple consisting of 1) a boolean indicating that the AcquireData RPC completed without any errors,
        and 2) an integer representing the request_id for the acquisition request. The request_id will be None
        if the AcquireData RPC fails.
    """
    acquire_data_request_id = None
    try:
        # Issue the AcquireData RPC to the on-robot data acquisition service.
        acquire_data_request_id = data_acq_client.acquire_data(
            acquisition_request, action_name, group_name)
    except InvalidRequestError as err:
        _LOGGER.error(
            "The AcquireData RPC to the data-acquisition service for %s was invalid: %s",
            capability_name, err.error_message)
        if verbose:
            _LOGGER.info(
                "The capture action ID associated with the request: %s",
                data_acquisition_pb2.CaptureActionId(action_name=action_name,
                                                     group_name=group_name))
            log_debug_information(err, acquisition_request)
        return False, acquire_data_request_id
    except ResponseError as err:
        _LOGGER.error(
            "Exception raised when testing the AcquireData RPC to the data-acquisition service for %s: %s",
            capability_name, err)
        if verbose:
            _LOGGER.info(
                "The capture action ID associated with the request: %s",
                data_acquisition_pb2.CaptureActionId(action_name=action_name,
                                                     group_name=group_name))
            log_debug_information(err, acquisition_request)
        return False, acquire_data_request_id
    return True, acquire_data_request_id
Esempio n. 4
0
def acquire_get_status_and_save(acquisition_request, capability_name, action_name, group_name,
                                data_acq_client, data_store_client, verbose):
    """Helper function which issues an acquisition request and checks that its data is saved to the data store, and the
    GetStatus RPC eventually respond with a status "complete".

    Args:
        acquisition_request (AcquisitionRequestList): The acquisition request proto message to send to the AcquireData RPC.
        capability_name (string): The name of the data capability being acquired.
        action_name (string): The action name for the acquisition request's CaptureActionId.
        group_name (string): The group name for the acquisition request's CaptureActionId.
        data_acq_client (DataAcquisitionClient): The client for the data acquisition service running on robot.
        data_store_client (DataAcquisitionStoreClient): The client for the data acquisition store service running on robot.
        verbose (boolean): Print additional logging information on failure.

    Returns:
        A boolean indicating that the acquisition request received a "complete" status for the GetStatus RPC and
        an action id for the acquisition can be found in the data store.
    """
    # Make a request for this data capability and check that it completes successfully.
    acquire_success, acquired_request_id = acquire_data_and_check_errors(
        acquisition_request, data_acq_client, capability_name, action_name, group_name, verbose)
    if not acquire_success:
        # Exit early if the AcquireData RPC did not succeed and did not return a request_id.
        return False
    success = monitor_status_until_complete_or_failed(acquired_request_id, data_acq_client,
                                                      capability_name, action_name, verbose)

    if success:
        # If the GetStatus responds with "Complete", then check the data store for the action id.
        action_id = data_acquisition_pb2.CaptureActionId(action_name=action_name,
                                                         group_name=group_name)
        query_params = data_acquisition_store_pb2.DataQueryParams(
            action_ids=data_acquisition_store_pb2.ActionIdQuery(action_ids=[action_id]))
        try:
            saved_capture_actions = data_store_client.list_capture_actions(query_params)
            if len(saved_capture_actions) == 0:
                # Nothing saved with a matching action and group name!
                _LOGGER.error(
                    "The request %s for data '%s' with action_name '%s' did NOT save to the data "
                    "acquisition store or returned prematurely with a STATUS_COMPLETE in the GetStatus RPC.",
                    acquired_request_id, capability_name, action_name)
                if verbose:
                    _LOGGER.info("ListCaptureAction RPC's query parameters: ", query_params)
                return False
        except ResponseError as err:
            _LOGGER.error(
                "Exception raised when checking if request %s for data '%s' with action_name '%s' was "
                "saved in the data acquisition store.", request_id, capability_name, action_name)
            if verbose:
                log_debug_information(err)
            return False
    else:
        # The GetStatus checks failed in some way.
        return False

    # The acquisition request went through, the GetStatus RPC responded with "status complete" and the data was
    # successfully found in the data store service.
    return True
Esempio n. 5
0
 def make_acquire_data_request(self, acquisition_requests, action_name, group_name, data_timestamp=None, metadata=None):
     """Helper utility to generate an AcquireDataRequest."""
     if data_timestamp is None:
         if not self._timesync_endpoint:
             data_timestamp = now_timestamp()
         else:
             data_timestamp = self._timesync_endpoint.robot_timestamp_from_local_secs(
                 time.time())
     action_id = data_acquisition.CaptureActionId(action_name=action_name, group_name=group_name,
                                                  timestamp=data_timestamp)
     return data_acquisition.AcquireDataRequest(acquisition_requests=acquisition_requests,
                                                action_id=action_id,
                                                metadata=metadata_to_proto(metadata))
Esempio n. 6
0
    def acquire_data(self,
                     acquisition_requests,
                     action_name,
                     group_name,
                     data_timestamp=None,
                     metadata=None,
                     **kwargs):
        """Trigger a data acquisition to save data and metadata to the data buffer.

        Args:
          acquisition_requests (bosdyn.api.AcquisitionRequestList): The different image sources and
                data sources to capture from and save to the data buffer with the same timestamp.
          action_name(string): The unique action name that all data will be saved with.
          group_name(string): The unique group name that all data will be saved with.
          data_timestamp (google.protobuf.Timestamp): The unique timestamp that all data will be
                saved with.
          metadata (bosdyn.api.Metadata | dict): The JSON structured metadata to be associated with
                the data returned by the DataAcquisitionService when logged in the data buffer
                service.

        Raises:
          RpcError: Problem communicating with the robot.

        Returns:
            If the RPC is successful, then it will return the acquire data request id, which can be
            used to check the status of the acquisition and get feedback.
        """

        if data_timestamp is None:
            if not self._timesync_endpoint:
                data_timestamp = now_timestamp()
            else:
                data_timestamp = self._timesync_endpoint.robot_timestamp_from_local_secs(
                    time.time())
        action_id = data_acquisition.CaptureActionId(action_name=action_name,
                                                     group_name=group_name,
                                                     timestamp=data_timestamp)

        metadata_proto = metadata_to_proto(metadata)
        request = data_acquisition.AcquireDataRequest(
            metadata=metadata_proto,
            acquisition_requests=acquisition_requests,
            action_id=action_id)
        return self.call(self._stub.AcquireData,
                         request,
                         value_from_response=get_request_id,
                         error_from_response=acquire_data_error,
                         **kwargs)
def make_time_query_params_from_group_name(group_name, data_store_client):
    """Create time-based query params for the download request using the group name.

    Args:
        group_name(string): The group name for the data to be downloaded.
        data_store_client(DataAcquisitionStoreClient): The data store client, used to get the
                                                       action ids for the group name.

    Returns:
        The query params (data_acquisition_store_pb2.DataQueryParams) for the time-range download.
    """
    action_id = data_acquisition_pb2.CaptureActionId(group_name=group_name)
    query_params = data_acquisition_store_pb2.DataQueryParams(
        action_ids=data_acquisition_store_pb2.ActionIdQuery(
            action_ids=[action_id]))
    saved_capture_actions = []
    try:
        saved_capture_actions = data_store_client.list_capture_actions(
            query_params)
    except Exception as err:
        _LOGGER.error(
            "Failed to list the capture action ids for group_name %s: %s",
            group_name, err)
        return None

    # Filter all the CaptureActionIds for the start/end time. These end times are already in
    # the robots clock and do not need to be converted using timesync.
    start_time = (None, None)
    end_time = (None, None)
    for action_id in saved_capture_actions:
        timestamp = action_id.timestamp
        time_secs = timestamp.seconds + timestamp.nanos / 1e9
        if time_secs == 0:
            # The plugin captures don't seem to set a timestamp, so ignore them when determining
            # the start/end times for what to download.
            continue
        if start_time[0] is None or time_secs < start_time[0]:
            start_time = (time_secs, timestamp)
        if end_time[0] is None or time_secs > end_time[0]:
            end_time = (time_secs, timestamp)

    if not (start_time and end_time):
        _LOGGER.error(
            "Could not find a start/end time from the list of capture action ids: %s",
            saved_capture_actions)
        return None

    # Ensure the timestamps are ordered correctly and the
    assert start_time[0] <= end_time[0]

    # Adjust the start/end time by a few seconds each to give buffer room.
    start_time[1].seconds -= 3
    end_time[1].seconds += 3

    _LOGGER.info(
        "Downloading data with a start time  of %s seconds and end time of %s seconds.",
        start_time[0], end_time[0])

    # Make the download data request with a time query parameter.
    query_params = data_acquisition_store_pb2.DataQueryParams(
        time_range=data_acquisition_store_pb2.TimeRangeQuery(
            from_timestamp=start_time[1], to_timestamp=end_time[1]))
    return query_params
Esempio n. 8
0
def test_downloading_all_data_via_REST(data_store_client, group_name, robot_hostname, robot, destination_folder):
    """Check that all of the data can successfully be downloaded via the REST endpoint.

    Args:
        data_store_client (DataAcquisitionStoreClient): The client for the data acquisition store service running on robot.
        group_name (string): The group name for all the acquisitions during the test, such that we can determine
                             which data to download.
        robot_hostname (string): The hostname for the robot used for testing.
        robot (Robot): The SDK robot object created for the robot used for testing.
        destination_folder (string): The filepath for where the downloaded data will be saved.

    Returns:
        Boolean indicating if the REST download succeeded or not.
    """
    # Need a start and end timestamp for the capture actions with a matching group_name.
    action_id = data_acquisition_pb2.CaptureActionId(group_name=group_name)
    query_params = data_acquisition_store_pb2.DataQueryParams(
        action_ids=data_acquisition_store_pb2.ActionIdQuery(action_ids=[action_id]))
    saved_capture_actions = []
    try:
        saved_capture_actions = data_store_client.list_capture_actions(query_params)
    except Exception as err:
        _LOGGER.error("Failed to list the capture action ids for group_name %s: %s", group_name, err)
        _LOGGER.info("ListCaptureAction RPC's query parameters: %s", query_params)
        return False

    # Filter all the CaptureActionIds for the start/end time.
    start_time = (None, None)
    end_time = (None, None)
    for action_id in saved_capture_actions:
        _LOGGER.info("Saved Capture Action ID: %s", action_id)
        timestamp = action_id.timestamp
        time_secs = timestamp.seconds + timestamp.nanos / 1e9
        if time_secs == 0:
            # The plugin captures don't seem to set a timestamp, so ignore them when determining
            # the start/end times for what to download.
            continue
        if start_time[0] is None or time_secs < start_time[0]:
            start_time = (time_secs, timestamp)
        if end_time[0] is None or time_secs > end_time[0]:
            end_time = (time_secs, timestamp)

    if not (start_time and end_time):
        _LOGGER.error("Could not find a start/end time from the list of capture action ids: %s", saved_capture_actions)
        return False

    # Ensure the timestamps are ordered correctly.
    assert start_time[0] <= end_time[0]

    # Adjust the start/end time by a few seconds each to give buffer room.
    start_time[1].seconds -= 3
    end_time[1].seconds += 3

    _LOGGER.info("Downloading data with a start time  of %s seconds and end time of %s seconds.", start_time[0], end_time[0])

    # Make the download data request with a time query parameter.
    query_params = data_acquisition_store_pb2.DataQueryParams(
        time_range=data_acquisition_store_pb2.TimeRangeQuery(from_timestamp=start_time[1],
                                                                to_timestamp=end_time[1]))
    success = download_data_REST(query_params, robot_hostname, robot.user_token, destination_folder)
    return success