save_maps.cpp
Go to the documentation of this file.
00001 /*
00002  * map_saver
00003  * Copyright (c) 2008, Willow Garage, Inc.
00004  * Copyright (c) 2016, the neonavigation authors
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <ORGANIZATION> nor the names of its
00016  *       contributors may be used to endorse or promote products derived from
00017  *       this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include <ros/ros.h>
00033 #include <ros/console.h>
00034 #include <nav_msgs/GetMap.h>
00035 #include <tf2/LinearMath/Matrix3x3.h>
00036 #include <geometry_msgs/Quaternion.h>
00037 
00038 #include <cstdio>
00039 #include <string>
00040 
00041 #include <map_organizer_msgs/OccupancyGridArray.h>
00042 
00046 class MapGeneratorNode
00047 {
00048 protected:
00049   ros::NodeHandle nh_;
00050   std::string mapname_;
00051   ros::Subscriber map_sub_;
00052   bool saved_map_;
00053 
00054 public:
00055   explicit MapGeneratorNode(const std::string& mapname)
00056     : nh_()
00057     , mapname_(mapname)
00058     , saved_map_(false)
00059   {
00060     ROS_INFO("Waiting for the map");
00061     map_sub_ = nh_.subscribe("maps", 1, &MapGeneratorNode::mapsCallback, this);
00062   }
00063 
00064   bool done() const
00065   {
00066     return saved_map_;
00067   }
00068   void mapsCallback(const map_organizer_msgs::OccupancyGridArrayConstPtr& maps)
00069   {
00070     int i = 0;
00071     for (auto& map : maps->maps)
00072     {
00073       mapCallback(&map, i);
00074       i++;
00075     }
00076     saved_map_ = true;
00077   }
00078   void mapCallback(const nav_msgs::OccupancyGrid* map, const int floor)
00079   {
00080     ROS_INFO("Received a %d X %d map @ %.3f m/pix",
00081              map->info.width,
00082              map->info.height,
00083              map->info.resolution);
00084 
00085     std::string mapdatafile = mapname_ + std::to_string(floor) + ".pgm";
00086     ROS_INFO("Writing map occupancy data to %s", mapdatafile.c_str());
00087     FILE* out = fopen(mapdatafile.c_str(), "w");
00088     if (!out)
00089     {
00090       ROS_ERROR("Couldn't save map file to %s", mapdatafile.c_str());
00091       return;
00092     }
00093 
00094     fprintf(out, "P5\n# CREATOR: Map_generator.cpp %.3f m/pix\n%d %d\n255\n",
00095             map->info.resolution, map->info.width, map->info.height);
00096     for (unsigned int y = 0; y < map->info.height; y++)
00097     {
00098       for (unsigned int x = 0; x < map->info.width; x++)
00099       {
00100         unsigned int i = x + (map->info.height - y - 1) * map->info.width;
00101         if (map->data[i] == 0)
00102         {  // occ [0,0.1)
00103           fputc(254, out);
00104         }
00105         else if (map->data[i] == +100)
00106         {  // occ (0.65,1]
00107           fputc(000, out);
00108         }
00109         else
00110         {  // occ [0.1,0.65]
00111           fputc(205, out);
00112         }
00113       }
00114     }
00115 
00116     fclose(out);
00117 
00118     std::string mapmetadatafile = mapname_ + std::to_string(floor) + ".yaml";
00119     ROS_INFO("Writing map occupancy data to %s", mapmetadatafile.c_str());
00120     FILE* yaml = fopen(mapmetadatafile.c_str(), "w");
00121 
00122     geometry_msgs::Quaternion orientation = map->info.origin.orientation;
00123     tf2::Matrix3x3 mat(tf2::Quaternion(orientation.x, orientation.y, orientation.z, orientation.w));
00124     double yaw, pitch, roll;
00125     mat.getEulerYPR(yaw, pitch, roll);
00126 
00127     fprintf(yaml, "image: %s\nresolution: %f\n"
00128                   "origin: [%f, %f, %f]\nheight: %f\n"
00129                   "negate: 0\noccupied_thresh: 0.65\nfree_thresh: 0.196\n\n",
00130             mapdatafile.c_str(), map->info.resolution,
00131             map->info.origin.position.x, map->info.origin.position.y, yaw, map->info.origin.position.z);
00132 
00133     fclose(yaml);
00134 
00135     ROS_INFO("Done\n");
00136   }
00137 };
00138 
00139 #define USAGE "Usage: \n"        \
00140               "  map_saver -h\n" \
00141               "  map_saver [-f <mapname>] [ROS remapping args]"
00142 
00143 int main(int argc, char** argv)
00144 {
00145   ros::init(argc, argv, "save_maps");
00146   std::string mapname = "map";
00147 
00148   for (int i = 1; i < argc; i++)
00149   {
00150     if (!strcmp(argv[i], "-h"))
00151     {
00152       puts(USAGE);
00153       return 0;
00154     }
00155     else if (!strcmp(argv[i], "-f"))
00156     {
00157       if (++i < argc)
00158         mapname = argv[i];
00159       else
00160       {
00161         puts(USAGE);
00162         return 1;
00163       }
00164     }
00165     else
00166     {
00167       puts(USAGE);
00168       return 1;
00169     }
00170   }
00171 
00172   MapGeneratorNode mg(mapname);
00173 
00174   while (!mg.done() && ros::ok())
00175     ros::spinOnce();
00176 
00177   return 0;
00178 }


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