Skip to content

Commit c8ea5a1

Browse files
authored
Feature/fault injection (#281)
1 parent 02c0516 commit c8ea5a1

File tree

10 files changed

+154
-1
lines changed

10 files changed

+154
-1
lines changed

include/rgl/api/core.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,15 @@ RGL_API rgl_status_t rgl_node_raytrace_configure_distortion(rgl_node_t node, boo
704704
*/
705705
RGL_API rgl_status_t rgl_node_raytrace_configure_non_hits(rgl_node_t node, float nearDistance, float farDistance);
706706

707+
/**
708+
* Modifies RaytraceNode to apply mask for non-hit values.
709+
* Masked rays will be non-hits and will have the default non-hit values no matter of raytracing result.
710+
* @param node RaytraceNode to modify.
711+
* @param rays_mask Pointer to the array of int32_t. 1 means point is hit, 0 means point is non-hit.
712+
* @param rays_count Number of elements in the `points_mask` array.
713+
*/
714+
RGL_API rgl_status_t rgl_node_raytrace_configure_mask(rgl_node_t node, const int8_t* rays_mask, int32_t rays_count);
715+
707716
/**
708717
* Creates or modifies FormatPointsNode.
709718
* The Node converts internal representation into a binary format defined by the `fields` array.

src/api/apiCore.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,28 @@ void TapeCore::tape_node_raytrace_configure_non_hits(const YAML::Node& yamlNode,
919919
rgl_node_raytrace_configure_non_hits(node, yamlNode[1].as<float>(), yamlNode[2].as<float>());
920920
}
921921

922+
RGL_API rgl_status_t rgl_node_raytrace_configure_mask(rgl_node_t node, const int8_t* rays_mask, int32_t rays_count)
923+
{
924+
auto status = rglSafeCall([&]() {
925+
RGL_API_LOG("rgl_node_raytrace_configure_mask(node={}, rays_mask={}, rays_count={})", repr(node), repr(rays_mask, rays_count),
926+
rays_count);
927+
CHECK_ARG(node != nullptr);
928+
CHECK_ARG(rays_mask != nullptr);
929+
CHECK_ARG(rays_count > 0);
930+
RaytraceNode::Ptr raytraceNode = Node::validatePtr<RaytraceNode>(node);
931+
raytraceNode->setNonHitsMask(rays_mask, rays_count);
932+
});
933+
TAPE_HOOK(node, TAPE_ARRAY(rays_mask, rays_count), rays_count);
934+
return status;
935+
}
936+
937+
void TapeCore::tape_node_raytrace_configure_mask(const YAML::Node& yamlNode, PlaybackState& state)
938+
{
939+
auto nodeId = yamlNode[0].as<TapeAPIObjectID>();
940+
rgl_node_t node = state.nodes.at(nodeId);
941+
rgl_node_raytrace_configure_mask(node, state.getPtr<const int8_t>(yamlNode[1]), yamlNode[2].as<int32_t>());
942+
}
943+
922944
RGL_API rgl_status_t rgl_node_points_format(rgl_node_t* node, const rgl_field_t* fields, int32_t field_count)
923945
{
924946
auto status = rglSafeCall([&]() {

src/gpu/RaytraceRequestContext.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct RaytraceRequestContext
4242
const float* rayTimeOffsetsMs;
4343
size_t rayTimeOffsetsCount;
4444

45+
const int8_t* rayMask;
46+
4547
OptixTraversableHandle scene;
4648
double sceneTime;
4749
float sceneDeltaTime;

src/gpu/nodeKernels.cu

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ __global__ void kFilterGroundPoints(size_t pointCount, const Vec3f sensor_up_vec
223223
outNonGround[tid] = normalUpAngle > ground_angle_threshold;
224224
}
225225

226-
227226
void gpuFindCompaction(cudaStream_t stream, size_t pointCount, const int32_t* shouldCompact,
228227
CompactionIndexType* hitCountInclusive, size_t* outHitCount)
229228
{

src/gpu/optixPrograms.cu

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ extern "C" __global__ void __raygen__()
4949
}
5050

5151
const int rayIdx = static_cast<int>(optixGetLaunchIndex().x);
52+
53+
if (ctx.rayMask != nullptr && ctx.rayMask[rayIdx] == 0) {
54+
saveNonHitRayResult(ctx.farNonHitDistance);
55+
return;
56+
}
57+
5258
Mat3x4f ray = ctx.rays[rayIdx];
5359
const Mat3x4f rayLocal =
5460
ctx.rayOriginToWorld.inverse() *

src/graph/NodesCore.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct RaytraceNode : IPointsNode
128128
void setVelocity(const Vec3f& linearVelocity, const Vec3f& angularVelocity);
129129
void enableRayDistortion(bool enabled) { doApplyDistortion = enabled; }
130130
void setNonHitDistanceValues(float nearDistance, float farDistance);
131+
void setNonHitsMask(const int8_t* maskRaw, size_t maskPointCount);
131132

132133
private:
133134
IRaysNode::Ptr raysNode;
@@ -140,6 +141,8 @@ struct RaytraceNode : IPointsNode
140141
float nearNonHitDistance{std::numeric_limits<float>::infinity()};
141142
float farNonHitDistance{std::numeric_limits<float>::infinity()};
142143

144+
DeviceAsyncArray<int8_t>::Ptr rayMask;
145+
143146
HostPinnedArray<RaytraceRequestContext>::Ptr requestCtxHst = HostPinnedArray<RaytraceRequestContext>::create();
144147
DeviceAsyncArray<RaytraceRequestContext>::Ptr requestCtxDev = DeviceAsyncArray<RaytraceRequestContext>::create(arrayMgr);
145148

src/graph/RaytraceNode.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ void RaytraceNode::validateImpl()
4747
auto msg = fmt::format("requested for raytrace with velocity distortion, but RaytraceNode cannot get time offsets");
4848
throw InvalidPipeline(msg);
4949
}
50+
if (rayMask != nullptr) {
51+
if (rayMask->getCount() != raysNode->getRayCount()) {
52+
throw InvalidPipeline("Mask size does not match the number of rays");
53+
}
54+
}
5055
}
5156

5257
template<rgl_field_t field>
@@ -99,6 +104,7 @@ void RaytraceNode::enqueueExecImpl()
99104
.ringIdsCount = ringIds.has_value() ? (*ringIds)->getCount() : 0,
100105
.rayTimeOffsetsMs = timeOffsets.has_value() ? (*timeOffsets)->asSubclass<DeviceAsyncArray>()->getReadPtr() : nullptr,
101106
.rayTimeOffsetsCount = timeOffsets.has_value() ? (*timeOffsets)->getCount() : 0,
107+
.rayMask = (rayMask != nullptr) ? rayMask->getReadPtr() : nullptr,
102108
.scene = sceneAS,
103109
.sceneTime = Scene::instance().getTime().value_or(Time::zero()).asSeconds(),
104110
.sceneDeltaTime = static_cast<float>(Scene::instance().getDeltaTime().value_or(Time::zero()).asSeconds()),
@@ -184,3 +190,8 @@ void RaytraceNode::setNonHitDistanceValues(float nearDistance, float farDistance
184190
nearNonHitDistance = nearDistance;
185191
farNonHitDistance = farDistance;
186192
}
193+
void RaytraceNode::setNonHitsMask(const int8_t* maskRaw, size_t maskPointCount)
194+
{
195+
rayMask = DeviceAsyncArray<int8_t>::create(arrayMgr);
196+
rayMask->copyFromExternal(maskRaw, maskPointCount);
197+
}

src/tape/TapeCore.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class TapeCore
5353
static void tape_node_raytrace_configure_velocity(const YAML::Node& yamlNode, PlaybackState& state);
5454
static void tape_node_raytrace_configure_distortion(const YAML::Node& yamlNode, PlaybackState& state);
5555
static void tape_node_raytrace_configure_non_hits(const YAML::Node& yamlNode, PlaybackState& state);
56+
static void tape_node_raytrace_configure_mask(const YAML::Node& yamlNode, PlaybackState& state);
5657
static void tape_node_points_format(const YAML::Node& yamlNode, PlaybackState& state);
5758
static void tape_node_points_yield(const YAML::Node& yamlNode, PlaybackState& state);
5859
static void tape_node_points_compact(const YAML::Node& yamlNode, PlaybackState& state);
@@ -105,6 +106,7 @@ class TapeCore
105106
TAPE_CALL_MAPPING("rgl_node_raytrace_configure_velocity", TapeCore::tape_node_raytrace_configure_velocity),
106107
TAPE_CALL_MAPPING("rgl_node_raytrace_configure_distortion", TapeCore::tape_node_raytrace_configure_distortion),
107108
TAPE_CALL_MAPPING("rgl_node_raytrace_configure_non_hits", TapeCore::tape_node_raytrace_configure_non_hits),
109+
TAPE_CALL_MAPPING("rgl_node_raytrace_configure_mask", TapeCore::tape_node_raytrace_configure_mask),
108110
TAPE_CALL_MAPPING("rgl_node_points_format", TapeCore::tape_node_points_format),
109111
TAPE_CALL_MAPPING("rgl_node_points_yield", TapeCore::tape_node_points_yield),
110112
TAPE_CALL_MAPPING("rgl_node_points_compact", TapeCore::tape_node_points_compact),

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(RGL_TEST_FILES
2424
src/graph/nodes/GaussianNoiseAngularHitpointNodeTest.cpp
2525
src/graph/nodes/GaussianNoiseAngularRayNodeTest.cpp
2626
src/graph/nodes/GaussianNoiseDistanceNodeTest.cpp
27+
src/graph/MaskRaysTest.cpp
2728
src/graph/nodes/RaytraceNodeTest.cpp
2829
src/graph/nodes/RadarPostprocessPointsNodeTest.cpp
2930
src/graph/nodes/RadarTrackObjectsNodeTest.cpp

test/src/graph/MaskRaysTest.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "helpers/testPointCloud.hpp"
2+
#include "helpers/commonHelpers.hpp"
3+
#include "RGLFields.hpp"
4+
#include "helpers/sceneHelpers.hpp"
5+
#include "helpers/lidarHelpers.hpp"
6+
7+
class MaskRaysTest : public RGLTest
8+
{
9+
10+
protected:
11+
const int maskCount = 100;
12+
std::vector<int8_t> points_mask;
13+
std::vector<rgl_field_t> fields = {XYZ_VEC3_F32, IS_HIT_I32, INTENSITY_F32, IS_GROUND_I32};
14+
15+
void initializeMask(int raysCount)
16+
{
17+
points_mask.resize(raysCount);
18+
std::fill(points_mask.begin(), points_mask.end(), 1);
19+
for (int i = 0; i < maskCount; i++) {
20+
points_mask[i] = 0;
21+
}
22+
}
23+
};
24+
25+
TEST_F(MaskRaysTest, invalid_argument_node) { EXPECT_RGL_INVALID_ARGUMENT(rgl_node_raytrace_configure_mask(nullptr, nullptr, 0)); }
26+
27+
TEST_F(MaskRaysTest, invalid_argument_mask)
28+
{
29+
rgl_node_t raytraceNode = nullptr;
30+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&raytraceNode, nullptr));
31+
32+
EXPECT_RGL_INVALID_ARGUMENT(rgl_node_raytrace_configure_mask(raytraceNode, nullptr, 0));
33+
}
34+
35+
TEST_F(MaskRaysTest, invalid_argument_count)
36+
{
37+
rgl_node_t raytraceNode = nullptr;
38+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&raytraceNode, nullptr));
39+
40+
EXPECT_RGL_INVALID_ARGUMENT(rgl_node_raytrace_configure_mask(raytraceNode, points_mask.data(), 0));
41+
}
42+
43+
TEST_F(MaskRaysTest, valid_arguments)
44+
{
45+
const int raysNumber = 100;
46+
rgl_node_t raytraceNode = nullptr;
47+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&raytraceNode, nullptr));
48+
49+
// Mask
50+
initializeMask(raysNumber);
51+
52+
EXPECT_RGL_SUCCESS(rgl_node_raytrace_configure_mask(raytraceNode, points_mask.data(), raysNumber));
53+
}
54+
55+
TEST_F(MaskRaysTest, use_case)
56+
{
57+
// Scene
58+
rgl_entity_t wall = makeEntity(makeCubeMesh());
59+
rgl_mat3x4f wallPose = Mat3x4f::TRS(Vec3f(0,0,0), Vec3f(0, 0, 0), Vec3f(10,10,10)).toRGL();
60+
EXPECT_RGL_SUCCESS(rgl_entity_set_pose(wall, &wallPose));
61+
62+
// Rays
63+
std::vector<rgl_mat3x4f> rays = makeLidar3dRays(360, 180, 0.36, 0.18);
64+
65+
const int raysNumber = rays.size();
66+
// Mask
67+
initializeMask(raysNumber);
68+
69+
// Graph
70+
rgl_node_t useRaysNode = nullptr;
71+
rgl_node_t raytraceNode = nullptr;
72+
rgl_node_t compactNode = nullptr;
73+
rgl_node_t yieldNode = nullptr;
74+
75+
// Prepare graph without filtering
76+
EXPECT_RGL_SUCCESS(rgl_node_rays_from_mat3x4f(&useRaysNode, rays.data(), rays.size()));
77+
EXPECT_RGL_SUCCESS(rgl_node_raytrace(&raytraceNode, nullptr));
78+
EXPECT_RGL_SUCCESS(rgl_node_points_compact_by_field(&compactNode, IS_HIT_I32));
79+
EXPECT_RGL_SUCCESS(rgl_node_points_yield(&yieldNode, fields.data(), fields.size()));
80+
81+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(useRaysNode, raytraceNode));
82+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(raytraceNode, compactNode));
83+
EXPECT_RGL_SUCCESS(rgl_graph_node_add_child(compactNode, yieldNode));
84+
85+
EXPECT_RGL_SUCCESS(rgl_graph_run(raytraceNode));
86+
87+
TestPointCloud outputPointCloud = TestPointCloud::createFromNode(yieldNode, fields);
88+
auto fullCloudSize = outputPointCloud.getPointCount();
89+
90+
EXPECT_RGL_SUCCESS(rgl_node_raytrace_configure_mask(raytraceNode, points_mask.data(), raysNumber));
91+
92+
EXPECT_RGL_SUCCESS(rgl_graph_run(raytraceNode));
93+
TestPointCloud outputPointCloudMasked = TestPointCloud::createFromNode(yieldNode, fields);
94+
auto maskedCloudSize = outputPointCloudMasked.getPointCount();
95+
96+
EXPECT_EQ(fullCloudSize - maskCount, maskedCloudSize);
97+
98+
}

0 commit comments

Comments
 (0)