ulog_parser.cpp
Go to the documentation of this file.
1 #include "ulog_parser.h"
2 #include "ulog_messages.h"
3 
4 #include <fstream>
5 #include <string.h>
6 #include <iosfwd>
7 #include <sstream>
8 #include <iomanip>
9 #include <QDebug>
10 
11 using ios = std::ios;
12 
13 
14 
15 ULogParser::ULogParser(const std::string& filename) : _file_start_time(0)
16 {
17 
18  DataStream datastream;
19 
20  {
21  std::ifstream file(filename, std::ifstream::in);
22  if (!file.is_open())
23  {
24  throw std::runtime_error("ULog: Failed to open replay file");
25  }
26 
27  file.seekg(0, std::ios::end); // go to the end
28  long length = file.tellg();
29  file.seekg(0, std::ios::beg);
30 
31  datastream.data.resize(length);
32  file.read( &datastream.data[0], length);
33  }
34 
35  bool ret = readFileHeader(datastream);
36 
37  if (!ret)
38  {
39  throw std::runtime_error("ULog: wrong header");
40  }
41 
42  if (!readFileDefinitions(datastream))
43  {
44  throw std::runtime_error("ULog: error loading definitions");
45  }
46 
47  datastream.offset = _data_section_start;
48 
49  while (datastream)
50  {
51  ulog_message_header_s message_header;
52  datastream.read((char*)&message_header, ULOG_MSG_HEADER_LEN);
53 
54  _read_buffer.reserve(message_header.msg_size + 1);
55  char* message = (char*)_read_buffer.data();
56  datastream.read(message, message_header.msg_size);
57  message[message_header.msg_size] = '\0';
58 
59  switch (message_header.msg_type)
60  {
62  Subscription sub;
63 
64  sub.multi_id = *reinterpret_cast<uint8_t*>(message);
65  sub.msg_id = *reinterpret_cast<uint16_t*>(message + 1);
66  message += 3;
67  sub.message_name.assign(message, message_header.msg_size - 3);
68 
69  const auto it = _formats.find(sub.message_name);
70  if (it != _formats.end())
71  {
72  sub.format = &it->second;
73  }
74  _subscriptions.insert({ sub.msg_id, sub });
75 
76  if (sub.multi_id > 0)
77  {
79  }
80 
81  // printf("ADD_LOGGED_MSG: %d %d %s\n", sub.msg_id, sub.multi_id, sub.message_name.c_str() );
82  // std::cout << std::endl;
83  }
84  break;
86  printf("REMOVE_LOGGED_MSG\n");
87  {
88  uint16_t msg_id = *reinterpret_cast<uint16_t*>(message);
89  _subscriptions.erase(msg_id);
90  }
91  break;
92  case (int)ULogMessageType::DATA: {
93  uint16_t msg_id = *reinterpret_cast<uint16_t*>(message);
94  message += 2;
95  auto sub_it = _subscriptions.find(msg_id);
96  if (sub_it == _subscriptions.end())
97  {
98  continue;
99  }
100  const Subscription& sub = sub_it->second;
101 
102  parseDataMessage(sub, message);
103  }
104  break;
105 
106  case (int)ULogMessageType::LOGGING: {
107  MessageLog msg;
108  msg.level = static_cast<char>(message[0]);
109  message += sizeof(char);
110  msg.timestamp = *reinterpret_cast<uint64_t*>(message);
111  message += sizeof(uint64_t);
112  msg.msg.assign(message, message_header.msg_size - 9);
113  // printf("LOG %c (%ld): %s\n", msg.level, msg.timestamp, msg.msg.c_str() );
114  _message_logs.push_back(std::move(msg));
115  }
116  break;
117  case (int)ULogMessageType::SYNC: // printf("SYNC\n" );
118  break;
119  case (int)ULogMessageType::DROPOUT: // printf("DROPOUT\n" );
120  break;
121  case (int)ULogMessageType::INFO: // printf("INFO\n" );
122  break;
123  case (int)ULogMessageType::INFO_MULTIPLE: // printf("INFO_MULTIPLE\n" );
124  break;
125  case (int)ULogMessageType::PARAMETER:
126  printf("PARAMETER changed at run-time. Ignored\n");
127  std::cout << std::flush;
128  break;
129  }
130  }
131 }
132 
134 {
135  size_t other_fields_count = 0;
136  std::string ts_name = sub.message_name;
137 
138  for (const auto& field : sub.format->fields)
139  {
140  if (field.type == OTHER)
141  {
142  other_fields_count++;
143  }
144  }
145 
146  if (_message_name_with_multi_id.count(ts_name) > 0)
147  {
148  char buff[16];
149  sprintf(buff, ".%02d", sub.multi_id);
150  ts_name += std::string(buff);
151  }
152 
153  // get the timeseries or create if if it doesn't exist
154  auto ts_it = _timeseries.find(ts_name);
155  if (ts_it == _timeseries.end())
156  {
157  ts_it = _timeseries.insert({ ts_name, createTimeseries(sub.format) }).first;
158  }
159  Timeseries& timeseries = ts_it->second;
160 
161  uint64_t time_val = *reinterpret_cast<uint64_t*>(message);
162  timeseries.timestamps.push_back(time_val);
163  message += sizeof(uint64_t);
164 
165  size_t index = 0;
166  parseSimpleDataMessage(timeseries, sub.format, message, &index);
167 }
168 
169 char* ULogParser::parseSimpleDataMessage(Timeseries& timeseries, const Format* format, char* message, size_t* index)
170 {
171  for (const auto& field : format->fields)
172  {
173  // skip _padding messages which are one byte in size
174  if (StringView(field.field_name).starts_with("_padding"))
175  {
176  message += field.array_size;
177  continue;
178  }
179 
180  for (int array_pos = 0; array_pos < field.array_size; array_pos++)
181  {
182  double value = 0;
183  switch (field.type)
184  {
185  case UINT8: {
186  value = static_cast<double>(*reinterpret_cast<uint8_t*>(message));
187  message += 1;
188  }
189  break;
190  case INT8: {
191  value = static_cast<double>(*reinterpret_cast<int8_t*>(message));
192  message += 1;
193  }
194  break;
195  case UINT16: {
196  value = static_cast<double>(*reinterpret_cast<uint16_t*>(message));
197  message += 2;
198  }
199  break;
200  case INT16: {
201  value = static_cast<double>(*reinterpret_cast<int16_t*>(message));
202  message += 2;
203  }
204  break;
205  case UINT32: {
206  value = static_cast<double>(*reinterpret_cast<uint32_t*>(message));
207  message += 4;
208  }
209  break;
210  case INT32: {
211  value = static_cast<double>(*reinterpret_cast<int32_t*>(message));
212  message += 4;
213  }
214  break;
215  case UINT64: {
216  value = static_cast<double>(*reinterpret_cast<uint64_t*>(message));
217  message += 8;
218  }
219  break;
220  case INT64: {
221  value = static_cast<double>(*reinterpret_cast<int64_t*>(message));
222  message += 8;
223  }
224  break;
225  case FLOAT: {
226  value = static_cast<double>(*reinterpret_cast<float*>(message));
227  message += 4;
228  }
229  break;
230  case DOUBLE: {
231  value = (*reinterpret_cast<double*>(message));
232  message += 8;
233  }
234  break;
235  case CHAR: {
236  value = static_cast<double>(*reinterpret_cast<char*>(message));
237  message += 1;
238  }
239  break;
240  case BOOL: {
241  value = static_cast<double>(*reinterpret_cast<bool*>(message));
242  message += 1;
243  }
244  break;
245  case OTHER: {
246  // recursion!!!
247  auto child_format = _formats.at(field.other_type_ID);
248  message += sizeof(uint64_t); // skip timestamp
249  message = parseSimpleDataMessage(timeseries, &child_format, message, index);
250  }
251  break;
252 
253  } // end switch
254 
255  if (field.type != OTHER)
256  {
257  timeseries.data[(*index)++].second.push_back(value);
258  }
259  } // end for
260  }
261  return message;
262 }
263 
264 const std::map<std::string, ULogParser::Timeseries>& ULogParser::getTimeseriesMap() const
265 {
266  return _timeseries;
267 }
268 
269 const std::vector<ULogParser::Parameter>& ULogParser::getParameters() const
270 {
271  return _parameters;
272 }
273 
274 const std::map<std::string, std::string>& ULogParser::getInfo() const
275 {
276  return _info;
277 }
278 
279 const std::vector<ULogParser::MessageLog>& ULogParser::getLogs() const
280 {
281  return _message_logs;
282 }
283 
284 bool ULogParser::readSubscription(DataStream& datastream, uint16_t msg_size)
285 {
286  _read_buffer.reserve(msg_size + 1);
287  char* message = (char*)_read_buffer.data();
288 
289  datastream.read(message, msg_size);
290  message[msg_size] = 0;
291 
292  if (!datastream)
293  {
294  return false;
295  }
296 
297  return true;
298 }
299 
301 {
302  size_t count = 0;
303  for (const auto& field : format.fields)
304  {
305  if (field.type == OTHER)
306  {
307  // recursion!
308  count += fieldsCount(_formats.at(field.other_type_ID));
309  }
310  else
311  {
312  count += size_t(field.array_size);
313  }
314  }
315  return count;
316 }
317 
318 std::vector<StringView> ULogParser::splitString(const StringView& strToSplit, char delimeter)
319 {
320  std::vector<StringView> splitted_strings;
321  splitted_strings.reserve(4);
322 
323  size_t pos = 0;
324  while (pos < strToSplit.size())
325  {
326  size_t new_pos = strToSplit.find_first_of(delimeter, pos);
327  if (new_pos == std::string::npos)
328  {
329  new_pos = strToSplit.size();
330  }
331  StringView sv = { &strToSplit.data()[pos], new_pos - pos };
332  splitted_strings.push_back(sv);
333  pos = new_pos + 1;
334  }
335  return splitted_strings;
336 }
337 
339 {
340  ulog_file_header_s msg_header;
341  datastream.read((char*)&msg_header, sizeof(msg_header));
342 
343  if (!datastream)
344  {
345  return false;
346  }
347 
348  _file_start_time = msg_header.timestamp;
349 
350  // verify it's an ULog file
351  char magic[8];
352  magic[0] = 'U';
353  magic[1] = 'L';
354  magic[2] = 'o';
355  magic[3] = 'g';
356  magic[4] = 0x01;
357  magic[5] = 0x12;
358  magic[6] = 0x35;
359  return memcmp(magic, msg_header.magic, 7) == 0;
360 }
361 
363 {
364  ulog_message_header_s message_header;
365 
366  while (true)
367  {
368  qDebug() <<"\n" << datastream.offset;
369  datastream.read((char*)&message_header, ULOG_MSG_HEADER_LEN);
370  qDebug() << message_header.msg_size;
371  qDebug() << datastream.offset;
372 
373  if (!datastream)
374  {
375  return false;
376  }
377 
378  switch (message_header.msg_type)
379  {
380  case (int)ULogMessageType::FLAG_BITS:
381  if (!readFlagBits(datastream, message_header.msg_size))
382  {
383  return false;
384  }
385  break;
386 
387  case (int)ULogMessageType::FORMAT:
388  if (!readFormat(datastream, message_header.msg_size))
389  {
390  return false;
391  }
392 
393  break;
394 
395  case (int)ULogMessageType::PARAMETER:
396  if (!readParameter(datastream, message_header.msg_size))
397  {
398  return false;
399  }
400 
401  break;
402 
405  return true;
406  }
407 
408  case (int)ULogMessageType::INFO: {
409  if (!readInfo(datastream, message_header.msg_size))
410  {
411  return false;
412  }
413  }
414  break;
415  case (int)ULogMessageType::INFO_MULTIPLE: // skip
416  datastream.offset += message_header.msg_size;
417  break;
418 
419  default:
420  printf("unknown log definition type %i, size %i (offset %i)",
421  (int)message_header.msg_type,
422  (int)message_header.msg_size,
423  (int)datastream.offset);
424  datastream.offset += message_header.msg_size;
425  break;
426  }
427  }
428  return true;
429 }
430 
431 bool ULogParser::readFlagBits(DataStream& datastream, uint16_t msg_size)
432 {
433  if (msg_size != 40)
434  {
435  printf("unsupported message length for FLAG_BITS message (%i)", msg_size);
436  return false;
437  }
438 
439  _read_buffer.reserve(msg_size);
440  uint8_t* message = (uint8_t*)_read_buffer.data();
441  datastream.read((char*)message, msg_size);
442 
443  // uint8_t *compat_flags = message;
444  uint8_t* incompat_flags = message + 8;
445 
446  // handle & validate the flags
447  bool contains_appended_data = incompat_flags[0] & ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK;
448  bool has_unknown_incompat_bits = false;
449 
450  if (incompat_flags[0] & ~0x1)
451  {
452  has_unknown_incompat_bits = true;
453  }
454 
455  for (int i = 1; i < 8; ++i)
456  {
457  if (incompat_flags[i])
458  {
459  has_unknown_incompat_bits = true;
460  }
461  }
462 
463  if (has_unknown_incompat_bits)
464  {
465  printf("Log contains unknown incompat bits set. Refusing to parse");
466  return false;
467  }
468 
469  if (contains_appended_data)
470  {
471  uint64_t appended_offsets[3];
472  memcpy(appended_offsets, message + 16, sizeof(appended_offsets));
473 
474  if (appended_offsets[0] > 0)
475  {
476  // the appended data is currently only used for hardfault dumps, so it's safe to ignore it.
477  // LOG_INFO("Log contains appended data. Replay will ignore this data" );
478  _read_until_file_position = appended_offsets[0];
479  }
480  }
481  return true;
482 }
483 
484 bool ULogParser::readFormat(DataStream& datastream, uint16_t msg_size)
485 {
486  static int count = 0;
487 
488  _read_buffer.reserve(msg_size + 1);
489  char* buffer = (char*)_read_buffer.data();
490  datastream.read(buffer, msg_size);
491  buffer[msg_size] = 0;
492 
493  if (!datastream)
494  {
495  return false;
496  }
497 
498  std::string str_format(buffer);
499  size_t pos = str_format.find(':');
500 
501  if (pos == std::string::npos)
502  {
503  return false;
504  }
505 
506  std::string name = str_format.substr(0, pos);
507  std::string fields = str_format.substr(pos + 1);
508 
509  Format format;
510  auto fields_split = splitString(fields, ';');
511  format.fields.reserve(fields_split.size());
512  for (auto field_section : fields_split)
513  {
514  auto field_pair = splitString(field_section, ' ');
515  auto field_type = field_pair.at(0);
516  auto field_name = field_pair.at(1);
517 
518  Field field;
519  if (field_type.starts_with("int8_t"))
520  {
521  field.type = INT8;
522  field_type.remove_prefix(6);
523  }
524  else if (field_type.starts_with("int16_t"))
525  {
526  field.type = INT16;
527  field_type.remove_prefix(7);
528  }
529  else if (field_type.starts_with("int32_t"))
530  {
531  field.type = INT32;
532  field_type.remove_prefix(7);
533  }
534  else if (field_type.starts_with("int64_t"))
535  {
536  field.type = INT64;
537  field_type.remove_prefix(7);
538  }
539  else if (field_type.starts_with("uint8_t"))
540  {
541  field.type = UINT8;
542  field_type.remove_prefix(7);
543  }
544  else if (field_type.starts_with("uint16_t"))
545  {
546  field.type = UINT16;
547  field_type.remove_prefix(8);
548  }
549  else if (field_type.starts_with("uint32_t"))
550  {
551  field.type = UINT32;
552  field_type.remove_prefix(8);
553  }
554  else if (field_type.starts_with("uint64_t"))
555  {
556  field.type = UINT64;
557  field_type.remove_prefix(8);
558  }
559  else if (field_type.starts_with("double"))
560  {
561  field.type = DOUBLE;
562  field_type.remove_prefix(6);
563  }
564  else if (field_type.starts_with("float"))
565  {
566  field.type = FLOAT;
567  field_type.remove_prefix(5);
568  }
569  else if (field_type.starts_with("bool"))
570  {
571  field.type = BOOL;
572  field_type.remove_prefix(4);
573  }
574  else if (field_type.starts_with("char"))
575  {
576  field.type = CHAR;
577  field_type.remove_prefix(4);
578  }
579  else
580  {
581  field.type = OTHER;
582 
583  if (field_type.ends_with("]"))
584  {
585  StringView helper = field_type;
586  while (!helper.ends_with("["))
587  {
588  helper.remove_suffix(1);
589  }
590 
591  helper.remove_suffix(1);
592  field.other_type_ID = helper.to_string();
593 
594  while (!field_type.starts_with("["))
595  {
596  field_type.remove_prefix(1);
597  }
598  }
599  else
600  {
601  field.other_type_ID = field_type.to_string();
602  }
603  }
604 
605  field.array_size = 1;
606 
607  if (field_type.size() > 0 && field_type[0] == '[')
608  {
609  field_type.remove_prefix(1);
610  field.array_size = field_type[0] - '0';
611  field_type.remove_prefix(1);
612 
613  while (field_type[0] != ']')
614  {
615  field.array_size = 10 * field.array_size + field_type[0] - '0';
616  field_type.remove_prefix(1);
617  }
618  }
619 
620  if (field.type == UINT64 && field_name == StringView("timestamp"))
621  {
622  // skip
623  }
624  else
625  {
626  field.field_name = field_name.to_string();
627  format.fields.push_back(field);
628  }
629  }
630 
631  format.name = name;
632  _formats[name] = std::move(format);
633 
634  return true;
635 }
636 
637 template <typename T>
638 std::string int_to_hex(T i)
639 {
640  std::stringstream stream;
641  stream << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex << i;
642  return stream.str();
643 }
644 
645 bool ULogParser::readInfo(DataStream& datastream, uint16_t msg_size)
646 {
647  _read_buffer.reserve(msg_size);
648  uint8_t* message = (uint8_t*)_read_buffer.data();
649  datastream.read((char*)message, msg_size);
650 
651  if (!datastream)
652  {
653  return false;
654  }
655  uint8_t key_len = message[0];
656  message++;
657  std::string raw_key((char*)message, key_len);
658  message += key_len;
659 
660  auto key_parts = splitString(raw_key, ' ');
661 
662  std::string key = key_parts[1].to_string();
663 
664  std::string value;
665  if (key_parts[0].starts_with("char["))
666  {
667  value = std::string((char*)message, msg_size - key_len - 1);
668  }
669  else if (key_parts[0] == StringView("bool"))
670  {
671  bool val = *reinterpret_cast<const bool*>(key_parts[0].data());
672  value = std::to_string(val);
673  }
674  else if (key_parts[0] == StringView("uint8_t"))
675  {
676  uint8_t val = *reinterpret_cast<const uint8_t*>(key_parts[0].data());
677  value = std::to_string(val);
678  }
679  else if (key_parts[0] == StringView("int8_t"))
680  {
681  int8_t val = *reinterpret_cast<const int8_t*>(key_parts[0].data());
682  value = std::to_string(val);
683  }
684  else if (key_parts[0] == StringView("uint16_t"))
685  {
686  uint16_t val = *reinterpret_cast<const uint16_t*>(key_parts[0].data());
687  value = std::to_string(val);
688  }
689  else if (key_parts[0] == StringView("int16_t"))
690  {
691  int16_t val = *reinterpret_cast<const int16_t*>(key_parts[0].data());
692  value = std::to_string(val);
693  }
694  else if (key_parts[0] == StringView("uint32_t"))
695  {
696  uint32_t val = *reinterpret_cast<const uint32_t*>(key_parts[0].data());
697  if (key_parts[1].starts_with("ver_") && key_parts[1].ends_with("_release"))
698  {
699  value = int_to_hex(val);
700  }
701  else
702  {
703  value = std::to_string(val);
704  }
705  }
706  else if (key_parts[0] == StringView("int32_t"))
707  {
708  int32_t val = *reinterpret_cast<const int32_t*>(key_parts[0].data());
709  value = std::to_string(val);
710  }
711  else if (key_parts[0] == StringView("float"))
712  {
713  float val = *reinterpret_cast<const float*>(key_parts[0].data());
714  value = std::to_string(val);
715  }
716  else if (key_parts[0] == StringView("double"))
717  {
718  double val = *reinterpret_cast<const double*>(key_parts[0].data());
719  value = std::to_string(val);
720  }
721  else if (key_parts[0] == StringView("uint64_t"))
722  {
723  uint64_t val = *reinterpret_cast<const uint64_t*>(key_parts[0].data());
724  value = std::to_string(val);
725  }
726  else if (key_parts[0] == StringView("int64_t"))
727  {
728  int64_t val = *reinterpret_cast<const int64_t*>(key_parts[0].data());
729  value = std::to_string(val);
730  }
731 
732  _info.insert({ key, value });
733  return true;
734 }
735 
736 bool ULogParser::readParameter(DataStream& datastream, uint16_t msg_size)
737 {
738  _read_buffer.reserve(msg_size);
739  uint8_t* message = (uint8_t*)_read_buffer.data();
740  datastream.read((char*)message, msg_size);
741 
742  if (!datastream)
743  {
744  return false;
745  }
746 
747  uint8_t key_len = message[0];
748  std::string key((char*)message + 1, key_len);
749 
750  size_t pos = key.find(' ');
751 
752  if (pos == std::string::npos)
753  {
754  return false;
755  }
756 
757  std::string type = key.substr(0, pos);
758 
759  Parameter param;
760  param.name = key.substr(pos + 1);
761 
762  if (type == "int32_t")
763  {
764  param.value.val_int = *reinterpret_cast<int32_t*>(message + 1 + key_len);
765  param.val_type = INT32;
766  }
767  else if (type == "float")
768  {
769  param.value.val_real = *reinterpret_cast<float*>(message + 1 + key_len);
770  param.val_type = FLOAT;
771  }
772  else
773  {
774  throw std::runtime_error("unknown parameter type");
775  }
776  _parameters.push_back(param);
777  return true;
778 }
779 
781 {
782  std::function<void(const Format& format, const std::string& prefix)> appendVector;
783 
784  Timeseries timeseries;
785 
786  appendVector = [&appendVector, this, &timeseries](const Format& format, const std::string& prefix) {
787  for (const auto& field : format.fields)
788  {
789  // skip padding messages
790  if (StringView(field.field_name).starts_with("_padding"))
791  {
792  continue;
793  }
794 
795  std::string new_prefix = prefix + "/" + field.field_name;
796  for (int i = 0; i < field.array_size; i++)
797  {
798  std::string array_suffix = "";
799  if (field.array_size > 1)
800  {
801  char buff[16];
802  sprintf(buff, ".%02d", i);
803  array_suffix = buff;
804  }
805  if (field.type != OTHER)
806  {
807  timeseries.data.push_back({ new_prefix + array_suffix, std::vector<double>() });
808  }
809  else
810  {
811  appendVector(this->_formats.at(field.other_type_ID), new_prefix + array_suffix);
812  }
813  }
814  }
815  };
816 
817  appendVector(*format, {});
818  return timeseries;
819 }
std::vector< uint64_t > timestamps
Definition: ulog_parser.h:86
const std::vector< MessageLog > & getLogs() const
static int str_format(lua_State *L)
Definition: lstrlib.c:1224
enum MQTTPropertyCodes value
Timeseries createTimeseries(const Format *format)
std::vector< Field > fields
Definition: ulog_parser.h:61
FMT_INLINE std::basic_string< Char > format(const S &format_str, Args &&...args)
Definition: core.h:2081
std::vector< MessageLog > _message_logs
Definition: ulog_parser.h:160
std::streampos _data_section_start
first ADD_LOGGED_MSG message
Definition: ulog_parser.h:142
#define ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK
std::string message_name
Definition: ulog_parser.h:80
bool readParameter(DataStream &datastream, uint16_t msg_size)
uint64_t _file_start_time
Definition: ulog_parser.h:136
std::vector< Parameter > _parameters
Definition: ulog_parser.h:138
std::map< std::string, Timeseries > _timeseries
Definition: ulog_parser.h:154
nonstd::string_view StringView
Definition: ulog_parser.h:11
std::string name
Definition: ulog_parser.h:60
const Format * format
Definition: ulog_parser.h:81
std::ios ios
Definition: ulog_parser.cpp:11
constexpr size_t count()
Definition: core.h:960
std::vector< StringView > splitString(const StringView &strToSplit, char delimeter)
bool readSubscription(DataStream &datastream, uint16_t msg_size)
std::string int_to_hex(T i)
int64_t _read_until_file_position
read limit if log contains appended data
Definition: ulog_parser.h:144
const std::map< std::string, Timeseries > & getTimeseriesMap() const
ULogParser(const std::string &filename)
Definition: ulog_parser.cpp:15
size_t fieldsCount(const Format &format) const
std::map< std::string, std::string > _info
Definition: ulog_parser.h:150
const char * name
static void field(LexState *ls, ConsControl *cc)
Definition: lparser.c:893
std::vector< char > data
Definition: ulog_parser.h:106
const T & move(const T &v)
Definition: backward.hpp:394
const std::vector< Parameter > & getParameters() const
#define ULOG_MSG_HEADER_LEN
Definition: ulog_messages.h:63
std::vector< uint8_t > _read_buffer
Definition: ulog_parser.h:140
std::set< std::string > _message_name_with_multi_id
Definition: ulog_parser.h:158
void read(char *dst, int len)
Definition: ulog_parser.h:109
FormatType type
Definition: ulog_parser.h:38
char * parseSimpleDataMessage(Timeseries &timeseries, const Format *format, char *message, size_t *index)
bool readInfo(DataStream &datastream, uint16_t msg_size)
bool readFormat(DataStream &datastream, uint16_t msg_size)
std::map< std::string, Format > _formats
Definition: ulog_parser.h:148
union ULogParser::Parameter::@102 value
std::vector< std::pair< std::string, std::vector< double > > > data
Definition: ulog_parser.h:87
void parseDataMessage(const Subscription &sub, char *message)
std::map< uint16_t, Subscription > _subscriptions
Definition: ulog_parser.h:152
bool readFlagBits(DataStream &datastream, uint16_t msg_size)
bool readFileHeader(DataStream &datastream)
bool readFileDefinitions(DataStream &datastream)
std::string field_name
Definition: ulog_parser.h:39
const std::map< std::string, std::string > & getInfo() const
std::string other_type_ID
Definition: ulog_parser.h:40


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48