4 #include <boost/program_options.hpp>
8 #include <fmt/chrono.h>
16 namespace po = boost::program_options;
19 int info(
const std::vector<std::string>& options)
25 po::options_description desc(
"Options");
27 (
"help",
"Display this help message")
30 po::options_description hidden(
"Hidden");
32 (
"input", po::value<std::string>()->required(),
"Input file")
35 po::options_description all(
"All");
36 all.add(desc).add(hidden);
38 po::positional_options_description p;
42 std::cout <<
"Usage: rosbag_fancy info [options] <bag file>\n\n";
43 std::cout << desc <<
"\n\n";
49 po::command_line_parser(options).options(all).positional(p).
run(),
63 std::cerr <<
"Could not parse arguments: " << e.what() <<
"\n\n";
69 std::string filename = vm[
"input"].as<std::string>();
73 std::map<std::string, std::vector<std::uint32_t>> connectionsForTopic;
74 for(
auto& c : reader.connections())
75 connectionsForTopic[c.second.topicInBag].push_back(c.second.id);
78 std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> startTimeC(std::chrono::nanoseconds(reader.startTime().toNSec()));
79 std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> endTimeC(std::chrono::nanoseconds(reader.endTime().toNSec()));
81 std::chrono::seconds startTimeS = std::chrono::duration_cast<std::chrono::seconds>(startTimeC.time_since_epoch());
82 std::time_t startTimeSC(startTimeS.count());
84 std::tm startTimeBUTC;
85 localtime_r(&startTimeSC, &startTimeB);
86 gmtime_r(&startTimeSC, &startTimeBUTC);
88 std::chrono::seconds endTimeS = std::chrono::duration_cast<std::chrono::seconds>(endTimeC.time_since_epoch());
89 std::time_t endTimeSC(endTimeS.count());
92 localtime_r(&endTimeSC, &endTimeB);
93 gmtime_r(&endTimeSC, &endTimeBUTC);
95 std::chrono::nanoseconds duration{(reader.endTime() - reader.startTime()).toNSec()};
97 fmt::print(
"File: {}\n", filename);
98 fmt::print(
"Start time: {:%Y-%m-%d %H:%M:%S} ({}) / {:%Y-%m-%d %H:%M:%S} (UTC)\n", startTimeB, daylight ? tzname[1] : tzname[0], startTimeBUTC);
99 fmt::print(
"End time: {:%Y-%m-%d %H:%M:%S} ({}) / {:%Y-%m-%d %H:%M:%S} (UTC)\n", endTimeB, daylight ? tzname[1] : tzname[0], endTimeBUTC);
100 fmt::print(
"Duration: {:%H:%M:%S} ({:.2f}s)\n", duration, (reader.endTime() - reader.startTime()).toSec());
103 auto it = reader.begin();
104 if(it != reader.end())
106 fmt::print(
"Compression: ");
107 switch(it.currentChunkCompression())
112 default: fmt::print(
"unknown\n");
116 fmt::print(
"Types:\n");
117 std::map<std::string, std::set<std::string>> types;
118 for(
auto& con : reader.connections())
119 types[con.second.type].insert(con.second.md5sum);
123 maxTypeLength = std::max(maxTypeLength, t.first.size());
126 fmt::print(
" - {:{}} {}\n", t.first, maxTypeLength, t.second);
128 fmt::print(
"Topics:\n");
130 for(
auto& topicPair : connectionsForTopic)
131 maxTopicLength = std::max(maxTopicLength, topicPair.first.size());
133 for(
auto& topicPair : connectionsForTopic)
135 std::uint64_t count = 0;
136 std::set<std::string> types;
137 for(
auto& conID : topicPair.second)
139 auto it = reader.connections().find(conID);
140 auto& conn = it->second;
142 types.insert(conn.type);
144 count += conn.totalCount;
147 fmt::print(
" - {:{}} {:8d} msgs: ",
148 topicPair.first, maxTopicLength, count
151 if(types.size() == 1)
152 fmt::print(
"{:10}", *types.begin());
154 fmt::print(
"{:10}", types);
156 if(topicPair.second.size() > 1)
158 fmt::print(
" ({} connections)",
159 topicPair.second.size()