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();