Main MRPT website > C++ reference for MRPT 1.9.9
CPointCloudFilterByDistance.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "maps-precomp.h" // Precomp header
11 
15 
16 using namespace mrpt::maps;
17 using namespace mrpt::utils;
18 
20  /** [in,out] The input pointcloud, which will be modified upon return after
21  filtering. */
23  /** [in] The timestamp of the input pointcloud */
24  const mrpt::system::TTimeStamp pc_timestamp,
25  /** [in] If nullptr, the PC is assumed to be given in global coordinates.
26  Otherwise, it will be transformed from local coordinates to global using
27  this transformation. */
28  const mrpt::poses::CPose3D& cur_pc_pose,
29  /** [in,out] additional in/out parameters */
31 {
32  using namespace mrpt::poses;
33  using namespace mrpt::math;
34  using mrpt::math::square;
35 
36  MRPT_START;
37  ASSERT_(pc_timestamp != INVALID_TIMESTAMP);
38  ASSERT_(pc != nullptr);
39 
40  CSimplePointsMap::Ptr original_pc =
41  mrpt::make_aligned_shared<CSimplePointsMap>();
42  original_pc->copyFrom(*pc);
43 
44  // 1) Filter:
45  // ---------------------
46  const size_t N = pc->size();
47  std::vector<bool> deletion_mask;
48  deletion_mask.assign(N, false);
49  size_t del_count = 0;
50 
51  // get reference, previous PC:
52  ASSERT_(options.previous_keyframes >= 1);
53  bool can_do_filter = true;
54 
55  std::vector<FrameInfo*> prev_pc; // (options.previous_keyframes, nullptr);
56  {
57  auto it = m_last_frames.rbegin();
58  for (int i = 0;
59  i < options.previous_keyframes && it != m_last_frames.rend();
60  ++i, ++it)
61  {
62  prev_pc.push_back(&it->second);
63  }
64  }
65 
66  if (prev_pc.size() < static_cast<size_t>(options.previous_keyframes))
67  {
68  can_do_filter = false;
69  }
70  else
71  {
72  for (int i = 0; can_do_filter && i < options.previous_keyframes; ++i)
73  {
75  m_last_frames.rbegin()->first, pc_timestamp) >
76  options.too_old_seconds)
77  {
78  can_do_filter = false; // A required keyframe is too old
79  break;
80  }
81  }
82  }
83 
84  if (can_do_filter)
85  {
86  // Reference poses of each PC:
87  // Previous: prev_pc.pose
89  for (int k = 0; k < options.previous_keyframes; ++k)
90  {
91  const CPose3D rel_pose = cur_pc_pose - prev_pc[k]->pose;
92  rel_poses.push_back(rel_pose);
93  }
94 
95  // The idea is that we can now find matches between pt{i} in time_{k},
96  // composed with rel_pose
97  // with the local points in time_{k-1}.
98 
99  std::vector<TPoint3D> pt_km1(options.previous_keyframes);
100 
101  for (size_t i = 0; i < N; i++)
102  {
103  // get i-th point in time=k:
104  TPoint3Df ptf_k;
105  pc->getPointFast(i, ptf_k.x, ptf_k.y, ptf_k.z);
106  const TPoint3D pt_k = TPoint3D(ptf_k);
107 
108  // Point, referred to time=k-1 frame of reference
109  for (int k = 0; k < options.previous_keyframes; ++k)
110  rel_poses[k].composePoint(pt_k, pt_km1[k]);
111 
112  // Look for neighbors in "time=k"
113  std::vector<TPoint3D> neig_k;
114  std::vector<float> neig_sq_dist_k;
116  pt_k, 2 /*num queries*/, neig_k, neig_sq_dist_k);
117 
118  // Look for neighbors in "time=k-i"
119  std::vector<TPoint3D> neig_kmi(options.previous_keyframes);
120  std::vector<float> neig_sq_dist_kmi(
121  options.previous_keyframes, std::numeric_limits<float>::max());
122 
123  for (int k = 0; k < options.previous_keyframes; ++k)
124  {
125  for (int prev_tim_idx = 0;
126  prev_tim_idx < options.previous_keyframes; prev_tim_idx++)
127  {
128  if (prev_pc[prev_tim_idx]->pc->size() > 0)
129  {
130  prev_pc[prev_tim_idx]->pc->kdTreeClosestPoint3D(
131  pt_km1[prev_tim_idx], neig_kmi[prev_tim_idx],
132  neig_sq_dist_kmi[prev_tim_idx]);
133  }
134  }
135  }
136 
137  // Rule:
138  // we must have at least 1 neighbor in t=k, and 1 neighbor in t=k-i
139  const double max_allowed_dist_sq = square(
140  options.min_dist + options.angle_tolerance * pt_k.norm());
141 
142  bool ok_total = true;
143  const bool ok_t =
144  neig_k.size() > 1 && neig_sq_dist_k[1] < max_allowed_dist_sq;
145  ok_total = ok_total && ok_t;
146 
147  for (int k = 0; k < options.previous_keyframes; ++k)
148  {
149  const bool ok_tm1 = neig_sq_dist_kmi[k] < max_allowed_dist_sq;
150  ok_total = ok_total && ok_tm1;
151  }
152 
153  // Delete?
154  const bool do_delete = !(ok_total);
155  deletion_mask[i] = do_delete;
156 
157  if (do_delete) del_count++;
158  }
159 
160  // Remove points:
161  if ((params == nullptr || params->do_not_delete == false) && N > 0 &&
162  del_count / double(N) <
163  options.max_deletion_ratio // If we are deleting too many
164  // points, it may be that the filter
165  // is plainly wrong
166  )
167  {
168  pc->applyDeletionMask(deletion_mask);
169  }
170  } // we can do filter
171 
172  if (params != nullptr && params->out_deletion_mask != nullptr)
173  {
174  *params->out_deletion_mask = deletion_mask;
175  }
176 
177  // 2) Add PC to list
178  // ---------------------
179  {
180  FrameInfo fi;
181  fi.pc = original_pc;
182  fi.pose = cur_pc_pose;
183 
184  m_last_frames[pc_timestamp] = fi;
185  }
186 
187  // 3) Remove too-old PCs.
188  // ---------------------
189  for (auto it = m_last_frames.begin(); it != m_last_frames.end();)
190  {
191  if (mrpt::system::timeDifference(it->first, pc_timestamp) >
192  options.too_old_seconds)
193  {
194  it = m_last_frames.erase(it);
195  }
196  else
197  {
198  ++it;
199  }
200  }
201 
202  MRPT_END;
203 }
204 
206  : min_dist(0.10),
207  angle_tolerance(mrpt::utils::DEG2RAD(5)),
208  too_old_seconds(1.0),
209  previous_keyframes(1),
210  max_deletion_ratio(.4)
211 {
212 }
213 
216 {
217  MRPT_LOAD_CONFIG_VAR(min_dist, double, c, s);
218  MRPT_LOAD_CONFIG_VAR_DEGREES(angle_tolerance, c, s);
219  MRPT_LOAD_CONFIG_VAR(too_old_seconds, double, c, s);
220  MRPT_LOAD_CONFIG_VAR(previous_keyframes, int, c, s);
221  MRPT_LOAD_CONFIG_VAR(max_deletion_ratio, double, c, s);
222 }
223 
226 {
227  MRPT_SAVE_CONFIG_VAR_COMMENT(min_dist, "");
229  "angle_tolerance", angle_tolerance, "");
230  MRPT_SAVE_CONFIG_VAR_COMMENT(too_old_seconds, "");
232  previous_keyframes,
233  "(Default: 1) How many previous keyframes will be compared with the "
234  "latest pointcloud.");
236  max_deletion_ratio,
237  "(Default: 0.4) If the ratio [0,1] of points considered invalid "
238  "(`deletion` ) is larger than this ratio, no point will be deleted "
239  "since it'd be too suspicious and may indicate a failure of this "
240  "filter.");
241 }
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
Definition: datetime.h:32
void getPointFast(size_t index, float &x, float &y, float &z) const
Just like getPoint() but without checking out-of-bound index and without returning the point weight...
Definition: CPointsMap.h:427
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define MRPT_SAVE_CONFIG_VAR_DEGREES_COMMENT( __entryName, __variable, __comment)
double norm() const
Point norm.
GLdouble s
Definition: glext.h:3676
This class allows loading and storing values and vectors of different types from a configuration text...
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans or other sensors...
Definition: CPointsMap.h:63
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
#define MRPT_SAVE_CONFIG_VAR_COMMENT(variableName, __comment)
Lightweight 3D point (float version).
#define MRPT_END
const GLubyte * c
Definition: glext.h:6313
void kdTreeNClosestPoint3D(float x0, float y0, float z0, size_t knn, std::vector< float > &out_x, std::vector< float > &out_y, std::vector< float > &out_z, std::vector< float > &out_dist_sqr) const
KD Tree-based search for the N closest points to some given 3D coordinates.
#define DEG2RAD
GLsizei const GLchar ** string
Definition: glext.h:4101
void saveToConfigFile(mrpt::utils::CConfigFileBase &c, const std::string &section) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:16
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
T square(const T x)
Inline function for the square of a number.
std::shared_ptr< CSimplePointsMap > Ptr
#define ASSERT_(f)
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
#define MRPT_LOAD_CONFIG_VAR_DEGREES( variableName, configFileObject, sectionNameStr)
Loads a double variable, stored as radians but entered in the INI-file as degrees.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
Definition: datetime.cpp:208
#define MRPT_LOAD_CONFIG_VAR( variableName, variableType, configFileObject, sectionNameStr)
An useful macro for loading variables stored in a INI-like file under a key with the same name that t...
Lightweight 3D point.
size_t size() const
Returns the number of stored points in the map.
Definition: CPointsMap.h:385
void filter(mrpt::maps::CPointsMap *inout_pointcloud, const mrpt::system::TTimeStamp pc_timestamp, const mrpt::poses::CPose3D &pc_reference_pose, TExtraFilterParams *params=nullptr) override
Apply the filtering algorithm to the pointcloud.
GLenum const GLfloat * params
Definition: glext.h:3534
std::vector< TYPE1, Eigen::aligned_allocator< TYPE1 > > vector_t
void applyDeletionMask(const std::vector< bool > &mask)
Remove from the map the points marked in a bool&#39;s array as "true".



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019