tie_maps.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014-2017, the neonavigation authors
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the copyright holder nor the names of its 
00014  *       contributors may be used to endorse or promote products derived from 
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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 // The >> operator disappeared in yaml-cpp 0.5, so this function is
00047 // added to provide support for code written under the yaml-cpp 0.3 API.
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       // The document loading process changed in yaml-cpp 0.5.
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         // TODO(at-wat): make this path-handling more robust
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           // dirname can modify what you pass it
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 }


map_organizer
Author(s): Atsushi Watanabe
autogenerated on Sat Jun 22 2019 20:07:17