test_parser.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from pathlib import Path
  2. import pandas as pd
  3. from mlog_tool.constants import MLOG_BEGIN_MSG1, MLOG_BEGIN_MSG2, MLOG_END_MSG
  4. from mlog_tool.models import BusFrame, LogHeader, ParsedLog, PlotTraceSpec
  5. from mlog_tool.parser import MLogParser
  6. from mlog_tool.plotting import LogPlotter
  7. from mlog_tool.utils import normalize_field_name
  8. def test_parser_type_exists() -> None:
  9. parser = MLogParser()
  10. assert parser is not None
  11. def test_message_markers_match_matlab_definition() -> None:
  12. assert MLOG_BEGIN_MSG1 == 0x92
  13. assert MLOG_BEGIN_MSG2 == 0x05
  14. assert MLOG_END_MSG == 0x26
  15. def test_normalize_field_name() -> None:
  16. assert normalize_field_name("timestamp_ms") == "timestamp_ms"
  17. assert normalize_field_name("gyro[0]") == "gyro_0"
  18. assert normalize_field_name(" att roll ") == "att_roll"
  19. def test_parsed_log_parameter_lookup_returns_none_when_missing() -> None:
  20. header = LogHeader(
  21. version=1,
  22. timestamp=0,
  23. max_name_len=16,
  24. max_desc_len=16,
  25. max_model_info_len=16,
  26. description="demo",
  27. model_info="demo",
  28. )
  29. parsed_log = ParsedLog(source_path=Path("demo.bin"), header=header)
  30. assert parsed_log.get_parameter("INS", "acc_bias") is None
  31. def test_parser_can_parse_sample_log() -> None:
  32. parser = MLogParser()
  33. sample_log = Path(__file__).resolve().parents[2] / "mlog16.bin"
  34. parsed_log = parser.parse(sample_log)
  35. assert parsed_log.header.version >= 1
  36. assert len(parsed_log.header.buses) == 48
  37. assert len(parsed_log.header.parameter_groups) == 9
  38. assert len(parsed_log.buses) == 19
  39. assert "IMU0" in parsed_log.buses
  40. assert "GPS" in parsed_log.buses
  41. assert "time_s" in parsed_log.buses["IMU0"].frame.columns
  42. assert parsed_log.get_parameter_group("SYSTEM") is not None
  43. assert parsed_log.get_parameter("SYSTEM", "MAV_SYS_ID") == 2
  44. def test_plotter_can_compare_traces_across_subplots() -> None:
  45. header = LogHeader(
  46. version=1,
  47. timestamp=0,
  48. max_name_len=16,
  49. max_desc_len=16,
  50. max_model_info_len=16,
  51. description="demo",
  52. model_info="demo",
  53. )
  54. frame = pd.DataFrame(
  55. {
  56. "time_s": [0.0, 0.1, 0.2],
  57. "ax": [1.0, 2.0, 3.0],
  58. "ay": [4.0, 5.0, 6.0],
  59. }
  60. )
  61. parsed_log = ParsedLog(
  62. source_path=Path("demo.bin"),
  63. header=header,
  64. buses={
  65. "IMU0": BusFrame(name="IMU0", frame=frame, timestamp_field="time_s"),
  66. "GPS": BusFrame(name="GPS", frame=frame.rename(columns={"ax": "ve", "ay": "vn"}), timestamp_field="time_s"),
  67. },
  68. )
  69. figure = LogPlotter().build_comparison_figure(
  70. parsed_log,
  71. [
  72. [
  73. PlotTraceSpec(bus_name="IMU0", field_name="ax", subplot_index=0, label="IMU0.ax"),
  74. PlotTraceSpec(bus_name="GPS", field_name="ve", subplot_index=0, label="GPS.ve"),
  75. ],
  76. [PlotTraceSpec(bus_name="IMU0", field_name="ay", subplot_index=1, label="IMU0.ay")],
  77. ],
  78. subplot_count=2,
  79. )
  80. assert len(figure.axes) == 2
  81. assert figure.axes[0].get_title() == "Subplot 1"
  82. assert figure.axes[1].get_title() == "Subplot 2"
  83. assert figure.axes[0].get_shared_x_axes().joined(figure.axes[0], figure.axes[1])
  84. assert len(figure._mlog_cursor_payload) == 2
  85. assert len(figure._mlog_cursor_payload[0]["traces"]) == 2
  86. assert len(figure._mlog_cursor_payload[1]["traces"]) == 1