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 #include <humanoid_localization/RaycastingModel.h>
00025 
00026 #include <pcl/point_types.h>
00027 #include <pcl/ros/conversions.h>
00028 #include <pcl_ros/transforms.h>
00029 #include <octomap_ros/conversions.h>
00030 
00031 namespace humanoid_localization{
00032 
00033 RaycastingModel::RaycastingModel(ros::NodeHandle* nh, boost::shared_ptr<MapModel> mapModel, EngineT * rngEngine)
00034 : ObservationModel(nh, mapModel, rngEngine)
00035 {
00036   
00037   nh->param("raycasting/z_hit", m_zHit, 0.8);
00038   nh->param("raycasting/z_short", m_zShort, 0.1);
00039   nh->param("raycasting/z_max", m_zMax, 0.05);
00040   nh->param("raycasting/z_rand", m_zRand, 0.05);
00041   nh->param("raycasting/sigma_hit", m_sigmaHit, 0.02);
00042   nh->param("raycasting/lambda_short", m_lambdaShort, 0.1);
00043 
00044   if (m_zMax <= 0.0){
00045     ROS_ERROR("raycasting/z_max needs to be > 0.0");
00046   }
00047 
00048   if (m_zRand <= 0.0){
00049     ROS_ERROR("raycasting/z_rand needs to be > 0.0");
00050   }
00051 }
00052 
00053 RaycastingModel::~RaycastingModel(){
00054 
00055 }
00056 
00057 void RaycastingModel::integrateMeasurement(Particles& particles, const PointCloud& pc, const std::vector<float>& ranges, float max_range, const tf::Transform& base_to_laser){
00058   assert(pc.size() == ranges.size());
00059 
00060   if (!m_map){
00061     ROS_ERROR("Map file is not set in raycasting");
00062     return;
00063   }
00064   
00065 #pragma omp parallel for
00066   for (unsigned i=0; i < particles.size(); ++i){
00067     Eigen::Matrix4f globalLaserOrigin;
00068     tf::Transform globalLaserOriginTf = particles[i].pose * base_to_laser;
00069     pcl_ros::transformAsMatrix(globalLaserOriginTf, globalLaserOrigin);
00070 
00071     
00072     octomap::point3d originP(globalLaserOriginTf.getOrigin().x(),
00073                              globalLaserOriginTf.getOrigin().y(),
00074                              globalLaserOriginTf.getOrigin().z());
00075     PointCloud pc_transformed;
00076     pcl::transformPointCloud(pc, pc_transformed, globalLaserOrigin);
00077 
00078     
00079     PointCloud::const_iterator pc_it = pc_transformed.begin();
00080     std::vector<float>::const_iterator ranges_it = ranges.begin();
00081     for ( ; pc_it != pc_transformed.end(); ++pc_it, ++ranges_it){
00082 
00083       double p = 0.0; 
00084 
00085       if (*ranges_it <= max_range){
00086 
00087         
00088         octomap::point3d direction(pc_it->x , pc_it->y, pc_it->z);
00089         direction = direction - originP;
00090 
00091         
00092         octomap::point3d end;
00093         
00094         
00095         if(m_map->castRay(originP,direction, end, true, 1.5*max_range)){
00096           assert(m_map->isNodeOccupied(m_map->search(end)));
00097           float raycastRange = (originP - end).norm();
00098           float z = raycastRange - *ranges_it;
00099           float sigma_scaled = m_sigmaHit;
00100           if (m_use_squared_error)
00101              sigma_scaled = (*ranges_it) * (*ranges_it) * (m_sigmaHit);
00102 
00103           
00104           p = m_zHit / (SQRT_2_PI * sigma_scaled) * exp(-(z * z) / (2 * sigma_scaled * sigma_scaled));
00105 
00106           
00107           if (*ranges_it <= raycastRange)
00108             p += m_zShort * m_lambdaShort * exp(-m_lambdaShort* (*ranges_it)) / (1-exp(-m_lambdaShort*raycastRange));
00109 
00110           
00111           p += m_zRand / max_range;
00112         } else { 
00113           p = m_zRand / max_range;
00114         }
00115 
00116       } else{ 
00117         p = m_zMax;
00118       }
00119 
00120       
00121       
00122       assert(p > 0.0);
00123       particles[i].weight += log(p);
00124 
00125     } 
00126 
00127   } 
00128 
00129 
00130 }
00131 
00132 bool RaycastingModel::getHeightError(const Particle& p, const tf::StampedTransform& footprintToBase, double& heightError) const{
00133 
00134   octomap::point3d direction = octomap::pointTfToOctomap(footprintToBase.inverse().getOrigin());
00135   octomap::point3d origin = octomap::pointTfToOctomap(p.pose.getOrigin());
00136   octomap::point3d end;
00137   
00138   if (!m_map->castRay(origin, direction, end, true, 2*direction.norm()))
00139     return false;
00140 
00141   heightError =  std::max(0.0, std::abs((origin-end).z() - footprintToBase.getOrigin().z()) - m_map->getResolution());
00142   
00143 
00144   return true;
00145 }
00146 
00147 }