9 #ifndef cpointsmap_crtp_common_H 10 #define cpointsmap_crtp_common_H 18 template <
class Derived>
19 struct loadFromRangeImpl
28 obj.mark_as_modified();
45 if (!
obj.insertionOptions.addToExistingPointsMap)
50 const int sizeRangeScan = rangeScan.
scan.
size();
52 if (!sizeRangeScan)
return;
55 if (
obj.m_x.size() + sizeRangeScan >
obj.m_x.capacity())
57 obj.reserve((
size_t)(
obj.m_x.size() * 1.2f) + 3 * sizeRangeScan);
67 float m00 = lric.
HM.get_unsafe(0, 0);
68 float m01 = lric.
HM.get_unsafe(0, 1);
69 float m03 = lric.
HM.get_unsafe(0, 3);
70 float m10 = lric.
HM.get_unsafe(1, 0);
71 float m11 = lric.
HM.get_unsafe(1, 1);
72 float m13 = lric.
HM.get_unsafe(1, 3);
73 float m20 = lric.
HM.get_unsafe(2, 0);
74 float m21 = lric.
HM.get_unsafe(2, 1);
75 float m23 = lric.
HM.get_unsafe(2, 3);
77 float lx_1, ly_1, lz_1, lx = 0, ly = 0,
89 const bool useMinDist =
90 obj.insertionOptions.minDistBetweenLaserPoints > 0;
91 const float minDistSqrBetweenLaserPoints =
92 square(
obj.insertionOptions.minDistBetweenLaserPoints);
97 bool lastPointWasValid =
true;
98 bool thisIsTheFirst =
true;
99 bool lastPointWasInserted =
false;
107 const size_t nPointsAtStart =
obj.size();
108 size_t nextPtIdx = nPointsAtStart;
111 const size_t expectedMaxSize =
114 (
obj.insertionOptions.also_interpolate ? 3 : 1));
115 obj.m_x.resize(expectedMaxSize);
116 obj.m_y.resize(expectedMaxSize);
117 obj.m_z.resize(expectedMaxSize);
126 sincos_vals =
obj.m_scans_sincos_cache.getSinCosForScan(rangeScan);
129 Eigen::Array<float, Eigen::Dynamic, 1> scan_gx(sizeRangeScan + 3),
130 scan_gy(sizeRangeScan + 3),
137 size_t nPackets = sizeRangeScan / 4;
138 if ((sizeRangeScan & 0x03) != 0) nPackets++;
148 const __m128 m00_4val =
150 const __m128 m01_4val = _mm_set1_ps(m01);
151 const __m128 m03_4val = _mm_set1_ps(m03);
153 const __m128 m10_4val = _mm_set1_ps(m10);
154 const __m128 m11_4val = _mm_set1_ps(m11);
155 const __m128 m13_4val = _mm_set1_ps(m13);
157 const __m128 m20_4val = _mm_set1_ps(m20);
158 const __m128 m21_4val = _mm_set1_ps(m21);
159 const __m128 m23_4val = _mm_set1_ps(m23);
168 const float* ptr_in_scan = &rangeScan.
scan[0];
169 const float* ptr_in_cos = &sincos_vals.
ccos[0];
170 const float* ptr_in_sin = &sincos_vals.
csin[0];
172 float* ptr_out_x = &scan_gx[0];
173 float* ptr_out_y = &scan_gy[0];
174 float* ptr_out_z = &scan_gz[0];
176 for (; nPackets; nPackets--, ptr_in_scan += 4, ptr_in_cos += 4,
177 ptr_in_sin += 4, ptr_out_x += 4, ptr_out_y += 4,
180 const __m128 scan_4vals =
181 _mm_loadu_ps(ptr_in_scan);
184 _mm_mul_ps(scan_4vals, _mm_load_ps(ptr_in_cos));
186 _mm_mul_ps(scan_4vals, _mm_load_ps(ptr_in_sin));
189 ptr_out_x, _mm_add_ps(
190 m03_4val, _mm_add_ps(
191 _mm_mul_ps(xs, m00_4val),
192 _mm_mul_ps(ys, m01_4val))));
194 ptr_out_y, _mm_add_ps(
195 m13_4val, _mm_add_ps(
196 _mm_mul_ps(xs, m10_4val),
197 _mm_mul_ps(ys, m11_4val))));
199 ptr_out_z, _mm_add_ps(
200 m23_4val, _mm_add_ps(
201 _mm_mul_ps(xs, m20_4val),
202 _mm_mul_ps(ys, m21_4val))));
204 #else // MRPT_HAS_SSE2 207 Eigen::Array<float, Eigen::Dynamic, 1> scan_x(sizeRangeScan + 3),
208 scan_y(sizeRangeScan + 3);
211 const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, 1>> scan_vals(
212 const_cast<float*>(&rangeScan.
scan[0]), rangeScan.
scan.
size(),
216 const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, 1>> ccos(
217 const_cast<float*>(&sincos_vals.
ccos[0]), rangeScan.
scan.
size(),
219 const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, 1>> csin(
220 const_cast<float*>(&sincos_vals.
csin[0]), rangeScan.
scan.
size(),
224 scan_x = scan_vals.array() * ccos.array();
225 scan_y = scan_vals.array() * csin.array();
229 scan_gx = m00 * scan_x + m01 * scan_y + m03;
230 scan_gy = m10 * scan_x + m11 * scan_y + m13;
231 scan_gz = m20 * scan_x + m21 * scan_y + m23;
232 #endif // MRPT_HAS_SSE2 235 for (
int i = 0; i < sizeRangeScan; i++)
246 obj, lx, ly, lz, lric);
248 lastPointWasInserted =
false;
251 bool pt_pass_min_dist =
true;
253 if (useMinDist ||
obj.insertionOptions.also_interpolate)
255 if (!lastPointWasValid)
256 pt_pass_min_dist =
false;
262 pt_pass_min_dist = (d2 > minDistSqrBetweenLaserPoints);
266 if (thisIsTheFirst || pt_pass_min_dist)
268 thisIsTheFirst =
false;
272 if (
obj.insertionOptions.also_interpolate && i > 1)
274 float changeInDirection;
275 const float d = std::sqrt(d2);
277 if ((lx != lx_1 || ly != ly_1) &&
278 (lx_1 != lx_2 || ly_1 != ly_2))
279 changeInDirection = atan2(ly - ly_1, lx - lx_1) -
280 atan2(ly_1 - ly_2, lx_1 - lx_2);
282 changeInDirection = 0;
287 .minDistBetweenLaserPoints &&
288 d <
obj.insertionOptions
289 .maxDistForInterpolatePoints &&
290 fabs(changeInDirection) <
DEG2RAD(5))
293 d / (2 * sqrt(minDistSqrBetweenLaserPoints)));
295 for (
int q = 1;
q < nInterpol;
q++)
297 float i_x = lx_1 +
q * (lx - lx_1) / nInterpol;
298 float i_y = ly_1 +
q * (ly - ly_1) / nInterpol;
299 float i_z = lz_1 +
q * (lz - lz_1) / nInterpol;
300 if (!
obj.m_heightfilter_enabled ||
301 (i_z >=
obj.m_heightfilter_z_min &&
302 i_z <=
obj.m_heightfilter_z_max))
304 obj.m_x.push_back(i_x);
305 obj.m_y.push_back(i_y);
306 obj.m_z.push_back(i_z);
317 if (!
obj.m_heightfilter_enabled ||
318 (lz >=
obj.m_heightfilter_z_min &&
319 lz <=
obj.m_heightfilter_z_max))
321 obj.m_x[nextPtIdx] = lx;
322 obj.m_y[nextPtIdx] = ly;
323 obj.m_z[nextPtIdx] = lz;
332 lastPointWasInserted =
true;
347 lastPointWasValid = rangeScan.
validRange[i] != 0;
351 if (lastPointWasValid && !lastPointWasInserted)
353 if (!
obj.m_heightfilter_enabled ||
354 (lz >=
obj.m_heightfilter_z_min &&
355 lz <=
obj.m_heightfilter_z_max))
357 obj.m_x[nextPtIdx] = lx;
358 obj.m_y[nextPtIdx] = ly;
359 obj.m_z[nextPtIdx] = lz;
369 obj.m_x.resize(nextPtIdx);
370 obj.m_y.resize(nextPtIdx);
371 obj.m_z.resize(nextPtIdx);
380 obj.mark_as_modified();
390 if (!
obj.insertionOptions.addToExistingPointsMap)
397 const size_t sizeRangeScan = rangeScan.
points3D_x.size();
400 if (
obj.m_x.size() + sizeRangeScan >
obj.m_x.capacity())
401 obj.reserve(
size_t(
obj.m_x.size() + 1.1 * sizeRangeScan));
408 float m00 = lric.
HM.get_unsafe(0, 0);
409 float m01 = lric.
HM.get_unsafe(0, 1);
410 float m02 = lric.
HM.get_unsafe(0, 2);
411 float m03 = lric.
HM.get_unsafe(0, 3);
412 float m10 = lric.
HM.get_unsafe(1, 0);
413 float m11 = lric.
HM.get_unsafe(1, 1);
414 float m12 = lric.
HM.get_unsafe(1, 2);
415 float m13 = lric.
HM.get_unsafe(1, 3);
416 float m20 = lric.
HM.get_unsafe(2, 0);
417 float m21 = lric.
HM.get_unsafe(2, 1);
418 float m22 = lric.
HM.get_unsafe(2, 2);
419 float m23 = lric.
HM.get_unsafe(2, 3);
421 float lx_1, ly_1, lz_1, lx = 0, ly = 0,
429 float minDistSqrBetweenLaserPoints =
430 square(
obj.insertionOptions.minDistBetweenLaserPoints);
433 if (
obj.insertionOptions.minDistBetweenLaserPoints <= 0)
434 minDistSqrBetweenLaserPoints = -1;
439 bool lastPointWasValid =
true;
440 bool thisIsTheFirst =
true;
441 bool lastPointWasInserted =
false;
446 for (
size_t i = 0; i < sizeRangeScan; i++)
451 obj.insertionOptions.insertInvalidPoints)
467 obj, lx, ly, lz, lric);
469 lastPointWasInserted =
false;
474 if (thisIsTheFirst ||
475 (lastPointWasValid && (d2 > minDistSqrBetweenLaserPoints)))
477 thisIsTheFirst =
false;
479 obj.m_x.push_back(lx);
480 obj.m_y.push_back(ly);
481 obj.m_z.push_back(lz);
487 lastPointWasInserted =
true;
494 lastPointWasValid =
true;
498 lastPointWasValid =
false;
506 if (lastPointWasValid && !lastPointWasInserted)
508 if (lx != 0 || ly != 0 || lz != 0)
510 obj.m_x.push_back(lx);
511 obj.m_y.push_back(ly);
512 obj.m_z.push_back(lz);
double DEG2RAD(const double x)
Degrees to radians.
GLdouble GLdouble GLdouble GLdouble q
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement, as from a time-of-flight range camera or any other RGBD sensor.
GLsizei GLsizei GLuint * obj
size_t getScanSize() const
Get number of scan rays.
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< char > > validRange
It's false (=0) on no reflected rays, referenced to elements in scan.
std::vector< float > points3D_z
static void templ_loadFromRangeScan(Derived &obj, const mrpt::obs::CObservation3DRangeScan &rangeScan, const mrpt::poses::CPose3D *robotPose)
T square(const T x)
Inline function for the square of a number.
mrpt::math::CVectorFloat ccos
std::vector< float > points3D_y
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< float > > scan
The range values of the scan, in meters.
void composeFrom(const CPose3D &A, const CPose3D &B)
Makes "this = A (+) B"; this method is slightly more efficient than "this= A + B;" since it avoids th...
mrpt::math::CMatrixDouble44 HM
Homog matrix of the local sensor pose within the robot.
float scan_x
In internal_loadFromRangeScan3D_prepareOneRange, these are the local coordinates of the scan points b...
static void templ_loadFromRangeScan(Derived &obj, const mrpt::obs::CObservation2DRangeScan &rangeScan, const mrpt::poses::CPose3D *robotPose)
bool hasPoints3D
true means the field points3D contains valid data.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
mrpt::math::CVectorFloat csin
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
A pair of vectors with the cos and sin values.
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
std::vector< float > points3D_x
If hasPoints3D=true, the (X,Y,Z) coordinates of the 3D point cloud detected by the camera...
Helper struct used for internal_loadFromRangeScan3D_prepareOneRange()
mrpt::math::CMatrixDouble44 HM
Homog matrix of the local sensor pose within the robot.
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
void getHomogeneousMatrix(mrpt::math::CMatrixDouble44 &out_HM) const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
Helper struct used for internal_loadFromRangeScan2D_prepareOneRange()
int round(const T value)
Returns the closer integer (int) to x.