Files
clearpilot/selfdrive/thermald/fan_controller.py
Brian Hanson bf030db9fe modeld standby, fan standstill clamping, log rotation, diagnostic logging
- modeld standby: skip inference at standstill (model stays loaded in GPU),
  ModelStandby param + ModelStandbyTs heartbeat for race-free suppression
- controlsd: suppress commIssue/modeldLagging when ModelStandbyTs < 2s old,
  ignore telemetryd/dashcamd in process_not_running check
- Fan controller: standstill below 74°C clamps to 0-10% (near silent),
  standstill above 74°C allows 0-100%, thermald reads carState.standstill
- Deleter: enforce 4GB quota on /data/log2 session logs, oldest-first cleanup
- Diagnostic logging: steerTempUnavailable and controlsdLagging log to stderr
  with full context (steering angle, torque, speed, remaining time)
- CLAUDE.md: document memory params method name difference (C++ camelCase
  vs Python snake_case)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 01:35:14 -05:00

51 lines
1.6 KiB
Python
Executable File

#!/usr/bin/env python3
from abc import ABC, abstractmethod
from openpilot.common.realtime import DT_TRML
from openpilot.common.numpy_fast import interp
from openpilot.common.swaglog import cloudlog
from openpilot.selfdrive.controls.lib.pid import PIDController
class BaseFanController(ABC):
@abstractmethod
def update(self, cur_temp: float, ignition: bool, standstill: bool = False) -> int:
pass
class TiciFanController(BaseFanController):
def __init__(self) -> None:
super().__init__()
cloudlog.info("Setting up TICI fan handler")
self.last_ignition = False
self.controller = PIDController(k_p=0, k_i=4e-3, k_f=1, rate=(1 / DT_TRML))
def update(self, cur_temp: float, ignition: bool, standstill: bool = False) -> int:
# CLEARPILOT: at standstill below 74°C, clamp to 0-10% (near silent)
# at standstill above 74°C, allow full 0-100% range
if ignition and standstill and cur_temp < 74:
self.controller.neg_limit = -10
self.controller.pos_limit = 0
elif ignition and standstill:
self.controller.neg_limit = -100
self.controller.pos_limit = 0
elif ignition:
self.controller.neg_limit = -100
self.controller.pos_limit = -30
else:
self.controller.neg_limit = -30
self.controller.pos_limit = 0
if ignition != self.last_ignition:
self.controller.reset()
error = 70 - cur_temp
fan_pwr_out = -int(self.controller.update(
error=error,
feedforward=interp(cur_temp, [60.0, 100.0], [0, -100])
))
self.last_ignition = ignition
return fan_pwr_out