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
00028 getFootSize(nh_, foot_size);
00029
00030
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& ) 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
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
00121 if (support == 0.0)
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
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
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
00170 unknown++;
00171 continue;
00172 }
00173
00174
00175 double diff = trans_pos.getZ()-height;
00176
00177
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
00188 }
00189
00190
00191 if (diff < -max_intrusion_z)
00192 return true;
00193 else if (diff < max_ground_clearance)
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
00219 bool result = true;
00220
00221
00222 double z = s.getZ();
00223 if (!getHeight(s.getX(), s.getY(), z))
00224 {
00225
00226 result = false;
00227 }
00228 else
00229 {
00230 s.setZ(z);
00231 }
00232
00233
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
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
00250 double support = 0.0;
00251 if (!getFootContactSupport(s.getPose(), support))
00252 {
00253
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)