Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <algorithm>
00031 #include <string>
00032 #include <vector>
00033
00034 #include <ros/ros.h>
00035
00036 #include <pcl/point_types.h>
00037 #include <pcl_ros/point_cloud.h>
00038
00039 #include <mcl_3dl/pf.h>
00040 #include <mcl_3dl/point_cloud_random_sampler.h>
00041 #include <mcl_3dl/point_types.h>
00042 #include <mcl_3dl/vec3.h>
00043
00044 #include <mcl_3dl/lidar_measurement_models/lidar_measurement_model_likelihood.h>
00045
00046 namespace mcl_3dl
00047 {
00048 void LidarMeasurementModelLikelihood::loadConfig(
00049 const ros::NodeHandle& nh,
00050 const std::string& name)
00051 {
00052 ros::NodeHandle pnh(nh, name);
00053
00054 int num_points, num_points_global;
00055 pnh.param("num_points", num_points, 96);
00056 pnh.param("num_points_global", num_points_global, 8);
00057 num_points_default_ = num_points_ = num_points;
00058 num_points_global_ = num_points_global;
00059
00060 double clip_near, clip_far;
00061 pnh.param("clip_near", clip_near, 0.5);
00062 pnh.param("clip_far", clip_far, 10.0);
00063 clip_near_sq_ = clip_near * clip_near;
00064 clip_far_sq_ = clip_far * clip_far;
00065
00066 double clip_z_min, clip_z_max;
00067 pnh.param("clip_z_min", clip_z_min, -2.0);
00068 pnh.param("clip_z_max", clip_z_max, 2.0);
00069 clip_z_min_ = clip_z_min;
00070 clip_z_max_ = clip_z_max;
00071
00072 double match_weight;
00073 pnh.param("match_weight", match_weight, 5.0);
00074 match_weight_ = match_weight;
00075
00076 double match_dist_min, match_dist_flat;
00077 pnh.param("match_dist_min", match_dist_min, 0.2);
00078 pnh.param("match_dist_flat", match_dist_flat, 0.05);
00079 match_dist_min_ = match_dist_min;
00080 match_dist_flat_ = match_dist_flat;
00081 }
00082 void LidarMeasurementModelLikelihood::setGlobalLocalizationStatus(
00083 const size_t num_particles,
00084 const size_t current_num_particles)
00085 {
00086 if (current_num_particles <= num_particles)
00087 {
00088 num_points_ = num_points_default_;
00089 return;
00090 }
00091 size_t num = num_points_default_ * num_particles / current_num_particles;
00092 if (num < num_points_global_)
00093 num = num_points_global_;
00094
00095 num_points_ = num;
00096 }
00097
00098 typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr
00099 LidarMeasurementModelLikelihood::filter(
00100 const typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::ConstPtr& pc) const
00101 {
00102 const auto local_points_filter = [this](const LidarMeasurementModelBase::PointType& p)
00103 {
00104 if (p.x * p.x + p.y * p.y > clip_far_sq_)
00105 return true;
00106 if (p.x * p.x + p.y * p.y < clip_near_sq_)
00107 return true;
00108 if (p.z < clip_z_min_ || clip_z_max_ < p.z)
00109 return true;
00110 return false;
00111 };
00112 pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr pc_filtered(
00113 new pcl::PointCloud<LidarMeasurementModelBase::PointType>);
00114 *pc_filtered = *pc;
00115 pc_filtered->erase(
00116 std::remove_if(pc_filtered->begin(), pc_filtered->end(), local_points_filter), pc_filtered->end());
00117 pc_filtered->width = 1;
00118 pc_filtered->height = pc_filtered->points.size();
00119
00120 return sampler_.sample<LidarMeasurementModelBase::PointType>(pc_filtered, num_points_);
00121 }
00122
00123 LidarMeasurementResult LidarMeasurementModelLikelihood::measure(
00124 typename ChunkedKdtree<LidarMeasurementModelBase::PointType>::Ptr& kdtree,
00125 const typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::ConstPtr& pc,
00126 const std::vector<Vec3>& origins,
00127 const State6DOF& s) const
00128 {
00129 if (!pc)
00130 return LidarMeasurementResult(1, 0);
00131 if (pc->size() == 0)
00132 return LidarMeasurementResult(1, 0);
00133 pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr pc_particle(
00134 new pcl::PointCloud<LidarMeasurementModelBase::PointType>);
00135 std::vector<int> id(1);
00136 std::vector<float> sqdist(1);
00137
00138 float score_like = 0;
00139 *pc_particle = *pc;
00140 s.transform(*pc_particle);
00141 size_t num = 0;
00142 for (auto& p : pc_particle->points)
00143 {
00144 if (kdtree->radiusSearch(p, match_dist_min_, id, sqdist, 1))
00145 {
00146 const float dist = match_dist_min_ - std::max(sqrtf(sqdist[0]), match_dist_flat_);
00147 if (dist < 0.0)
00148 continue;
00149
00150 score_like += dist * match_weight_;
00151 num++;
00152 }
00153 }
00154 const float match_ratio = static_cast<float>(num) / pc_particle->points.size();
00155
00156 return LidarMeasurementResult(score_like, match_ratio);
00157 }
00158 }