Files
opendbc-meb/opendbc/car/logreader.py
Daniel Koepping 80f030ac5d Car diff (#3024)
* Opendbc replay (#6)

* add replay POC

* compare HEAD to master

* split in compare and worker

* copy worker.py

* cleanup

* fix

* apply tesla brake PR

* fix

* fix mutation test

* add panda

* add timestamps

* simplify

* add falling edge

* add remaining carstate

* simple lines

* bump

* rename

* use zst as ref

* ref commit

* cleanup

* formatting

* no failing

* fix git

* clean

* use pool.map

* fix docker build

* clean

* Revert "fix docker build"

This reverts commit da3577441eaa4b7fdc5763f73e779dd32c03a3c3.

* use flat paths

* format

* use azure test instance

* print full diff

* no stderr output

* use GIT_REF

* Revert "apply tesla brake PR"

This reverts commit f377e21f3865c574db5d618be20b4efa86fba66f.

* allow overwrite blobs

* supress stderr

* add error on failed generation (#8)

* Opendbc replay (#129)

* add replay POC

* compare HEAD to master

* split in compare and worker

* copy worker.py

* cleanup

* fix

* apply tesla brake PR

* fix

* fix mutation test

* add panda

* add timestamps

* simplify

* add falling edge

* add remaining carstate

* simple lines

* bump

* rename

* use zst as ref

* ref commit

* cleanup

* formatting

* no failing

* fix git

* clean

* use pool.map

* fix docker build

* clean

* Revert "fix docker build"

This reverts commit da3577441eaa4b7fdc5763f73e779dd32c03a3c3.

* use flat paths

* format

* use azure test instance

* print full diff

* no stderr output

* use GIT_REF

* Revert "apply tesla brake PR"

This reverts commit f377e21f3865c574db5d618be20b4efa86fba66f.

* allow overwrite blobs

* supress stderr

* print upload refs

* add error on failed generation

* Revert "use azure test instance"

This reverts commit ba969ccda452a4841934440d3ced22829861f70f.

* Revert "fix mutation test"

This reverts commit 8f5e01de7743ee38c340df90751cf370634fe2b2.

* detect safety changes

* use logReader

* only use valid platforms

* use local database

* Revert "use local database"

This reverts commit 4ebe9fe0800fb1631efe8672817a8c21b8780b65.

* Reapply "use azure test instance"

This reverts commit e9968a04e4ddee00b69174fd30ee1cdcdfa506fb.

* cutoff diff

* parallel downloads

* enable stderr

* fix interface

* logprint errors

* add comment to PR

* fix

* FORMAT: lines

* FORMAT: plots

* FORMAT: fix

* modules

* Revert "use azure test instance"

This reverts commit ba969ccda452a4841934440d3ced22829861f70f.

* build on forks

* clean

* rename

* replace azure with ci-artifacts

* auto bootstrap

* help

* FORK TEST

* Revert "FORMAT: fix"

This reverts commit 0262b1fad446691d594adef6baf284938d2d115d.

* Revert "FORMAT: plots"

This reverts commit 314417db1fb4c01206d8b3880f240a44d70b5a7e.

* Revert "FORMAT: lines"

This reverts commit 5cdd4c567f0440874a74678ca7cb3b6f909bc0ba.

* clean

* no comment on empty output

* output errors

* fix pr comment

* fix diff more

* increase tolerance

* less files

* one file

* Revert "FORK TEST"

This reverts commit fc691b500c58e76a41c8f5785b6acf89ff4e1573.

* Revert "fix mutation test"

This reverts commit 8f5e01de7743ee38c340df90751cf370634fe2b2.

* fix comment

* fix comment

* move car_diff.py

* Revert "fix mutation test"

This reverts commit 8f5e01de7743ee38c340df90751cf370634fe2b2.

* move car_diff.py

* inline helpers

* inline helpers

* fix ruff

* fix ruff

* use all carstate fields

* add --all

* use all carstate fields

* add --all

* bootstrap

* bootstrap

* Revert "bootstrap"

This reverts commit c3c2ba41e8d1dbdeb74cef8498caf9fd13325fe3.

* add line formatting

* commit workflow

* adjust formatting

* return err

* subprocess

* comma_car_segments

* dead code

* minimal logreader

* remove openpilot

* add deps

* remove all deps

* fix source

* request

* less parallel

* fix push

* bootstrap

* Revert "bootstrap"

This reverts commit b4af0d3bbd31f119ed3f18933329dcc64c9cf634.

* fix graph

* push

* regex

* optimize dict_diff

* reduce tolerance

* use comma_car_segments

* remove

* use requests

* timestamps

* frame_ms

* id

* logreader

* align logreader

* use logreader

* remove requests

* return

* more line

* ruff

* use test pip package

* push on commaai

* use zstandard lib

* clean

* rename

* use decompress

* fix

* index

* lr filter

* union types

* find edges

* group frames

* render waveform

* format timing

* signals

* numeric diff

* boolean diff

* real timestamp

* impreza fingerprint

* Revert "impreza fingerprint"

This reverts commit 692e34c7f8df6540c26eca79799a8eac47f352bc.

* apply tesla brake PR

* honda clear startup fault

* Revert "honda clear startup fault"

This reverts commit 91c4a5d3c896cf0936c5cf00a484127b9665d21c.

* skip unrelated edges

* fix exit

* fix down edge

* use hf pip package

* comment on fail

* fix

* comment

* no exit 1 in CI
2026-01-19 14:31:20 -08:00

68 lines
1.7 KiB
Python

#!/usr/bin/env python3
import os
import capnp
import urllib.parse
import warnings
from urllib.request import urlopen
import zstandard as zstd
from opendbc.car.common.basedir import BASEDIR
capnp_log = capnp.load(os.path.join(BASEDIR, "rlog.capnp"))
def decompress_stream(data: bytes):
dctx = zstd.ZstdDecompressor()
decompressed_data = b""
with dctx.stream_reader(data) as reader:
decompressed_data = reader.read()
return decompressed_data
class LogReader:
def __init__(self, fn, only_union_types=False, sort_by_time=False):
self._only_union_types = only_union_types
_, ext = os.path.splitext(urllib.parse.urlparse(fn).path)
if fn.startswith("http"):
with urlopen(fn) as f:
dat = f.read()
else:
with open(fn, "rb") as f:
dat = f.read()
if ext == ".zst" or dat.startswith(b'\x28\xB5\x2F\xFD'):
# https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#zstandard-frames
dat = decompress_stream(dat)
ents = capnp_log.Event.read_multiple_bytes(dat)
self._ents = []
try:
for e in ents:
self._ents.append(e)
except capnp.KjException:
warnings.warn("Corrupted events detected", RuntimeWarning, stacklevel=1)
if sort_by_time:
self._ents.sort(key=lambda x: x.logMonoTime)
def __iter__(self):
for ent in self._ents:
if self._only_union_types:
try:
ent.which()
yield ent
except capnp.lib.capnp.KjException:
pass
else:
yield ent
def filter(self, msg_type: str):
return (getattr(m, m.which()) for m in filter(lambda m: m.which() == msg_type, self))
def first(self, msg_type: str):
return next(self.filter(msg_type), None)