15 #include <mrpt/containers/yaml.h>
16 #include <mrpt/maps/CSimplePointsMap.h>
17 #include <mrpt/math/utils.h>
18 #include <mrpt/obs/CObservation3DRangeScan.h>
19 #include <mrpt/obs/CObservationRotatingScan.h>
20 #include <mrpt/version.h>
33 auto calcStats(
const int64_t* data,
const size_t N)
34 -> std::pair<int64_t , int64_t >
39 for (
size_t i = 0; i < N; i++) sumMean += data[i];
41 const int64_t mean = sumMean / (N - 1);
43 int64_t sumVariance = 0;
44 for (
size_t i = 0; i < N; i++)
46 mrpt::square(mrpt::math::absDiff<int64_t>(data[i], mean));
48 const int64_t variance = sumVariance / (N - 1);
50 return {mean, variance};
56 const mrpt::containers::yaml& c)
72 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
74 #if MRPT_VERSION >= 0x020b04
75 constexpr
int FIXED_POINT_BITS = 8;
77 auto outPc = mrpt::maps::CSimplePointsMap::Create();
79 ASSERT_(!pc.organizedPoints.empty());
81 const auto nRows = pc.rowCount;
82 const auto nCols = pc.columnCount;
84 ASSERT_EQUAL_(nRows, pc.organizedPoints.rows());
85 ASSERT_EQUAL_(nCols, pc.organizedPoints.cols());
87 ASSERT_EQUAL_(nRows, pc.rangeImage.rows());
88 ASSERT_EQUAL_(nCols, pc.rangeImage.cols());
90 constexpr
unsigned int BLOCK_BITS = 3;
91 constexpr
unsigned int W = 1 << BLOCK_BITS;
93 std::vector<int64_t> rowRangeDiff;
96 for (
size_t r = 0; r < nRows; r++)
98 rowRangeDiff.assign(nCols, 0);
101 for (
size_t i = 1; i < nCols; i++)
103 rowRangeDiff[i] = (
static_cast<int64_t
>(pc.rangeImage(r, i)) -
104 static_cast<int64_t
>(pc.rangeImage(r, i - 1)))
108 for (
size_t i = 1 + W; i < nCols - W; i++)
111 const auto [rdFiltered, rdVar] =
112 calcStats(&rowRangeDiff[i - W], 1 + 2 * W);
114 if (rdVar == 0)
continue;
117 const int64_t riFixPt = pc.rangeImage(r, i) << FIXED_POINT_BITS;
118 int64_t scoreSqrFixPt =
119 mrpt::square(mrpt::math::absDiff(riFixPt, rdFiltered)) / rdVar;
121 const int32_t scoreSqr = scoreSqrFixPt >> (2 * FIXED_POINT_BITS);
128 robotPose->composePoint(pc.organizedPoints(r, i)));
130 outPc->insertPoint(pc.organizedPoints(r, i));
139 THROW_EXCEPTION(
"This class requires MRPT >=v2.11.4");
145 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
147 constexpr
int FIXED_POINT_BITS = 8;
153 "mrpt::maps::CSimplePointsMap");
158 "mrpt::maps::CSimplePointsMap");
162 ASSERT_(outEdges || outPlanes);
164 ASSERT_(rgbd.hasRangeImage);
166 if (rgbd.rangeImage_isExternallyStored()) rgbd.load();
169 const auto nRows = rgbd.rangeImage.rows();
170 const auto nCols = rgbd.rangeImage.cols();
173 constexpr
unsigned int BLOCK_BITS = 3;
174 constexpr
unsigned int BLOCKS = 1 << BLOCK_BITS;
176 const mrpt::math::CMatrix_u16& ri = rgbd.rangeImage;
177 const auto nRowsDecim = nRows >> BLOCK_BITS;
178 const auto nColsDecim = nCols >> BLOCK_BITS;
180 mrpt::math::CMatrix_u16 R(nRowsDecim, nColsDecim);
182 for (
int rd = 0; rd < nRowsDecim; rd++)
184 for (
int cd = 0; cd < nColsDecim; cd++)
188 for (
unsigned int i = 0; i < BLOCKS; i++)
190 for (
unsigned int j = 0; j < BLOCKS; j++)
193 ri((rd << BLOCK_BITS) + i, (cd << BLOCK_BITS) + j);
199 if (count) R(rd, cd) = sum / count;
203 std::vector<int64_t> rowRangeDiff, rowRangeDiff2;
205 const size_t WH = nRows * nCols;
206 const auto& lut = rgbd.get_unproj_lut();
209 const auto& Kxs = lut.Kxs_rot;
210 const auto& Kys = lut.Kys_rot;
211 const auto& Kzs = lut.Kzs_rot;
213 ASSERT_EQUAL_(WH,
size_t(Kxs.size()));
214 ASSERT_EQUAL_(WH,
size_t(Kys.size()));
215 ASSERT_EQUAL_(WH,
size_t(Kzs.size()));
216 const float* kxs = &Kxs[0];
217 const float* kys = &Kys[0];
218 const float* kzs = &Kzs[0];
220 const auto sensorTranslation = rgbd.sensorPose.translation();
222 const int MIN_SPACE_BETWEEN_PLANE_POINTS = nColsDecim / 16;
224 auto lambdaUnprojectPoint = [&](
const int rd,
const int cd) {
226 const float D = R(rd, cd) * rgbd.rangeUnits;
228 const int r = rd * BLOCKS + BLOCKS / 2;
229 const int c = cd * BLOCKS + BLOCKS / 2;
231 const auto kx = kxs[r * nCols + c], ky = kys[r * nCols + c],
232 kz = kzs[r * nCols + c];
235 auto pt = mrpt::math::TPoint3Df(kx * D, ky * D , kz * D );
236 pt += sensorTranslation;
238 if (robotPose)
pt = robotPose->composePoint(
pt);
244 for (
int rd = 0; rd < nRowsDecim; rd++)
246 rowRangeDiff.assign(nColsDecim, 0);
247 rowRangeDiff2.assign(nColsDecim, 0);
250 for (
int cd = 1; cd < nColsDecim; cd++)
252 if (!R(rd, cd) || !R(rd, cd - 1))
continue;
254 rowRangeDiff[cd] = (
static_cast<int64_t
>(R(rd, cd)) -
255 static_cast<int64_t
>(R(rd, cd - 1)))
258 for (
int cd = 1; cd < nColsDecim; cd++)
259 rowRangeDiff2[cd] = rowRangeDiff[cd] - rowRangeDiff[cd - 1];
262 const auto [rdMean, rdVar] =
263 calcStats(rowRangeDiff2.data(), rowRangeDiff2.size());
265 std::optional<int> currentPlaneStart;
267 for (
int cd = 1; cd < nColsDecim; cd++)
272 currentPlaneStart.reset();
277 rdVar != 0 ? mrpt::square(rowRangeDiff2[cd]) / rdVar : 0;
282 currentPlaneStart.reset();
284 outEdges->insertPoint(lambdaUnprojectPoint(rd, cd));
289 if (!currentPlaneStart) currentPlaneStart = cd;
291 if (cd - *currentPlaneStart > MIN_SPACE_BETWEEN_PLANE_POINTS)
294 outPlanes->insertPoint(lambdaUnprojectPoint(rd, cd));
295 currentPlaneStart.reset();