cmd_info.cpp
Go to the documentation of this file.
1 // Info command
2 // Author: Max Schwarz <max.schwarz@ais.uni-bonn.de>
3 
4 #include <boost/program_options.hpp>
5 
6 #include <iostream>
7 #include <rosfmt/full.h>
8 #include <fmt/chrono.h>
9 
10 #include <chrono>
11 
12 #include "bag_reader.h"
13 #include "mem_str.h"
14 #include "rosbag/stream.h"
15 
16 namespace po = boost::program_options;
17 using namespace rosbag_fancy;
18 
19 int info(const std::vector<std::string>& options)
20 {
21  po::variables_map vm;
22 
23  // Handle CLI arguments
24  {
25  po::options_description desc("Options");
26  desc.add_options()
27  ("help", "Display this help message")
28  ;
29 
30  po::options_description hidden("Hidden");
31  hidden.add_options()
32  ("input", po::value<std::string>()->required(), "Input file")
33  ;
34 
35  po::options_description all("All");
36  all.add(desc).add(hidden);
37 
38  po::positional_options_description p;
39  p.add("input", 1);
40 
41  auto usage = [&](){
42  std::cout << "Usage: rosbag_fancy info [options] <bag file>\n\n";
43  std::cout << desc << "\n\n";
44  };
45 
46  try
47  {
48  po::store(
49  po::command_line_parser(options).options(all).positional(p).run(),
50  vm
51  );
52 
53  if(vm.count("help"))
54  {
55  usage();
56  return 0;
57  }
58 
59  po::notify(vm);
60  }
61  catch(po::error& e)
62  {
63  std::cerr << "Could not parse arguments: " << e.what() << "\n\n";
64  usage();
65  return 1;
66  }
67  }
68 
69  std::string filename = vm["input"].as<std::string>();
70 
71  BagReader reader(filename);
72 
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);
76 
77  // A lot of std::chrono magic to get local/UTC time
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()));
80 
81  std::chrono::seconds startTimeS = std::chrono::duration_cast<std::chrono::seconds>(startTimeC.time_since_epoch());
82  std::time_t startTimeSC(startTimeS.count());
83  std::tm startTimeB;
84  std::tm startTimeBUTC;
85  localtime_r(&startTimeSC, &startTimeB);
86  gmtime_r(&startTimeSC, &startTimeBUTC);
87 
88  std::chrono::seconds endTimeS = std::chrono::duration_cast<std::chrono::seconds>(endTimeC.time_since_epoch());
89  std::time_t endTimeSC(endTimeS.count());
90  std::tm endTimeB;
91  std::tm endTimeBUTC;
92  localtime_r(&endTimeSC, &endTimeB);
93  gmtime_r(&endTimeSC, &endTimeBUTC);
94 
95  std::chrono::nanoseconds duration{(reader.endTime() - reader.startTime()).toNSec()};
96 
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());
101  fmt::print("Size: {}\n", mem_str::memoryToString(reader.size()));
102 
103  auto it = reader.begin();
104  if(it != reader.end())
105  {
106  fmt::print("Compression: ");
107  switch(it.currentChunkCompression())
108  {
109  case rosbag::compression::Uncompressed: fmt::print("Uncompressed\n"); break;
110  case rosbag::compression::BZ2: fmt::print("BZ2\n"); break;
111  case rosbag::compression::LZ4: fmt::print("LZ4\n"); break;
112  default: fmt::print("unknown\n");
113  }
114  }
115 
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);
120 
121  std::size_t maxTypeLength = 0;
122  for(auto& t : types)
123  maxTypeLength = std::max(maxTypeLength, t.first.size());
124 
125  for(auto& t : types)
126  fmt::print(" - {:{}} {}\n", t.first, maxTypeLength, t.second);
127 
128  fmt::print("Topics:\n");
129  std::size_t maxTopicLength = 0;
130  for(auto& topicPair : connectionsForTopic)
131  maxTopicLength = std::max(maxTopicLength, topicPair.first.size());
132 
133  for(auto& topicPair : connectionsForTopic)
134  {
135  std::uint64_t count = 0;
136  std::set<std::string> types;
137  for(auto& conID : topicPair.second)
138  {
139  auto it = reader.connections().find(conID);
140  auto& conn = it->second;
141 
142  types.insert(conn.type);
143 
144  count += conn.totalCount;
145  }
146 
147  fmt::print(" - {:{}} {:8d} msgs: ",
148  topicPair.first, maxTopicLength, count
149  );
150 
151  if(types.size() == 1)
152  fmt::print("{:10}", *types.begin());
153  else
154  fmt::print("{:10}", types);
155 
156  if(topicPair.second.size() > 1)
157  {
158  fmt::print(" ({} connections)",
159  topicPair.second.size()
160  );
161  }
162 
163  fmt::print("\n");
164  }
165 
166  return 0;
167 }
run
void run(class_loader::ClassLoader *loader)
rosbag_fancy
Definition: bag_reader.cpp:240
rosbag::compression::LZ4
LZ4
rosbag::compression::BZ2
BZ2
std::size_t
decltype(sizeof(void *)) typede size_t)
Definition: doctest.h:501
info
int info(const std::vector< std::string > &options)
Definition: cmd_info.cpp:19
rosbag_fancy::mem_str::memoryToString
std::string memoryToString(uint64_t memory)
Definition: mem_str.cpp:15
full.h
rosbag_fancy::BagReader
Definition: bag_reader.h:21
bag_reader.h
rosbag::compression::Uncompressed
Uncompressed
mem_str.h
usage
def usage(progname)
stream.h


rosbag_fancy
Author(s):
autogenerated on Tue Feb 20 2024 03:20:59