Example #1
0
    def _do_image_capture(self):
        """Main loop for the image capture thread, which requests and saves images."""
        # The service fault to report when this thread fails to capture an image from a source
        capture_fault_id = service_fault_pb2.ServiceFaultId(
            fault_name='Image Capture Failure', service_name=self.service_name)
        capture_fault = service_fault_pb2.ServiceFault(
            fault_id=capture_fault_id,
            error_message='Failed to capture an image from ' +
            self.device_name,
            severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)
        try:
            self.fault_client.clear_service_fault(capture_fault_id)
        except ServiceFaultDoesNotExistError:
            pass
        fault_active = False
        while self.is_alive:
            # Get the image from the video capture.
            capture_time = time.time()
            success, image = self.capture.read()
            if success:
                self.set_last_frame(image, capture_time)
                if fault_active:
                    self.fault_client.clear_service_fault(capture_fault_id)
                    fault_active = False
            elif not fault_active:
                self.fault_client.trigger_service_fault(capture_fault)
                fault_active = True

        # Cleanup the video capture when the thread is done.
        self.capture.release()
Example #2
0
def direct_faulting(robot):
    """Trigger and clear ServiceFaults directly using the SDK clients methods."""
    # Set up robot state client
    robot_state_client = robot.ensure_client(
        RobotStateClient.default_service_name)

    # Set up fault client
    fault_client = robot.ensure_client(FaultClient.default_service_name)

    # Set up fake service fault
    service_fault = service_fault_pb2.ServiceFault()
    service_fault.fault_id.fault_name = 'ManualExampleFault'
    service_fault.fault_id.service_name = kServiceName
    service_fault.error_message = 'Example service fault triggered by the service_faults.py SDK example.'
    service_fault.severity = service_fault_pb2.ServiceFault.SEVERITY_WARN

    # Trigger the service fault
    try:
        fault_client.trigger_service_fault(service_fault)
    except ServiceFaultAlreadyExistsError:
        print('\nServiceFault was already registered. Proceeding...')

    # Continually display ServiceFaults. Should see the manually triggered fault.
    print('\n\n\nShould see locally triggered fault')
    watch_service_fault_state(robot_state_client, 4)

    # Clear the service fault
    fault_client.clear_service_fault(service_fault.fault_id)

    # Continually display ServiceFaults. Should not see the manually triggered fault.
    print('\n\n\nShould not see locally triggered fault.')
    watch_service_fault_state(robot_state_client, 4)
def test_active_faults():
    # Check that active faults are managed correctly.

    visual_src = VisualImageSource("source1", FakeCamera(capture_with_error, decode_with_error))
    fault_client = MockFaultClient()
    visual_src.initialize_faults(fault_client, "service1")
    # Initialize function calls the clear_service_fault RPC.
    assert fault_client.clear_service_fault_called_count == 1
    assert len(visual_src.active_fault_id_names) == 0

    fake_fault_id = service_fault_pb2.ServiceFaultId(fault_name="Fake Capture Failure")
    fake_fault = service_fault_pb2.ServiceFault(
        fault_id=fake_fault_id, severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)

    # Make sure we don't call clear_service_fault RPC because the fake fault is not active yet.
    visual_src.clear_fault(fake_fault)
    assert len(visual_src.active_fault_id_names) == 0
    assert fault_client.clear_service_fault_called_count == 1

    # Make the fake fault active.
    visual_src.trigger_fault("error", fake_fault)
    assert len(visual_src.active_fault_id_names) == 1
    assert fault_client.service_fault_counts[fake_fault.fault_id.fault_name] == 1

    # Clear the fake fault, but make sure RPC is only called once.
    visual_src.clear_fault(fake_fault)
    assert fault_client.clear_service_fault_called_count == 2
    visual_src.clear_fault(fake_fault)
    # Make sure clear_service_fault is not called for a cleared fault.
    assert fault_client.clear_service_fault_called_count == 2
    assert len(visual_src.active_fault_id_names) == 0
Example #4
0
    def __init__(self,
                 image_name,
                 camera_interface,
                 rows=None,
                 cols=None,
                 gain=None,
                 exposure=None,
                 logger=None):
        self.image_source_name = image_name
        self.image_source_proto = self.make_image_source(
            image_name, rows, cols)
        self.get_image_capture_params = lambda: self.make_capture_parameters(
            gain, exposure)

        # Ensure the camera_interface is a subclass of CameraInterface and has the defined capture and
        # decode methods.
        assert isinstance(camera_interface, CameraInterface)
        self.camera_interface = camera_interface
        self.capture_function = lambda: self._do_capture_with_error_checking(
            self.camera_interface.blocking_capture)

        # Optional background thread to continuously capture image data. This will help an image
        # service to respond quickly to a GetImage request, since it can use the last captured image.
        self.capture_thread = None

        # Fault client to report errors. Requires the image service name to
        # properly create the fault id.
        self.fault_client = None

        # Create fault to throw if a failure occurs when calling the blocking_capture function.
        camera_capture_fault_id = service_fault_pb2.ServiceFaultId(
            fault_name="Image Capture Failure for %s" % self.image_source_name)
        self.camera_capture_fault = service_fault_pb2.ServiceFault(
            fault_id=camera_capture_fault_id,
            severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)
        # Create a fault to throw if a failure occurs when calling the image_decode function.
        decode_data_fault_id = service_fault_pb2.ServiceFaultId(
            fault_name="Decoding Image %s Failure" % self.image_source_name)
        self.decode_data_fault = service_fault_pb2.ServiceFault(
            fault_id=decode_data_fault_id,
            severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)

        # Logger for warning messages and the last error message (used only when the background thread
        # is capturing such that error messages from the last capture can be shown still).
        self.logger = logger or _LOGGER
        self.last_error_message = None
def test_faults_in_visual_source():
    # Create the fault client
    fault_client = MockFaultClient()

    # Populate fault client with at least one "old" fault.
    fault_client.trigger_service_fault_async(
        service_fault_pb2.ServiceFault(
            fault_id=service_fault_pb2.ServiceFaultId(fault_name="fault1")))
    init_fault_amount = fault_client.get_total_fault_count()

    visual_src = VisualImageSource(
        "source1", FakeCamera(capture_with_error, decode_with_error))

    # Attempt to get an image with no fault client enabled. Make sure no error is raised, and
    # values are returned as none.
    image, timestamp = visual_src.get_image_and_timestamp()
    assert image is None
    assert timestamp is None

    # attempt to decode an image with no fault client enabled. Make sure no error is raised.
    im_proto = image_pb2.Image(rows=10)
    success = visual_src.image_decode_with_error_checking(
        None, im_proto, None, None)
    assert im_proto.rows == 15
    assert not success

    # Setup faults
    visual_src.initialize_faults(fault_client, "service1")
    assert fault_client.get_total_fault_count() == 0
    assert visual_src.camera_capture_fault is not None
    assert visual_src.camera_capture_fault.fault_id.service_name == "service1"
    assert visual_src.decode_data_fault is not None
    assert visual_src.decode_data_fault.fault_id.service_name == "service1"

    # With fault client setup, check that faults are thrown when the bad functions get called.
    image, timestamp = visual_src.get_image_and_timestamp()
    assert image is None
    assert timestamp is None
    assert fault_client.service_fault_counts[
        visual_src.camera_capture_fault.fault_id.fault_name] == 1
    im_proto = image_pb2.Image(rows=21)
    success = visual_src.image_decode_with_error_checking(
        None, im_proto, None, None)
    assert im_proto.rows == 15
    assert fault_client.service_fault_counts[
        visual_src.decode_data_fault.fault_id.fault_name] == 1
    assert not success
Example #6
0
PLACEHOLDER_PAYLOAD = payload_protos.Payload()
PLACEHOLDER_PAYLOAD.name = 'Ricoh Theta Image Service'
PLACEHOLDER_PAYLOAD.description = 'This is currently a virtual/weightless payload defined for the software service only. \
                                   Please define weight and dimensions if the Ricoh Theta is mounted to Spot.'

# See https://dev.bostondynamics.com/docs/payload/configuring_payload_software#registering-payloads for more information.

DIRECTORY_NAME = 'ricoh-theta-image-service'
AUTHORITY = 'robot-ricoh-theta'
SERVICE_TYPE = 'bosdyn.api.ImageService'

_LOGGER = logging.getLogger(__name__)

# Define ServiceFaultIds for possible faults that will be thrown by the Ricoh Theta image service.
CAMERA_SETUP_FAULT = service_fault_pb2.ServiceFault(
    fault_id=service_fault_pb2.ServiceFaultId(fault_name='Ricoh Theta Initialization Failure',
                                              service_name=DIRECTORY_NAME),
    severity=service_fault_pb2.ServiceFault.SEVERITY_CRITICAL)


class RicohThetaServiceHelper(CameraInterface):

    def __init__(self, theta_ssid, theta_instance, logger=None):
        # Setup the logger.
        self.logger = logger or _LOGGER

        # Name of the image source that is being requested from.
        self.theta_ssid = theta_ssid
        self.image_source_name = "RicohTheta_" + theta_ssid

        # Default value for JPEG image quality, in case one is not provided in the GetImage request.
        self.default_jpeg_quality = 95
Example #7
0
from bosdyn.api import image_pb2
from bosdyn.api import image_service_pb2
from bosdyn.api import image_service_pb2_grpc
from bosdyn.api import service_fault_pb2

from ricoh_theta import Theta

DIRECTORY_NAME = 'ricoh-theta-image-service'
AUTHORITY = 'robot-ricoh-theta'
SERVICE_TYPE = 'bosdyn.api.ImageService'

_LOGGER = logging.getLogger(__name__)

# Define ServiceFaultIds for possible faults that will be thrown by the Ricoh Theta image service.
CAMERA_SETUP_FAULT = service_fault_pb2.ServiceFault(
    fault_id=service_fault_pb2.ServiceFaultId(fault_name='Ricoh Theta Initialization Failure',
                                              service_name=DIRECTORY_NAME),
    severity=service_fault_pb2.ServiceFault.SEVERITY_CRITICAL)

CAPTURE_PARAMETERS_FAULT = service_fault_pb2.ServiceFault(
    fault_id=service_fault_pb2.ServiceFaultId(fault_name='Get CaptureParameters Failure',
                                              service_name=DIRECTORY_NAME),
    error_message="Failed to get exposure/gain parameters.",
    severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)

CAPTURE_FAILURE_FAULT = service_fault_pb2.ServiceFault(
    fault_id=service_fault_pb2.ServiceFaultId(fault_name='RicohTheta Image Capture Failure',
                                              service_name=DIRECTORY_NAME),
    severity=service_fault_pb2.ServiceFault.SEVERITY_WARN)

class RicohThetaImageServicer(image_service_pb2_grpc.ImageServiceServicer):
    """GRPC service to provide access to multiple different image sources. The service can list the