CARLA
Loading...
Searching...
No Matches
test_point_cloud_fields.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "test.h"
8
10
11namespace {
12
13constexpr std::uint32_t SizeOf(carla::ros2::PointFieldDataType datatype) {
14 switch (datatype) {
23 }
24 return 0u;
25}
26
27// Compile-time check that within a layout the fields are tightly packed
28// (each field's offset equals the running sum of previous field sizes).
29template <std::size_t N>
30constexpr std::uint32_t LastFieldEnd(
31 const std::array<carla::ros2::PointFieldDescriptor, N> &layout) {
32 return layout.back().offset + SizeOf(layout.back().datatype) * layout.back().count;
33}
34
35} // namespace
36
37TEST(PointCloudFields, lidar_layout_matches_lidar_detection_size) {
38 const auto &fields = carla::ros2::kLidarFields;
39 ASSERT_EQ(fields.size(), 4u);
40 EXPECT_EQ(fields[0].name, "x");
41 EXPECT_EQ(fields[1].name, "y");
42 EXPECT_EQ(fields[2].name, "z");
43 EXPECT_EQ(fields[3].name, "intensity");
44 EXPECT_EQ(LastFieldEnd(fields), 16u);
45}
46
47TEST(PointCloudFields, extended_lidar_layout_is_autoware_xyzircaedt) {
48 const auto &fields = carla::ros2::kLidarFieldsEx;
49 ASSERT_EQ(fields.size(), 10u);
50 EXPECT_EQ(fields[0].name, "x");
51 EXPECT_EQ(fields[1].name, "y");
52 EXPECT_EQ(fields[2].name, "z");
53 EXPECT_EQ(fields[3].name, "intensity");
54 EXPECT_EQ(fields[4].name, "return_type");
55 EXPECT_EQ(fields[5].name, "channel");
56 EXPECT_EQ(fields[6].name, "azimuth");
57 EXPECT_EQ(fields[7].name, "elevation");
58 EXPECT_EQ(fields[8].name, "distance");
59 EXPECT_EQ(fields[9].name, "time_stamp");
60 EXPECT_EQ(fields[3].datatype, carla::ros2::PointFieldDataType::UInt8);
61 EXPECT_EQ(fields[4].datatype, carla::ros2::PointFieldDataType::UInt8);
62 EXPECT_EQ(fields[5].datatype, carla::ros2::PointFieldDataType::UInt16);
63 EXPECT_EQ(fields[9].datatype, carla::ros2::PointFieldDataType::UInt32);
64 // Tightly packed 32 B stride: matches both the Autoware PointXYZIRCAEDT
65 // struct and the naturally aligned LidarPointEx POD in the publisher.
66 EXPECT_EQ(LastFieldEnd(fields), 32u);
67}
68
69TEST(PointCloudFields, semantic_lidar_layout_matches_semantic_lidar_detection_size) {
70 const auto &fields = carla::ros2::kSemanticLidarFields;
71 ASSERT_EQ(fields.size(), 6u);
72 EXPECT_EQ(fields[0].name, "x");
73 EXPECT_EQ(fields[3].name, "cos_inc_angle");
74 EXPECT_EQ(fields[4].name, "object_idx");
75 EXPECT_EQ(fields[5].name, "object_tag");
76 EXPECT_EQ(fields[4].datatype, carla::ros2::PointFieldDataType::UInt32);
77 EXPECT_EQ(fields[5].datatype, carla::ros2::PointFieldDataType::UInt32);
78 EXPECT_EQ(LastFieldEnd(fields), 24u);
79}
80
81TEST(PointCloudFields, radar_layout_carries_seven_float_fields) {
82 const auto &fields = carla::ros2::kRadarFields;
83 ASSERT_EQ(fields.size(), 7u);
84 EXPECT_EQ(fields[3].name, "velocity");
85 EXPECT_EQ(fields[4].name, "azimuth");
86 EXPECT_EQ(fields[5].name, "altitude");
87 EXPECT_EQ(fields[6].name, "depth");
88 for (const auto &field : fields) {
89 EXPECT_EQ(field.datatype, carla::ros2::PointFieldDataType::Float32);
90 EXPECT_EQ(field.count, 1u);
91 }
92 EXPECT_EQ(LastFieldEnd(fields), 28u);
93}
94
95TEST(PointCloudFields, dvs_layout_matches_packed_dvs_event_size) {
96 const auto &fields = carla::ros2::kDvsFields;
97 ASSERT_EQ(fields.size(), 4u);
98 EXPECT_EQ(fields[0].name, "x");
99 EXPECT_EQ(fields[1].name, "y");
100 EXPECT_EQ(fields[2].name, "t");
101 EXPECT_EQ(fields[3].name, "pol");
102 EXPECT_EQ(fields[0].datatype, carla::ros2::PointFieldDataType::UInt16);
103 EXPECT_EQ(fields[2].datatype, carla::ros2::PointFieldDataType::Float64);
104 EXPECT_EQ(fields[3].datatype, carla::ros2::PointFieldDataType::Int8);
105 // sensor::data::DVSEvent is #pragma pack(push, 1): 2 + 2 + 8 + 1 = 13.
106 EXPECT_EQ(LastFieldEnd(fields), 13u);
107}
108
109TEST(PointCloudFields, layouts_offsets_are_monotonically_increasing) {
110 auto check_monotonic = [](auto &layout) {
111 for (std::size_t i = 1; i < layout.size(); ++i) {
112 EXPECT_GT(layout[i].offset, layout[i - 1].offset);
113 }
114 };
115 check_monotonic(carla::ros2::kLidarFields);
116 check_monotonic(carla::ros2::kLidarFieldsEx);
117 check_monotonic(carla::ros2::kSemanticLidarFields);
118 check_monotonic(carla::ros2::kRadarFields);
119 check_monotonic(carla::ros2::kDvsFields);
120}
constexpr std::array< PointFieldDescriptor, 4 > kLidarFields
constexpr std::array< PointFieldDescriptor, 7 > kRadarFields
constexpr std::array< PointFieldDescriptor, 4 > kDvsFields
constexpr std::array< PointFieldDescriptor, 6 > kSemanticLidarFields
constexpr std::array< PointFieldDescriptor, 10 > kLidarFieldsEx
TEST(PointCloudFields, lidar_layout_matches_lidar_detection_size)