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>
32 auto calcStats(
const int64_t* data,
const size_t N)
33 -> std::pair<int64_t , int64_t >
38 for (
size_t i = 0; i < N; i++) sumMean += data[i];
40 const int64_t mean = sumMean / (N - 1);
42 int64_t sumVariance = 0;
43 for (
size_t i = 0; i < N; i++)
44 sumVariance += mrpt::square(mrpt::math::absDiff<int64_t>(data[i], mean));
46 const int64_t variance = sumVariance / (N - 1);
48 return {mean, variance};
69 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
71 #if MRPT_VERSION >= 0x020b04
72 constexpr
int FIXED_POINT_BITS = 8;
74 auto outPc = mrpt::maps::CSimplePointsMap::Create();
76 ASSERT_(!pc.organizedPoints.empty());
78 const auto nRows = pc.rowCount;
79 const auto nCols = pc.columnCount;
81 ASSERT_EQUAL_(nRows, pc.organizedPoints.rows());
82 ASSERT_EQUAL_(nCols, pc.organizedPoints.cols());
84 ASSERT_EQUAL_(nRows, pc.rangeImage.rows());
85 ASSERT_EQUAL_(nCols, pc.rangeImage.cols());
87 constexpr
unsigned int BLOCK_BITS = 3;
88 constexpr
unsigned int W = 1 << BLOCK_BITS;
90 std::vector<int64_t> rowRangeDiff;
93 for (
size_t r = 0; r < nRows; r++)
95 rowRangeDiff.assign(nCols, 0);
98 for (
size_t i = 1; i < nCols; i++)
100 rowRangeDiff[i] = (
static_cast<int64_t
>(pc.rangeImage(r, i)) -
101 static_cast<int64_t
>(pc.rangeImage(r, i - 1)))
105 for (
size_t i = 1 + W; i < nCols - W; i++)
108 const auto [rdFiltered, rdVar] = calcStats(&rowRangeDiff[i - W], 1 + 2 * W);
110 if (rdVar == 0)
continue;
113 const int64_t riFixPt = pc.rangeImage(r, i) << FIXED_POINT_BITS;
114 int64_t scoreSqrFixPt = mrpt::square(mrpt::math::absDiff(riFixPt, rdFiltered)) / rdVar;
116 const int32_t scoreSqr = scoreSqrFixPt >> (2 * FIXED_POINT_BITS);
122 outPc->insertPoint(robotPose->composePoint(pc.organizedPoints(r, i)));
124 outPc->insertPoint(pc.organizedPoints(r, i));
133 THROW_EXCEPTION(
"This class requires MRPT >=v2.11.4");
139 const std::optional<mrpt::poses::CPose3D>& robotPose)
const
141 constexpr
int FIXED_POINT_BITS = 8;
147 "mrpt::maps::CSimplePointsMap");
152 "mrpt::maps::CSimplePointsMap");
156 ASSERT_(outEdges || outPlanes);
158 ASSERT_(rgbd.hasRangeImage);
160 if (rgbd.rangeImage_isExternallyStored()) rgbd.load();
163 const auto nRows = rgbd.rangeImage.rows();
164 const auto nCols = rgbd.rangeImage.cols();
167 constexpr
unsigned int BLOCK_BITS = 3;
168 constexpr
unsigned int BLOCKS = 1 << BLOCK_BITS;
170 const mrpt::math::CMatrix_u16& ri = rgbd.rangeImage;
171 const auto nRowsDecim = nRows >> BLOCK_BITS;
172 const auto nColsDecim = nCols >> BLOCK_BITS;
174 mrpt::math::CMatrix_u16 R(nRowsDecim, nColsDecim);
176 for (
int rd = 0; rd < nRowsDecim; rd++)
178 for (
int cd = 0; cd < nColsDecim; cd++)
182 for (
unsigned int i = 0; i < BLOCKS; i++)
184 for (
unsigned int j = 0; j < BLOCKS; j++)
186 const auto val = ri((rd << BLOCK_BITS) + i, (cd << BLOCK_BITS) + j);
192 if (count) R(rd, cd) = sum / count;
196 std::vector<int64_t> rowRangeDiff, rowRangeDiff2;
198 const size_t WH = nRows * nCols;
199 const auto& lut = rgbd.get_unproj_lut();
202 const auto& Kxs = lut.Kxs_rot;
203 const auto& Kys = lut.Kys_rot;
204 const auto& Kzs = lut.Kzs_rot;
206 ASSERT_EQUAL_(WH,
size_t(Kxs.size()));
207 ASSERT_EQUAL_(WH,
size_t(Kys.size()));
208 ASSERT_EQUAL_(WH,
size_t(Kzs.size()));
209 const float* kxs = &Kxs[0];
210 const float* kys = &Kys[0];
211 const float* kzs = &Kzs[0];
213 const auto sensorTranslation = rgbd.sensorPose.translation();
215 const int MIN_SPACE_BETWEEN_PLANE_POINTS = nColsDecim / 16;
217 auto lambdaUnprojectPoint = [&](
const int rd,
const int cd)
220 const float D = R(rd, cd) * rgbd.rangeUnits;
222 const int r = rd * BLOCKS + BLOCKS / 2;
223 const int c = cd * BLOCKS + BLOCKS / 2;
225 const auto kx = kxs[r * nCols + c], ky = kys[r * nCols + c], kz = kzs[r * nCols + c];
228 auto pt = mrpt::math::TPoint3Df(kx * D, ky * D , kz * D );
229 pt += sensorTranslation;
231 if (robotPose)
pt = robotPose->composePoint(
pt);
237 for (
int rd = 0; rd < nRowsDecim; rd++)
239 rowRangeDiff.assign(nColsDecim, 0);
240 rowRangeDiff2.assign(nColsDecim, 0);
243 for (
int cd = 1; cd < nColsDecim; cd++)
245 if (!R(rd, cd) || !R(rd, cd - 1))
continue;
248 (
static_cast<int64_t
>(R(rd, cd)) -
static_cast<int64_t
>(R(rd, cd - 1)))
251 for (
int cd = 1; cd < nColsDecim; cd++)
252 rowRangeDiff2[cd] = rowRangeDiff[cd] - rowRangeDiff[cd - 1];
255 const auto [rdMean, rdVar] = calcStats(rowRangeDiff2.data(), rowRangeDiff2.size());
257 std::optional<int> currentPlaneStart;
259 for (
int cd = 1; cd < nColsDecim; cd++)
264 currentPlaneStart.reset();
268 int64_t scoreSqr = rdVar != 0 ? mrpt::square(rowRangeDiff2[cd]) / rdVar : 0;
273 currentPlaneStart.reset();
275 outEdges->insertPoint(lambdaUnprojectPoint(rd, cd));
280 if (!currentPlaneStart) currentPlaneStart = cd;
282 if (cd - *currentPlaneStart > MIN_SPACE_BETWEEN_PLANE_POINTS)
285 outPlanes->insertPoint(lambdaUnprojectPoint(rd, cd));
286 currentPlaneStart.reset();