Skip to content

Commit 9cdcaea

Browse files
nebraszkaprybicki
andauthored
Add MR test (#290)
Co-authored-by: Piotr Rybicki <[email protected]>
1 parent f9b6a43 commit 9cdcaea

File tree

4 files changed

+323
-27
lines changed

4 files changed

+323
-27
lines changed

src/gpu/optixPrograms.cu

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ extern "C" __global__ void __closesthit__()
137137
// Hitpoint
138138
Vec3f hitObject = Vec3f((1 - u - v) * A + u * B + v * C);
139139
const Vec3f hitWorldRaytraced = optixTransformPointFromObjectToWorldSpace(hitObject);
140-
const float distance = (hitWorldRaytraced - beamSampleOrigin).length();
140+
const Vector<3, double> hwrd = hitWorldRaytraced;
141+
const Vector<3, double> hso = beamSampleOrigin;
142+
const double distance = (hwrd - hso).length();
141143
const Vec3f hitWorldSeenBySensor = [&]() {
142144
if (!ctx.doApplyDistortion) {
143145
return hitWorldRaytraced;

test/include/helpers/geometryData.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <rgl/api/core.h>
44

55
static constexpr float CUBE_HALF_EDGE = 1.0;
6+
static constexpr float CUBE_EDGE = 2.0;
67

78
static rgl_vec3f cubeVertices[] = {
89
{-1, -1, -1}, // 0

test/include/helpers/testPointCloud.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ class TestPointCloud
241241
}
242242

243243
template<rgl_field_t T>
244-
std::vector<typename Field<T>::type> getFieldValues()
244+
std::vector<typename Field<T>::type> getFieldValues() const
245245
{
246246
int fieldIndex = std::find(fields.begin(), fields.end(), T) - fields.begin();
247247

@@ -252,7 +252,7 @@ class TestPointCloud
252252

253253
for (int i = 0; i < getPointCount(); i++) {
254254
fieldValues.emplace_back(
255-
*reinterpret_cast<typename Field<T>::type*>(data.data() + i * getPointByteSize() + offset));
255+
*reinterpret_cast<const typename Field<T>::type*>(data.data() + i * getPointByteSize() + offset));
256256
}
257257

258258
return fieldValues;

test/src/graph/multiReturnTest.cpp

Lines changed: 317 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,333 @@
11
#include <helpers/commonHelpers.hpp>
2-
#include "math/Mat3x4f.hpp"
32
#include "helpers/lidarHelpers.hpp"
4-
#include "RGLFields.hpp"
53
#include "helpers/testPointCloud.hpp"
64
#include "helpers/sceneHelpers.hpp"
75

6+
#include "RGLFields.hpp"
7+
#include "math/Mat3x4f.hpp"
8+
9+
using namespace std::chrono_literals;
10+
11+
#if RGL_BUILD_ROS2_EXTENSION
12+
#include <rgl/api/extensions/ros2.h>
13+
#endif
14+
815
class GraphMultiReturn : public RGLTest
9-
{};
16+
{
17+
protected:
18+
// VLP16 data
19+
const float vlp16LidarObjectDistance = 100.0f;
20+
const float vlp16LidarHBeamDivergence = 0.003f; // Velodyne VLP16 horizontal beam divergence in rads
21+
const float vlp16LidarHBeamDiameter = 0.2868f; // Velodyne VLP16 beam horizontal diameter at 100m
22+
23+
std::vector<Mat3x4f> vlp16Channels{Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(11.2f)}, {0.0f, -15.0f, 0.0f}),
24+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(0.7f)}, {0.0f, +1.0f, 0.0f}),
25+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(9.7f)}, {0.0f, -13.0f, 0.0f}),
26+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-2.2f)}, {0.0f, +3.0f, 0.0f}),
27+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(8.1f)}, {0.0f, -11.0f, 0.0f}),
28+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-3.7f)}, {0.0f, +5.0f, 0.0f}),
29+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(6.6f)}, {0.0f, -9.0f, 0.0f}),
30+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-5.1f)}, {0.0f, +7.0f, 0.0f}),
31+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(5.1f)}, {0.0f, -7.0f, 0.0f}),
32+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-6.6f)}, {0.0f, +9.0f, 0.0f}),
33+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(3.7f)}, {0.0f, -5.0f, 0.0f}),
34+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-8.1f)}, {0.0f, +11.0f, 0.0f}),
35+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(2.2f)}, {0.0f, -3.0f, 0.0f}),
36+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-9.7f)}, {0.0f, +13.0f, 0.0f}),
37+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(0.7f)}, {0.0f, -1.0f, 0.0f}),
38+
Mat3x4f::TRS({0.0f, 0.0f, mmToMeters(-11.2f)}, {0.0f, +15.0f, 0.0f})};
39+
40+
const std::vector<rgl_field_t> fields = {XYZ_VEC3_F32, IS_HIT_I32, DISTANCE_F32 /*, INTENSITY_F32, ENTITY_ID_I32*/};
41+
42+
rgl_node_t rays = nullptr, mrRays = nullptr, cameraRays = nullptr, transform = nullptr, mrTransform = nullptr,
43+
cameraTransform = nullptr, raytrace = nullptr, mrRaytrace = nullptr, cameraRaytrace = nullptr, mrFirst = nullptr,
44+
mrLast = nullptr, format = nullptr, mrFormatFirst = nullptr, mrFormatLast = nullptr, cameraFormat = nullptr,
45+
publish = nullptr, cameraPublish = nullptr, mrPublishFirst = nullptr, mrPublishLast = nullptr,
46+
compactFirst = nullptr, compactLast = nullptr;
47+
48+
void constructMRGraph(const std::vector<rgl_mat3x4f>& raysTf, const rgl_mat3x4f& lidarPose, const float beamDivAngle,
49+
bool withPublish = false)
50+
{
51+
EXPECT_RGL_SUCCESS(rgl_node_rays_from_mat3x4f(&mrRays, raysTf.data(), raysTf.size()));
52+
EXPECT_RGL_SUCCESS(rgl_node_rays_transform(&mrTransform, &lidarPose));
53+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&mrRaytrace, nullptr));
54+
EXPECT_RGL_SUCCESS(rgl_node_raytrace_configure_beam_divergence(mrRaytrace, beamDivAngle));
55+
EXPECT_RGL_SUCCESS(rgl_node_multi_return_switch(&mrFirst, RGL_RETURN_TYPE_FIRST));
56+
EXPECT_RGL_SUCCESS(rgl_node_multi_return_switch(&mrLast, RGL_RETURN_TYPE_LAST));
57+
EXPECT_RGL_SUCCESS(rgl_node_points_compact_by_field(&compactFirst, RGL_FIELD_IS_HIT_I32));
58+
EXPECT_RGL_SUCCESS(rgl_node_points_compact_by_field(&compactLast, RGL_FIELD_IS_HIT_I32));
59+
EXPECT_RGL_SUCCESS(rgl_node_points_format(&mrFormatFirst, fields.data(), fields.size()));
60+
EXPECT_RGL_SUCCESS(rgl_node_points_format(&mrFormatLast, fields.data(), fields.size()));
61+
#if RGL_BUILD_ROS2_EXTENSION
62+
if (withPublish) {
63+
EXPECT_RGL_SUCCESS(rgl_node_points_ros2_publish(&mrPublishFirst, "MRTest_First", "world"));
64+
EXPECT_RGL_SUCCESS(rgl_node_points_ros2_publish(&mrPublishLast, "MRTest_Last", "world"));
65+
}
66+
#else
67+
if (withPublish) {
68+
GTEST_SKIP() << "Publishing is not supported without ROS2 extension. Skippping the test.";
69+
}
70+
#endif
71+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrRays, mrTransform));
72+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrTransform, mrRaytrace));
73+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrRaytrace, mrFirst));
74+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrRaytrace, mrLast));
75+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrFirst, compactFirst));
76+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrLast, compactLast));
77+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(compactFirst, mrFormatFirst));
78+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(compactLast, mrFormatLast));
79+
if (withPublish) {
80+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrFormatFirst, mrPublishFirst));
81+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(mrFormatLast, mrPublishLast));
82+
}
83+
}
84+
85+
void constructCameraGraph(const rgl_mat3x4f& cameraPose)
86+
{
87+
#if RGL_BUILD_ROS2_EXTENSION
88+
const std::vector<rgl_mat3x4f> cameraRayTf = makeLidar3dRays(360.0f, 180.0f, 1.0f, 1.0f);
89+
EXPECT_RGL_SUCCESS(rgl_node_rays_from_mat3x4f(&cameraRays, cameraRayTf.data(), cameraRayTf.size()));
90+
EXPECT_RGL_SUCCESS(rgl_node_rays_transform(&cameraTransform, &cameraPose));
91+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&cameraRaytrace, nullptr));
92+
EXPECT_RGL_SUCCESS(rgl_node_points_format(&cameraFormat, fields.data(), fields.size()));
93+
EXPECT_RGL_SUCCESS(rgl_node_points_ros2_publish(&cameraPublish, "MRTest_Camera", "world"));
94+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(cameraRays, cameraTransform));
95+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(cameraTransform, cameraRaytrace));
96+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(cameraRaytrace, cameraFormat));
97+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(cameraFormat, cameraPublish));
98+
#else
99+
GTEST_SKIP() << "Publishing is not supported without ROS2 extension. Skippping the test with camera.";
100+
#endif
101+
}
102+
103+
void spawnStairsOnScene(const float stepWidth, const float stepHeight, const float stepDepth, const float stairsBaseHeight,
104+
const Vec3f& stairsTranslation) const
105+
{
106+
const Vec3f cubeHalfEdgeScaled{CUBE_HALF_EDGE * stepDepth / CUBE_EDGE, CUBE_HALF_EDGE * stepWidth / CUBE_EDGE,
107+
CUBE_HALF_EDGE * stepHeight / CUBE_EDGE};
108+
109+
const auto firstCubeTf =
110+
Mat3x4f::translation(stairsTranslation) *
111+
Mat3x4f::TRS({cubeHalfEdgeScaled.x(), 0.0f, -cubeHalfEdgeScaled.z() + stairsBaseHeight + stepHeight},
112+
{0.0f, 0.0f, 0.0f}, {stepDepth / CUBE_EDGE, stepWidth / CUBE_EDGE, stepHeight / CUBE_EDGE});
113+
spawnCubeOnScene(firstCubeTf);
114+
spawnCubeOnScene(Mat3x4f::translation(stepDepth, 0.0f, stepHeight) * firstCubeTf);
115+
spawnCubeOnScene(Mat3x4f::translation(2 * stepDepth, 0.0f, 2 * stepHeight) * firstCubeTf);
116+
}
117+
118+
constexpr float mmToMeters(float mm) const { return mm * 0.001f; }
119+
};
120+
121+
/**
122+
* This test verifies the accuracy of multiple return handling for the data specified for LiDAR VLP16
123+
* by firing a single beam into a cube and making sure the first and last hits are correctly calculated.
124+
*/
125+
TEST_F(GraphMultiReturn, vlp16_data_compare)
126+
{
127+
// Lidar
128+
const std::vector<rgl_mat3x4f> raysTf{Mat3x4f::TRS({0.0f, 0.0f, 0.0f}, {90.0f, 0.0f, -90.0f}).toRGL()};
129+
const float lidarCubeFaceDist = vlp16LidarObjectDistance;
130+
const float lidarCubeCenterDist = lidarCubeFaceDist + CUBE_HALF_EDGE;
131+
const auto lidarTransl = Vec3f{lidarCubeCenterDist, 0.0f, 0.0f};
132+
const rgl_mat3x4f lidarPose = Mat3x4f::TRS(lidarTransl).toRGL();
133+
134+
// Scene
135+
spawnCubeOnScene(Mat3x4f::identity());
136+
137+
// VLP16 horizontal beam divergence in rads
138+
const float beamDivAngle = vlp16LidarHBeamDivergence;
139+
constructMRGraph(raysTf, lidarPose, beamDivAngle);
140+
141+
EXPECT_RGL_SUCCESS(rgl_graph_run(mrRays));
142+
143+
// Verify the output
144+
const float epsilon = 1e-4f;
145+
146+
const auto mrFirstOutPointcloud = TestPointCloud::createFromNode(mrFormatFirst, fields);
147+
const auto mrFirstIsHits = mrFirstOutPointcloud.getFieldValues<IS_HIT_I32>();
148+
const auto mrFirstPoints = mrFirstOutPointcloud.getFieldValues<XYZ_VEC3_F32>();
149+
const auto mrFirstDistances = mrFirstOutPointcloud.getFieldValues<DISTANCE_F32>();
150+
const auto expectedFirstPoint = Vec3f{CUBE_HALF_EDGE, 0.0f, 0.0f};
151+
EXPECT_EQ(mrFirstOutPointcloud.getPointCount(), raysTf.size());
152+
EXPECT_TRUE(mrFirstIsHits.at(0));
153+
EXPECT_NEAR(mrFirstDistances.at(0), lidarCubeFaceDist, epsilon);
154+
EXPECT_NEAR(mrFirstPoints.at(0).x(), expectedFirstPoint.x(), epsilon);
155+
EXPECT_NEAR(mrFirstPoints.at(0).y(), expectedFirstPoint.y(), epsilon);
156+
EXPECT_NEAR(mrFirstPoints.at(0).z(), expectedFirstPoint.z(), epsilon);
157+
158+
const auto mrLastOutPointcloud = TestPointCloud::createFromNode(mrFormatLast, fields);
159+
const auto mrLastIsHits = mrLastOutPointcloud.getFieldValues<IS_HIT_I32>();
160+
const auto mrLastPoints = mrLastOutPointcloud.getFieldValues<XYZ_VEC3_F32>();
161+
const auto mrLastDistances = mrLastOutPointcloud.getFieldValues<DISTANCE_F32>();
162+
const float expectedDiameter = vlp16LidarHBeamDiameter;
163+
const auto expectedLastDistance = static_cast<float>(sqrt(pow(lidarCubeFaceDist, 2) + pow(expectedDiameter / 2, 2)));
164+
// Substract because the ray is pointing as is the negative X axis
165+
const auto expectedLastPoint = lidarTransl - Vec3f{expectedLastDistance, 0.0f, 0.0f};
166+
EXPECT_EQ(mrLastOutPointcloud.getPointCount(), raysTf.size());
167+
EXPECT_TRUE(mrLastIsHits.at(0));
168+
EXPECT_NEAR(mrLastDistances.at(0), expectedLastDistance, epsilon);
169+
EXPECT_NEAR(mrLastPoints.at(0).x(), expectedLastPoint.x(), epsilon);
170+
EXPECT_NEAR(mrLastPoints.at(0).y(), expectedLastPoint.y(), epsilon);
171+
EXPECT_NEAR(mrLastPoints.at(0).z(), expectedLastPoint.z(), epsilon);
172+
}
10173

11-
TEST_F(GraphMultiReturn, basic)
174+
#if RGL_BUILD_ROS2_EXTENSION
175+
/**
176+
* This test verifies the performance of the multiple return feature in a dynamic scene
177+
* with two cubes placed one behind the other, one cube cyclically moving sideways.
178+
* LiDAR fires the beam in such a way that in some frames the beam partially overlaps the edge of the moving cube.
179+
*/
180+
TEST_F(GraphMultiReturn, pairs_of_cubes_in_motion)
12181
{
13-
rgl_node_t useRays = nullptr, raytrace = nullptr, lidarPose = nullptr, compact = nullptr, yield = nullptr;
14-
std::vector<rgl_field_t> mrFields = {IS_HIT_I32, DISTANCE_F32, XYZ_VEC3_F32, INTENSITY_F32, ENTITY_ID_I32};
182+
/*
183+
* gap
184+
* ________ <---->
185+
* | | |
186+
* | | |
187+
* |________| |
188+
* |
189+
* X
190+
* LIDAR
191+
*/
15192

16-
std::vector<rgl_mat3x4f> rays = {Mat3x4f::identity().toRGL()};
17-
rgl_mat3x4f lidarPoseTf = Mat3x4f::TRS({1, 2, 3}, {0, 30, 0}).toRGL();
193+
GTEST_SKIP(); // Comment to run the test
18194

19-
rgl_entity_t cube = makeEntity();
20-
rgl_mat3x4f cubeTf = Mat3x4f::TRS({0, 0, 0}, {0, 0, 0}, {10, 10, 10}).toRGL();
21-
EXPECT_RGL_SUCCESS(rgl_entity_set_pose(cube, &cubeTf));
195+
// Lidar
196+
const std::vector<rgl_mat3x4f> raysTf{Mat3x4f::TRS({0.0f, 0.0f, 0.0f}, {90.0f, 0.0f, 90.0f}).toRGL()};
197+
const float lidarCubeFaceDist = 100.0f;
198+
const float lidarCubeCenterDist = lidarCubeFaceDist + CUBE_HALF_EDGE * 2;
199+
const Vec3f lidarTransl = {-lidarCubeCenterDist, 3.0f, 3.0f};
200+
const rgl_mat3x4f lidarPose = Mat3x4f::translation(lidarTransl).toRGL();
22201

23-
EXPECT_RGL_SUCCESS(rgl_node_rays_from_mat3x4f(&useRays, rays.data(), rays.size()));
24-
EXPECT_RGL_SUCCESS(rgl_node_rays_transform(&lidarPose, &lidarPoseTf));
202+
// Scene
203+
const Vec2f gapRange = {0.001f, 0.5f};
204+
const std::vector<Mat3x4f> entitiesTransforms = {
205+
Mat3x4f::TRS(Vec3f{-5.0f, lidarTransl.y() + gapRange.x() + CUBE_HALF_EDGE, lidarTransl.z()}),
206+
Mat3x4f::TRS(Vec3f{0.0f, lidarTransl.y(), lidarTransl.z()}, {0, 0, 0}, {2, 2, 2})};
207+
std::vector<rgl_entity_t> entities = {spawnCubeOnScene(entitiesTransforms.at(0)),
208+
spawnCubeOnScene(entitiesTransforms.at(1))};
209+
210+
// Lidar with MR
211+
const float beamDivAngle = 0.003f;
212+
constructMRGraph(raysTf, lidarPose, beamDivAngle, true);
213+
214+
// Lidar without MR
215+
EXPECT_RGL_SUCCESS(rgl_node_rays_from_mat3x4f(&rays, raysTf.data(), raysTf.size()));
216+
EXPECT_RGL_SUCCESS(rgl_node_rays_transform(&transform, &lidarPose));
25217
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&raytrace, nullptr));
26-
EXPECT_RGL_SUCCESS(rgl_node_points_compact_by_field(&compact, RGL_FIELD_IS_HIT_I32));
27-
EXPECT_RGL_SUCCESS(rgl_node_points_yield(&yield, mrFields.data(), mrFields.size()));
218+
EXPECT_RGL_SUCCESS(rgl_node_points_format(&format, fields.data(), fields.size()));
219+
EXPECT_RGL_SUCCESS(rgl_node_points_ros2_publish(&publish, "MRTest_Lidar_Without_MR", "world"));
220+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(rays, transform));
221+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(transform, raytrace));
222+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(raytrace, format));
223+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(format, publish));
224+
225+
// Camera
226+
const rgl_mat3x4f cameraPose = Mat3x4f::TRS(Vec3f{-8.0f, 1.0f, 5.0f}, {90.0f, 30.0f, -70.0f}).toRGL();
227+
constructCameraGraph(cameraPose);
228+
229+
int frameId = 0;
230+
while (true) {
231+
232+
const auto newPose = (entitiesTransforms.at(0) *
233+
Mat3x4f::translation(0.0f, std::abs(std::sin(frameId * 0.05f)) * gapRange.y(), 0.0f))
234+
.toRGL();
235+
EXPECT_RGL_SUCCESS(rgl_entity_set_pose(entities.at(0), &newPose));
236+
237+
ASSERT_RGL_SUCCESS(rgl_graph_run(cameraRays));
238+
ASSERT_RGL_SUCCESS(rgl_graph_run(rays));
239+
ASSERT_RGL_SUCCESS(rgl_graph_run(mrRays));
240+
241+
std::this_thread::sleep_for(50ms);
242+
frameId += 1;
243+
}
244+
}
245+
#endif
246+
247+
#if RGL_BUILD_ROS2_EXTENSION
248+
/**
249+
* This test verifies how changing the beam divergence affects the results obtained with the multi return feature enabled.
250+
* Three cubes arranged in the shape of a stairs are placed on the scene. LiDAR aims the only ray at the center of the middle “stair",
251+
* during the test the beam divergence angle is increased/decreased periodically.
252+
*/
253+
TEST_F(GraphMultiReturn, stairs)
254+
{
255+
/*
256+
* ____ ^
257+
* ____| | Z+
258+
* ____| middle step |
259+
* | ----> X+
260+
*/
261+
262+
GTEST_SKIP(); // Comment to run the test
263+
264+
// Scene
265+
const float stairsBaseHeight = 0.0f;
266+
const float stepWidth = 1.0f;
267+
const float stepHeight = vlp16LidarHBeamDiameter + 0.1f;
268+
const float stepDepth = 0.8f;
269+
const Vec3f stairsTranslation{2.0f, 0.0f, 0.0f};
270+
271+
spawnStairsOnScene(stepWidth, stepHeight, stepDepth, stairsBaseHeight, stairsTranslation);
272+
273+
// Lidar
274+
const std::vector<rgl_mat3x4f> raysTf{Mat3x4f::TRS({0.0f, 0.0f, 0.0f}, {90.0f, 0.0f, 90.0f}).toRGL()};
275+
276+
const float lidarMiddleStepDist = 1.5f * vlp16LidarObjectDistance;
277+
const Vec3f lidarTransl{-lidarMiddleStepDist + stepDepth, 0.0f, stepHeight * 1.5f};
278+
279+
const rgl_mat3x4f lidarPose{(Mat3x4f::translation(lidarTransl + stairsTranslation)).toRGL()};
280+
281+
// Lidar with MR
282+
const float beamDivAngle = vlp16LidarHBeamDivergence;
283+
constructMRGraph(raysTf, lidarPose, beamDivAngle, true);
284+
285+
// Camera
286+
rgl_mat3x4f cameraPose = Mat3x4f::translation({0.0f, -1.5f, stepHeight * 3 + 1.0f}).toRGL();
287+
constructCameraGraph(cameraPose);
288+
ASSERT_RGL_SUCCESS(rgl_graph_run(cameraRays));
289+
290+
int frameId = 0;
291+
while (true) {
292+
const float newBeamDivAngle = beamDivAngle + std::sin(frameId * 0.1f) * beamDivAngle;
293+
ASSERT_RGL_SUCCESS(rgl_node_raytrace_configure_beam_divergence(mrRaytrace, newBeamDivAngle));
294+
295+
ASSERT_RGL_SUCCESS(rgl_graph_run(mrRaytrace));
296+
297+
std::this_thread::sleep_for(100ms);
298+
frameId += 1;
299+
}
300+
}
301+
302+
/**
303+
* This test verifies the performance of the multi return feature when releasing multiple ray beams at once.
304+
*/
305+
TEST_F(GraphMultiReturn, multiple_ray_beams)
306+
{
307+
GTEST_SKIP(); // Comment to run the test
308+
309+
// Scene
310+
spawnCubeOnScene(Mat3x4f::TRS({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {2.0f, 2.0f, 2.0f}));
28311

29-
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(useRays, lidarPose));
30-
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(lidarPose, raytrace));
31-
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(raytrace, compact));
32-
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(compact, yield));
312+
// Camera
313+
constructCameraGraph(Mat3x4f::identity().toRGL());
33314

34-
EXPECT_RGL_SUCCESS(rgl_graph_run(useRays));
315+
// Lidar with MR
316+
const int horizontalSteps = 10;
317+
const auto resolution = 360.0f / horizontalSteps;
318+
std::vector<rgl_mat3x4f> vlp16RaysTf;
319+
vlp16RaysTf.reserve(horizontalSteps * vlp16Channels.size());
35320

36-
TestPointCloud pc = TestPointCloud::createFromNode(yield, mrFields);
37-
EXPECT_EQ(pc.getPointCount(), 1);
321+
for (int i = 0; i < horizontalSteps; ++i) {
322+
for (const auto& velodyneVLP16Channel : vlp16Channels) {
323+
vlp16RaysTf.emplace_back((Mat3x4f::rotationDeg(0.0f, 90.0f, resolution * i) * velodyneVLP16Channel).toRGL());
324+
}
325+
}
326+
const rgl_mat3x4f lidarPose = Mat3x4f::identity().toRGL();
327+
const float beamDivAngle = vlp16LidarHBeamDivergence;
328+
constructMRGraph(vlp16RaysTf, lidarPose, beamDivAngle, true);
38329

39-
EXPECT_RGL_SUCCESS(rgl_graph_destroy(useRays));
40-
}
330+
ASSERT_RGL_SUCCESS(rgl_graph_run(cameraRays));
331+
ASSERT_RGL_SUCCESS(rgl_graph_run(mrRays));
332+
}
333+
#endif

0 commit comments

Comments
 (0)