22 #include <geometry_msgs/Quaternion.h> 25 #include <glog/logging.h> 27 #include <yaml-cpp/yaml.h> 30 void AddTrailingSlashToDirectoryPathIfNeeded(std::string* directory_path) {
31 if (!directory_path->empty() && directory_path->back() !=
'/') {
32 (*directory_path) +=
'/';
35 bool DirectoryPathExists(
const std::string& path) {
37 return (stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFDIR));
39 bool MakeDirectoryPath(
const std::string& input_path, mode_t mode) {
40 if (input_path.empty()) {
45 size_t previous_slash_pos = 0;
46 size_t current_slash_pos;
48 int make_dir_status = 0;
50 std::string path = input_path;
51 AddTrailingSlashToDirectoryPathIfNeeded(&path);
53 while ((current_slash_pos = path.find_first_of(
'/', previous_slash_pos)) !=
55 dir = path.substr(0, current_slash_pos++);
56 previous_slash_pos = current_slash_pos;
57 if (dir.empty() || dir ==
".")
60 if ((make_dir_status = mkdir(dir.c_str(), mode)) && errno != EEXIST) {
70 const std::string& map_name,
const std::string& map_uuid,
71 const std::string& map_directory,
const nav_msgs::OccupancyGrid& occupancy_grid) {
77 const std::string& map_name,
const std::string& map_directory,
78 const nav_msgs::OccupancyGrid& occupancy_grid) {
79 std::string map_directory_with_trailing_slash = map_directory;
80 AddTrailingSlashToDirectoryPathIfNeeded(&map_directory_with_trailing_slash);
81 if (!DirectoryPathExists(map_directory_with_trailing_slash)) {
82 LOG(INFO) <<
"Directory " << map_directory_with_trailing_slash <<
" does not exist, creating it now.";
83 if (!MakeDirectoryPath(map_directory_with_trailing_slash, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
84 LOG(ERROR) <<
"Could not create directory: " << map_directory_with_trailing_slash;
89 std::string map_pgm_file_path = map_directory_with_trailing_slash + map_name +
".pgm";
90 FILE* pgm_file = fopen(map_pgm_file_path.c_str(),
"w");
92 LOG(ERROR) <<
"Could no open file " << map_pgm_file_path;
96 fprintf(pgm_file,
"P5\n# CREATOR: TangoRosStreamer %.3f m/pix\n%d %d\n255\n",
97 occupancy_grid.info.resolution,
98 occupancy_grid.info.width, occupancy_grid.info.height);
99 for (
size_t i = 0; i < occupancy_grid.info.height; ++i) {
100 for (
size_t j = 0; j < occupancy_grid.info.width; ++j) {
103 int value = occupancy_grid.data[j + (occupancy_grid.info.height - i - 1) * occupancy_grid.info.width];
105 fputc(254, pgm_file);
106 }
else if (value == +100) {
107 fputc(000, pgm_file);
109 fputc(205, pgm_file);
114 LOG(INFO) <<
"Map image successfully saved to " << map_pgm_file_path;
119 const std::string& map_name,
const std::string& map_uuid,
120 const std::string& map_directory,
const nav_msgs::MapMetaData& map_metadata) {
121 std::string map_directory_with_trailing_slash = map_directory;
122 AddTrailingSlashToDirectoryPathIfNeeded(&map_directory_with_trailing_slash);
123 if (!DirectoryPathExists(map_directory_with_trailing_slash)) {
124 LOG(INFO) <<
"Directory " << map_directory_with_trailing_slash <<
" does not exist, creating it now.";
125 if (!MakeDirectoryPath(map_directory_with_trailing_slash, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
126 LOG(ERROR) <<
"Could not create directory: " << map_directory_with_trailing_slash;
131 std::string image_name = map_name;
132 if (image_name.empty())
134 std::string uuid = map_uuid;
138 std::string map_yaml_file_path = map_directory_with_trailing_slash + map_name +
".yaml";
139 FILE* yaml_file = fopen(map_yaml_file_path.c_str(),
"w");
141 LOG(ERROR) <<
"Could no open file " << map_yaml_file_path;
146 map_metadata.origin.orientation.y,
147 map_metadata.origin.orientation.z,
148 map_metadata.origin.orientation.w));
149 double yaw, pitch, roll;
154 fprintf(yaml_file,
"image: %s.pgm\nresolution: %f\norigin: [%f, %f, %f]\nnegate: 0\n" 155 "occupied_thresh: 0.65\nfree_thresh: 0.196\nuuid: %s\n\n",
156 map_name.c_str(), map_metadata.resolution, map_metadata.origin.position.x,
157 map_metadata.origin.position.y, yaw, uuid.c_str());
160 LOG(INFO) <<
"Map yaml file successfully saved to " << map_yaml_file_path;
165 const std::string& map_name,
const std::string& map_directory,
166 nav_msgs::OccupancyGrid* occupancy_grid, std::string* map_uuid) {
168 double occupied_threshold;
169 double free_threshold;
171 map_name, map_directory, &(occupancy_grid->info), &negate,
172 &occupied_threshold, &free_threshold, map_uuid);
174 map_name, map_directory, negate, occupied_threshold, free_threshold,
179 const std::string& map_name,
const std::string& map_directory,
180 bool negate,
double occupied_threshold,
double free_threshold,
181 nav_msgs::OccupancyGrid* occupancy_grid) {
182 std::string map_directory_with_trailing_slash = map_directory;
183 AddTrailingSlashToDirectoryPathIfNeeded(&map_directory_with_trailing_slash);
185 std::string map_pgm_file_path = map_directory_with_trailing_slash + map_name +
".pgm";
186 std::ifstream pgm_file(map_pgm_file_path, std::ios::binary);
187 if (pgm_file.fail()) {
188 LOG(ERROR) <<
"Could no open file " << map_pgm_file_path;
193 std::string file_type;
194 getline(pgm_file, file_type);
195 LOG(INFO) << file_type;
196 if (file_type.compare(
"P5") != 0) {
197 LOG(ERROR) <<
"Pgm file type error. Type is " << file_type
198 <<
" while supported type is P5.";
203 getline(pgm_file, comment);
204 LOG(INFO) << comment;
206 std::string image_size;
207 getline(pgm_file, image_size);
208 std::stringstream size_stream(image_size);
209 size_stream >> occupancy_grid->info.width >> occupancy_grid->info.height;
210 LOG(INFO) <<
"Image size is " << occupancy_grid->info.width <<
"x" << occupancy_grid->info.height;
212 std::string max_value_string;
213 getline(pgm_file, max_value_string);
214 std::stringstream max_val_stream(max_value_string);
216 max_val_stream >> max_value;
218 int pixel_array[occupancy_grid->info.height * occupancy_grid->info.width];
219 for (
size_t i = 0; i < occupancy_grid->info.height * occupancy_grid->info.width; ++i) {
220 char pixel = pgm_file.get();
221 pixel_array[i] =
static_cast<int>(pixel);
225 occupancy_grid->data.reserve(occupancy_grid->info.height * occupancy_grid->info.width);
226 for (
size_t i = 0; i < occupancy_grid->info.height; ++i) {
227 for (
size_t j = 0; j < occupancy_grid->info.width; ++j) {
228 int value = pixel_array[j + (occupancy_grid->info.height - i - 1) * occupancy_grid->info.width];
230 value = max_value - value;
231 double occupancy = (max_value - value) / static_cast<double>(max_value);
232 if (occupancy < free_threshold) {
233 occupancy_grid->data.push_back(0);
234 }
else if (occupancy > occupied_threshold) {
235 occupancy_grid->data.push_back(100);
237 occupancy_grid->data.push_back(-1);
242 LOG(INFO) <<
"Map image successfully loaded from " << map_pgm_file_path;
247 const std::string& map_name,
const std::string& map_directory,
248 nav_msgs::MapMetaData* map_metadata,
int* negate,
249 double* occupied_threshold,
double* free_threshold, std::string* map_uuid) {
250 std::string map_directory_with_trailing_slash = map_directory;
251 AddTrailingSlashToDirectoryPathIfNeeded(&map_directory_with_trailing_slash);
253 std::string map_yam_file_path = map_directory_with_trailing_slash + map_name +
".yaml";
254 std::ifstream yaml_file(map_yam_file_path.c_str());
255 if (yaml_file.fail()) {
256 LOG(ERROR) <<
"Could no open file " << map_yam_file_path;
260 YAML::Node node = YAML::Load(yaml_file);
262 map_metadata->resolution = node[
"resolution"].as<
double>();
263 }
catch (YAML::RepresentationException& e) {
264 LOG(ERROR) <<
"The map does not contain a resolution tag or it is invalid. " << e.msg;
268 *negate = node[
"negate"].as<
int>();
269 }
catch (YAML::RepresentationException& e) {
270 LOG(ERROR) <<
"The map does not contain a negate tag or it is invalid. " << e.msg;
274 *occupied_threshold = node[
"occupied_thresh"].as<
double>();
275 }
catch (YAML::RepresentationException& e) {
276 LOG(ERROR) <<
"The map does not contain an occupied_thresh tag or it is invalid. " << e.msg;
280 *free_threshold = node[
"free_thresh"].as<
double>();
281 }
catch (YAML::RepresentationException& e) {
282 LOG(ERROR) <<
"The map does not contain a free_thresh tag or it is invalid. " << e.msg;
286 map_metadata->origin.position.x = node[
"origin"][0].as<
double>();
287 map_metadata->origin.position.y = node[
"origin"][1].as<
double>();
288 map_metadata->origin.position.z = 0.0;
290 double yaw = node[
"origin"][2].as<
double>();
291 quaternion.
setRPY(0., 0., yaw);
292 map_metadata->origin.orientation.x = quaternion.x();
293 map_metadata->origin.orientation.y = quaternion.y();
294 map_metadata->origin.orientation.z = quaternion.z();
295 map_metadata->origin.orientation.w = quaternion.w();
296 }
catch (YAML::RepresentationException& e) {
297 LOG(ERROR) <<
"The map does not contain an origin tag or it is invalid. " << e.msg;
301 *map_uuid = node[
"uuid"].as<std::string>();
302 }
catch (YAML::RepresentationException& e) {
303 LOG(WARNING) <<
"The map does not contain a uuid tag or it is invalid. " << e.msg;
306 LOG(INFO) <<
"Map yaml file successfully loaded from " << map_yam_file_path;
bool SaveOccupancyGridDataToPgmFile(const std::string &map_name, const std::string &map_directory, const nav_msgs::OccupancyGrid &occupancy_grid)
bool LoadOccupancyGridFromFiles(const std::string &map_name, const std::string &map_directory, nav_msgs::OccupancyGrid *occupancy_grid, std::string *map_uuid)
bool SaveOccupancyGridToFiles(const std::string &map_name, const std::string &map_uuid, const std::string &map_directory, const nav_msgs::OccupancyGrid &occupancy_grid)
void getEulerYPR(tfScalar &yaw, tfScalar &pitch, tfScalar &roll, unsigned int solution_number=1) const
bool LoadOccupancyGridMetadataFromYamlFile(const std::string &map_name, const std::string &map_directory, nav_msgs::MapMetaData *map_metadata, int *negate, double *occupied_threshold, double *free_threshold, std::string *map_uuid)
bool LoadOccupancyGridDataFromPgmFile(const std::string &map_name, const std::string &map_directory, bool negate, double occupied_threshold, double free_threshold, nav_msgs::OccupancyGrid *occupancy_grid)
bool SaveOccupancyGridMetadataToYamlFile(const std::string &map_name, const std::string &map_uuid, const std::string &map_directory, const nav_msgs::MapMetaData &map_metadata)
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)