Go to the documentation of this file.00001
00068
00069
00070
00071
00072
00073 #include <sstream>
00074 #include <fstream>
00075
00076
00077
00078 #include <ros/ros.h>
00079 #include <ros/console.h>
00080
00081 #include <pluginlib/class_list_macros.h>
00082 #include <dynamic_reconfigure/server.h>
00083 #include <cob_3d_mapping_point_map/point_map_nodeletConfig.h>
00084
00085
00086 #include <pcl/io/pcd_io.h>
00087 #include <pcl/point_types.h>
00088 #include <pcl/filters/voxel_grid.h>
00089 #include <pcl_ros/point_cloud.h>
00090 #include <nodelet/nodelet.h>
00091
00092
00093
00094
00095 #include <cob_3d_mapping_msgs/SetPointMap.h>
00096 #include <cob_3d_mapping_msgs/GetPointMap.h>
00097 #include <cob_srvs/Trigger.h>
00098
00099
00100
00101
00102 class PointMapNodelet : public nodelet::Nodelet
00103 {
00104 typedef pcl::PointXYZRGB Point;
00105
00106 public:
00107
00108 PointMapNodelet()
00109 : ctr_(0),
00110 is_running_(false),
00111 map_frame_id_("/map")
00112 {
00113
00114 map_.header.frame_id = map_frame_id_;
00115 }
00116
00117
00118
00119 ~PointMapNodelet()
00120 {
00121
00122 }
00123
00131 void
00132 dynReconfCallback(cob_3d_mapping_point_map::point_map_nodeletConfig &config, uint32_t level)
00133 {
00134 file_path_ = config.file_path;
00135 save_ = config.save;
00136 voxel_leafsize_ = config.voxel_leafsize;
00137 map_frame_id_ = config.map_frame_id;
00138 map_.header.frame_id = map_frame_id_;
00139 }
00140
00141
00149 void
00150 onInit()
00151 {
00152 n_ = getNodeHandle();
00153
00154 config_server_ = boost::shared_ptr<dynamic_reconfigure::Server<cob_3d_mapping_point_map::point_map_nodeletConfig> >(new dynamic_reconfigure::Server<cob_3d_mapping_point_map::point_map_nodeletConfig>(getPrivateNodeHandle()));
00155 config_server_->setCallback(boost::bind(&PointMapNodelet::dynReconfCallback, this, _1, _2));
00156
00157 point_cloud_sub_ = n_.subscribe("point_cloud2", 1, &PointMapNodelet::updateCallback, this);
00158 map_pub_ = n_.advertise<pcl::PointCloud<Point> >("map",1);
00159 clear_map_server_ = n_.advertiseService("clear_map", &PointMapNodelet::clearMap, this);
00160 get_map_server_ = n_.advertiseService("get_map", &PointMapNodelet::getMap, this);
00161 set_map_server_ = n_.advertiseService("set_map", &PointMapNodelet::setMap, this);
00162
00163
00164
00165
00166 }
00167
00182 void
00183 updateCallback(const pcl::PointCloud<Point>::Ptr& pc)
00184 {
00185 ROS_DEBUG("PointCloudSubCallback");
00186 if (pc->size() < 1)
00187 {
00188 ROS_WARN("[point_map] Incoming point cloud is empty, skipping map update.");
00189 return;
00190 }
00191 if(pc->header.frame_id != map_frame_id_)
00192 {
00193 ROS_ERROR("[point_map] Frame ID of incoming point cloud (%s) does not match map frame ID (%s), aborting...", pc->header.frame_id.c_str(), map_frame_id_.c_str());
00194 return;
00195 }
00196
00197 updateMap(pc);
00198 map_pub_.publish(map_);
00199
00200 ROS_DEBUG("[point_map] Updated map has %d points", map_.size());
00201
00202 if(save_)
00203 {
00204 std::stringstream ss;
00205 ss << file_path_ << "/map_" << ctr_ << ".pcd";
00206 pcl::io::savePCDFileASCII (ss.str(), map_);
00207 }
00208 ctr_++;
00209 return;
00210 }
00211
00212 void
00213 updateMap(const pcl::PointCloud<Point>::Ptr& pc)
00214 {
00215 map_ += *pc;
00216 downsampleMap();
00217 }
00218
00219
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00264 bool
00265 clearMap(cob_srvs::Trigger::Request &req,
00266 cob_srvs::Trigger::Response &res)
00267 {
00268
00269 ROS_INFO("Clearing point map...");
00270 map_.clear();
00271 Point p;
00272 map_.points.push_back(p);
00273 map_pub_.publish(map_);
00274 return true;
00275 }
00276
00287 bool
00288 getMap(cob_3d_mapping_msgs::GetPointMap::Request &req,
00289 cob_3d_mapping_msgs::GetPointMap::Response &res)
00290 {
00291 pcl::toROSMsg(map_, res.map);
00292 return true;
00293 }
00294
00306 bool
00307 setMap(cob_3d_mapping_msgs::SetPointMap::Request &req,
00308 cob_3d_mapping_msgs::SetPointMap::Response &res)
00309 {
00310 pcl::fromROSMsg(req.map, map_);
00311 downsampleMap();
00312 map_pub_.publish(map_);
00313
00314 return true;
00315 }
00316
00317
00325 void
00326 downsampleMap()
00327 {
00328 pcl::VoxelGrid<Point> vox_filter;
00329 vox_filter.setInputCloud(map_.makeShared());
00330 vox_filter.setLeafSize(voxel_leafsize_,voxel_leafsize_,voxel_leafsize_);
00331 vox_filter.filter(map_);
00332 }
00333
00334
00335 ros::NodeHandle n_;
00336
00337
00338 protected:
00339 ros::Subscriber point_cloud_sub_;
00340 ros::Publisher map_pub_;
00341 ros::ServiceServer clear_map_server_;
00342 ros::ServiceServer get_map_server_;
00343 ros::ServiceServer set_map_server_;
00344
00345 boost::shared_ptr<dynamic_reconfigure::Server<cob_3d_mapping_point_map::point_map_nodeletConfig> > config_server_;
00346
00347 unsigned int ctr_;
00348 bool is_running_;
00349
00350
00351 std::string file_path_;
00352 bool save_;
00353 std::string map_frame_id_;
00354 double voxel_leafsize_;
00355
00356 pcl::PointCloud<Point> map_;
00357
00358 };
00359
00360 PLUGINLIB_DECLARE_CLASS(cob_3d_mapping_point_map, PointMapNodelet, PointMapNodelet, nodelet::Nodelet)
00361