costmap_converter_node.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2016,
00006  *  TU Dortmund - Institute of Control Theory and Systems Engineering.
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the institute nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * Author: Christoph Rösmann, Otniel Rinaldo
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       // load converter plugin from parameter server, otherwise set default
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         //converter_->startWorker(ros::Rate(5), &map, true);
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       // convert
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     // convert
00154     // TODO(roesmann): currently, the converter updates the complete costmap and not the part which is updated in this callback
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       // close loop for current polygon
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       // close loop for current polygon
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 


costmap_converter
Author(s): Christoph Rösmann , Franz Albers , Otniel Rinaldo
autogenerated on Sat Jun 8 2019 20:53:15