00001
00004
00005
00006
00007
00008 #include <boost/thread/lock_guard.hpp>
00009 #include <cmath>
00010 #include <cost_map_core/cost_map_core.hpp>
00011 #include <cost_map_msgs/CostMap.h>
00012 #include <ecl/console.hpp>
00013 #include <limits>
00014 #include <map>
00015 #include <sensor_msgs/Image.h>
00016 #include <sensor_msgs/image_encodings.h>
00017 #include <std_msgs/UInt8MultiArray.h>
00018 #include <stdexcept>
00019 #include <string>
00020 #include "../../include/cost_map_ros/converter.hpp"
00021
00022 #include <grid_map_costmap_2d/grid_map_costmap_2d.hpp>
00023
00024
00025
00026
00027
00028 namespace cost_map {
00029
00030
00031
00032
00033
00034
00035
00036
00037 bool addLayerFromROSImage(const sensor_msgs::Image& image,
00038 const std::string& layer_name,
00039 cost_map::CostMap& cost_map
00040 )
00041 {
00042 cv_bridge::CvImagePtr cvPtrAlpha, cvPtrMono;
00043
00044
00045 if (image.encoding == sensor_msgs::image_encodings::BGRA8
00046 || image.encoding == sensor_msgs::image_encodings::BGRA16) {
00047 try {
00048 cvPtrAlpha = cv_bridge::toCvCopy(image, image.encoding);
00049 } catch (cv_bridge::Exception& e) {
00050 std::cout << ecl::red << "[ERROR] cv_bridge exception: " << e.what() << ecl::reset << std::endl;
00051 return false;
00052 }
00053 }
00054
00055 unsigned int depth;
00056 try {
00057 if (image.encoding == sensor_msgs::image_encodings::BGRA8
00058 || image.encoding == sensor_msgs::image_encodings::BGR8
00059 || image.encoding == sensor_msgs::image_encodings::MONO8) {
00060 cvPtrMono = cv_bridge::toCvCopy(image,
00061 sensor_msgs::image_encodings::MONO8);
00062 depth = std::pow(2, 8);
00063
00064 } else if (image.encoding == sensor_msgs::image_encodings::BGRA16
00065 || image.encoding == sensor_msgs::image_encodings::BGR16
00066 || image.encoding == sensor_msgs::image_encodings::MONO16) {
00067 cvPtrMono = cv_bridge::toCvCopy(image,
00068 sensor_msgs::image_encodings::MONO16);
00069 depth = std::pow(2, 16);
00070
00071 } else {
00072 std::cout << ecl::red << "[ERROR] expected BGR, BGRA, or MONO image encoding." << ecl::reset << std::endl;
00073 return false;
00074 }
00075 } catch (cv_bridge::Exception& e) {
00076 std::cout << ecl::red << "[ERROR] cv_bridge exception: " << e.what() << ecl::reset << std::endl;
00077 return false;
00078 }
00079
00080 cost_map.add(layer_name);
00081
00082 if (cost_map.getSize()(0) != image.height
00083 || cost_map.getSize()(1) != image.width) {
00084 std::cout << ecl::red << "[ERROR] Image size does not correspond to grid map size!" << ecl::reset << std::endl;
00085 return false;
00086 }
00087
00088 for (CostMapIterator iterator(cost_map); !iterator.isPastEnd(); ++iterator) {
00089
00090 if (image.encoding == sensor_msgs::image_encodings::BGRA8) {
00091 const auto& cvAlpha = cvPtrAlpha->image.at<cv::Vec4b>((*iterator)(0),
00092 (*iterator)(1));
00093 unsigned int alpha = cvAlpha[3];
00094 if (cvAlpha[3] < depth / 2)
00095 continue;
00096 }
00097 if (image.encoding == sensor_msgs::image_encodings::BGRA16) {
00098 const auto& cvAlpha = cvPtrAlpha->image.at<cv::Vec<uchar, 8>>(
00099 (*iterator)(0), (*iterator)(1));
00100 int alpha = (cvAlpha[6] << 8) + cvAlpha[7];
00101 if (alpha < depth / 2)
00102 continue;
00103 }
00104
00105
00106 unsigned int grayValue;
00107 if (depth == std::pow(2, 8)) {
00108 uchar cvGrayscale = cvPtrMono->image.at<uchar>((*iterator)(0),
00109 (*iterator)(1));
00110 grayValue = cvGrayscale;
00111 }
00112 if (depth == std::pow(2, 16)) {
00113 const auto& cvGrayscale = cvPtrMono->image.at<cv::Vec2b>((*iterator)(0),
00114 (*iterator)(1));
00115 grayValue = (cvGrayscale[0] << 8) + cvGrayscale[1];
00116 }
00117
00118
00119 cost_map::DataType value = static_cast<cost_map::DataType>(254.0 * ( 1.0 - (static_cast<double>(grayValue) / static_cast<double>(depth))));
00120 cost_map.at(layer_name, *iterator) = value;
00121 }
00122 return true;
00123 }
00124
00125
00126
00127
00128
00129
00130 void toGridMap(const cost_map::CostMap cost_map, grid_map::GridMap& grid_map)
00131 {
00132 grid_map.setGeometry(cost_map.getLength(), cost_map.getResolution(), cost_map.getPosition());
00133 grid_map.setFrameId(cost_map.getFrameId());
00134 grid_map.setTimestamp(cost_map.getTimestamp());
00135 for (const std::string& layer_name : cost_map.getLayers()) {
00136 const cost_map::Matrix& cost_map_data = cost_map[layer_name];
00137 grid_map::Matrix grid_map_data(cost_map_data.rows(), cost_map_data.cols());
00138 const cost_map::DataType *cost_map_ptr = cost_map_data.data();
00139 float *grid_map_ptr = grid_map_data.data();
00140 for (unsigned int i = 0; i < cost_map_data.size(); ++i ) {
00141 *grid_map_ptr = 100.0 * static_cast<double>(*cost_map_ptr) / static_cast<double>(cost_map::NO_INFORMATION);
00142 ++cost_map_ptr; ++grid_map_ptr;
00143 }
00144 grid_map.add(layer_name, grid_map_data);
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 void toMessage(const cost_map::CostMap& cost_map, cost_map_msgs::CostMap& message)
00155 {
00156 std::vector<std::string> layers = cost_map.getLayers();
00157
00158 message.info.header.stamp.fromNSec(cost_map.getTimestamp());
00159 message.info.header.frame_id = cost_map.getFrameId();
00160 message.info.resolution = cost_map.getResolution();
00161 message.info.length_x = cost_map.getLength().x();
00162 message.info.length_y = cost_map.getLength().y();
00163 message.info.pose.position.x = cost_map.getPosition().x();
00164 message.info.pose.position.y = cost_map.getPosition().y();
00165 message.info.pose.position.z = 0.0;
00166 message.info.pose.orientation.x = 0.0;
00167 message.info.pose.orientation.y = 0.0;
00168 message.info.pose.orientation.z = 0.0;
00169 message.info.pose.orientation.w = 1.0;
00170
00171 message.layers = layers;
00172 message.basic_layers = cost_map.getBasicLayers();
00173
00174 message.data.clear();
00175 for (const auto& layer : layers) {
00176 const cost_map::Matrix& data = cost_map.get(layer);
00177 std_msgs::UInt8MultiArray data_array;
00178 grid_map::matrixEigenCopyToMultiArrayMessage(cost_map.get(layer), data_array);
00179 message.data.push_back(data_array);
00180 }
00181
00182 message.outer_start_index = cost_map.getStartIndex()(0);
00183 message.inner_start_index = cost_map.getStartIndex()(1);
00184 }
00185
00186 bool fromMessage(const cost_map_msgs::CostMap& message, cost_map::CostMap& cost_map)
00187 {
00188 cost_map.setTimestamp(message.info.header.stamp.toNSec());
00189 cost_map.setFrameId(message.info.header.frame_id);
00190 cost_map.setGeometry(Length(message.info.length_x, message.info.length_y), message.info.resolution,
00191 Position(message.info.pose.position.x, message.info.pose.position.y));
00192
00193 if (message.layers.size() != message.data.size()) {
00194
00195 return false;
00196 }
00197
00198 for (unsigned int i = 0; i < message.layers.size(); i++) {
00199 Matrix data;
00200
00201
00202 grid_map::multiArrayMessageCopyToMatrixEigen(message.data[i], data);
00203
00204 cost_map.add(message.layers[i], data);
00205 }
00206
00207 cost_map.setBasicLayers(message.basic_layers);
00208 cost_map.setStartIndex(Index(message.outer_start_index, message.inner_start_index));
00209 return true;
00210 }
00211
00212
00213
00214
00215
00216 bool fromCostmap2DROS(costmap_2d::Costmap2DROS& ros_costmap,
00217 const std::string& layer_name,
00218 cost_map::CostMap& cost_map) {
00219
00220 grid_map::Costmap2DConverter<cost_map::CostMap> converter;
00221 boost::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*(ros_costmap.getCostmap()->getMutex()));
00222 converter.initializeFromCostmap2D(ros_costmap, cost_map);
00223 if ( !converter.addLayerFromCostmap2D(ros_costmap, layer_name, cost_map) ) {
00224 return false;
00225 }
00226 return true;
00227 }
00228
00229 bool fromCostmap2DROSAtRobotPose(costmap_2d::Costmap2DROS& ros_costmap,
00230 const cost_map::Length& geometry,
00231 const std::string& layer_name,
00232 cost_map::CostMap& cost_map)
00233 {
00234 grid_map::Costmap2DConverter<cost_map::CostMap> converter;
00235 boost::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*(ros_costmap.getCostmap()->getMutex()));
00236 if ( !converter.initializeFromCostmap2DAtRobotPose(ros_costmap, geometry, cost_map) ) {
00237 return false;
00238 }
00239 if (!converter.addLayerFromCostmap2DAtRobotPose(ros_costmap, layer_name, cost_map) ) {
00240 return false;
00241 }
00242 return true;
00243 }
00244
00245 void toOccupancyGrid(const cost_map::CostMap& cost_map, const std::string& layer, nav_msgs::OccupancyGrid& msg) {
00246 msg.header.frame_id = cost_map.getFrameId();
00247 msg.header.stamp.fromNSec(cost_map.getTimestamp());
00248 msg.info.map_load_time = msg.header.stamp;
00249 msg.info.resolution = cost_map.getResolution();
00250 msg.info.width = cost_map.getSize()(0);
00251 msg.info.height = cost_map.getSize()(1);
00252
00253
00254 Position positionOfOrigin = cost_map.getPosition() - 0.5 * cost_map.getLength().matrix();
00255 msg.info.origin.position.x = positionOfOrigin.x();
00256 msg.info.origin.position.y = positionOfOrigin.y();
00257 msg.info.origin.position.z = 0.0;
00258 msg.info.origin.orientation.x = 0.0;
00259 msg.info.origin.orientation.y = 0.0;
00260 msg.info.origin.orientation.z = 0.0;
00261 msg.info.origin.orientation.w = 1.0;
00262 msg.data.resize(msg.info.width * msg.info.height);
00263
00264 size_t nCells = cost_map.getSize().prod();
00265 msg.data.resize(nCells);
00266
00267
00268 const float cellMin = 0;
00269 const float cellMax = 98;
00270 const float cellRange = cellMax - cellMin;
00271
00272 const float data_minimum = 0;
00273 const float data_maximum = 252;
00274 for (CostMapIterator iterator(cost_map); !iterator.isPastEnd(); ++iterator)
00275 {
00276 float value;
00277 if (cost_map.at(layer, *iterator) == cost_map::NO_INFORMATION)
00278 {
00279 value = -1;
00280 }
00281 else if (cost_map.at(layer, *iterator) == cost_map::LETHAL_OBSTACLE)
00282 {
00283 value = 100;
00284 }
00285 else if (cost_map.at(layer, *iterator) == cost_map::INSCRIBED_OBSTACLE)
00286 {
00287 value = 99;
00288 }
00289 else
00290 {
00291 value = (cost_map.at(layer, *iterator) - data_minimum) / (data_maximum - data_minimum);
00292 value = cellMin + std::min(std::max(0.0f, value), 1.0f) * cellRange;
00293 }
00294 unsigned int index = grid_map::getLinearIndexFromIndex(*iterator, cost_map.getSize(), false);
00295 msg.data[nCells - index - 1] = value;
00296 }
00297 }
00298 Costmap2DROSServiceProvider::Costmap2DROSServiceProvider(costmap_2d::Costmap2DROS* ros_costmap,
00299 const std::string& service_name)
00300 : ros_costmap(ros_costmap)
00301 {
00302 ros::NodeHandle private_nodehandle("~");
00303 service = private_nodehandle.advertiseService(service_name, &Costmap2DROSServiceProvider::callback, this);
00304 }
00305
00306 Costmap2DROSServiceProvider::Costmap2DROSServiceProvider(costmap_2d::Costmap2DROS* ros_costmap,
00307 ros::NodeHandle& node_handle,
00308 const std::string& service_name)
00309 : ros_costmap(ros_costmap)
00310 {
00311 service = node_handle.advertiseService(service_name, &Costmap2DROSServiceProvider::callback, this);
00312 }
00313
00314 bool Costmap2DROSServiceProvider::callback(
00315 cost_map_msgs::GetCostMap::Request &request,
00316 cost_map_msgs::GetCostMap::Response &response)
00317 {
00318 CostMap cost_map;
00319 cost_map::Length geometry;
00320 geometry << request.length_x, request.length_y;
00321 if ( !fromCostmap2DROSAtRobotPose(*ros_costmap, geometry, "obstacle_costs", cost_map) ) {
00322 ROS_ERROR_STREAM("CostMap Service : failed to convert from Costmap2DROS");
00323 }
00324 toMessage(cost_map, response.map);
00325 return true;
00326 }
00327
00328
00329
00330
00331
00332 }