diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a620693..fac81f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,6 +71,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install Clang if: matrix.platform[2] == 'clang' uses: KyleMayes/install-llvm-action@v1 @@ -112,6 +116,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install Clang if: matrix.platform[2] == 'clang' uses: KyleMayes/install-llvm-action@v1 diff --git a/test/test_pcap.py b/test/test_pcap.py index 33b02c2..af65fa4 100644 --- a/test/test_pcap.py +++ b/test/test_pcap.py @@ -15,6 +15,8 @@ def test_pcap_as_contiguous_array(sample_pcap_path): # Check that the column index is monotonically increasing column_idx = pcd[:, vd.PointField.column].astype(int) assert np.diff(column_idx).min() == 0 + # Sanity check that the point clouds are actually distinct + assert not all(len(x) == len(pcd) for _, x in pcds) def test_pcap_as_struct_array(sample_pcap_path, pcl_struct_dtype): @@ -27,6 +29,7 @@ def test_pcap_as_struct_array(sample_pcap_path, pcl_struct_dtype): # Check that the column index is monotonically increasing column_idx = pcd["column"].astype(int) assert np.diff(column_idx).min() == 0 + assert not all(len(x) == len(pcd) for _, x in pcds) def test_pcap_time_range(sample_pcap_path): @@ -35,3 +38,23 @@ def test_pcap_time_range(sample_pcap_path): stamp, pcd = pcds[0] assert stamp.host >= t0 assert stamp.device >= t0 + + +def _struct_pcd_to_contiguous(pcd_struct): + shape = (len(pcd_struct), len(pcd_struct.dtype.fields)) + converted_pcd = np.empty(shape, dtype=np.float32) + for i, field in enumerate(pcd_struct.dtype.fields): + converted_pcd[:, i] = pcd_struct[field] + return converted_pcd + + +def test_pcap_structs_match_contiguous(sample_pcap_path): + """Check that the contents of as_pcl_structs=True/False match.""" + pcds_struct = list(vd.read_pcap(sample_pcap_path, as_pcl_structs=True)) + pcds_contiguous = list(vd.read_pcap(sample_pcap_path, as_pcl_structs=False)) + assert len(pcds_struct) == len(pcds_contiguous) + for (stamp_struct, pcd_struct), (stamp_contiguous, pcd_contiguous) in zip(pcds_struct, pcds_contiguous): + assert stamp_struct.host == stamp_contiguous.host + assert stamp_struct.device == stamp_contiguous.device + cast_struct_pcd = _struct_pcd_to_contiguous(pcd_struct) + assert np.allclose(cast_struct_pcd, pcd_contiguous, rtol=1e-6) diff --git a/test/test_ros.py b/test/test_ros.py index 73acfd0..5925269 100644 --- a/test/test_ros.py +++ b/test/test_ros.py @@ -1,6 +1,6 @@ # Copyright (c) 2021-2023, Martin Valgur # SPDX-License-Identifier: BSD-3-Clause - +import numpy as np import velodyne_decoder as vd @@ -13,6 +13,8 @@ def test_bag_as_contiguous_array(sample_bag_path): assert pcd.shape == (27300, 8) assert pcd.dtype.name == "float32" assert frame_id == "velodyne" + # Sanity check that the point clouds are actually distinct + assert not all(len(x) == len(pcd) for _, x, _, _ in pcds) def test_bag_as_struct_array(sample_bag_path, pcl_struct_dtype): @@ -24,6 +26,7 @@ def test_bag_as_struct_array(sample_bag_path, pcl_struct_dtype): assert pcd.shape == (27300,) assert pcd.dtype == pcl_struct_dtype assert frame_id == "velodyne" + assert not all(len(x) == len(pcd) for _, x, _, _ in pcds) def test_bag_automatic_topic(sample_bag_path): @@ -40,3 +43,23 @@ def test_bag_time_range(sample_bag_path): t0 = 1636622717 pcds = list(vd.read_bag(sample_bag_path, time_range=(t0, None))) assert pcds[0].stamp.host >= t0 + + +def _struct_pcd_to_contiguous(pcd_struct): + shape = (len(pcd_struct), len(pcd_struct.dtype.fields)) + converted_pcd = np.empty(shape, dtype=np.float32) + for i, field in enumerate(pcd_struct.dtype.fields): + converted_pcd[:, i] = pcd_struct[field] + return converted_pcd + + +def test_pcap_structs_match_contiguous(sample_bag_path): + """Check that the contents of as_pcl_structs=True/False match.""" + pcds_struct = list(vd.read_bag(sample_bag_path, topics="/velodyne_packets", as_pcl_structs=True)) + pcds_contiguous = list(vd.read_bag(sample_bag_path, topics="/velodyne_packets", as_pcl_structs=False)) + assert len(pcds_struct) == len(pcds_contiguous) + for (stamp_struct, pcd_struct, _, _), (stamp_contiguous, pcd_contiguous, _, _) in zip(pcds_struct, pcds_contiguous): + assert stamp_struct.host == stamp_contiguous.host + assert stamp_struct.device == stamp_contiguous.device + cast_struct_pcd = _struct_pcd_to_contiguous(pcd_struct) + assert np.allclose(cast_struct_pcd, pcd_contiguous, rtol=1e-6)