Ejemplo n.º 1
0
def test_incompatible_profile(lidar_stream: client.PacketSource) -> None:
    """Test batching of a LidarScan with custom fields set."""

    info = lidar_stream.metadata
    assert info.format.udp_profile_lidar == client.UDPProfileLidar.PROFILE_LIDAR_LEGACY

    packets_per_frame = (info.format.columns_per_frame //
                         info.format.columns_per_packet)

    batch = ScanBatcher(lidar_stream.metadata)

    ls = client.LidarScan(info.format.pixels_per_column,
                          info.format.columns_per_frame,
                          client.UDPProfileLidar.PROFILE_LIDAR_RNG19_RFL8_SIG16_NIR16_DUAL)

    # Try to decode a legacy packet into a dual returns scan
    # TODO change exception thrown on the cpp side
    with pytest.raises(IndexError):
        for p in take(packets_per_frame, lidar_stream):
            batch(p._data, ls)

    batch = ScanBatcher(lidar_stream.metadata)

    fields = {
        client.ChanField.RANGE: np.uint8,
    }
    ls = client.LidarScan(info.format.pixels_per_column,
                          info.format.columns_per_frame,
                          fields)

    # Test for decoding scans to a bad dest buffer type
    with pytest.raises(ValueError):
        for p in take(packets_per_frame, lidar_stream):
            batch(p._data, ls)
Ejemplo n.º 2
0
def test_xyz_lut_scan_dims(stream_digest: digest.StreamDigest, meta: client.SensorInfo) -> None:
    """Check that (in)valid lidar scan dimensions are handled by xyzlut."""
    w = meta.format.columns_per_frame
    h = meta.format.pixels_per_column

    xyzlut = client.XYZLut(meta)

    assert xyzlut(client.LidarScan(h, w)).shape == (h, w, 3)

    with pytest.raises(ValueError):
        xyzlut(client.LidarScan(h + 1, w))

    with pytest.raises(ValueError):
        xyzlut(client.LidarScan(h, w - 1))
Ejemplo n.º 3
0
def test_scan_writeable() -> None:
    """Check that a native scan is a writeable view of data."""
    ls = client.LidarScan(1024, 32)

    assert not ls.field(client.ChanField.RANGE).flags.owndata
    assert not ls.status.flags.owndata

    assert ls.field(client.ChanField.SIGNAL).flags.aligned
    assert ls.measurement_id.flags.aligned

    assert ls.field(client.ChanField.NEAR_IR).flags.aligned
    assert ls.timestamp.flags.aligned

    ls.field(client.ChanField.RANGE)[0, 0] = 42
    assert ls.field(client.ChanField.RANGE)[0, 0] == 42

    ls.field(client.ChanField.RANGE)[:] = 7
    assert np.all(ls.field(client.ChanField.RANGE) == 7)

    ls.status[-1] = 0xffff
    assert ls.status[-1] == 0xffff
    assert ls.header(client.ColHeader.STATUS)[-1] == 0xffff

    ls.header(client.ColHeader.STATUS)[-2] = 0xffff
    assert ls.status[-2] == 0xffff
    assert ls.header(client.ColHeader.STATUS)[-2] == 0xffff

    ls.status[:] = 0x1
    assert np.all(ls.status == 0x1)
    assert np.all(ls.header(client.ColHeader.STATUS) == 0x1)
Ejemplo n.º 4
0
def test_batch_custom_fields(lidar_stream: client.PacketSource) -> None:
    """Test batching of a LidarScan with custom fields set."""

    info = lidar_stream.metadata

    packets_per_frame = (info.format.columns_per_frame //
                         info.format.columns_per_packet)

    batch = ScanBatcher(lidar_stream.metadata)

    # create LidarScan with only 2 fields
    fields: Dict[client.ChanField, client.FieldDType] = {
        client.ChanField.RANGE: np.uint32,
        client.ChanField.SIGNAL: np.uint16
    }

    ls = client.LidarScan(info.format.pixels_per_column,
                          info.format.columns_per_frame, fields)

    # we expect zero initialized fields
    for f in ls.fields:
        assert np.count_nonzero(ls.field(f)) == 0

    # do batching into ls with a fields subset
    for p in take(packets_per_frame, lidar_stream):
        batch(p._data, ls)

    # it should contain the same num fields as we've added
    assert len(list(ls.fields)) == len(fields)

    # and the content shouldn't be zero after batching
    for f in ls.fields:
        assert np.count_nonzero(ls.field(f)) > 0
Ejemplo n.º 5
0
def test_scan_copy_eq() -> None:
    """Test equality with a copy."""

    ls0 = client.LidarScan(32, 512)
    ls0.status[:] = 0x1
    ls0.field(client.ChanField.SIGNAL)[:] = 100

    ls1 = deepcopy(ls0)

    assert ls0 is not ls1
    assert ls0 == ls1

    ls0.frame_id = 9
    assert ls0 != ls1

    ls1.frame_id = 9
    assert ls0 == ls1

    ls0.measurement_id[0] = 1
    assert ls0 != ls1

    ls1.measurement_id[0] = 1
    assert ls0 == ls1

    ls0.field(client.ChanField.RANGE)[0, 0] = 42
    assert ls0 != ls1

    ls1.field(client.ChanField.RANGE)[0, 0] = 42
    assert ls0 == ls1
Ejemplo n.º 6
0
def test_scan_empty() -> None:
    """Sanity check scan with no fields."""
    ls = client.LidarScan(32, 1024, {})

    assert set(ls.fields) == set()

    for f in client.ChanField.values:
        with pytest.raises(ValueError):
            ls.field(f)
Ejemplo n.º 7
0
def test_scan_fields_ref() -> None:
    """Make sure ref to fields keeps scan alive."""
    fields = client.LidarScan(32, 1024).fields

    # should fail (or trip asan) if the field iterator doesn't keep scan alive
    assert set(fields) == {
        client.ChanField.RANGE,
        client.ChanField.REFLECTIVITY,
        client.ChanField.SIGNAL,
        client.ChanField.NEAR_IR,
    }
Ejemplo n.º 8
0
def _simple_scans(source: client.PacketSource) -> Iterator[client.LidarScan]:
    """Batch packets to scans without zeroing between frames."""
    batch = ScanBatcher(source.metadata)
    info = source.metadata

    ls = client.LidarScan(info.format.pixels_per_column,
                          info.format.columns_per_frame,
                          info.format.udp_profile_lidar)

    for p in source:
        if batch(p._data, ls):
            yield deepcopy(ls)
Ejemplo n.º 9
0
def test_scan_field_ref() -> None:
    """Test that field references keep scans alive."""

    ls = client.LidarScan(512, 16)
    range = ls.field(client.ChanField.RANGE)
    range[:] = 42

    del ls
    assert np.all(range == 42)

    range[:] = 43
    assert np.all(range == 43)
Ejemplo n.º 10
0
def test_scan_header_ref() -> None:
    """Test that header references keep scans alive."""

    ls = client.LidarScan(512, 16)
    status = ls.status
    status[:] = 0x11

    del ls
    assert np.all(status == 0x11)

    status[:] = 0x01
    assert np.all(status == 0x01)
Ejemplo n.º 11
0
def test_scan_custom() -> None:
    """Sanity check scan with a custom set of fields."""
    ls = client.LidarScan(32, 1024, {
        client.ChanField.SIGNAL: np.uint16,
        client.ChanField.FLAGS: np.uint8
    })

    assert set(ls.fields) == {client.ChanField.SIGNAL, client.ChanField.FLAGS}
    assert ls.field(client.ChanField.SIGNAL).dtype == np.uint16

    with pytest.raises(ValueError):
        ls.field(client.ChanField.RANGE)
Ejemplo n.º 12
0
def test_scan_to_native() -> None:
    """Check that converting to a native scan copies data."""
    ls = client.LidarScan(32, 1024)

    ls._data[:] = np.arange(ls._data.size).reshape(N_FIELDS, -1)
    native = ls.to_native()

    assert ls._data.base is not native.data.base
    assert np.array_equal(ls._data, native.data)

    ls._data[0, 0] = 42
    native.data[:] = 1
    assert ls._data[0, 0] == 42
Ejemplo n.º 13
0
def test_scan_default_fields() -> None:
    """Default scan has the expected fields for the LEGACY profile."""
    ls = client.LidarScan(32, 1024)

    assert set(ls.fields) == {
        client.ChanField.RANGE,
        client.ChanField.REFLECTIVITY,
        client.ChanField.SIGNAL,
        client.ChanField.NEAR_IR,
    }

    for f in ls.fields:
        assert ls.field(f).dtype == np.uint32
Ejemplo n.º 14
0
def test_scan_complete(w, win_start, win_end) -> None:
    """Set the status headers to the specified window and check _complete()."""
    ls = client.LidarScan(32, w)

    status = ls.status

    if win_start <= win_end:
        status[win_start:win_end + 1] = 0xFFFFFFFF
    else:
        status[0:win_end + 1] = 0xFFFFFFFF
        status[win_start:] = 0xFFFFFFFF

    assert ls._complete((win_start, win_end))
Ejemplo n.º 15
0
def test_scan_zero_init() -> None:
    """Test that scan fields and headers are zero initialized."""
    ls = client.LidarScan(
        64, 1024,
        client.UDPProfileLidar.PROFILE_LIDAR_RNG19_RFL8_SIG16_NIR16_DUAL)

    assert ls.frame_id == -1

    assert np.count_nonzero(ls.timestamp) == 0
    assert np.count_nonzero(ls.measurement_id) == 0
    assert np.count_nonzero(ls.status) == 0

    for f in ls.fields:
        assert np.count_nonzero(ls.field(f)) == 0
Ejemplo n.º 16
0
def test_scan_dual_profile() -> None:
    """Dual returns scan has the expected fields."""
    ls = client.LidarScan(
        32, 1024,
        client.UDPProfileLidar.PROFILE_LIDAR_RNG19_RFL8_SIG16_NIR16_DUAL)

    assert set(ls.fields) == {
        client.ChanField.RANGE,
        client.ChanField.RANGE2,
        client.ChanField.REFLECTIVITY,
        client.ChanField.REFLECTIVITY2,
        client.ChanField.SIGNAL,
        client.ChanField.SIGNAL2,
        client.ChanField.NEAR_IR,
    }
Ejemplo n.º 17
0
def test_batch_missing_zeroed(lidar_stream: client.PacketSource) -> None:
    """Check that missing data is zeroed out when batching."""

    info = lidar_stream.metadata

    packets_per_frame = (info.format.columns_per_frame //
                         info.format.columns_per_packet)

    batch = ScanBatcher(lidar_stream.metadata)

    ls = client.LidarScan(info.format.pixels_per_column,
                          info.format.columns_per_frame,
                          info.format.udp_profile_lidar)

    # initialize fields and headers with nonzero values
    ls.timestamp[:] = 1
    ls.measurement_id[:] = 1
    ls.status[:] = 1
    for f in ls.fields:
        ls.field(f)[:] = 1

    # packet indices to drop
    drop_inds = [10, 20]

    # drop some packets
    packets = list(take(packets_per_frame, lidar_stream))
    for i in drop_inds:
        del packets[i]

    # parse the packets into a scan
    for p in packets:
        batch(p._data, ls)

    # check that data associated with the dropped packets is zeroed
    n = info.format.columns_per_packet

    assert np.count_nonzero(
        ls.status) == info.format.columns_per_frame - n * len(drop_inds)

    for i in drop_inds:
        assert (ls.timestamp[i * n:n] == 0).all()
        assert (ls.measurement_id[i * n:n] == 0).all()
        assert (ls.status[i * n:n] == 0).all()

        for f in ls.fields:
            assert (ls.field(f)[:, i * n:n] == 0).all()
Ejemplo n.º 18
0
def test_scan_not_complete() -> None:
    """Test that not all scans are considered complete."""
    ls = client.LidarScan(32, 1024)

    status = ls.status
    assert not ls._complete()

    status[0] = 0x02
    assert not ls._complete()
    assert not ls._complete((0, 0))

    status[1:] = 0xFFFFFFFF
    assert not ls._complete()

    status[:] = 0xFFFFFFFF
    status[-1] = 0x02
    assert not ls._complete()

    # windows are inclusive but python slicing is not
    status[:] = 0x00
    status[:10] = 0xFFFFFFFF
    assert not ls._complete((0, 10))

    status[:] = 0x00
    status[11:21] = 0xFFFFFFFF
    assert not ls._complete((10, 20))

    # window [i, i]
    status[:] = 0x00
    status[0] = 0xFFFFFFFF
    assert not ls._complete()
    assert not ls._complete((0, 1))
    assert ls._complete((0, 0))

    status[:] = 0x00
    status[128] = 0xFFFFFFFF
    assert not ls._complete()
    assert not ls._complete((127, 128))
    assert ls._complete((128, 128))
Ejemplo n.º 19
0
def test_scan_eq_fields() -> None:
    """Test equality between scans with different fields."""
    ls0 = client.LidarScan(32, 1024)
    ls1 = client.LidarScan(32, 1024,
                           client.UDPProfileLidar.PROFILE_LIDAR_LEGACY)
    ls2 = client.LidarScan(
        32, 1024,
        client.UDPProfileLidar.PROFILE_LIDAR_RNG19_RFL8_SIG16_NIR16_DUAL)
    ls3 = client.LidarScan(32, 1024, {client.ChanField.SIGNAL: np.uint32})
    ls4 = client.LidarScan(32, 1024, {client.ChanField.SIGNAL: np.uint16})
    ls5 = client.LidarScan(32, 1024, {})

    assert ls0 == ls1
    assert not (ls0 != ls1)  # should be implemented using __eq__
    assert ls1 != ls2
    assert ls3 != ls4
    assert ls5 != ls0
    assert ls5 != ls2
    assert ls5 != ls4
Ejemplo n.º 20
0
def test_scan_from_native() -> None:
    ls = client.LidarScan(1024, 32)
    ls2 = client.LidarScan.from_native(ls)

    assert ls is ls2
Ejemplo n.º 21
0
def test_scan_to_native() -> None:
    ls = client.LidarScan(1024, 32)
    ls2 = ls.to_native()

    assert ls is ls2