4 #include <boost/program_options.hpp>
11 #include <rosbag_fancy_msgs/Status.h>
13 #include <std_srvs/Trigger.h>
23 namespace po = boost::program_options;
25 using namespace rosbag_fancy_msgs;
27 int record(
const std::vector<std::string>& options)
33 po::options_description desc(
"Options");
35 (
"help",
"Display this help message")
36 (
"prefix,p", po::value<std::string>()->default_value(
"bag"),
"Prefix for output bag file. The prefix is extended with a timestamp.")
37 (
"output,o", po::value<std::string>()->value_name(
"FILE"),
"Output bag file (overrides --prefix)")
38 (
"topic", po::value<std::vector<std::string>>()->required(),
"Topics to record")
39 (
"queue-size", po::value<std::string>()->value_name(
"SIZE")->default_value(
"500MB"),
"Queue size")
40 (
"delete-old-at", po::value<std::string>()->value_name(
"SIZE"),
"Delete old bags at given size, e.g. 100GB or 1TB")
41 (
"split-bag-size", po::value<std::string>()->value_name(
"SIZE"),
"Bag size for splitting, e.g. 1GB")
42 (
"paused",
"Start paused")
43 (
"no-ui",
"Disable terminal UI")
44 (
"udp",
"Subscribe using UDP transport")
45 (
"bz2",
"Enable BZ2 compression")
46 (
"lz4",
"Enable LZ2 compression")
49 po::positional_options_description p;
53 std::cout <<
"Usage: rosbag_fancy record [options] -o <bag file> <topics...>\n\n";
54 std::cout << desc <<
"\n\n";
55 std::cout <<
"Topics may be annotated with a rate limit in Hz, e.g.:\n";
56 std::cout <<
" rosbag_fancy /camera/image_raw=10.0\n";
63 po::command_line_parser(options).options(desc).positional(p).
run(),
77 std::cerr <<
"Could not parse arguments: " << e.what() <<
"\n\n";
85 std::vector<std::string> topics = vm[
"topic"].as<std::vector<std::string>>();
86 std::sort(topics.begin(), topics.end());
89 for(
auto& topicSpec : topics)
91 std::string name = topicSpec;
92 float rateLimit = 0.0f;
94 auto sepIdx = topicSpec.find(
'=');
96 if(sepIdx != std::string::npos)
98 name = topicSpec.substr(0, sepIdx);
102 rateLimit = boost::lexical_cast<float>(topicSpec.substr(sepIdx+1));
104 catch(boost::bad_lexical_cast&)
106 std::cerr <<
"Bad topic spec: '" << topicSpec <<
"'\n";
115 topicManager.
addTopic(name, rateLimit, flags);
123 std::string bagName =
"";
124 if(vm.count(
"output"))
126 bagName = vm[
"output"].as<std::string>();
131 bagName = vm[
"prefix"].as<std::string>();
135 std::uint64_t splitBagSizeInBytes = 0;
136 if(vm.count(
"split-bag-size"))
141 std::uint64_t deleteOldAtInBytes = 0;
142 if(vm.count(
"delete-old-at"))
145 if(splitBagSizeInBytes != 0 && deleteOldAtInBytes < splitBagSizeInBytes)
147 ROSFMT_WARN(
"Chosen split-bag-size is larger than delete-old-at size!");
153 ROSFMT_INFO(
"Waiting for ros::Time to become valid...");
157 BagWriter writer{queue, bagName, namingMode, splitBagSizeInBytes, deleteOldAtInBytes};
159 if(vm.count(
"bz2") && vm.count(
"lz4"))
161 fmt::print(stderr,
"Options --bz2 and --lz4 are mutually exclusive\n");
177 ROSFMT_ERROR(
"Could not open output bag file: {}", e.what());
184 ros::ServiceServer srv_start = nh.advertiseService(
"start", boost::function<
bool(std_srvs::TriggerRequest&, std_srvs::TriggerResponse&)>([&](
auto&,
auto& resp){
185 resp.success =
start();
188 ros::ServiceServer srv_stop = nh.advertiseService(
"stop", boost::function<
bool(std_srvs::TriggerRequest&, std_srvs::TriggerResponse&)>([&](
auto&,
auto& resp){
199 StatusPtr msg = boost::make_shared<Status>();
202 msg->status = writer.running() ? Status::STATUS_RUNNING : Status::STATUS_PAUSED;
204 msg->bagfile = writer.bagfileName();
206 msg->bytes = writer.sizeInBytes();
207 msg->free_bytes = writer.freeSpace();
210 auto& counts = writer.messageCounts();
212 for(
auto& topic : topicManager.
topics())
214 msg->topics.emplace_back();
215 auto& topicMsg = msg->topics.back();
217 msg->bandwidth += topic.bandwidth;
219 topicMsg.name = topic.name;
220 topicMsg.publishers = topic.numPublishers;
221 topicMsg.bandwidth = topic.bandwidth;
222 topicMsg.bytes = topic.totalBytes;
223 topicMsg.messages = topic.totalMessages;
225 if(topic.id < counts.size())
226 topicMsg.messages_in_current_bag = counts[topic.id];
228 topicMsg.rate = topic.messageRateAt(now);
235 if(vm.count(
"paused") == 0)
243 std::unique_ptr<UI> ui;
245 if(!vm.count(
"no-ui"))
246 ui.reset(
new UI{topicManager, queue, writer});