rosout_log_loader.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2017, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE
21 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28 //
29 // *****************************************************************************
30 
31 #include <QFileDialog>
32 #include <QDir>
33 #include <QDirIterator>
34 
35 #include <fstream>
36 #include <ros/time.h>
37 #include <rosbag/bag.h>
39 #include <time.h>
40 #include <string>
41 
42 namespace swri_console
43 {
44  const int MIN_MSG_SIZE=10;
45 
46  void RosoutLogLoader::loadRosLogDirectory(const QString& logdirectory_name)
47  {
48  QDirIterator it(logdirectory_name, QStringList() << "*.log", QDir::Files);
49  while (it.hasNext())
50  {
51  QString filename = it.next();
52  printf("Loading log file %s ...\n", filename.toStdString().c_str());
53  loadRosLog(filename);
54  }
55  }
56 
57  void RosoutLogLoader::loadRosLog(const QString& logfile_name)
58  {
59  std::string std_string_logfile = logfile_name.toStdString();
60  std::ifstream logfile(std_string_logfile.c_str());
61  int seq = 0;
62  for( std::string line; getline( logfile, line ); )
63  {
64  rosgraph_msgs::Log log;
65  unsigned found = std_string_logfile.find_last_of("/\\");
66  log.name = std_string_logfile.substr(found+1);
67  int result = parseLine(line, seq, &log);
68  if (result == 0)
69  {
70  rosgraph_msgs::LogConstPtr log_ptr(new rosgraph_msgs::Log(log));
71  emit logReceived(log_ptr);
72  }
73  seq++;
74  }
75  emit finishedReading();
76  }
77 
78  int RosoutLogLoader::parseLine(std::string line, int seq, rosgraph_msgs::Log* log)
79  {
80  // Example: 1507066364.728102032 INFO [/home/pwesthart/code/src/mapviz/tile_map/src/tile_map_plugin.cpp:260(TileMapPlugin::PrintInfo) [topics: /rosout] OK
81  char log_msg_fmt0[] = "%d.%d %s [%[^:]:%u(%[^)]) [topics: %[^]]] %[^\n]s";
82  int secs = 0;
83  int nsecs = 0;
84  char level[16];
85  char file[1024];
86  unsigned int line_num = 1;
87  char function[128];
88  char topics[1024];
89  char msg[1024*32];
90  ros::Time stamp;
91 
93  int num_parsed = sscanf(line.c_str(),log_msg_fmt0,&secs, &nsecs, level, file, &line_num, function, topics, msg);
94  if (num_parsed == 8 )
95  {
96  // Populate new log message
97  log->file = file;
98  log->function = function;
99  log->header.seq = seq;
100  stamp.sec = secs;
101  stamp.nsec = nsecs;
102  log->header.stamp = stamp;
103  log->level = level_string_to_level_type(std::string(level));
104  log->line = line_num;
105  log->msg = msg;
106  }
107  else // try another format
108  {
109  char log_msg_fmt1[] = "%d.%d %s [%[^:]:%u(%[^)])) [topics: %[^]]] %[^\n]s";
110  num_parsed = sscanf(line.c_str(), log_msg_fmt1, &secs, &nsecs, level, file, &line_num, function, topics, msg);
111  if (num_parsed == 8 )
112  {
113  // Populate new log message
114  log->file = file;
115  log->function = function;
116  log->header.seq = seq;
117  stamp.sec = secs;
118  stamp.nsec = nsecs;
119  log->header.stamp = stamp;
120  log->level = level_string_to_level_type(std::string(level));
121  log->line = line_num;
122  log->msg = msg;
123  }
124  else // try another format
125  {
126  // Example: [rospy.registration][INFO] 2017-11-30 08:11:39,231: registering subscriber topic [/tf] type [tf2_msgs/TFMessage] with master
127  char log_msg_fmt2[] = "[%[^]]][%[^]]] %d-%d-%d %d:%d:%d,%d: %[^\n]s";
128  int year;
129  int month;
130  int day;
131  int hour;
132  int minute;
133  int msecs;
134  char name[1024];
135  time_t rawtime;
136  struct tm * timeinfo;
137 
138  num_parsed = sscanf(line.c_str(), log_msg_fmt2, name, level, &year, &month, &day, &hour, &minute, &secs, &msecs, msg);
139  if (num_parsed == 10)
140  {
141  // Populate new log message
142  file[0] = 0;
143  function[0] = 0;
144  line_num = 0;
145  time ( &rawtime );
146  timeinfo = localtime ( &rawtime );
147  timeinfo->tm_year = year - 1900;
148  timeinfo->tm_mon = month - 1;
149  timeinfo->tm_mday = day;
150  timeinfo->tm_hour = hour;
151  timeinfo->tm_min = minute;
152  timeinfo->tm_sec = secs;
153  rawtime = mktime ( timeinfo );
154  secs = rawtime;
155  nsecs = msecs * 1000000;
156  log->file = file;
157  log->function = function;
158  log->header.seq = seq;
159  stamp.sec = secs;
160  stamp.nsec = nsecs;
161  log->header.stamp = stamp;
162  log->level = level_string_to_level_type(std::string(level));
163  log->line = line_num;
164  log->msg = msg;
165  }
166  else
167  {
168  // Example: [ INFO] [1512051098.518631473]: Read parameter lower_cost_threshold = 0.000000
169  char log_msg_fmt3[] = "\x1b[%dm[ %[^]]] [%d.%d]: %[^\n\x1b]s";
170 // char log_msg_fmt3[] = "\x1b[%dm[ %[^]]] [%d.%d]]%[^\n]";
171  int ansi_color;
172  msg[0] = 0;
173  num_parsed = sscanf(line.c_str(), log_msg_fmt3, &ansi_color, level, &secs, &nsecs, msg);
174  if (num_parsed == 5)
175  {
176  // Populate new log message
177  file[0] = 0;
178  function[0] = 0;
179  line_num = 0;
180  log->file = file;
181  log->function = function;
182  log->header.seq = seq;
183  stamp.sec = secs;
184  stamp.nsec = nsecs;
185  log->header.stamp = stamp;
186  log->level = level_string_to_level_type(std::string(level));
187  log->line = line_num;
188  log->msg = msg;
189  }
190  else
191  {
192  // Example: [ WARN] [1512051107.153917534, 1507066358.521849475]: Offset change exceeds limit! reduce from 0.814476 to 0.500000
193  char log_msg_fmt4[] = "\x1b[%dm[ %[^]]] [%d.%d, %d.%d]: %[^\n\x1b]";
194  int secs2;
195  int nsecs2;
196  msg[0] = 0;
197  num_parsed = sscanf(line.c_str(), log_msg_fmt4, &ansi_color, level, &secs, &nsecs, &secs2, &nsecs2, msg);
198  if (num_parsed == 7)
199  {
200  // Populate new log message
201  file[0] = 0;
202  function[0] = 0;
203  line_num = 0;
204  log->file = file;
205  log->function = function;
206  log->header.seq = seq;
207  stamp.sec = secs;
208  stamp.nsec = nsecs;
209  log->header.stamp = stamp;
210  log->level = level_string_to_level_type(std::string(level));
211  log->line = line_num;
212  log->msg = msg;
213  }
214  else // Couldn't parse with known formats
215  {
216  if (line.length() < MIN_MSG_SIZE)
217  {
218  return -1;
219  }
220  log->file = std::string("");
221  log->function = std::string("");
222  log->header.seq = seq;
223  stamp.sec = 0;
224  stamp.nsec = 0;
225  log->header.stamp = stamp;
226  log->level = level_string_to_level_type(std::string("DEBUG"));
227  log->line = 0;
228  log->msg = line;
229  log->name = log->name + "-unparsed";
230  }
231  }
232  }
233  }
234  }
235  return 0;
236  }
237 
238  rosgraph_msgs::Log::_level_type RosoutLogLoader::level_string_to_level_type(std::string level_str)
239  {
240  if (level_str.compare("FATAL") == 0)
241  {
242  return rosgraph_msgs::Log::FATAL;
243  }
244  if (level_str.compare("ERROR") == 0)
245  {
246  return rosgraph_msgs::Log::ERROR;
247  }
248  if (level_str.compare("WARN") == 0)
249  {
250  return rosgraph_msgs::Log::WARN;
251  }
252  if (level_str.compare("INFO") == 0)
253  {
254  return rosgraph_msgs::Log::INFO;
255  }
256  return rosgraph_msgs::Log::DEBUG;
257  }
258 
259 
261  {
262  QString filename = QFileDialog::getOpenFileName(NULL,
263  tr("Open ROS Log File"),
264  QDir::homePath(),
265  tr("Log Files (*.log)"));
266 
267  if (filename != NULL)
268  {
269  loadRosLog(filename);
270  }
271  }
272 
274  {
275  QString dirname = QFileDialog::getExistingDirectory(NULL,
276  tr("Open directory containing log files"),
277  QDir::homePath());
278 
279  if (dirname != NULL)
280  {
281  loadRosLogDirectory(dirname);
282  }
283  }
284 
285 
286 }
void loadRosLogDirectory(const QString &logdirectory_name)
rosgraph_msgs::Log::_level_type level_string_to_level_type(std::string level_str)
int parseLine(std::string line, int seq, rosgraph_msgs::Log *log)
void logReceived(const rosgraph_msgs::LogConstPtr &msg)
const int MIN_MSG_SIZE
void loadRosLog(const QString &filename)


swri_console
Author(s):
autogenerated on Fri Apr 3 2020 03:20:03