Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
main_cli.cpp
1 // Copyright 2019 Rover Robotics
2 // Copyright (c) 2008, Willow Garage, Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <memory>
17 #include <string>
18 #include <vector>
19 #include <stdexcept>
20 
21 #include "nav2_map_server/map_mode.hpp"
22 #include "nav2_map_server/map_saver.hpp"
23 
24 #include "rclcpp/logger.hpp"
25 #include "rclcpp/logging.hpp"
26 #include "rclcpp/parameter.hpp"
27 #include "rclcpp/utilities.hpp"
28 
29 using namespace nav2_map_server; // NOLINT
30 
31 const char * USAGE_STRING{
32  "Usage:\n"
33  " map_saver_cli [arguments] [--ros-args ROS remapping args]\n"
34  "\n"
35  "Arguments:\n"
36  " -h/--help\n"
37  " -t <map_topic>\n"
38  " -f <mapname>\n"
39  " --occ <threshold_occupied>\n"
40  " --free <threshold_free>\n"
41  " --fmt <image_format>\n"
42  " --mode trinary(default)/scale/raw\n"
43  "\n"
44  "NOTE: --ros-args should be passed at the end of command line"};
45 
46 typedef enum
47 {
48  COMMAND_MAP_TOPIC,
49  COMMAND_MAP_FILE_NAME,
50  COMMAND_IMAGE_FORMAT,
51  COMMAND_OCCUPIED_THRESH,
52  COMMAND_FREE_THRESH,
53  COMMAND_MODE
54 } COMMAND_TYPE;
55 
56 struct cmd_struct
57 {
58  const char * cmd;
59  COMMAND_TYPE command_type;
60 };
61 
62 typedef enum
63 {
64  ARGUMENTS_INVALID,
65  ARGUMENTS_VALID,
66  HELP_MESSAGE
67 } ARGUMENTS_STATUS;
68 
69 // Arguments parser
70 // Input parameters: logger, argc, argv
71 // Output parameters: map_topic, save_parameters
72 ARGUMENTS_STATUS parse_arguments(
73  const rclcpp::Logger & logger, int argc, char ** argv,
74  std::string & map_topic, SaveParameters & save_parameters)
75 {
76  const struct cmd_struct commands[] = {
77  {"-t", COMMAND_MAP_TOPIC},
78  {"-f", COMMAND_MAP_FILE_NAME},
79  {"--occ", COMMAND_OCCUPIED_THRESH},
80  {"--free", COMMAND_FREE_THRESH},
81  {"--mode", COMMAND_MODE},
82  {"--fmt", COMMAND_IMAGE_FORMAT},
83  };
84 
85  std::vector<std::string> arguments(argv + 1, argv + argc);
86  std::vector<rclcpp::Parameter> params_from_args;
87 
88 
89  size_t cmd_size = sizeof(commands) / sizeof(commands[0]);
90  size_t i;
91  for (auto it = arguments.begin(); it != arguments.end(); it++) {
92  if (*it == "-h" || *it == "--help") {
93  std::cout << USAGE_STRING << std::endl;
94  return HELP_MESSAGE;
95  }
96  if (*it == "--ros-args") {
97  break;
98  }
99  for (i = 0; i < cmd_size; i++) {
100  if (commands[i].cmd == *it) {
101  if ((it + 1) == arguments.end()) {
102  RCLCPP_ERROR(logger, "Wrong argument: %s should be followed by a value.", it->c_str());
103  return ARGUMENTS_INVALID;
104  }
105  it++;
106  switch (commands[i].command_type) {
107  case COMMAND_MAP_TOPIC:
108  map_topic = *it;
109  break;
110  case COMMAND_MAP_FILE_NAME:
111  save_parameters.map_file_name = *it;
112  break;
113  case COMMAND_FREE_THRESH:
114  save_parameters.free_thresh = atof(it->c_str());
115  break;
116  case COMMAND_OCCUPIED_THRESH:
117  save_parameters.occupied_thresh = atof(it->c_str());
118  break;
119  case COMMAND_IMAGE_FORMAT:
120  save_parameters.image_format = *it;
121  break;
122  case COMMAND_MODE:
123  try {
124  save_parameters.mode = map_mode_from_string(*it);
125  } catch (std::invalid_argument &) {
126  save_parameters.mode = MapMode::Trinary;
127  RCLCPP_WARN(
128  logger,
129  "Map mode parameter not recognized: %s, using default value (trinary)",
130  it->c_str());
131  }
132  break;
133  }
134  break;
135  }
136  }
137  if (i == cmd_size) {
138  RCLCPP_ERROR(logger, "Wrong argument: %s", it->c_str());
139  return ARGUMENTS_INVALID;
140  }
141  }
142 
143  return ARGUMENTS_VALID;
144 }
145 
146 int main(int argc, char ** argv)
147 {
148  // ROS2 init
149  rclcpp::init(argc, argv);
150  auto logger = rclcpp::get_logger("map_saver_cli");
151 
152  // Parse CLI-arguments
153  SaveParameters save_parameters;
154  std::string map_topic = "map";
155  switch (parse_arguments(logger, argc, argv, map_topic, save_parameters)) {
156  case ARGUMENTS_INVALID:
157  rclcpp::shutdown();
158  return -1;
159  case HELP_MESSAGE:
160  rclcpp::shutdown();
161  return 0;
162  case ARGUMENTS_VALID:
163  break;
164  }
165 
166  // Call saveMapTopicToFile()
167  int retcode;
168  try {
169  auto map_saver = std::make_shared<nav2_map_server::MapSaver>();
170  map_saver->on_configure(rclcpp_lifecycle::State());
171  if (map_saver->saveMapTopicToFile(map_topic, save_parameters)) {
172  retcode = 0;
173  } else {
174  retcode = 1;
175  }
176  } catch (std::exception & e) {
177  RCLCPP_ERROR(logger, "Unexpected problem appear: %s", e.what());
178  retcode = -1;
179  }
180 
181  // Exit
182  rclcpp::shutdown();
183  return retcode;
184 }