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
00030 #include <ros/ros.h>
00031 #include <nav_msgs/OccupancyGrid.h>
00032 #include <map_organizer_msgs/OccupancyGridArray.h>
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <libgen.h>
00037 #include <fstream>
00038 #include <sstream>
00039 #include <string>
00040 #include <vector>
00041
00042 #include <map_server/image_loader.h>
00043 #include <yaml-cpp/yaml.h>
00044
00045 #ifdef HAVE_NEW_YAMLCPP
00046
00047
00048 template <typename T>
00049 void operator>>(const YAML::Node& node, T& i)
00050 {
00051 i = node.as<T>();
00052 }
00053 #endif
00054
00055 class TieMapNode
00056 {
00057 private:
00058 ros::NodeHandle pnh_;
00059 ros::NodeHandle nh_;
00060 ros::Publisher pub_map_array_;
00061 std::vector<ros::Publisher> pub_map_;
00062
00063 public:
00064 TieMapNode()
00065 : pnh_("~")
00066 , nh_()
00067 {
00068 pub_map_array_ = nh_.advertise<map_organizer_msgs::OccupancyGridArray>("maps", 1, true);
00069
00070 map_organizer_msgs::OccupancyGridArray maps;
00071
00072 std::string files_str;
00073 std::string mapfname;
00074 double res;
00075 double origin[3], height;
00076 int negate;
00077 double occ_th, free_th;
00078 MapMode mode;
00079 std::string frame_id;
00080 pnh_.param("map_files", files_str, std::string(""));
00081 pnh_.param("frame_id", frame_id, std::string("map"));
00082
00083 int i = 0;
00084 std::string file;
00085 std::stringstream ss(files_str);
00086 while (std::getline(ss, file, ','))
00087 {
00088 std::ifstream fin(file);
00089 if (fin.fail())
00090 {
00091 ROS_ERROR("Map_server could not open %s.", file.c_str());
00092 ros::shutdown();
00093 return;
00094 }
00095 #ifdef HAVE_NEW_YAMLCPP
00096
00097 YAML::Node doc = YAML::Load(fin);
00098 #else
00099 YAML::Parser parser(fin);
00100 YAML::Node doc;
00101 parser.GetNextDocument(doc);
00102 #endif
00103 try
00104 {
00105 doc["resolution"] >> res;
00106 }
00107 catch (YAML::InvalidScalar)
00108 {
00109 ROS_ERROR("The map does not contain a resolution tag or it is invalid.");
00110 ros::shutdown();
00111 return;
00112 }
00113 try
00114 {
00115 doc["negate"] >> negate;
00116 }
00117 catch (YAML::InvalidScalar)
00118 {
00119 ROS_ERROR("The map does not contain a negate tag or it is invalid.");
00120 ros::shutdown();
00121 return;
00122 }
00123 try
00124 {
00125 doc["occupied_thresh"] >> occ_th;
00126 }
00127 catch (YAML::InvalidScalar)
00128 {
00129 ROS_ERROR("The map does not contain an occupied_thresh tag or it is invalid.");
00130 ros::shutdown();
00131 return;
00132 }
00133 try
00134 {
00135 doc["free_thresh"] >> free_th;
00136 }
00137 catch (YAML::InvalidScalar)
00138 {
00139 ROS_ERROR("The map does not contain a free_thresh tag or it is invalid.");
00140 ros::shutdown();
00141 return;
00142 }
00143 try
00144 {
00145 std::string modeS = "";
00146 doc["mode"] >> modeS;
00147
00148 if (modeS == "trinary")
00149 mode = TRINARY;
00150 else if (modeS == "scale")
00151 mode = SCALE;
00152 else if (modeS == "raw")
00153 mode = RAW;
00154 else
00155 {
00156 ROS_ERROR("Invalid mode tag \"%s\".", modeS.c_str());
00157 exit(-1);
00158 }
00159 }
00160 catch (YAML::Exception)
00161 {
00162 ROS_DEBUG("The map does not contain a mode tag or it is invalid... assuming trinary");
00163 mode = TRINARY;
00164 }
00165 try
00166 {
00167 doc["origin"][0] >> origin[0];
00168 doc["origin"][1] >> origin[1];
00169 doc["origin"][2] >> origin[2];
00170 }
00171 catch (YAML::InvalidScalar)
00172 {
00173 ROS_ERROR("The map does not contain an origin tag or it is invalid.");
00174 ros::shutdown();
00175 return;
00176 }
00177 try
00178 {
00179 doc["height"] >> height;
00180 }
00181 catch (YAML::Exception)
00182 {
00183 height = 0;
00184 }
00185 try
00186 {
00187 doc["image"] >> mapfname;
00188
00189 if (mapfname.size() == 0)
00190 {
00191 ROS_ERROR("The image tag cannot be an empty string.");
00192 ros::shutdown();
00193 return;
00194 }
00195 if (mapfname[0] != '/')
00196 {
00197
00198 char* fname_copy = strdup(file.c_str());
00199 mapfname = std::string(dirname(fname_copy)) + '/' + mapfname;
00200 free(fname_copy);
00201 }
00202 }
00203 catch (YAML::InvalidScalar)
00204 {
00205 ROS_ERROR("The map does not contain an image tag or it is invalid.");
00206 ros::shutdown();
00207 return;
00208 }
00209
00210 ROS_INFO("Loading map from image \"%s\"", mapfname.c_str());
00211
00212 nav_msgs::GetMap::Response map_resp;
00213 map_server::loadMapFromFile(&map_resp,
00214 mapfname.c_str(), res, negate, occ_th, free_th, origin, mode);
00215 map_resp.map.info.origin.position.z = height;
00216 map_resp.map.info.map_load_time = ros::Time::now();
00217 map_resp.map.header.frame_id = frame_id;
00218 map_resp.map.header.stamp = ros::Time::now();
00219 ROS_INFO("Read a %d X %d map @ %.3lf m/cell",
00220 map_resp.map.info.width,
00221 map_resp.map.info.height,
00222 map_resp.map.info.resolution);
00223 maps.maps.push_back(map_resp.map);
00224 pub_map_.push_back(nh_.advertise<nav_msgs::OccupancyGrid>(
00225 "map" + std::to_string(i), 1, true));
00226 pub_map_.back().publish(map_resp.map);
00227 i++;
00228 }
00229 pub_map_array_.publish(maps);
00230 }
00231 };
00232
00233 int main(int argc, char** argv)
00234 {
00235 ros::init(argc, argv, "tie_maps");
00236
00237 TieMapNode tmn;
00238 ros::spin();
00239
00240 return 0;
00241 }