Skip to content

Commit 7e5833b

Browse files
Implement support for non-repetitive/alternating lidar scan patterns (#52)
* Implement alternating lidar pattern Improve performance by only toggling between existing nodes in graph Simplify pattern loader * Add Livox Mid360 preset * Add Livox Avia preset * Add Livox Horizon preset * Add Livox Mid40 preset * Add Livox Mid70 preset * Add Livox Tele15 preset * Add new lidar presets to readme * Refactor LidarPatternLoader
1 parent 7184305 commit 7e5833b

File tree

11 files changed

+129
-44
lines changed

11 files changed

+129
-44
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ Inside the link entity in your model, add a custom sensor:
194194
<pattern_preset>OS1 64</pattern_preset>
195195
<pattern_preset>Pandar64</pattern_preset>
196196
<pattern_preset>Pandar40P</pattern_preset>
197+
<pattern_preset>Livox Avia</pattern_preset>
198+
<pattern_preset>Livox Horizon</pattern_preset>
199+
<pattern_preset>Livox Mid40</pattern_preset>
200+
<pattern_preset>Livox Mid70</pattern_preset>
201+
<pattern_preset>Livox Mid360</pattern_preset>
202+
<pattern_preset>Livox Tele15</pattern_preset>
197203
```
198204
**Note:** Before launching the simulation it is required to set `RGL_PATTERNS_DIR` environment variable with the path to pattern presets directory (`lidar_patterns` from repository).
199205
```shell

RGLServerPlugin/include/LidarPatternLoader.hh

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
#pragma once
1616

1717
#include <filesystem>
18+
#include <functional>
19+
#include <map>
20+
#include <string>
21+
#include <utility>
1822
#include <vector>
1923

2024
#include <rgl/api/core.h>
@@ -26,9 +30,10 @@ namespace rgl
2630
class LidarPatternLoader
2731
{
2832
public:
29-
using LoadFuncType = std::function<bool(const sdf::ElementConstPtr&, std::vector<rgl_mat3x4f>&)>;
33+
using LoadFuncType = std::function<bool(const sdf::ElementConstPtr&, std::vector<rgl_mat3x4f>&, std::size_t&)>;
3034

31-
static bool Load(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
35+
static bool Load(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern,
36+
std::size_t& outPatternScanSize);
3237

3338
private:
3439
LidarPatternLoader() {};
@@ -37,11 +42,11 @@ private:
3742
gz::math::Angle& angleMin, gz::math::Angle& angleMax,
3843
int& samples);
3944

40-
static bool LoadPatternFromUniform(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
41-
static bool LoadPatternFromCustom(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
42-
static bool LoadPatternFromPreset(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
43-
static bool LoadPatternFromPresetPath(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
44-
static bool LoadPatternFromLidar2d(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern);
45+
static bool LoadPatternFromUniform(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern, std::size_t& outPatternScanSize);
46+
static bool LoadPatternFromCustom(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern, std::size_t& outPatternScanSize);
47+
static bool LoadPatternFromPreset(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern, std::size_t& outPatternScanSize);
48+
static bool LoadPatternFromPresetPath(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern, std::size_t& outPatternScanSize);
49+
static bool LoadPatternFromLidar2d(const sdf::ElementConstPtr& sdf, std::vector<rgl_mat3x4f>& outPattern, std::size_t& outPatternScanSize);
4550

4651
static rgl_mat3x4f AnglesToRglMat3x4f(const gz::math::Angle& roll,
4752
const gz::math::Angle& pitch,
@@ -50,7 +55,7 @@ private:
5055
template<typename T>
5156
static std::vector<T> LoadVector(const std::filesystem::path& path);
5257

53-
static std::map<std::string, std::string> presetNameToFilename;
58+
static std::map<std::string, std::pair<std::string, std::size_t>> presetNameToLoadInfo;
5459
static std::map<std::string, LoadFuncType> patternLoadFunctions;
5560
};
5661

RGLServerPlugin/include/RGLServerPluginInstance.hh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ private:
6666
gz::sim::EntityComponentManager& ecm);
6767

6868
void UpdateLidarPose(const gz::sim::EntityComponentManager& ecm);
69+
void UpdateAlternatingLidarPattern();
6970

7071
bool ShouldRayTrace(std::chrono::steady_clock::duration sim_time,
7172
bool paused);
@@ -86,6 +87,7 @@ private:
8687
gz::math::Angle scanHMax;
8788
int scanHSamples;
8889
std::vector<rgl_mat3x4f> lidarPattern;
90+
std::size_t alternatingPatternIndex = 0;
8991

9092
struct ResultPointCloud
9193
{
@@ -118,7 +120,7 @@ private:
118120
gz::transport::Node::Publisher pointCloudWorldPublisher;
119121
gz::transport::Node gazeboNode;
120122

121-
rgl_node_t rglNodeUseRays = nullptr;
123+
std::vector<rgl_node_t> rglNodesUseRays;
122124
rgl_node_t rglNodeLidarPose = nullptr;
123125
rgl_node_t rglNodeSetRange = nullptr;
124126
rgl_node_t rglNodeRaytrace = nullptr;
@@ -136,6 +138,8 @@ private:
136138
int onPausedSimUpdateCounter = 0;
137139
const int onPausedSimRaytraceInterval = 100;
138140

141+
std::size_t lidarPatternSampleSize = 0;
142+
139143
const std::string worldFrameId = "world";
140144
const std::string worldTopicPostfix = "/world";
141145
};

RGLServerPlugin/src/Lidar.cc

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ bool RGLServerPluginInstance::LoadConfiguration(const std::shared_ptr<const sdf:
7373
topicName = sdf->Get<std::string>(PARAM_TOPIC_ID);
7474
frameId = sdf->Get<std::string>(PARAM_FRAME_ID);
7575

76-
if (!LidarPatternLoader::Load(sdf, lidarPattern)) {
76+
if (!LidarPatternLoader::Load(sdf, lidarPattern, lidarPatternSampleSize)) {
77+
return false;
78+
}
79+
80+
if ((lidarPattern.size() % lidarPatternSampleSize) != 0) {
81+
gzerr << "Total pattern size (" << lidarPattern.size() << ") must be a multiple of the sample size (" << lidarPatternSampleSize << "). Disabling plugin.\n";
7782
return false;
7883
}
7984

@@ -83,7 +88,7 @@ bool RGLServerPluginInstance::LoadConfiguration(const std::shared_ptr<const sdf:
8388
publishLaserScan = true;
8489
scanHMin = sdf->FindElement("pattern_lidar2d")->FindElement("horizontal")->Get<float>("min_angle");
8590
scanHMax = sdf->FindElement("pattern_lidar2d")->FindElement("horizontal")->Get<float>("max_angle");
86-
scanHSamples = lidarPattern.size();
91+
scanHSamples = lidarPatternSampleSize;
8792
}
8893

8994
return true;
@@ -102,15 +107,25 @@ void RGLServerPluginInstance::CreateLidar(gz::sim::Entity entity,
102107

103108
// Resize result data containers with the maximum possible point count (number of lasers).
104109
// This improves performance in runtime because no additional allocations are needed.
105-
resultPointCloud.data.resize(resultPointCloud.pointSize * lidarPattern.size());
110+
resultPointCloud.data.resize(resultPointCloud.pointSize * lidarPatternSampleSize);
106111
if (publishLaserScan)
107112
{
108-
resultLaserScan.distances.resize(lidarPattern.size());
109-
resultLaserScan.intensities.resize(lidarPattern.size());
113+
resultLaserScan.distances.resize(lidarPatternSampleSize);
114+
resultLaserScan.intensities.resize(lidarPatternSampleSize);
115+
}
116+
117+
for (std::size_t i = 0; i < lidarPattern.size(); i += lidarPatternSampleSize)
118+
{
119+
rglNodesUseRays.emplace_back();
120+
if (!CheckRGL(rgl_node_rays_from_mat3x4f(&rglNodesUseRays.back(),
121+
lidarPattern.data() + i,
122+
lidarPatternSampleSize))) {
123+
gzerr << "Failed to create RGL nodes when initializing lidar. Disabling plugin.\n";
124+
return;
125+
}
110126
}
111127

112-
if (!CheckRGL(rgl_node_rays_from_mat3x4f(&rglNodeUseRays, lidarPattern.data(), lidarPattern.size())) ||
113-
!CheckRGL(rgl_node_rays_set_range(&rglNodeSetRange, &lidarMinMaxRange, 1)) ||
128+
if (!CheckRGL(rgl_node_rays_set_range(&rglNodeSetRange, &lidarMinMaxRange, 1)) ||
114129
!CheckRGL(rgl_node_rays_transform(&rglNodeLidarPose, &identity)) ||
115130
!CheckRGL(rgl_node_raytrace(&rglNodeRaytrace, nullptr)) ||
116131
!CheckRGL(rgl_node_points_compact_by_field(&rglNodeCompact, RGL_FIELD_IS_HIT_I32)) ||
@@ -123,7 +138,7 @@ void RGLServerPluginInstance::CreateLidar(gz::sim::Entity entity,
123138
return;
124139
}
125140

126-
if (!CheckRGL(rgl_graph_node_add_child(rglNodeUseRays, rglNodeSetRange)) ||
141+
if (!CheckRGL(rgl_graph_node_add_child(rglNodesUseRays.front(), rglNodeSetRange)) ||
127142
!CheckRGL(rgl_graph_node_add_child(rglNodeSetRange, rglNodeLidarPose)) ||
128143
!CheckRGL(rgl_graph_node_add_child(rglNodeLidarPose, rglNodeRaytrace)) ||
129144
!CheckRGL(rgl_graph_node_add_child(rglNodeRaytrace, rglNodeCompact)) ||
@@ -166,6 +181,25 @@ void RGLServerPluginInstance::UpdateLidarPose(const gz::sim::EntityComponentMana
166181
CheckRGL(rgl_node_points_transform(&rglNodeToLidarFrame, &rglWorldToLidar));
167182
}
168183

184+
void RGLServerPluginInstance::UpdateAlternatingLidarPattern()
185+
{
186+
// remove old child
187+
if(!CheckRGL(rgl_graph_node_remove_child(rglNodesUseRays[alternatingPatternIndex], rglNodeSetRange)))
188+
{
189+
gzerr << "Failed to update alternating lidar pattern, not able to remove child.\n";
190+
return;
191+
}
192+
193+
alternatingPatternIndex = (alternatingPatternIndex + 1) % rglNodesUseRays.size();
194+
195+
// add new child
196+
if(!CheckRGL(rgl_graph_node_add_child(rglNodesUseRays[alternatingPatternIndex], rglNodeSetRange)))
197+
{
198+
gzerr << "Failed to update alternating lidar pattern, not able to add new child.\n";
199+
return;
200+
}
201+
}
202+
169203
bool RGLServerPluginInstance::ShouldRayTrace(std::chrono::steady_clock::duration simTime,
170204
bool paused)
171205
{
@@ -194,6 +228,10 @@ bool RGLServerPluginInstance::ShouldRayTrace(std::chrono::steady_clock::duration
194228

195229
void RGLServerPluginInstance::RayTrace(std::chrono::steady_clock::duration simTime)
196230
{
231+
if (rglNodesUseRays.size() > 1) {
232+
UpdateAlternatingLidarPattern();
233+
}
234+
197235
lastRaytraceTime = simTime;
198236

199237
if (!CheckRGL(rgl_graph_run(rglNodeRaytrace))) {

0 commit comments

Comments
 (0)