CanLab/docs

Reference

The details that do not belong anywhere else.

Log formats

FormatNotes
SavvyCAN CSVGVRET and SavvyCAN exports. Handles both the hex byte format real exports use and older decimal ones, and the trailing comma SavvyCAN writes after the last data byte.
candump .logcandump -l output, including CAN FD lines.
pcap / pcapngLinux SocketCAN, link type 227, via dpkt.
Vector BLFThrough python-can's reader.
Vector ASCThrough python-can's reader.
MDF4 .mf4 / .mdfCANedge and similar. Needs asammdf.
openpilot rlog / qlogPlain, .bz2 or .zst. Needs canlab[openpilot]; the schema ships with CanLab. Frames the panda sent itself are kept apart from the car's traffic.

Every parser produces the same columns, so the rest of the application does not care where a capture came from: Timestamp, ID, Bus, DLC, Extended, B0..B7, plus a per-ID Delta.

Where things live

PathWhat
~/.canlab/plugins/Plugins you have installed.
~/.canlab/opendbc_cache/Cached opendbc index, so matching works offline after the first fetch.
~/.canlab/memory.jsonAI engine memory across sessions.
canlab/sample_data/The bundled sample capture, its generator, and an example seed-key script.
docs/AUDIT_FIXES.mdThe full list of defects fixed in the deep-audit pass, each with a regression test.

Settings

Nine panels: API KEYS, CAN ADAPTERS, VEHICLE, REST API, MCP, BACKEND, MULTI-BUS, PLUGINS and frame cap. The ones you will actually touch are CAN ADAPTERS (add, detect and test your hardware), API KEYS if you want the AI features, MCP to connect an assistant, and PLUGINS to approve anything you have installed. Everything persists across restarts.

Validated against real captures

Separately from the unit suite, the whole application is run end to end over real vehicle recordings, because synthetic data agrees with whatever the code assumes. Two corpora, ninety checks.

CorpusWhat it isChecks
SavvyCAN examples12,974 frames, 180 IDs, 11-bit, one bus36
CANedge recordings and python-can format files2 to 154,896 frames, native MDF4, 11-bit and 29-bit, dual-bus, CAN FD and error frames54

The second corpus is other people's hardware output, none of it produced here: five CANedge logger recordings in native MDF4 from CSS Electronics. They are different kinds of bus: a 145,534-frame J1939 log that is 29-bit end to end, a 22.8-minute two-channel car recording of 154,896 11-bit frames, and a 9,600-frame marine bus that is NMEA 2000. Plus Vector BLF and ASC written by python-can's own writers covering CAN FD, 64-byte FD, error frames and a comma-decimal locale. One real log is then written out in all five formats and read back by every parser, which all have to agree about the same traffic.

A third run pushes the size rather than the variety: the 145,534-frame J1939 truck log and the 154,896-frame two-channel car log are merged into one 300,430-frame capture with 11-bit and 29-bit identifiers on three bus tags, and every stage is timed against a budget. 29 checks, all passing: parsing at 200,912 frames/s, the merged capture into the running window in 8.1 s at 691 MB resident, the frame table refreshing in 65 ms, the sniffer folding the capture in 128 ms, and 145,534 frames written out and read back through five formats with every payload byte equal. Engine speed decodes to 913 to 1762 rpm over 19,584 frames, which is external evidence rather than the code agreeing with itself. That run also found a real defect: the PGN scan crashed on any log carrying an active fault code, and this truck sends 196 of them.

It found defects the older corpus could not reach. The openpilot DBC exporter wrote a bare 29-bit frame id, so every J1939 capture exported a file cantools refuses. The sniffer aged a loaded capture against wall-clock time, so every row expired the moment a file opened. The PGN decoder read the marine bus with J1939 tables and named nothing. All are fixed and pinned by tests. A narrated recording of the run is in the repository as docs/canlab-realdata-validation.mp4.

Testing

The suite runs headless:

QT_QPA_PLATFORM=offscreen python -m pytest -q     # 753 passed

Tests that need an optional dependency skip cleanly when it is absent: the MDF4 importer without asammdf, the transport tests without the MCP SDK, the Lua dissector without a Lua runtime.

It covers the log parsers against fixtures in the real formats, DBC encode and decode round trips through cantools, the ARM TX gate on every transmit path including that disarming mid-run stops a worker, ISO-TP and UDS wire format, DTC and PID decoding, the REST authentication and NaN-safe JSON, and an import smoke test of every tab.

Limitations

  • Not validated on many real vehicles. Signal identification is heuristic. Verify every result before trusting it.
  • ARM TX covers the transmit features, not diagnostic reads. See the gate for exactly which paths it covers.
  • ARXML export is experimental and is not validated against the AUTOSAR schema.
  • openpilot logs need pycapnp (canlab[openpilot]); the schema ships with CanLab.
  • MDF4 needs asammdf.
  • CAN FD is parsed, decoded, injected and replayed end to end, but has been tested on a virtual bus, not on FD hardware.
  • No real ECU. UDS, ISO-TP, security access and OBD-II are tested against scripted responders and independent implementations, not against a vehicle's modules.
  • The gateway needs two hardware channels.
  • The prebuilt binary is Linux x86_64 and unsigned. No macOS or Windows build; run from source there.

Getting help

Bugs and questions belong in the issue tracker. A capture that reproduces the problem helps enormously; the sample format is plain CSV and easy to trim.

Credits

The calibration refinements in core/calibrate_refine.py, sentinel masking and scale snapping, are adapted from CSS Electronics' CAN bus reverse engineering skills (MIT). The OEM checksum algorithms in core/checksums.py follow commaai/opendbc (MIT).

NMEA 2000 definitions are distilled from canboat (Apache 2.0). openpilot logs are read with comma.ai's cereal schema (MIT), and the real-car calibration checks use comma.ai's comma2k19 segment (MIT) and a drive from openpilot's public CI routes. The interoperability tests run against can-isotp, udsoncan and can-j1939 (all MIT).

Built on python-can, cantools, PyQt6, pandas, NumPy and pyqtgraph.