1 #ifndef PCL_TRACKING_IMPL_PARTICLE_FILTER_H_
2 #define PCL_TRACKING_IMPL_PARTICLE_FILTER_H_
5 #include <pcl/common/transforms.h>
6 #include <pcl/tracking/particle_filter.h>
12 template <
typename Po
intInT,
typename StateT>
17 PCL_ERROR(
"[pcl::%s::initCompute] Init failed.\n", getClassName().c_str());
21 if (transed_reference_vector_.empty()) {
23 transed_reference_vector_.resize(particle_num_);
24 for (
int i = 0; i < particle_num_; i++) {
29 coherence_->setTargetCloud(input_);
31 if (!change_detector_)
33 change_detector_resolution_));
35 if (!particles_ || particles_->points.empty())
40 template <
typename Po
intInT,
typename StateT>
43 const std::vector<int>& a,
const std::vector<double>& q)
45 static std::mt19937 rng{std::random_device{}()};
46 std::uniform_real_distribution<> rd(0.0, 1.0);
48 double rU = rd(rng) *
static_cast<double>(particles_->size());
49 int k =
static_cast<int>(rU);
56 template <
typename Po
intInT,
typename StateT>
60 std::vector<double>& q,
64 std::vector<int> HL(particles->size());
66 auto L = HL.end() - 1;
67 const auto num = particles->size();
68 for (std::size_t i = 0; i < num; i++)
69 q[i] = (*particles)[i].weight *
static_cast<float>(num);
70 for (std::size_t i = 0; i < num; i++)
71 a[i] =
static_cast<int>(i);
73 for (std::size_t i = 0; i < num; i++)
75 *H++ =
static_cast<int>(i);
77 *L-- =
static_cast<int>(i);
79 while (H != HL.begin() && L != HL.end() - 1) {
92 template <
typename Po
intInT,
typename StateT>
98 representative_state_.zero();
99 StateT offset = StateT::toState(trans_);
100 representative_state_ = offset;
101 representative_state_.weight = 1.0f /
static_cast<float>(particle_num_);
105 for (
int i = 0; i < particle_num_; i++) {
108 p.sample(initial_noise_mean_, initial_noise_covariance_);
109 p = p + representative_state_;
110 p.weight = 1.0f /
static_cast<float>(particle_num_);
111 particles_->points.push_back(p);
115 template <
typename Po
intInT,
typename StateT>
120 double w_min = std::numeric_limits<double>::max();
121 double w_max = -std::numeric_limits<double>::max();
122 for (
const auto& point : *particles_) {
123 double weight = point.weight;
126 if (weight != 0.0 && w_max < weight)
131 if (w_max != w_min) {
132 for (
auto& point : *particles_) {
133 if (point.weight != 0.0) {
135 static_cast<float>(normalizeParticleWeight(point.weight, w_min, w_max));
140 for (
auto& point : *particles_)
141 point.weight = 1.0f /
static_cast<float>(particles_->size());
145 for (
const auto& point : *particles_) {
150 for (
auto& point : *particles_)
151 point.weight /=
static_cast<float>(sum);
154 for (
auto& point : *particles_)
155 point.weight = 1.0f /
static_cast<float>(particles_->size());
160 template <
typename Po
intInT,
typename StateT>
165 double x_min, y_min, z_min, x_max, y_max, z_max;
166 calcBoundingBox(x_min, x_max, y_min, y_max, z_min, z_max);
167 pass_x_.setFilterLimits(
static_cast<float>(x_min),
static_cast<float>(x_max));
168 pass_y_.setFilterLimits(
static_cast<float>(y_min),
static_cast<float>(y_max));
169 pass_z_.setFilterLimits(
static_cast<float>(z_min),
static_cast<float>(z_max));
173 pass_x_.setInputCloud(input_);
174 pass_x_.filter(*xcloud);
177 pass_y_.setInputCloud(xcloud);
178 pass_y_.filter(*ycloud);
180 pass_z_.setInputCloud(ycloud);
181 pass_z_.filter(output);
185 template <
typename Po
intInT,
typename StateT>
194 x_min = y_min = z_min = std::numeric_limits<double>::max();
195 x_max = y_max = z_max = -std::numeric_limits<double>::max();
197 for (std::size_t i = 0; i < transed_reference_vector_.size(); i++) {
216 template <
typename Po
intInT,
typename StateT>
221 change_detector_->setInputCloud(input);
222 change_detector_->addPointsFromInputCloud();
224 change_detector_->getPointIndicesFromNewVoxels(newPointIdxVector,
225 change_detector_filter_);
226 change_detector_->switchBuffers();
227 return !newPointIdxVector.empty();
230 template <
typename Po
intInT,
typename StateT>
235 for (std::size_t i = 0; i < particles_->size(); i++) {
236 computeTransformedPointCloudWithoutNormal((*particles_)[i],
237 *transed_reference_vector_[i]);
241 cropInputPointCloud(input_, *coherence_input);
243 coherence_->setTargetCloud(coherence_input);
244 coherence_->initCompute();
245 for (std::size_t i = 0; i < particles_->size(); i++) {
248 transed_reference_vector_[i], indices, (*particles_)[i].weight);
252 for (std::size_t i = 0; i < particles_->size(); i++) {
254 computeTransformedPointCloudWithNormal(
255 (*particles_)[i], *indices, *transed_reference_vector_[i]);
259 cropInputPointCloud(input_, *coherence_input);
261 coherence_->setTargetCloud(coherence_input);
262 coherence_->initCompute();
263 for (std::size_t i = 0; i < particles_->size(); i++) {
266 transed_reference_vector_[i], indices, (*particles_)[i].weight);
273 template <
typename Po
intInT,
typename StateT>
279 computeTransformedPointCloudWithNormal(hypothesis, indices, cloud);
281 computeTransformedPointCloudWithoutNormal(hypothesis, cloud);
284 template <
typename Po
intInT,
typename StateT>
289 const Eigen::Affine3f trans = toEigenMatrix(hypothesis);
291 pcl::transformPointCloud<PointInT>(*ref_, cloud, trans);
295 template <
typename Po
intInT,
typename StateT>
296 template <
typename Po
intT, pcl::traits::HasNormal<Po
intT>>
301 const Eigen::Affine3f trans = toEigenMatrix(hypothesis);
303 pcl::transformPointCloudWithNormals<PointInT>(*ref_, cloud, trans);
304 for (std::size_t i = 0; i < cloud.size(); i++) {
305 PointInT input_point = cloud[i];
307 if (!std::isfinite(input_point.x) || !std::isfinite(input_point.y) ||
308 !std::isfinite(input_point.z))
311 Eigen::Vector4f p = input_point.getVector4fMap();
312 Eigen::Vector4f n = input_point.getNormalVector4fMap();
314 if (theta > occlusion_angle_thr_)
315 indices.push_back(i);
319 template <
typename Po
intInT,
typename StateT>
323 resampleWithReplacement();
326 template <
typename Po
intInT,
typename StateT>
330 std::vector<int> a(particles_->size());
331 std::vector<double> q(particles_->size());
332 genAliasTable(a, q, particles_);
334 const std::vector<double> zero_mean(StateT::stateDimension(), 0.0);
337 particles_->points.clear();
339 StateT p = representative_state_;
340 particles_->points.push_back(p);
344 static_cast<int>(particles_->size()) *
static_cast<int>(motion_ratio_);
345 for (
int i = 1; i < motion_num; i++) {
346 int target_particle_index = sampleWithReplacement(a, q);
347 StateT p = (*origparticles)[target_particle_index];
349 p.sample(zero_mean, step_noise_covariance_);
351 particles_->points.push_back(p);
355 for (
int i = motion_num; i < particle_num_; i++) {
356 int target_particle_index = sampleWithReplacement(a, q);
357 StateT p = (*origparticles)[target_particle_index];
359 p.sample(zero_mean, step_noise_covariance_);
360 particles_->points.push_back(p);
364 template <
typename Po
intInT,
typename StateT>
368 StateT orig_representative = representative_state_;
369 representative_state_.zero();
370 representative_state_.weight = 0.0;
371 representative_state_ =
372 StateT::weightedAverage(particles_->begin(), particles_->end());
373 representative_state_.weight = 1.0f /
static_cast<float>(particles_->size());
374 motion_ = representative_state_ - orig_representative;
377 template <
typename Po
intInT,
typename StateT>
382 for (
int i = 0; i < iteration_num_; i++) {
403 #define PCL_INSTANTIATE_ParticleFilterTracker(T, ST) \
404 template class PCL_EXPORTS pcl::tracking::ParticleFilterTracker<T, ST>;
void genAliasTable(std::vector< int > &a, std::vector< double > &q, const PointCloudStateConstPtr &particles)
Generate the tables for walker's alias method.
void calcBoundingBox(double &x_min, double &x_max, double &y_min, double &y_max, double &z_min, double &z_max)
Compute the parameters for the bounding box of hypothesis pointclouds.
void initParticles(bool reset)
Initialize the particles.
int sampleWithReplacement(const std::vector< int > &a, const std::vector< double > &q)
Implementation of "sample with replacement" using Walker's alias method.
bool testChangeDetection(const PointCloudInConstPtr &input)
Run change detection and return true if there is a change.
typename PointCloudIn::ConstPtr PointCloudInConstPtr
void computeTransformedPointCloud(const StateT &hypothesis, pcl::Indices &indices, PointCloudIn &cloud)
Compute a reference pointcloud transformed to the pose that hypothesis represents.
void computeTransformedPointCloudWithNormal(const StateT &hypothesis, pcl::Indices &indices, PointCloudIn &cloud)
Compute a reference pointcloud transformed to the pose that hypothesis represents and calculate indic...
void resampleWithReplacement()
Resampling the particle with replacement.
typename PointCloudState::Ptr PointCloudStatePtr
void computeTransformedPointCloudWithoutNormal(const StateT &hypothesis, PointCloudIn &cloud)
Compute a reference pointcloud transformed to the pose that hypothesis represents and calculate indic...
virtual void resample()
Resampling phase of particle filter method.
typename PointCloudState::ConstPtr PointCloudStateConstPtr
void computeTracking() override
Track the pointcloud using particle filter method.
void cropInputPointCloud(const PointCloudInConstPtr &cloud, PointCloudIn &output)
Crop the pointcloud by the bounding box calculated from hypothesis and the reference pointcloud.
virtual void update()
Calculate the weighted mean of the particles and set it as the result.
virtual void weight()
Weighting phase of particle filter method.
bool initCompute() override
This method should get called before starting the actual computation.
typename PointCloudIn::Ptr PointCloudInPtr
typename Tracker< PointInT, StateT >::PointCloudState PointCloudState
typename Tracker< PointInT, StateT >::PointCloudIn PointCloudIn
virtual void normalizeWeight()
Normalize the weights of all the particels.
Tracker represents the base tracker class.
Define standard C methods and C++ classes that are common to all methods.
void getMinMax3D(const pcl::PointCloud< PointT > &cloud, PointT &min_pt, PointT &max_pt)
Get the minimum and maximum values on each of the 3 (x-y-z) dimensions in a given pointcloud.
double getAngle3D(const Eigen::Vector4f &v1, const Eigen::Vector4f &v2, const bool in_degree=false)
Compute the smallest angle between two 3D vectors in radians (default) or degree.
IndicesAllocator<> Indices
Type used for indices in PCL.
shared_ptr< Indices > IndicesPtr