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
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <ros/ros.h>
00040
00041 #include <costmap_2d/costmap_2d.h>
00042 #include <nav_msgs/OccupancyGrid.h>
00043 #include <geometry_msgs/PolygonStamped.h>
00044 #include <visualization_msgs/Marker.h>
00045
00046 #include <costmap_converter/costmap_converter_interface.h>
00047 #include <pluginlib/class_loader.h>
00048
00049
00050
00051 class CostmapStandaloneConversion
00052 {
00053 public:
00054 CostmapStandaloneConversion() : converter_loader_("costmap_converter", "costmap_converter::BaseCostmapToPolygons"), n_("~")
00055 {
00056
00057 std::string converter_plugin = "costmap_converter::CostmapToPolygonsDBSMCCH";
00058 n_.param("converter_plugin", converter_plugin, converter_plugin);
00059
00060 try
00061 {
00062 converter_ = converter_loader_.createInstance(converter_plugin);
00063 }
00064 catch(const pluginlib::PluginlibException& ex)
00065 {
00066 ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
00067 ros::shutdown();
00068 }
00069
00070 ROS_INFO_STREAM("Standalone costmap converter:" << converter_plugin << " loaded.");
00071
00072 std::string costmap_topic = "/move_base/local_costmap/costmap";
00073 n_.param("costmap_topic", costmap_topic, costmap_topic);
00074
00075 std::string costmap_update_topic = "/move_base/local_costmap/costmap_updates";
00076 n_.param("costmap_update_topic", costmap_update_topic, costmap_update_topic);
00077
00078 std::string obstacles_topic = "costmap_obstacles";
00079 n_.param("obstacles_topic", obstacles_topic, obstacles_topic);
00080
00081 std::string polygon_marker_topic = "costmap_polygon_markers";
00082 n_.param("polygon_marker_topic", polygon_marker_topic, polygon_marker_topic);
00083
00084 costmap_sub_ = n_.subscribe(costmap_topic, 1, &CostmapStandaloneConversion::costmapCallback, this);
00085 costmap_update_sub_ = n_.subscribe(costmap_update_topic, 1, &CostmapStandaloneConversion::costmapUpdateCallback, this);
00086 obstacle_pub_ = n_.advertise<costmap_converter::ObstacleArrayMsg>(obstacles_topic, 1000);
00087 marker_pub_ = n_.advertise<visualization_msgs::Marker>(polygon_marker_topic, 10);
00088
00089 occupied_min_value_ = 100;
00090 n_.param("occupied_min_value", occupied_min_value_, occupied_min_value_);
00091
00092 std::string odom_topic = "/odom";
00093 n_.param("odom_topic", odom_topic, odom_topic);
00094
00095 if (converter_)
00096 {
00097 converter_->setOdomTopic(odom_topic);
00098 converter_->initialize(n_);
00099 converter_->setCostmap2D(&map_);
00100
00101 }
00102 }
00103
00104
00105 void costmapCallback(const nav_msgs::OccupancyGridConstPtr& msg)
00106 {
00107 ROS_INFO_ONCE("Got first costmap callback. This message will be printed once");
00108
00109 if (msg->info.width != map_.getSizeInCellsX() || msg->info.height != map_.getSizeInCellsY() || msg->info.resolution != map_.getResolution())
00110 {
00111 ROS_INFO("New map format, resizing and resetting map...");
00112 map_.resizeMap(msg->info.width, msg->info.height, msg->info.resolution, msg->info.origin.position.x, msg->info.origin.position.y);
00113 }
00114 else
00115 {
00116 map_.updateOrigin(msg->info.origin.position.x, msg->info.origin.position.y);
00117 }
00118
00119
00120 for (std::size_t i=0; i < msg->data.size(); ++i)
00121 {
00122 unsigned int mx, my;
00123 map_.indexToCells((unsigned int)i, mx, my);
00124 map_.setCost(mx, my, msg->data[i] >= occupied_min_value_ ? 255 : 0 );
00125 }
00126
00127
00128 converter_->updateCostmap2D();
00129 converter_->compute();
00130 costmap_converter::ObstacleArrayConstPtr obstacles = converter_->getObstacles();
00131
00132 if (!obstacles)
00133 return;
00134
00135 obstacle_pub_.publish(obstacles);
00136
00137 frame_id_ = msg->header.frame_id;
00138
00139 publishAsMarker(frame_id_, *obstacles, marker_pub_);
00140 }
00141
00142 void costmapUpdateCallback(const map_msgs::OccupancyGridUpdateConstPtr& update)
00143 {
00144 unsigned int di = 0;
00145 for (unsigned int y = 0; y < update->height ; ++y)
00146 {
00147 for (unsigned int x = 0; x < update->width ; ++x)
00148 {
00149 map_.setCost(x, y, update->data[di++] >= occupied_min_value_ ? 255 : 0 );
00150 }
00151 }
00152
00153
00154
00155 converter_->updateCostmap2D();
00156 converter_->compute();
00157 costmap_converter::ObstacleArrayConstPtr obstacles = converter_->getObstacles();
00158
00159 if (!obstacles)
00160 return;
00161
00162 obstacle_pub_.publish(obstacles);
00163
00164 publishAsMarker(frame_id_, *obstacles, marker_pub_);
00165 }
00166
00167 void publishAsMarker(const std::string& frame_id, const std::vector<geometry_msgs::PolygonStamped>& polygonStamped, ros::Publisher& marker_pub)
00168 {
00169 visualization_msgs::Marker line_list;
00170 line_list.header.frame_id = frame_id;
00171 line_list.header.stamp = ros::Time::now();
00172 line_list.ns = "Polygons";
00173 line_list.action = visualization_msgs::Marker::ADD;
00174 line_list.pose.orientation.w = 1.0;
00175
00176 line_list.id = 0;
00177 line_list.type = visualization_msgs::Marker::LINE_LIST;
00178
00179 line_list.scale.x = 0.1;
00180 line_list.color.g = 1.0;
00181 line_list.color.a = 1.0;
00182
00183 for (std::size_t i=0; i<polygonStamped.size(); ++i)
00184 {
00185 for (int j=0; j< (int)polygonStamped[i].polygon.points.size()-1; ++j)
00186 {
00187 geometry_msgs::Point line_start;
00188 line_start.x = polygonStamped[i].polygon.points[j].x;
00189 line_start.y = polygonStamped[i].polygon.points[j].y;
00190 line_list.points.push_back(line_start);
00191 geometry_msgs::Point line_end;
00192 line_end.x = polygonStamped[i].polygon.points[j+1].x;
00193 line_end.y = polygonStamped[i].polygon.points[j+1].y;
00194 line_list.points.push_back(line_end);
00195 }
00196
00197 if (!polygonStamped[i].polygon.points.empty() && polygonStamped[i].polygon.points.size() != 2 )
00198 {
00199 geometry_msgs::Point line_start;
00200 line_start.x = polygonStamped[i].polygon.points.back().x;
00201 line_start.y = polygonStamped[i].polygon.points.back().y;
00202 line_list.points.push_back(line_start);
00203 if (line_list.points.size() % 2 != 0)
00204 {
00205 geometry_msgs::Point line_end;
00206 line_end.x = polygonStamped[i].polygon.points.front().x;
00207 line_end.y = polygonStamped[i].polygon.points.front().y;
00208 line_list.points.push_back(line_end);
00209 }
00210 }
00211
00212
00213 }
00214 marker_pub.publish(line_list);
00215 }
00216
00217 void publishAsMarker(const std::string& frame_id, const costmap_converter::ObstacleArrayMsg& obstacles, ros::Publisher& marker_pub)
00218 {
00219 visualization_msgs::Marker line_list;
00220 line_list.header.frame_id = frame_id;
00221 line_list.header.stamp = ros::Time::now();
00222 line_list.ns = "Polygons";
00223 line_list.action = visualization_msgs::Marker::ADD;
00224 line_list.pose.orientation.w = 1.0;
00225
00226 line_list.id = 0;
00227 line_list.type = visualization_msgs::Marker::LINE_LIST;
00228
00229 line_list.scale.x = 0.1;
00230 line_list.color.g = 1.0;
00231 line_list.color.a = 1.0;
00232
00233 for (const costmap_converter::ObstacleMsg& obstacle : obstacles.obstacles)
00234 {
00235 for (int j=0; j< (int)obstacle.polygon.points.size()-1; ++j)
00236 {
00237 geometry_msgs::Point line_start;
00238 line_start.x = obstacle.polygon.points[j].x;
00239 line_start.y = obstacle.polygon.points[j].y;
00240 line_list.points.push_back(line_start);
00241 geometry_msgs::Point line_end;
00242 line_end.x = obstacle.polygon.points[j+1].x;
00243 line_end.y = obstacle.polygon.points[j+1].y;
00244 line_list.points.push_back(line_end);
00245 }
00246
00247 if (!obstacle.polygon.points.empty() && obstacle.polygon.points.size() != 2 )
00248 {
00249 geometry_msgs::Point line_start;
00250 line_start.x = obstacle.polygon.points.back().x;
00251 line_start.y = obstacle.polygon.points.back().y;
00252 line_list.points.push_back(line_start);
00253 if (line_list.points.size() % 2 != 0)
00254 {
00255 geometry_msgs::Point line_end;
00256 line_end.x = obstacle.polygon.points.front().x;
00257 line_end.y = obstacle.polygon.points.front().y;
00258 line_list.points.push_back(line_end);
00259 }
00260 }
00261
00262
00263 }
00264 marker_pub.publish(line_list);
00265 }
00266
00267 private:
00268 pluginlib::ClassLoader<costmap_converter::BaseCostmapToPolygons> converter_loader_;
00269 boost::shared_ptr<costmap_converter::BaseCostmapToPolygons> converter_;
00270
00271 ros::NodeHandle n_;
00272 ros::Subscriber costmap_sub_;
00273 ros::Subscriber costmap_update_sub_;
00274 ros::Publisher obstacle_pub_;
00275 ros::Publisher marker_pub_;
00276
00277 std::string frame_id_;
00278 int occupied_min_value_;
00279
00280 costmap_2d::Costmap2D map_;
00281
00282 };
00283
00284
00285 int main(int argc, char** argv)
00286 {
00287 ros::init(argc, argv, "costmap_converter");
00288
00289 CostmapStandaloneConversion convert_process;
00290
00291 ros::spin();
00292
00293 return 0;
00294 }
00295
00296