FilterDeskew.cpp
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * A repertory of multi primitive-to-primitive (MP2P) ICP algorithms in C++
3  * Copyright (C) 2018-2024 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
15 #include <mrpt/containers/yaml.h>
16 #include <mrpt/maps/CSimplePointsMap.h>
17 #include <mrpt/math/ops_containers.h> // dotProduct
18 #include <mrpt/poses/Lie/SO.h>
19 #include <mrpt/random/RandomGenerators.h>
20 #include <mrpt/version.h>
21 
22 #if MRPT_VERSION >= 0x020b04
23 #include <mrpt/maps/CPointsMapXYZIRT.h>
24 #endif
25 
26 #if defined(MP2P_HAS_TBB)
27 #include <tbb/parallel_for.h>
28 #endif
29 
31 
32 using namespace mp2p_icp_filters;
33 
34 FilterDeskew::FilterDeskew() { mrpt::system::COutputLogger::setLoggerName("FilterDeskew"); }
35 
36 void FilterDeskew::initialize(const mrpt::containers::yaml& c)
37 {
38  MRPT_LOG_DEBUG_STREAM("Loading these params:\n" << c);
39 
40  MCP_LOAD_REQ(c, input_pointcloud_layer);
41  MCP_LOAD_REQ(c, output_pointcloud_layer);
42 
43  MCP_LOAD_OPT(c, silently_ignore_no_timestamps);
44  MCP_LOAD_OPT(c, output_layer_class);
45  MCP_LOAD_OPT(c, skip_deskew);
46 
47  ASSERT_(c.has("twist") && c["twist"].isSequence());
48  ASSERT_EQUAL_(c["twist"].asSequence().size(), 6UL);
49 
50  const auto yamlTwist = c["twist"].asSequence();
51 
52  for (int i = 0; i < 6; i++)
53  Parameterizable::parseAndDeclareParameter(yamlTwist.at(i).as<std::string>(), twist[i]);
54 }
55 
57 {
58  MRPT_START
59 #if MRPT_VERSION >= 0x020b04
60 
62 
63  // Out:
64  ASSERT_(!output_pointcloud_layer.empty());
65 
66  // Create if new: Append to existing layer, if already existed.
67  mrpt::maps::CPointsMap::Ptr outPc = GetOrCreatePointLayer(
68  inOut, output_pointcloud_layer, false /*dont allow empty names*/, output_layer_class);
69 
70  // In:
71  ASSERT_(!input_pointcloud_layer.empty());
72 
73  const mrpt::maps::CPointsMap* inPc = nullptr;
74  if (auto itLy = inOut.layers.find(input_pointcloud_layer); itLy != inOut.layers.end())
75  {
76  inPc = mp2p_icp::MapToPointsMap(*itLy->second);
77  if (!inPc)
78  THROW_EXCEPTION_FMT(
79  "Layer '%s' must be of point cloud type.", input_pointcloud_layer.c_str());
80 
81  outPc->reserve(outPc->size() + inPc->size());
82  }
83  else
84  {
85  // Input layer doesn't exist:
86  THROW_EXCEPTION_FMT(
87  "Input layer '%s' not found on input map.", input_pointcloud_layer.c_str());
88  }
89 
90  // If the input is empty, just move on:
91  if (inPc->empty())
92  {
93  MRPT_LOG_DEBUG_STREAM(
94  "Silently ignoring empty input layer: '" << input_pointcloud_layer << "'");
95  return;
96  }
97 
98  // mandatory fields:
99  const auto& xs = inPc->getPointsBufferRef_x();
100  const auto& ys = inPc->getPointsBufferRef_y();
101  const auto& zs = inPc->getPointsBufferRef_z();
102  const size_t n = xs.size();
103 
104  // optional fields:
105  const auto* Is = inPc->getPointsBufferRef_intensity();
106  const auto* Ts = inPc->getPointsBufferRef_timestamp();
107  const auto* Rs = inPc->getPointsBufferRef_ring();
108 
109  auto* out_Is = outPc->getPointsBufferRef_intensity();
110  auto* out_Rs = outPc->getPointsBufferRef_ring();
111  auto* out_Ts = outPc->getPointsBufferRef_timestamp();
112 
113  // Do we have input timestamps per point?
114  if (!Ts || Ts->empty() || skip_deskew)
115  {
116  // not possible to do de-skew:
118  {
119  // just copy all points, including all optional attributes:
120  for (size_t i = 0; i < n; i++) //
121  outPc->insertPointFrom(*inPc, i);
122 
123  MRPT_LOG_DEBUG_STREAM(
124  "Skipping de-skewing in input cloud '" << input_pointcloud_layer
125  << "' with contents: " << inPc->asString());
126  }
127  else
128  {
129  THROW_EXCEPTION_FMT(
130  "Input layer '%s' does not contain per-point timestamps, "
131  "cannot do scan deskew. Set "
132  "'silently_ignore_no_timestamps=true' to skip de-skew."
133  "Input map contents: '%s'",
134  input_pointcloud_layer.c_str(), inPc->asString().c_str());
135  }
136  }
137  else
138  {
139  ASSERT_EQUAL_(Ts->size(), n);
140 
141  // Yes, we have timestamps, apply de-skew:
142  const size_t n0 = outPc->size();
143  outPc->resize(n0 + n);
144 
145  const auto v = mrpt::math::TVector3D(twist.vx, twist.vy, twist.vz);
146  const auto w = mrpt::math::TVector3D(twist.wx, twist.wy, twist.wz);
147 
148 #if defined(MP2P_HAS_TBB)
149  tbb::parallel_for(
150  static_cast<size_t>(0), n,
151  [&](size_t i)
152 #else
153  for (size_t i = 0; i < n; i++)
154 #endif
155  {
156  const auto pt = mrpt::math::TPoint3Df(xs[i], ys[i], zs[i]);
157  if (!(pt.x == 0 && pt.y == 0 && pt.z == 0))
158  {
159  // Forward integrate twist:
160  const mrpt::math::TVector3D v_dt = v * (*Ts)[i];
161  const mrpt::math::TVector3D w_dt = w * (*Ts)[i];
162 
163  const auto p = mrpt::poses::CPose3D::FromRotationAndTranslation(
164  // Rotation: From Lie group SO(3) exponential:
165  mrpt::poses::Lie::SO<3>::exp(mrpt::math::CVectorFixedDouble<3>(w_dt)),
166  // Translation: simple constant velocity model:
167  v_dt);
168 
169  const auto corrPt = p.composePoint(pt);
170 
171  outPc->setPointFast(n0 + i, corrPt.x, corrPt.y, corrPt.z);
172  if (Is && out_Is) (*out_Is)[n0 + i] = (*Is)[i];
173  if (Rs && out_Rs) (*out_Rs)[n0 + i] = (*Rs)[i];
174  if (Ts && out_Ts) (*out_Ts)[n0 + i] = (*Ts)[i];
175  }
176  }
177 #if defined(MP2P_HAS_TBB)
178  );
179 #endif
180  }
181 
182  outPc->mark_as_modified();
183 #else
184  THROW_EXCEPTION("This class requires MRPT >=v2.11.4");
185 #endif
186  MRPT_END
187 }
mp2p_icp::Parameterizable::checkAllParametersAreRealized
void checkAllParametersAreRealized() const
Definition: Parameterizable.cpp:135
mp2p_icp_filters::FilterDeskew::output_layer_class
std::string output_layer_class
Definition: FilterDeskew.h:74
mp2p_icp_filters::FilterDeskew::FilterDeskew
FilterDeskew()
Definition: FilterDeskew.cpp:34
mp2p_icp_filters::FilterDeskew
Definition: FilterDeskew.h:39
mp2p_icp_filters::FilterDeskew::filter
void filter(mp2p_icp::metric_map_t &inOut) const override
Definition: FilterDeskew.cpp:56
mp2p_icp_filters::FilterDeskew::skip_deskew
bool skip_deskew
Definition: FilterDeskew.h:84
testing::internal::string
::std::string string
Definition: gtest.h:1979
IMPLEMENTS_MRPT_OBJECT
IMPLEMENTS_MRPT_OBJECT(FilterDecimateVoxelsQuadratic, mp2p_icp_filters::FilterBase, mp2p_icp_filters) using namespace mp2p_icp_filters
mp2p_icp_filters::FilterDeskew::silently_ignore_no_timestamps
bool silently_ignore_no_timestamps
Definition: FilterDeskew.h:79
mp2p_icp::MapToPointsMap
const mrpt::maps::CPointsMap * MapToPointsMap(const mrpt::maps::CMetricMap &map)
Definition: metricmap.cpp:624
mp2p_icp_filters::FilterBase
Definition: FilterBase.h:46
mp2p_icp_filters::GetOrCreatePointLayer
mrpt::maps::CPointsMap::Ptr GetOrCreatePointLayer(mp2p_icp::metric_map_t &m, const std::string &layerName, bool allowEmptyName=true, const std::string &classForLayerCreation="mrpt::maps::CSimplePointsMap")
Definition: GetOrCreatePointLayer.cpp:15
mp2p_icp_filters::FilterDeskew::twist
mrpt::math::TTwist3D twist
Definition: FilterDeskew.h:90
boost::posix_time
GetOrCreatePointLayer.h
Auxiliary function GetOrCreatePointLayer.
mp2p_icp::metric_map_t
Generic container of pointcloud(s), extracted features and other maps.
Definition: metricmap.h:55
FilterDeskew.h
Deskew (motion compensate) a pointcloud from a moving LIDAR.
mp2p_icp::metric_map_t::layers
std::map< layer_name_t, mrpt::maps::CMetricMap::Ptr > layers
Definition: metricmap.h:82
mp2p_icp_filters
Definition: FilterAdjustTimestamps.h:19
mp2p_icp_filters::FilterDeskew::input_pointcloud_layer
std::string input_pointcloud_layer
Definition: FilterDeskew.h:67
mp2p_icp_filters::FilterDeskew::output_pointcloud_layer
std::string output_pointcloud_layer
Definition: FilterDeskew.h:70
mp2p_icp_filters::FilterDeskew::initialize
void initialize(const mrpt::containers::yaml &c) override
Definition: FilterDeskew.cpp:36


mp2p_icp
Author(s):
autogenerated on Mon May 26 2025 02:45:48