Go to the documentation of this file.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 #include "ros/ros.h"
00030
00031 #include <nav_msgs/GetMap.h>
00032 #include <geometry_msgs/Quaternion.h>
00033 #include <geometry_msgs/PoseStamped.h>
00034 #include <sensor_msgs/image_encodings.h>
00035
00036
00037 #include <cv_bridge/cv_bridge.h>
00038
00039 #include <image_transport/image_transport.h>
00040 #include <Eigen/Geometry>
00041
00042 #include <HectorMapTools.h>
00043 #include <math.h>
00044 #include <tf/transform_datatypes.h>
00045
00046 using namespace std;
00047 using namespace cv_bridge;
00048 using namespace cv;
00049
00054 class MapAsImageProvider
00055 {
00056 public:
00057 MapAsImageProvider()
00058 : pn_("~")
00059 {
00060
00061 image_transport_ = new image_transport::ImageTransport(n_);
00062 image_transport_publisher_full_position_ = image_transport_->advertise("map_image/full_with_position", 1);
00063 image_transport_publisher_full_ = image_transport_->advertise("map_image/full", 1);
00064 image_transport_publisher_tile_ = image_transport_->advertise("map_image/tile", 1);
00065
00066 pose_sub_ = n_.subscribe("pose", 1, &MapAsImageProvider::poseCallback, this);
00067 map_sub_ = n_.subscribe("map", 1, &MapAsImageProvider::mapCallback, this);
00068
00069
00070 cv_img_full_with_position_.header.frame_id = "map_image";
00071 cv_img_full_with_position_.encoding = sensor_msgs::image_encodings::RGB8;
00072
00073 cv_img_full_.header.frame_id = "map_image";
00074 cv_img_full_.encoding = sensor_msgs::image_encodings::MONO8;
00075
00076 cv_img_tile_.header.frame_id = "map_image";
00077 cv_img_tile_.encoding = sensor_msgs::image_encodings::RGB8;
00078
00079
00080 p_size_tiled_map_image_x_ = 64;
00081 p_size_tiled_map_image_y_ = 64;
00082
00083 ROS_INFO("Map to Image node started.");
00084 }
00085
00086 ~MapAsImageProvider()
00087 {
00088 delete image_transport_;
00089 }
00090
00091
00092 void poseCallback(const geometry_msgs::PoseStampedConstPtr& pose)
00093 {
00094 pose_ptr_ = pose;
00095 }
00096
00097
00098 void mapCallback(const nav_msgs::OccupancyGridConstPtr& map)
00099 {
00100 int size_x = map->info.width;
00101 int size_y = map->info.height;
00102
00103 if ((size_x < 3) || (size_y < 3) ){
00104 ROS_INFO("Map size is only x: %d, y: %d . Not running map to image conversion", size_x, size_y);
00105 return;
00106 }
00107
00108
00109 if (image_transport_publisher_full_.getNumSubscribers() > 0 && (pose_ptr_)){
00110 Mat* map_mat = &cv_img_full_.image;
00111 Mat* map_mat_position = &cv_img_full_with_position_.image;
00112
00113
00114 if ( (map_mat->rows != size_y) && (map_mat->cols != size_x)){
00115 *map_mat = Mat(size_y, size_x, CV_8U);
00116 *map_mat_position = Mat(size_y, size_x, CV_8UC3);
00117 }
00118
00119 const std::vector<int8_t>& map_data (map->data);
00120
00121 unsigned char *map_mat_data_p=(unsigned char*) map_mat->data;
00122 unsigned char *map_mat_position_data_p=(unsigned char*) map_mat_position->data;
00123
00124
00125 int size_y_rev = size_y-1;
00126
00127 for (int y = size_y_rev; y >= 0; --y){
00128
00129 int idx_map_y = size_x * (size_y -y);
00130 int idx_img_y = size_x * y;
00131
00132 for (int x = 0; x < size_x; ++x){
00133
00134 int idx = idx_img_y + x;
00135
00136 switch (map_data[idx_map_y + x])
00137 {
00138 case -1:
00139 map_mat_position_data_p[idx*3] = 127;
00140 map_mat_position_data_p[idx*3+1] = 127;
00141 map_mat_position_data_p[idx*3+2] = 127;
00142 map_mat_data_p[idx] = 127;
00143 break;
00144
00145 case 0:
00146 map_mat_position_data_p[idx*3] = 255;
00147 map_mat_position_data_p[idx*3+1] = 255;
00148 map_mat_position_data_p[idx*3+2] = 255;
00149 map_mat_data_p[idx] = 255;
00150 break;
00151
00152 case 100:
00153 map_mat_position_data_p[idx*3] = 0;
00154 map_mat_position_data_p[idx*3+1] = 0;
00155 map_mat_position_data_p[idx*3+2] = 0;
00156 map_mat_data_p[idx] = 0;
00157 break;
00158 }
00159 }
00160 }
00161
00162 image_transport_publisher_full_.publish(cv_img_full_.toImageMsg());
00163
00164 world_map_transformer_.setTransforms(*map);
00165
00166 Eigen::Vector2f rob_position_world (pose_ptr_->pose.position.x, pose_ptr_->pose.position.y);
00167 Eigen::Vector2f rob_position_map (world_map_transformer_.getC2Coords(rob_position_world));
00168
00169 Eigen::Vector2i rob_position_mapi (rob_position_map.cast<int>());
00170
00171 double yaw = tf::getYaw(pose_ptr_->pose.orientation);
00172 double radius = size_x / 100;
00173 circle(*map_mat_position, cvPoint(rob_position_mapi[0],size_y - rob_position_mapi[1]), radius, Scalar(255,0,0),3);
00174 line(*map_mat_position, cvPoint(rob_position_mapi[0],size_y - rob_position_mapi[1]), cvPoint(rob_position_mapi[0] + radius*cos(yaw),size_y - rob_position_mapi[1] - radius * sin(yaw)), Scalar(255,0,0),3);
00175
00176 image_transport_publisher_full_position_.publish(cv_img_full_with_position_.toImageMsg());
00177 }
00178
00179
00180 if ((image_transport_publisher_tile_.getNumSubscribers() > 0) && (pose_ptr_)){
00181
00182 world_map_transformer_.setTransforms(*map);
00183
00184 Eigen::Vector2f rob_position_world (pose_ptr_->pose.position.x, pose_ptr_->pose.position.y);
00185 Eigen::Vector2f rob_position_map (world_map_transformer_.getC2Coords(rob_position_world));
00186
00187 Eigen::Vector2i rob_position_mapi (rob_position_map.cast<int>());
00188
00189 Eigen::Vector2i tile_size_lower_halfi (p_size_tiled_map_image_x_ / 2, p_size_tiled_map_image_y_ / 2);
00190
00191 Eigen::Vector2i min_coords_map (rob_position_mapi - tile_size_lower_halfi);
00192
00193
00194 if (min_coords_map[0] < 0){
00195 min_coords_map[0] = 0;
00196 }
00197
00198 if (min_coords_map[1] < 0){
00199 min_coords_map[1] = 0;
00200 }
00201
00202 Eigen::Vector2i max_coords_map (min_coords_map + Eigen::Vector2i(p_size_tiled_map_image_x_,p_size_tiled_map_image_y_));
00203
00204
00205 if (max_coords_map[0] > size_x){
00206
00207 int diff = max_coords_map[0] - size_x;
00208 min_coords_map[0] -= diff;
00209
00210 max_coords_map[0] = size_x;
00211 }
00212
00213 if (max_coords_map[1] > size_y){
00214
00215 int diff = max_coords_map[1] - size_y;
00216 min_coords_map[1] -= diff;
00217
00218 max_coords_map[1] = size_y;
00219 }
00220
00221
00222 if (min_coords_map[0] < 0){
00223 min_coords_map[0] = 0;
00224 }
00225
00226 if (min_coords_map[1] < 0){
00227 min_coords_map[1] = 0;
00228 }
00229
00230 Eigen::Vector2i actual_map_dimensions(max_coords_map - min_coords_map);
00231
00232 Mat* map_mat = &cv_img_tile_.image;
00233
00234
00235 if ( (map_mat->rows != actual_map_dimensions[0]) || (map_mat->cols != actual_map_dimensions[1])){
00236 *map_mat = Mat(actual_map_dimensions[0], actual_map_dimensions[1], CV_8U);
00237 }
00238
00239 const std::vector<int8_t>& map_data (map->data);
00240
00241 unsigned char *map_mat_data_p=(unsigned char*) map_mat->data;
00242
00243
00244 int y_img = max_coords_map[1]-1;
00245
00246 for (int y = min_coords_map[1]; y < max_coords_map[1];++y){
00247
00248 int idx_map_y = y_img-- * size_x;
00249 int idx_img_y = (y-min_coords_map[1]) * actual_map_dimensions.x();
00250
00251 for (int x = min_coords_map[0]; x < max_coords_map[0];++x){
00252
00253 int img_index = idx_img_y + (x-min_coords_map[0]);
00254
00255 switch (map_data[idx_map_y+x])
00256 {
00257 case 0:
00258 map_mat_data_p[img_index] = 255;
00259 break;
00260
00261 case -1:
00262 map_mat_data_p[img_index] = 127;
00263 break;
00264
00265 case 100:
00266 map_mat_data_p[img_index] = 0;
00267 break;
00268 }
00269 }
00270 }
00271 image_transport_publisher_tile_.publish(cv_img_tile_.toImageMsg());
00272 }
00273 }
00274
00275 ros::Subscriber map_sub_;
00276 ros::Subscriber pose_sub_;
00277
00278 image_transport::Publisher image_transport_publisher_full_;
00279 image_transport::Publisher image_transport_publisher_full_position_;
00280 image_transport::Publisher image_transport_publisher_tile_;
00281
00282 image_transport::ImageTransport* image_transport_;
00283
00284 geometry_msgs::PoseStampedConstPtr pose_ptr_;
00285
00286 CvImage cv_img_full_;
00287 CvImage cv_img_full_with_position_;
00288 CvImage cv_img_tile_;
00289
00290 ros::NodeHandle n_;
00291 ros::NodeHandle pn_;
00292
00293 int p_size_tiled_map_image_x_;
00294 int p_size_tiled_map_image_y_;
00295
00296 HectorMapTools::CoordinateTransformer<float> world_map_transformer_;
00297
00298 };
00299
00300 int main(int argc, char** argv)
00301 {
00302 ros::init(argc, argv, "map_to_image_node");
00303
00304 MapAsImageProvider map_image_provider;
00305
00306 ros::spin();
00307
00308 return 0;
00309 }