Nav2 Navigation Stack - kilted  kilted
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/rclcpp.hpp"
25 
26 using namespace nav2_map_server; // NOLINT
27 
28 const char * USAGE_STRING{
29  "Usage:\n"
30  " map_saver_cli [arguments] [--ros-args ROS remapping args]\n"
31  "\n"
32  "Arguments:\n"
33  " -h/--help\n"
34  " -t <map_topic>\n"
35  " -f <mapname>\n"
36  " --occ <threshold_occupied>\n"
37  " --free <threshold_free>\n"
38  " --fmt <image_format>\n"
39  " --mode trinary(default)/scale/raw\n"
40  "\n"
41  "NOTE: --ros-args should be passed at the end of command line"};
42 
43 typedef enum
44 {
45  COMMAND_MAP_TOPIC,
46  COMMAND_MAP_FILE_NAME,
47  COMMAND_IMAGE_FORMAT,
48  COMMAND_OCCUPIED_THRESH,
49  COMMAND_FREE_THRESH,
50  COMMAND_MODE
51 } COMMAND_TYPE;
52 
53 struct cmd_struct
54 {
55  const char * cmd;
56  COMMAND_TYPE command_type;
57 };
58 
59 typedef enum
60 {
61  ARGUMENTS_INVALID,
62  ARGUMENTS_VALID,
63  HELP_MESSAGE
64 } ARGUMENTS_STATUS;
65 
66 // Arguments parser
67 // Input parameters: logger, argc, argv
68 // Output parameters: map_topic, save_parameters
69 ARGUMENTS_STATUS parse_arguments(
70  const rclcpp::Logger & logger, int argc, char ** argv,
71  std::string & map_topic, SaveParameters & save_parameters)
72 {
73  const struct cmd_struct commands[] = {
74  {"-t", COMMAND_MAP_TOPIC},
75  {"-f", COMMAND_MAP_FILE_NAME},
76  {"--occ", COMMAND_OCCUPIED_THRESH},
77  {"--free", COMMAND_FREE_THRESH},
78  {"--mode", COMMAND_MODE},
79  {"--fmt", COMMAND_IMAGE_FORMAT},
80  };
81 
82  std::vector<std::string> arguments(argv + 1, argv + argc);
83  std::vector<rclcpp::Parameter> params_from_args;
84 
85 
86  size_t cmd_size = sizeof(commands) / sizeof(commands[0]);
87  size_t i;
88  for (auto it = arguments.begin(); it != arguments.end(); it++) {
89  if (*it == "-h" || *it == "--help") {
90  std::cout << USAGE_STRING << std::endl;
91  return HELP_MESSAGE;
92  }
93  if (*it == "--ros-args") {
94  break;
95  }
96  for (i = 0; i < cmd_size; i++) {
97  if (commands[i].cmd == *it) {
98  if ((it + 1) == arguments.end()) {
99  RCLCPP_ERROR(logger, "Wrong argument: %s should be followed by a value.", it->c_str());
100  return ARGUMENTS_INVALID;
101  }
102  it++;
103  switch (commands[i].command_type) {
104  case COMMAND_MAP_TOPIC:
105  map_topic = *it;
106  break;
107  case COMMAND_MAP_FILE_NAME:
108  save_parameters.map_file_name = *it;
109  break;
110  case COMMAND_FREE_THRESH:
111  save_parameters.free_thresh = atof(it->c_str());
112  break;
113  case COMMAND_OCCUPIED_THRESH:
114  save_parameters.occupied_thresh = atof(it->c_str());
115  break;
116  case COMMAND_IMAGE_FORMAT:
117  save_parameters.image_format = *it;
118  break;
119  case COMMAND_MODE:
120  try {
121  save_parameters.mode = map_mode_from_string(*it);
122  } catch (std::invalid_argument &) {
123  save_parameters.mode = MapMode::Trinary;
124  RCLCPP_WARN(
125  logger,
126  "Map mode parameter not recognized: %s, using default value (trinary)",
127  it->c_str());
128  }
129  break;
130  }
131  break;
132  }
133  }
134  if (i == cmd_size) {
135  RCLCPP_ERROR(logger, "Wrong argument: %s", it->c_str());
136  return ARGUMENTS_INVALID;
137  }
138  }
139 
140  return ARGUMENTS_VALID;
141 }
142 
143 int main(int argc, char ** argv)
144 {
145  // ROS2 init
146  rclcpp::init(argc, argv);
147  auto logger = rclcpp::get_logger("map_saver_cli");
148 
149  // Parse CLI-arguments
150  SaveParameters save_parameters;
151  std::string map_topic = "map";
152  switch (parse_arguments(logger, argc, argv, map_topic, save_parameters)) {
153  case ARGUMENTS_INVALID:
154  rclcpp::shutdown();
155  return -1;
156  case HELP_MESSAGE:
157  rclcpp::shutdown();
158  return 0;
159  case ARGUMENTS_VALID:
160  break;
161  }
162 
163  // Call saveMapTopicToFile()
164  int retcode;
165  try {
166  auto map_saver = std::make_shared<nav2_map_server::MapSaver>();
167  map_saver->on_configure(rclcpp_lifecycle::State());
168  if (map_saver->saveMapTopicToFile(map_topic, save_parameters)) {
169  retcode = 0;
170  } else {
171  retcode = 1;
172  }
173  } catch (std::exception & e) {
174  RCLCPP_ERROR(logger, "Unexpected problem appear: %s", e.what());
175  retcode = -1;
176  }
177 
178  // Exit
179  rclcpp::shutdown();
180  return retcode;
181 }