38 #include "boost/program_options.hpp"
43 namespace po = boost::program_options;
49 po::options_description desc(
"Allowed options");
52 (
"help,h",
"produce help message")
53 (
"all,a",
"record all topics")
54 (
"regex,e",
"match topics using regular expressions")
55 (
"exclude,x", po::value<std::string>(),
"exclude topics matching regular expressions")
56 (
"quiet,q",
"suppress console output")
57 (
"snapshot,s",
"Run in snapshot mode")
58 (
"publish,p",
"Publish a msg when the recording begins")
59 (
"output-prefix,o", po::value<std::string>(),
"prepend PREFIX to beginning of bag name")
60 (
"output-name,O", po::value<std::string>(),
"record bagnamed NAME.bag")
61 (
"buffsize,b", po::value<int>()->default_value(256),
"Use an internal buffer of SIZE MB (Default: 256)")
62 (
"chunksize", po::value<int>()->default_value(768),
"Set chunk size of message data, in KB (Default: 768. Advanced)")
63 (
"limit,l", po::value<int>()->default_value(0),
"Only record NUM messages on each topic")
64 (
"min-space,L", po::value<std::string>()->default_value(
"1G"),
"Minimum allowed space on recording device (use G,M,k multipliers)")
65 (
"bz2,j",
"use BZ2 compression")
66 (
"lz4",
"use LZ4 compression")
67 (
"split", po::value<int>()->implicit_value(0),
"Split the bag file and continue recording when maximum size or maximum duration reached.")
68 (
"max-splits", po::value<int>(),
"Keep a maximum of N bag files, when reaching the maximum erase the oldest one to keep a constant number of files.")
69 (
"topic", po::value< std::vector<std::string> >(),
"topic to record")
70 (
"size", po::value<uint64_t>(),
"The maximum size of the bag to record in MB.")
71 (
"duration", po::value<std::string>(),
"Record a bag of maximum duration in seconds, unless 'm', or 'h' is appended.")
72 (
"node", po::value<std::string>(),
"Record all topics subscribed to by a specific node.")
73 (
"tcpnodelay",
"Use the TCP_NODELAY transport hint when subscribing to topics.")
74 (
"udp",
"Use the UDP transport hint when subscribing to topics.")
75 (
"repeat-latched",
"Repeat latched msgs at the start of each new bag file.");
78 po::positional_options_description p;
85 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).
run(), vm);
86 }
catch (
const boost::program_options::invalid_command_line_syntax& e)
89 }
catch (
const boost::program_options::unknown_option& e)
94 if (vm.count(
"help")) {
95 std::cout << desc << std::endl;
101 if (vm.count(
"regex"))
103 if (vm.count(
"exclude"))
108 if (vm.count(
"quiet"))
110 if (vm.count(
"snapshot"))
112 if (vm.count(
"publish"))
114 if (vm.count(
"repeat-latched"))
116 if (vm.count(
"output-prefix"))
118 opts.
prefix = vm[
"output-prefix"].as<std::string>();
121 if (vm.count(
"output-name"))
123 opts.
prefix = vm[
"output-name"].as<std::string>();
126 if (vm.count(
"split"))
130 int S = vm[
"split"].as<
int>();
133 ROS_WARN(
"Use of \"--split <MAX_SIZE>\" has been deprecated. Please use --split --size <MAX_SIZE> or --split --duration <MAX_DURATION>");
136 opts.
max_size = 1048576 *
static_cast<uint64_t
>(S);
139 if(vm.count(
"max-splits"))
143 ROS_WARN(
"--max-splits is ignored without --split");
150 if (vm.count(
"buffsize"))
152 int m = vm[
"buffsize"].as<
int>();
157 if (vm.count(
"chunksize"))
159 int chnk_sz = vm[
"chunksize"].as<
int>();
164 if (vm.count(
"limit"))
166 opts.
limit = vm[
"limit"].as<
int>();
168 if (vm.count(
"min-space"))
170 std::string ms = vm[
"min-space"].as<std::string>();
171 long long int value = 1073741824ull;
176 if (sscanf(ms.c_str(),
" %lld%c", &value, &mul) > 0) {
198 if (vm.count(
"bz2") && vm.count(
"lz4"))
210 if (vm.count(
"duration"))
212 std::string duration_str = vm[
"duration"].as<std::string>();
215 double multiplier = 1.0;
216 std::string unit(
"");
218 std::istringstream iss(duration_str);
219 if ((iss >> duration).fail())
220 throw ros::Exception(
"Duration must start with a floating point number.");
222 if ( (!iss.eof() && ((iss >> unit).fail())) )
226 if (unit == std::string(
""))
228 else if (unit == std::string(
"s"))
230 else if (unit == std::string(
"m"))
232 else if (unit == std::string(
"h"))
242 if (vm.count(
"size"))
244 opts.
max_size = vm[
"size"].as<uint64_t>() * 1048576;
248 if (vm.count(
"node"))
250 opts.
node = vm[
"node"].as<std::string>();
251 std::cout <<
"Recording from: " << opts.
node << std::endl;
253 if (vm.count(
"tcpnodelay"))
263 if (vm.count(
"topic"))
265 std::vector<std::string> bags = vm[
"topic"].as< std::vector<std::string> >();
266 std::sort(bags.begin(), bags.end());
267 bags.erase(std::unique(bags.begin(), bags.end()), bags.end());
268 for (std::vector<std::string>::iterator i = bags.begin();
271 opts.
topics.push_back(*i);
278 fprintf(stderr,
"Warning: Exclusion regex given, but no topics to subscribe to.\n"
279 "Adding implicit 'record all'.");
296 int main(
int argc,
char** argv) {
308 ROS_ERROR(
"Error reading options: %s", ex.what());
311 catch(
const boost::regex_error& ex) {
312 ROS_ERROR(
"Error reading options: %s\n", ex.what());
318 int result = recorder.
run();