diff --git a/.github/workflows/repo.yml b/.github/workflows/repo.yml index 5c12fd9..4c4a7c4 100644 --- a/.github/workflows/repo.yml +++ b/.github/workflows/repo.yml @@ -2,7 +2,7 @@ name: repo on: schedule: - - cron: "0 15 * * 2" + - cron: "0 15 1 * *" workflow_dispatch: jobs: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cebce11..03360e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-ast - id: check-yaml @@ -11,7 +11,7 @@ repos: hooks: - id: mypy - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.3 + rev: v0.3.5 hooks: - id: ruff - repo: local diff --git a/Dockerfile b/Dockerfile index 94f9768..d2e3ab5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,8 +35,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ && rm -rf /var/lib/apt/lists/* -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" RUN pip3 install --break-system-packages --no-cache-dir pyyaml Cython scons pycapnp pre-commit ruff parameterized coverage numpy WORKDIR /project/ diff --git a/car.capnp b/car.capnp index 78ef79e..d7ec1b2 100644 --- a/car.capnp +++ b/car.capnp @@ -96,7 +96,6 @@ struct CarEvent @0x9b1657f34caf3ad3 { fanMalfunction @91; cameraMalfunction @92; cameraFrameRate @110; - gpsMalfunction @94; processNotRunning @95; dashcamMode @96; controlsInitializing @98; @@ -116,6 +115,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { locationdPermanentError @118; paramsdTemporaryError @50; paramsdPermanentError @119; + actuatorsApiUnavailable @120; radarCanErrorDEPRECATED @15; communityFeatureDisallowedDEPRECATED @62; @@ -142,6 +142,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { noTargetDEPRECATED @25; brakeUnavailableDEPRECATED @2; plannerErrorDEPRECATED @32; + gpsMalfunctionDEPRECATED @94; } } @@ -154,6 +155,8 @@ struct CarState { # CAN health canValid @26 :Bool; # invalid counter/checksums canTimeout @40 :Bool; # CAN bus dropped out + canErrorCounter @48 :UInt32; + canRcvTimeout @49 :Bool; # car speed vEgo @1 :Float32; # best estimate of speed @@ -219,6 +222,9 @@ struct CarState { fuelGauge @41 :Float32; # battery or fuel tank level from 0.0 to 1.0 charging @43 :Bool; + # process meta + cumLagMs @50 :Float32; + struct WheelSpeeds { # optional wheel speeds fl @0 :Float32; diff --git a/log.capnp b/log.capnp index 1b7c982..269a224 100644 --- a/log.capnp +++ b/log.capnp @@ -198,6 +198,13 @@ struct Thumbnail { frameId @0 :UInt32; timestampEof @1 :UInt64; thumbnail @2 :Data; + encoding @3 :Encoding; + + enum Encoding { + unknown @0; + jpeg @1; + keyframe @2; + } } struct GPSNMEAData { @@ -713,7 +720,6 @@ struct ControlsState @0x97ff69c53601abf1 { engageable @41 :Bool; # can OP be engaged? cumLagMs @15 :Float32; - canErrorCounter @57 :UInt32; lateralControlState :union { indiState @52 :LateralINDIState; @@ -858,6 +864,7 @@ struct ControlsState @0x97ff69c53601abf1 { steeringAngleDesiredDegDEPRECATED @29 :Float32; canMonoTimesDEPRECATED @21 :List(UInt64); desiredCurvatureRateDEPRECATED @62 :Float32; + canErrorCounterDEPRECATED @57 :UInt32; } # All SI units and in device frame diff --git a/messaging/__init__.py b/messaging/__init__.py index ddc0866..a2695bd 100644 --- a/messaging/__init__.py +++ b/messaging/__init__.py @@ -93,20 +93,8 @@ def drain_sock_raw(sock: SubSocket, wait_for_one: bool = False) -> List[bytes]: def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]: """Receive all message currently available on the queue""" - ret: List[capnp.lib.capnp._DynamicStructReader] = [] - while 1: - if wait_for_one and len(ret) == 0: - dat = sock.receive() - else: - dat = sock.receive(non_blocking=True) - - if dat is None: # Timeout hit - break - - dat = log_from_bytes(dat) - ret.append(dat) - - return ret + msgs = drain_sock_raw(sock, wait_for_one=wait_for_one) + return [log_from_bytes(m) for m in msgs] # TODO: print when we drop packets? @@ -180,9 +168,8 @@ class SubMaster: self.ignore_average_freq = [] if ignore_avg_freq is None else ignore_avg_freq self.ignore_alive = [] if ignore_alive is None else ignore_alive self.ignore_valid = [] if ignore_valid is None else ignore_valid - if bool(int(os.getenv("SIMULATION", "0"))): - self.ignore_alive = services - self.ignore_average_freq = services + + self.simulation = bool(int(os.getenv("SIMULATION", "0"))) # if freq and poll aren't specified, assume the max to be conservative assert frequency is None or poll is None, "Do not specify 'frequency' - frequency of the polled service will be used." @@ -253,7 +240,7 @@ class SubMaster: self.valid[s] = msg.valid for s in self.data: - if SERVICE_LIST[s].frequency > 1e-5: + if SERVICE_LIST[s].frequency > 1e-5 and not self.simulation: # alive if delay is within 10x the expected frequency self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) @@ -273,7 +260,10 @@ class SubMaster: self.freq_ok[s] = avg_freq_ok or recent_freq_ok else: self.freq_ok[s] = True - self.alive[s] = True + if self.simulation: + self.alive[s] = self.seen[s] # alive is defined as seen when simulation flag set + else: + self.alive[s] = True def all_alive(self, service_list: Optional[List[str]] = None) -> bool: if service_list is None: diff --git a/services.py b/services.py index f6d5aa5..ed87ced 100755 --- a/services.py +++ b/services.py @@ -18,7 +18,7 @@ class Service: self.decimation = decimation -services: dict[str, tuple] = { +_services: dict[str, tuple] = { # service: (should_log, frequency, qlog decimation (optional)) # note: the "EncodeIdx" packets will still be in the log "gyroscope": (True, 104., 104), @@ -98,7 +98,7 @@ services: dict[str, tuple] = { "customReservedRawData2": (True, 0.), } SERVICE_LIST = {name: Service(new_port(idx), *vals) for - idx, (name, vals) in enumerate(services.items())} + idx, (name, vals) in enumerate(_services.items())} def build_header():