terrain_model.cpp
Go to the documentation of this file.
00001 #include <vigir_footstep_planning_default_plugins/world_model/terrain_model.h>
00002 
00003 #include <pcl_conversions/pcl_conversions.h>
00004 
00005 #include <pcl/io/pcd_io.h>
00006 #include <pcl/kdtree/kdtree_flann.h>
00007 
00008 #include <vigir_footstep_planning_lib/helper.h>
00009 #include <vigir_footstep_planning_lib/math.h>
00010 
00011 #include <vigir_terrain_classifier/terrain_model.h>
00012 
00013 
00014 
00015 namespace vigir_footstep_planning
00016 {
00017 TerrainModel::TerrainModel(const std::string& name)
00018   : TerrainModelPlugin(name)
00019 {
00020 }
00021 
00022 bool TerrainModel::initialize(const vigir_generic_params::ParameterSet& params)
00023 {
00024   if (!TerrainModelPlugin::initialize(params))
00025     return false;
00026 
00027   // get foot dimensions
00028   getFootSize(nh_, foot_size);
00029 
00030   // subscribe
00031   std::string topic;
00032   getParam("terrain_model_topic", topic, std::string("terrain_model"), true);
00033   terrain_model_sub = nh_.subscribe(topic, 1, &TerrainModel::setTerrainModel, this);
00034 
00035   return true;
00036 }
00037 
00038 bool TerrainModel::loadParams(const vigir_generic_params::ParameterSet& params)
00039 {
00040   if (!TerrainModelPlugin::loadParams(params))
00041     return false;
00042 
00043   params.getParam("foot_contact_support/min_sampling_steps_x", min_sampling_steps_x);
00044   params.getParam("foot_contact_support/min_sampling_steps_y", min_sampling_steps_y);
00045   params.getParam("foot_contact_support/max_sampling_steps_x", max_sampling_steps_x);
00046   params.getParam("foot_contact_support/max_sampling_steps_y", max_sampling_steps_y);
00047   params.getParam("foot_contact_support/max_intrusion_z", max_intrusion_z);
00048   params.getParam("foot_contact_support/max_ground_clearance", max_ground_clearance);
00049   params.getParam("foot_contact_support/minimal_support", minimal_support);
00050 
00051   return true;
00052 }
00053 
00054 void TerrainModel::reset()
00055 {
00056   TerrainModelPlugin::reset();
00057 
00058   boost::unique_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00059 
00060   if (terrain_model)
00061     terrain_model->reset();
00062 }
00063 
00064 bool TerrainModel::isAccessible(const State& s) const
00065 {
00066   return s.getGroundContactSupport() >= minimal_support;
00067 }
00068 
00069 bool TerrainModel::isAccessible(const State& next, const State& /*current*/) const
00070 {
00071   return isAccessible(next);
00072 }
00073 
00074 bool TerrainModel::isTerrainModelAvailable() const
00075 {
00076   return terrain_model && terrain_model->hasTerrainModel();
00077 }
00078 
00079 void TerrainModel::setTerrainModel(const vigir_terrain_classifier::TerrainModelMsg::ConstPtr& terrain_model)
00080 {
00081   boost::unique_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00082 
00083   // update terrain model
00084   if (!this->terrain_model)
00085     this->terrain_model.reset(new vigir_terrain_classifier::TerrainModel(*terrain_model));
00086   else
00087     this->terrain_model->fromMsg(*terrain_model);
00088 }
00089 
00090 double TerrainModel::getResolution() const
00091 {
00092   boost::shared_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00093   return terrain_model->getResolution();
00094 }
00095 
00096 bool TerrainModel::getPointWithNormal(const pcl::PointNormal& p_search, pcl::PointNormal& p_result) const
00097 {
00098   boost::shared_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00099   return terrain_model->getPointWithNormal(p_search, p_result);
00100 }
00101 
00102 bool TerrainModel::getHeight(double x, double y, double& height) const
00103 {
00104   boost::shared_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00105   return terrain_model->getHeight(x, y, height);
00106 }
00107 
00108 bool TerrainModel::getFootContactSupport(const geometry_msgs::Pose& p, double &support, pcl::PointCloud<pcl::PointXYZI>::Ptr checked_positions) const
00109 {
00110   tf::Pose p_tf;
00111   tf::poseMsgToTF(p, p_tf);
00112   return getFootContactSupport(p_tf, support, checked_positions);
00113 }
00114 
00115 bool TerrainModel::getFootContactSupport(const tf::Pose& p, double& support, pcl::PointCloud<pcl::PointXYZI>::Ptr checked_positions) const
00116 {
00117   if (!getFootContactSupport(p, support, min_sampling_steps_x, min_sampling_steps_y, checked_positions))
00118     return false;
00119 
00120   // refinement of solution if needed
00121   if (support == 0.0) // collision, no refinement
00122   {
00123     return true;
00124   }
00125   else if (support < 0.95)
00126   {
00127     if (!getFootContactSupport(p, support, max_sampling_steps_x, max_sampling_steps_y, checked_positions))
00128       return false;
00129   }
00130 
00131   return true;
00132 }
00133 
00134 bool TerrainModel::getFootContactSupport(const tf::Pose& p, double &support, unsigned int sampling_steps_x, unsigned int sampling_steps_y, pcl::PointCloud<pcl::PointXYZI>::Ptr checked_positions) const
00135 {
00137   //boost::shared_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00138 
00139   support = 0.0;
00140 
00141   unsigned int contacts = 0;
00142   unsigned int unknown = 0;
00143   unsigned int total = 0;
00144 
00145   tf::Vector3 orig_pos;
00146   orig_pos.setZ(0.0);
00147 
00148   double foot_size_half_x = 0.5*foot_size.x;
00149   double foot_size_half_y = 0.5*foot_size.y;
00150 
00151   double sampling_step_x = foot_size.x/(double)(sampling_steps_x-1);
00152   double sampling_step_y = foot_size.y/(double)(sampling_steps_y-1);
00153 
00154   for (double y = -foot_size_half_y; y <= foot_size_half_y; y+=sampling_step_y)
00155   {
00156     orig_pos.setY(y);
00157     for (double x = -foot_size_half_x; x <= foot_size_half_x; x+=sampling_step_x)
00158     {
00159       total++;
00160 
00161       // determine point in world frame and get height at this point
00162       orig_pos.setX(x);
00163 
00164       const tf::Vector3 &trans_pos = p * orig_pos;
00165 
00166       double height = 0.0;
00167       if (!getHeight(trans_pos.getX(), trans_pos.getY(), height))
00168       {
00169         //ROS_WARN_THROTTLE(1.0, "getFootSupportArea: No height data found at %f/%f", p.getOrigin().getX(), p.getOrigin().getY());
00170         unknown++;
00171         continue;
00172       }
00173 
00174       // diff heights
00175       double diff = trans_pos.getZ()-height;
00176 
00177       // save evaluated point for visualization
00178       if (checked_positions)
00179       {
00180         pcl::PointXYZI p_checked;
00181         p_checked.x = trans_pos.getX();
00182         p_checked.y = trans_pos.getY();
00183         p_checked.z = trans_pos.getZ();
00184         p_checked.intensity = std::abs(diff);
00185         checked_positions->push_back(p_checked);
00186 
00187         //ROS_INFO("%f %f | %f %f | %f", x, y, p.z, height, diff);
00188       }
00189 
00190       // check diff in z
00191       if (diff < -max_intrusion_z) // collision -> no support!
00192         return true;
00193       else if (diff < max_ground_clearance) // ground contact
00194         contacts++;
00195     }
00196   }
00197 
00198   if (unknown == total)
00199   {
00200     return false;
00201   }
00202   else
00203   {
00205     support = static_cast<double>(contacts)/static_cast<double>(total);
00206     return true;
00207   }
00208 }
00209 
00210 bool TerrainModel::update3DData(geometry_msgs::Pose& p) const
00211 {
00212   return terrain_model->update3DData(p);
00213 }
00214 
00215 bool TerrainModel::update3DData(State& s) const
00216 {
00218   //boost::shared_lock<boost::shared_mutex> lock(terrain_model_shared_mutex);
00219   bool result = true;
00220 
00221   // get z
00222   double z = s.getZ();
00223   if (!getHeight(s.getX(), s.getY(), z))
00224   {
00225     //ROS_WARN_THROTTLE(1.0, "No height data found at %f/%f", s.getX(), s.getY());
00226     result = false;
00227   }
00228   else
00229   {
00230     s.setZ(z);
00231   }
00232 
00233   // get roll and pitch
00234   pcl::PointNormal p_n;
00235   p_n.x = s.getX();
00236   p_n.y = s.getY();
00237   p_n.z = s.getZ();
00238 
00239   if (!getPointWithNormal(p_n, p_n))
00240   {
00241     //ROS_WARN_THROTTLE(1.0, "No normal data found at %f/%f", s.getX(), s.getY());
00242     result = false;
00243   }
00244   else
00245   {
00246     s.setNormal(p_n.normal_x, p_n.normal_y, p_n.normal_z);
00247   }
00248 
00249   // determine ground contact support
00250   double support = 0.0;
00251   if (!getFootContactSupport(s.getPose(), support))
00252   {
00253     //ROS_WARN_THROTTLE(1.0, "Couldn't determine ground contact support at %f/%f", s.getX(), s.getY());
00254     result = false;
00255   }
00256   else
00257   {
00258     s.setGroundContactSupport(support);
00259   }
00260 
00261   return result;
00262 }
00263 }
00264 
00265 #include <pluginlib/class_list_macros.h>
00266 PLUGINLIB_EXPORT_CLASS(vigir_footstep_planning::TerrainModel, vigir_footstep_planning::TerrainModelPlugin)


vigir_footstep_planning_default_plugins
Author(s): Alexander Stumpf
autogenerated on Thu Jun 6 2019 18:38:06