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 (
"publish,p",
"Publish a msg when the record begin")
58 (
"output-prefix,o", po::value<std::string>(),
"prepend PREFIX to beginning of bag name")
59 (
"output-name,O", po::value<std::string>(),
"record bagnamed NAME.bag")
60 (
"buffsize,b", po::value<int>()->default_value(256),
"Use an internal buffer of SIZE MB (Default: 256)")
61 (
"chunksize", po::value<int>()->default_value(768),
"Set chunk size of message data, in KB (Default: 768. Advanced)")
62 (
"limit,l", po::value<int>()->default_value(0),
"Only record NUM messages on each topic")
63 (
"min-space,L", po::value<std::string>()->default_value(
"1G"),
"Minimum allowed space on recording device (use G,M,k multipliers)")
64 (
"bz2,j",
"use BZ2 compression")
65 (
"lz4",
"use LZ4 compression")
66 (
"split", po::value<int>()->implicit_value(0),
"Split the bag file and continue recording when maximum size or maximum duration reached.")
67 (
"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.")
68 (
"topic", po::value< std::vector<std::string> >(),
"topic to record")
69 (
"size", po::value<uint64_t>(),
"The maximum size of the bag to record in MB.")
70 (
"duration", po::value<std::string>(),
"Record a bag of maximum duration in seconds, unless 'm', or 'h' is appended.")
71 (
"node", po::value<std::string>(),
"Record all topics subscribed to by a specific node.")
72 (
"tcpnodelay",
"Use the TCP_NODELAY transport hint when subscribing to topics.")
73 (
"udp",
"Use the UDP transport hint when subscribing to topics.");
76 po::positional_options_description p;
83 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).
run(), vm);
84 }
catch (
const boost::program_options::invalid_command_line_syntax& e)
87 }
catch (
const boost::program_options::unknown_option& e)
92 if (vm.count(
"help")) {
93 std::cout << desc << std::endl;
99 if (vm.count(
"regex"))
101 if (vm.count(
"exclude"))
106 if (vm.count(
"quiet"))
108 if (vm.count(
"publish"))
110 if (vm.count(
"output-prefix"))
112 opts.
prefix = vm[
"output-prefix"].as<std::string>();
115 if (vm.count(
"output-name"))
117 opts.
prefix = vm[
"output-name"].as<std::string>();
120 if (vm.count(
"split"))
124 int S = vm[
"split"].as<
int>();
127 ROS_WARN(
"Use of \"--split <MAX_SIZE>\" has been deprecated. Please use --split --size <MAX_SIZE> or --split --duration <MAX_DURATION>");
130 opts.
max_size = 1048576 *
static_cast<uint64_t
>(S);
133 if(vm.count(
"max-splits"))
137 ROS_WARN(
"--max-splits is ignored without --split");
144 if (vm.count(
"buffsize"))
146 int m = vm[
"buffsize"].as<
int>();
151 if (vm.count(
"chunksize"))
153 int chnk_sz = vm[
"chunksize"].as<
int>();
158 if (vm.count(
"limit"))
160 opts.
limit = vm[
"limit"].as<
int>();
162 if (vm.count(
"min-space"))
164 std::string ms = vm[
"min-space"].as<std::string>();
165 long long int value = 1073741824ull;
170 if (sscanf(ms.c_str(),
" %lld%c", &value, &mul) > 0) {
192 if (vm.count(
"bz2") && vm.count(
"lz4"))
204 if (vm.count(
"duration"))
206 std::string duration_str = vm[
"duration"].as<std::string>();
209 double multiplier = 1.0;
210 std::string unit(
"");
212 std::istringstream iss(duration_str);
213 if ((iss >> duration).fail())
214 throw ros::Exception(
"Duration must start with a floating point number.");
216 if ( (!iss.eof() && ((iss >> unit).fail())) )
220 if (unit == std::string(
""))
222 else if (unit == std::string(
"s"))
224 else if (unit == std::string(
"m"))
226 else if (unit == std::string(
"h"))
236 if (vm.count(
"size"))
238 opts.
max_size = vm[
"size"].as<uint64_t>() * 1048576;
242 if (vm.count(
"node"))
244 opts.
node = vm[
"node"].as<std::string>();
245 std::cout <<
"Recording from: " << opts.
node << std::endl;
247 if (vm.count(
"tcpnodelay"))
257 if (vm.count(
"topic"))
259 std::vector<std::string> bags = vm[
"topic"].as< std::vector<std::string> >();
260 std::sort(bags.begin(), bags.end());
261 bags.erase(std::unique(bags.begin(), bags.end()), bags.end());
262 for (std::vector<std::string>::iterator i = bags.begin();
265 opts.
topics.push_back(*i);
272 fprintf(stderr,
"Warning: Exclusion regex given, but no topics to subscribe to.\n" 273 "Adding implicit 'record all'.");
290 int main(
int argc,
char** argv) {
302 ROS_ERROR(
"Error reading options: %s", ex.what());
305 catch(
const boost::regex_error& ex) {
306 ROS_ERROR(
"Error reading options: %s\n", ex.what());
312 int result = recorder.
run();
ros::TransportHints transport_hints
void run(class_loader::ClassLoader *loader)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::regex exclude_regex
ros::Duration max_duration
TransportHints & tcpNoDelay(bool nodelay=true)
rosbag::RecorderOptions parseOptions(int argc, char **argv)
Parse the command-line arguments for recorder options.
unsigned long long min_space
ROSCPP_DECL void requestShutdown()
int main(int argc, char **argv)
void signal_handler(int signal)
CompressionType compression
std::vector< std::string > topics
std::string min_space_str