예제 #1
0
def example(args):
    """ Example function for synchronizing several devices.

    Call this script with a list of hosts (the IP addresses or the hostnames of the devices).

    Some other parameters can be changed: frame_rate, vertical_fov, scan lines, pulse_mode, ntp_server_ip.

    To get help, call the script with -h.

    :param args: argparser will parse incoming arguments (hosts, frame_rate, vertical_fov, scan lines, pulse_mode, ntp_server_ip)
    """

    devices = [blickfeld_scanner.scanner(host)
               for host in args.hosts]  # Connect to the device

    config = scan_pattern_pb2.ScanPattern(
    )  # Create a scan pattern, see :any:`protobuf_protocol` ScanPattern
    if args.vertical_fov:
        config.vertical.fov = args.vertical_fov / 180 * math.pi  # Set vertical FoV in rad
    config.vertical.scanlines_up = args.scanlines[0]  # Set up scan lines
    config.vertical.scanlines_down = args.scanlines[1]  # Set down scan lines
    config.pulse.frame_mode = scan_pattern_pb2.ScanPattern.Pulse.FrameMode.Value(
        args.pulse_mode)  # Set pulse mode

    if args.ntp_server_ip != "":  # If the ntp_server_ip variable is set, set the ntp servers
        for device in devices:  # iterate through devices
            device.set_time_synchronization(ntp=[args.ntp_server_ip])

    print("Requested pattern:", config)
    print(devices[0].fill_scan_pattern(config))
    blickfeld_scanner.scanner.sync(devices=devices,
                                   scan_pattern=config,
                                   target_frame_rate=args.frame_rate)
def configure_point_cloud_stream(args):
    """Fetch a basic point cloud. Only get specific fields of each point: X, Y, Z, intensity and ID.
    Use a filter to filter out points which are closer than 5m or further away than 50m.

    :param args: arguments to parse out the hostname or IP address of the device and an optional file path to record to.
    """
    device = blickfeld_scanner.scanner(args.target)  # Connect to the device

    # Reference Frame with X, Y, Z coordinates, intensity and point IDs
    # The frame represents the desired data. To request a field, set it to any value (also in submessages). For a repeated field, add at least one element.
    reference_frame = point_cloud.REF_FRAME_XYZ_I_ID

    # Create filter to filter points and returns by point attributes during the post-processing on the device.
    point_filter = scan_pattern_pb2.ScanPattern().Filter()
    point_filter.range.minimum = 5  # minimum range for a point to be sent out is 5m
    point_filter.range.maximum = 50  # maximum range for a point to be sent out is 50m
    point_filter.max_number_of_returns_per_point = 2  # Set max number of returns to 2. The default value is 1.

    stream = device.get_point_cloud_stream(
        filter=point_filter,
        reference_frame=reference_frame)  # Create a point cloud stream object

    while True:
        # Receive frame. It has a reduced data size, as not all fields are requested. This also speeds up the Protobuf encoding & decoding.
        frame = stream.recv_frame()
        # Format of frame is described in protocol/blickfeld/data/frame.proto or doc/protocol.md
        # Protobuf API is described in https://developers.google.com/protocol-buffers/docs/pythontutorial
        print(f"Got {frame}")
def example(args):
    """ Example to for handling protocol exceptions.

    The errors are described in the protobuf protocol definition of the errors.

    This example tries to set an invalid ScanPattern and a protocol exception will be raised and catched.

    :param args: arguments to parse out the host name or IP address of the device
    """

    device = blickfeld_scanner.scanner(args.host)  # Connect to the device

    config = scan_pattern_pb2.ScanPattern(
    )  # Create a scan pattern, see protobuf protocol definition of the scan pattern
    config.horizontal.fov = np.deg2rad(10)
    config.vertical.fov = np.deg2rad(30)
    config.vertical.scanlines_up = 10  # Set invalid values
    config.vertical.scanlines_down = 30
    config.pulse.frame_mode = scan_pattern_pb2.ScanPattern.Pulse.FrameMode.Value(
        "COMBINE_UP_DOWN")

    try:
        device.fill_scan_pattern(
            config)  # Try to fill the remaining fields with default values
    except protocol_exception as pe:  # Catch protocol exception and print it
        print(pe)

    try:
        device.set_scan_pattern(config)  # Send scan pattern to device
    except protocol_exception as pe:  # Catch protocol exception and print it
        print(pe)
예제 #4
0
def store_and_set_named_scan_pattern(target):
    """Get a list of named scan patterns of a device and print them.
    Afterwards create a new scan pattern and store it with a name. 
    At last get the named scan patterns again and set the created scan pattern.

    :param target: hostname or IP address of the device
    """
    device = blickfeld_scanner.scanner(target)  # Connect to the device

    named_scan_patterns = device.get_named_scan_patterns()  # Get named scan patterns

    # Print if the scan pattern is a default or custom named scan pattern
    for scan_pattern in named_scan_patterns.configs:
        if scan_pattern.read_only:
            print("'" + str(scan_pattern.name) + "' is a default named scan pattern.")
        else:
            print("'" + str(scan_pattern.name) + "' is a custom named scan pattern.")

    # Set default scan pattern by name
    device.set_scan_pattern(name="Default")
    
    # Create new scan pattern
    new_scan_pattern = scan_pattern_pb2.ScanPattern()
    new_scan_pattern.vertical.scanlines_up = 100
    new_scan_pattern.vertical.scanlines_down = 100
    new_scan_pattern.pulse.frame_mode = scan_pattern_pb2.ScanPattern.Pulse.FrameMode.COMBINE_UP_DOWN

    # Fill scan pattern to add missing parameter (optional)
    new_scan_pattern = device.fill_scan_pattern(new_scan_pattern)

    # Store scan pattern as "python test"
    # This method persists the scan pattern on the device. Use 'device.delete_named_scan_pattern("python-test")' to delete it again.
    device.store_named_scan_pattern("python-test", new_scan_pattern)

    # Check if the stored scan pattern was correctly set (optional, just for visualisation)
    named_scan_patterns = device.get_named_scan_patterns()  # Get named scan patterns
    for scan_pattern in named_scan_patterns.configs:
        if scan_pattern.name == "python-test":
            print("'" + str(scan_pattern.name) + "' succesfully stored.")

    # Set scan pattern by name
    device.set_scan_pattern(name="python-test")
def fetch_numpy_frame(target):
    """Fetch the point cloud of a device as a numpy structued array.

    This example will stop after 10 received frames.

    :param target: hostname or IP address of the device
    """
    device = blickfeld_scanner.scanner(target)  # Connect to the device

    # Create filter to filter points and returns by point attributes during the post-processing on the device.
    point_filter = scan_pattern_pb2.ScanPattern().Filter()
    point_filter.max_number_of_returns_per_point = 2  # Set max number of returns to 2. The default value is 1.
    point_filter.delete_points_without_returns = True  # Filter points with no returns. This reduces the dataset only to valid returns.

    # Create a point cloud stream object
    # The `as_numpy` flag enables the numpy support.
    stream = device.get_point_cloud_stream(point_filter=point_filter,
                                           as_numpy=True)

    for i in range(10):
        frame, data = stream.recv_frame_as_numpy()
        print("Frame", str(frame.id) + ":", data)
        print("Size:", data.size, "Type:", data.dtype)

        # Example for filtering the strucuted array
        multiple_returns = data[np.argwhere(data['return_id'] > 0)]
        print("Got %d multiple returns" % (len(multiple_returns)))

        # Extract cartesian coordinates
        x, y, z = (data['cartesian']['x'], data['cartesian']['y'],
                   data['cartesian']['z'])
        print(x, y, z)

        print()  # newline

    stream.stop()