Skip to content

Commit 5a098ad

Browse files
Update multi-return for more types of return and all RGL fields. (#324)
* Add return mode and type enums. Adjust node interfaces. Update multi-return configuration on RaytraceNode. * Add API call to set return mode on RaytraceNode. * Update raytrace pipeline to handle multi-return. * Fix saving non hit samples. * Fix indexing in saving shared beam data. * Fix isHit values being not initialized. * Add value checkout on setting return mode. * Remove kernel and MultiReturnPointers used in previous implementation of multi-return. * Make adjustments in RaytraceNode definition. Remove unused code. Add minor TODOs. * Add minor explanation to MultiReturnSamplePointers. * Make cleanup and minor refactors in nodeKernels. * Make cleanup in optixPrograms. * Add TODO and explanation for nodeKernels. * Make cleanup in RaytraceNode. * Remove MultiReturnSwitch Node and update multi-return tests. * Fix multi-return VLP-16 test. * Fix multi-return test with cube in motion. * Make last cleanup in multi-return tests. * Add option to set cube intensity to spawnCubeOnScene helper. * Update GraphMultiReturn test to verify also strongest return. * Make changes based on review. --------- Signed-off-by: Paweł Liberadzki <[email protected]>
1 parent f9586a0 commit 5a098ad

16 files changed

+674
-376
lines changed

include/rgl/api/core.h

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -450,15 +450,59 @@ typedef enum : int32_t
450450
} rgl_field_t;
451451

452452
/**
453-
* Kinds of return type for multi-return LiDAR output.
454-
*/
455-
typedef enum : int32_t
453+
* Bitshift and masks for coding return modes and types. Most significant byte encodes the number of returns. Return mode is
454+
* encoded on 8 most significant bits (24-31) - 1 for single return mode, 2 for dual return. Remaining 24 bits are for encoding
455+
* return type. First return is on 8 LEAST significant bits (0-7), and next 8 bits (8-15) are for second return. Bits 16-23 are
456+
* not used at this moment - in the future e.g. the third return may be encoded there. Return type comes from rgl_return_type_t.
457+
* Example: RGL_RETURN_LAST_STRONGEST would be encoded as:
458+
* 0x02000201
459+
* 02 - dual return
460+
* 00 - not used bits
461+
* 02 - second return - RGL_RETURN_TYPE_LAST
462+
* 01 - first return - RGL_RETURN_TYPE_STRONGEST
463+
*/
464+
const int32_t RGL_RETURN_MODE_BIT_SHIFT = 24;
465+
const int32_t RGL_RETURN_MODE_SINGLE = 1 << RGL_RETURN_MODE_BIT_SHIFT;
466+
const int32_t RGL_RETURN_MODE_DUAL = 2 << RGL_RETURN_MODE_BIT_SHIFT;
467+
const int32_t RGL_RETURN_TYPE_BIT_SHIFT = 8;
468+
469+
/**
470+
* Kinds of return types for multi-return LiDAR output.
471+
*/
472+
typedef enum : uint8_t
456473
{
457-
RGL_RETURN_TYPE_NOT_DIVERGENT = 0,
458-
RGL_RETURN_TYPE_FIRST = 1,
474+
RGL_RETURN_TYPE_UNKNOWN = 0,
475+
RGL_RETURN_TYPE_STRONGEST = 1,
459476
RGL_RETURN_TYPE_LAST = 2,
477+
RGL_RETURN_TYPE_SECOND = 3,
478+
RGL_RETURN_TYPE_FIRST = 4,
479+
RGL_RETURN_TYPE_SECOND_STRONGEST = 5,
460480
} rgl_return_type_t;
461481

482+
/**
483+
* Kinds of return modes for multi-return LiDAR output.
484+
*/
485+
typedef enum : int32_t
486+
{
487+
RGL_RETURN_UNKNOWN = RGL_RETURN_TYPE_UNKNOWN,
488+
// Single return modes
489+
RGL_RETURN_FIRST = RGL_RETURN_MODE_SINGLE | RGL_RETURN_TYPE_FIRST,
490+
RGL_RETURN_SECOND = RGL_RETURN_MODE_SINGLE | RGL_RETURN_TYPE_SECOND,
491+
RGL_RETURN_LAST = RGL_RETURN_MODE_SINGLE | RGL_RETURN_TYPE_LAST,
492+
RGL_RETURN_STRONGEST = RGL_RETURN_MODE_SINGLE | RGL_RETURN_TYPE_STRONGEST,
493+
// Dual return modes
494+
RGL_RETURN_LAST_STRONGEST = RGL_RETURN_MODE_DUAL | (RGL_RETURN_TYPE_LAST) |
495+
(RGL_RETURN_TYPE_STRONGEST << RGL_RETURN_TYPE_BIT_SHIFT),
496+
RGL_RETURN_FIRST_LAST = RGL_RETURN_MODE_DUAL | (RGL_RETURN_TYPE_FIRST) |
497+
(RGL_RETURN_TYPE_LAST << RGL_RETURN_TYPE_BIT_SHIFT),
498+
RGL_RETURN_FIRST_STRONGEST = RGL_RETURN_MODE_DUAL | (RGL_RETURN_TYPE_FIRST) |
499+
(RGL_RETURN_TYPE_STRONGEST << RGL_RETURN_TYPE_BIT_SHIFT),
500+
RGL_RETURN_STRONGEST_SECOND_STRONGEST = RGL_RETURN_MODE_DUAL | (RGL_RETURN_TYPE_STRONGEST) |
501+
(RGL_RETURN_TYPE_SECOND_STRONGEST << RGL_RETURN_TYPE_BIT_SHIFT),
502+
RGL_RETURN_FIRST_SECOND = RGL_RETURN_MODE_DUAL | (RGL_RETURN_TYPE_FIRST) |
503+
(RGL_RETURN_TYPE_SECOND << RGL_RETURN_TYPE_BIT_SHIFT),
504+
} rgl_return_mode_t;
505+
462506
/**
463507
* Helper enum for axis selection
464508
*/
@@ -848,6 +892,18 @@ RGL_API rgl_status_t rgl_node_raytrace_configure_beam_divergence(rgl_node_t node
848892
*/
849893
RGL_API rgl_status_t rgl_node_raytrace_configure_default_intensity(rgl_node_t node, float default_intensity);
850894

895+
/**
896+
* Modifies RaytraceNode to set return mode.
897+
* Point return types (RGL_FIELD_RETURN_TYPE_U8) will be set to corresponding rgl_return_type_t values, e.g. return mode
898+
* RGL_RETURN_FIRST_LAST will result in point return types to be set to RGL_RETURN_TYPE_FIRST or RGL_RETURN_TYPE_LAST,
899+
* interchangeably.
900+
* Default return mode on RaytraceNode is RGL_RETURN_FIRST.
901+
* Passing RGL_RETURN_UNKNOWN is an invalid operation and will fail - user can not set RGL_RETURN_UNKNOWN as return mode.
902+
* @param node RaytraceNode to modify.
903+
* @param return_mode Return mode to set.
904+
*/
905+
RGL_API rgl_status_t rgl_node_raytrace_configure_return_mode(rgl_node_t node, rgl_return_mode_t return_mode);
906+
851907
/**
852908
* Creates or modifies FormatPointsNode.
853909
* The Node converts internal representation into a binary format defined by the `fields` array.
@@ -886,7 +942,10 @@ RGL_API rgl_status_t rgl_node_points_compact_by_field(rgl_node_t* node, rgl_fiel
886942
/**
887943
* Creates or modifies SpatialMergePointsNode.
888944
* The Node merges point clouds spatially (e.g., multiple lidars outputs into one point cloud).
889-
* Only provided fields are merged (RGL_FIELD_DYNAMIC_FORMAT is not supported).
945+
* Only provided fields are merged (RGL_FIELD_DYNAMIC_FORMAT is not supported). This Node do not resolve point return types
946+
* (RGL_FIELD_RETURN_TYPE_U8) in any way - output return mode is always assumed to be RGL_RETURN_UNKNOWN and respective
947+
* cloud points keep their return types. This may results in a case, where output point cloud contain points e.g. from
948+
* four or more return types (rgl_return_type_t).
890949
* Input point clouds must be unorganized (height == 1).
891950
* Any modification to the Node's parameters clears accumulated data.
892951
* Graph input: point cloud(s)
@@ -913,7 +972,9 @@ RGL_API rgl_status_t rgl_node_points_temporal_merge(rgl_node_t* node, const rgl_
913972

914973
/**
915974
* Creates or modifies FromArrayPointsNode.
916-
* The Node provides initial points for its children Nodes.
975+
* The Node provides initial points for its children Nodes. This Node does not handle return mode - it is assumed that
976+
* return mode is always RGL_RETURN_UNKNOWN. RGL_FIELD_RETURN_TYPE_U8 field values are still set according to data
977+
* passed by user.
917978
* Input: none
918979
* Output: point cloud
919980
* @param node If (*node) == nullptr, a new Node will be created. Otherwise, (*node) will be modified.
@@ -1059,17 +1120,6 @@ RGL_API rgl_status_t rgl_node_gaussian_noise_angular_hitpoint(rgl_node_t* node,
10591120
RGL_API rgl_status_t rgl_node_gaussian_noise_distance(rgl_node_t* node, float mean, float st_dev_base,
10601121
float st_dev_rise_per_meter);
10611122

1062-
/**
1063-
* Creates or modifies MultiReturnSwitchNode
1064-
* This is a special node which does not modify the data but acts as an adapter to the multi-return feature.
1065-
* Thanks to this node, user can attach unchanged pipelines to work with specific return type from multi-return raytracing.
1066-
* Graph input: point cloud (with multi-return fields)
1067-
* Graph output: point cloud (with a selected field from parent's multi-return point cloud)
1068-
* @param node If (*node) == nullptr, a new Node will be created. Otherwise, (*node) will be modified.
1069-
* @param return_type Return type to select from multi-return point cloud.
1070-
*/
1071-
RGL_API rgl_status_t rgl_node_multi_return_switch(rgl_node_t* node, rgl_return_type_t);
1072-
10731123
/**
10741124
* Assigns value true to out_alive if the given node is known and has not been destroyed,
10751125
* assigns value false otherwise.

src/api/apiCore.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,27 @@ void TapeCore::tape_node_raytrace_configure_default_intensity(const YAML::Node&
10661066
rgl_node_raytrace_configure_default_intensity(node, yamlNode[1].as<float>());
10671067
}
10681068

1069+
RGL_API rgl_status_t rgl_node_raytrace_configure_return_mode(rgl_node_t node, rgl_return_mode_t return_mode)
1070+
{
1071+
auto status = rglSafeCall([&]() {
1072+
RGL_API_LOG("rgl_node_raytrace_configure_return_mode(node={}, return_mode={})", repr(node), return_mode);
1073+
CHECK_ARG(node != nullptr);
1074+
CHECK_ARG(return_mode != RGL_RETURN_UNKNOWN);
1075+
RaytraceNode::Ptr raytraceNode = Node::validatePtr<RaytraceNode>(node);
1076+
raytraceNode->setReturnMode(return_mode);
1077+
});
1078+
TAPE_HOOK(node, return_mode);
1079+
return status;
1080+
}
1081+
1082+
void TapeCore::tape_node_raytrace_configure_return_mode(const YAML::Node& yamlNode, PlaybackState& state)
1083+
{
1084+
auto nodeId = yamlNode[0].as<TapeAPIObjectID>();
1085+
auto returnMode = static_cast<rgl_return_mode_t>(yamlNode[1].as<int>());
1086+
rgl_node_t node = state.nodes.contains(nodeId) ? state.nodes.at(nodeId) : nullptr;
1087+
rgl_node_raytrace_configure_return_mode(node, returnMode);
1088+
}
1089+
10691090
RGL_API rgl_status_t rgl_node_points_format(rgl_node_t* node, const rgl_field_t* fields, int32_t field_count)
10701091
{
10711092
auto status = rglSafeCall([&]() {
@@ -1422,27 +1443,6 @@ void TapeCore::tape_node_gaussian_noise_distance(const YAML::Node& yamlNode, Pla
14221443
state.nodes.insert({nodeId, node});
14231444
}
14241445

1425-
RGL_API rgl_status_t rgl_node_multi_return_switch(rgl_node_t* node, rgl_return_type_t return_type)
1426-
{
1427-
auto status = rglSafeCall([&]() {
1428-
RGL_API_LOG("rgl_node_multi_return_switch(node={}, return_type={})", repr(node), return_type);
1429-
CHECK_ARG(node != nullptr);
1430-
1431-
createOrUpdateNode<MultiReturnSwitchNode>(node, return_type);
1432-
});
1433-
TAPE_HOOK(node, return_type);
1434-
return status;
1435-
}
1436-
1437-
void TapeCore::tape_node_multi_return_switch(const YAML::Node& yamlNode, PlaybackState& state)
1438-
{
1439-
auto nodeId = yamlNode[0].as<TapeAPIObjectID>();
1440-
auto return_type = static_cast<rgl_return_type_t>(yamlNode[1].as<int>());
1441-
rgl_node_t node = state.nodes.contains(nodeId) ? state.nodes.at(nodeId) : nullptr;
1442-
rgl_node_multi_return_switch(&node, return_type);
1443-
state.nodes.insert({nodeId, node});
1444-
}
1445-
14461446
rgl_status_t rgl_node_is_alive(rgl_node_t node, bool* out_alive)
14471447
{
14481448
auto status = rglSafeCall([&]() {

src/gpu/MultiReturn.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@
2020
#define MULTI_RETURN_BEAM_LAYERS 3
2121
#define MULTI_RETURN_BEAM_SAMPLES (1 + (MULTI_RETURN_BEAM_VERTICES * MULTI_RETURN_BEAM_LAYERS))
2222

23-
struct MultiReturnPointers
23+
struct MultiReturnSamplesPointers
2424
{
25+
// XYZ is not stored for samples, because we calculate it alongside center ray direction. For this reason, only distance
26+
// is necessary.
2527
Field<IS_HIT_I32>::type* isHit;
26-
Field<XYZ_VEC3_F32>::type* xyz;
2728
Field<DISTANCE_F32>::type* distance;
29+
Field<INTENSITY_F32>::type* intensity;
30+
Field<LASER_RETRO_F32>::type* laserRetro;
31+
Field<ENTITY_ID_I32>::type* entityId;
32+
Field<ABSOLUTE_VELOCITY_VEC3_F32>::type* absVelocity;
33+
Field<RELATIVE_VELOCITY_VEC3_F32>::type* relVelocity;
34+
Field<RADIAL_SPEED_F32>::type* radialSpeed;
35+
Field<NORMAL_VEC3_F32>::type* normal;
36+
Field<INCIDENT_ANGLE_F32>::type* incidentAngle;
2837
};

src/gpu/RaytraceRequestContext.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct RaytraceRequestContext
5454
Field<IS_HIT_I32>::type* isHit;
5555
Field<RAY_IDX_U32>::type* rayIdx;
5656
Field<RING_ID_U16>::type* ringIdx;
57+
Field<RETURN_TYPE_U8>::type* returnType;
5758
Field<DISTANCE_F32>::type* distance;
5859
Field<INTENSITY_F32>::type* intensityF32;
5960
Field<INTENSITY_U8>::type* intensityU8;
@@ -70,8 +71,9 @@ struct RaytraceRequestContext
7071
Field<INCIDENT_ANGLE_F32>::type* incidentAngle;
7172

7273
// Multi-Return
74+
MultiReturnSamplesPointers mrSamples;
75+
int returnCount;
7376
float hBeamHalfDivergenceRad;
7477
float vBeamHalfDivergenceRad;
75-
MultiReturnPointers mrSamples;
7678
};
7779
static_assert(std::is_trivially_copyable<RaytraceRequestContext>::value);

0 commit comments

Comments
 (0)