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/raycast.h>
00043 #include <mcl_3dl/vec3.h>
00044
00045 #include <mcl_3dl/lidar_measurement_models/lidar_measurement_model_beam.h>
00046
00047 namespace mcl_3dl
00048 {
00049 LidarMeasurementModelBeam::LidarMeasurementModelBeam(
00050 const float x, const float y, const float z)
00051 {
00052
00053 map_grid_min_ = std::min({ x, y, z });
00054 map_grid_max_ = std::max({ x, y, z });
00055 }
00056
00057 void LidarMeasurementModelBeam::loadConfig(
00058 const ros::NodeHandle& nh,
00059 const std::string& name)
00060 {
00061 ros::NodeHandle pnh(nh, name);
00062
00063 int num_points, num_points_global;
00064 pnh.param("num_points", num_points, 3);
00065 pnh.param("num_points_global", num_points_global, 0);
00066 num_points_default_ = num_points_ = num_points;
00067 num_points_global_ = num_points_global;
00068
00069 double clip_near, clip_far;
00070 pnh.param("clip_near", clip_near, 0.5);
00071 pnh.param("clip_far", clip_far, 4.0);
00072 clip_near_sq_ = clip_near * clip_near;
00073 clip_far_sq_ = clip_far * clip_far;
00074
00075 double clip_z_min, clip_z_max;
00076 pnh.param("clip_z_min", clip_z_min, -2.0);
00077 pnh.param("clip_z_max", clip_z_max, 2.0);
00078 clip_z_min_ = clip_z_min;
00079 clip_z_max_ = clip_z_max;
00080
00081 double beam_likelihood_min;
00082 pnh.param("beam_likelihood", beam_likelihood_min, 0.2);
00083 beam_likelihood_min_ = beam_likelihood_min;
00084 beam_likelihood_ = powf(beam_likelihood_min, 1.0 / static_cast<float>(num_points));
00085
00086 double ang_total_ref;
00087 pnh.param("ang_total_ref", ang_total_ref, M_PI / 6.0);
00088 sin_total_ref_ = sinf(ang_total_ref);
00089 }
00090
00091 void LidarMeasurementModelBeam::setGlobalLocalizationStatus(
00092 const size_t num_particles,
00093 const size_t current_num_particles)
00094 {
00095 if (current_num_particles <= num_particles)
00096 {
00097 num_points_ = num_points_default_;
00098 return;
00099 }
00100 size_t num = num_points_default_ * num_particles / current_num_particles;
00101 if (num < num_points_global_)
00102 num = num_points_global_;
00103
00104 num_points_ = num;
00105 }
00106
00107 typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr
00108 LidarMeasurementModelBeam::filter(
00109 const typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::ConstPtr& pc) const
00110 {
00111 const auto local_points_filter = [this](const LidarMeasurementModelBase::PointType& p)
00112 {
00113 if (p.x * p.x + p.y * p.y > clip_far_sq_)
00114 return true;
00115 if (p.x * p.x + p.y * p.y < clip_near_sq_)
00116 return true;
00117 if (p.z < clip_z_min_ || clip_z_max_ < p.z)
00118 return true;
00119 return false;
00120 };
00121 pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr pc_filtered(
00122 new pcl::PointCloud<LidarMeasurementModelBase::PointType>);
00123 *pc_filtered = *pc;
00124 pc_filtered->erase(
00125 std::remove_if(pc_filtered->begin(), pc_filtered->end(), local_points_filter), pc_filtered->end());
00126 pc_filtered->width = 1;
00127 pc_filtered->height = pc_filtered->points.size();
00128
00129 return sampler_.sample<LidarMeasurementModelBase::PointType>(pc_filtered, num_points_);
00130 }
00131
00132 LidarMeasurementResult LidarMeasurementModelBeam::measure(
00133 typename ChunkedKdtree<LidarMeasurementModelBase::PointType>::Ptr& kdtree,
00134 const typename pcl::PointCloud<LidarMeasurementModelBase::PointType>::ConstPtr& pc,
00135 const std::vector<Vec3>& origins,
00136 const State6DOF& s) const
00137 {
00138 if (!pc)
00139 return LidarMeasurementResult(1, 0);
00140 if (pc->size() == 0)
00141 return LidarMeasurementResult(1, 0);
00142 pcl::PointCloud<LidarMeasurementModelBase::PointType>::Ptr pc_particle(
00143 new pcl::PointCloud<LidarMeasurementModelBase::PointType>);
00144 std::vector<int> id(1);
00145 std::vector<float> sqdist(1);
00146
00147 float score_beam = 1.0;
00148 *pc_particle = *pc;
00149 s.transform(*pc_particle);
00150 for (auto& p : pc_particle->points)
00151 {
00152 const int beam_header_id = p.label;
00153 Raycast<LidarMeasurementModelBase::PointType> ray(
00154 kdtree,
00155 s.pos_ + s.rot_ * origins[beam_header_id],
00156 Vec3(p.x, p.y, p.z),
00157 map_grid_min_, map_grid_max_);
00158 for (auto point : ray)
00159 {
00160 if (point.collision_)
00161 {
00162
00163 if (point.sin_angle_ > sin_total_ref_)
00164 {
00165 score_beam *= beam_likelihood_;
00166 }
00167 break;
00168 }
00169 }
00170 }
00171 if (score_beam < beam_likelihood_min_)
00172 score_beam = beam_likelihood_min_;
00173
00174 return LidarMeasurementResult(score_beam, 1.0);
00175 }
00176 }