Files
clearpilot/selfdrive/thermald/fan_controller.py
Brian Hanson 1eb8d41454 fix: fan 100% on overheat, FCW fps-aware, commIssue suppress, 10min shutdown
- Fan controller: allow full 100% fan when offroad temp >= 75°C (startup cooling)
- ModelFps memory param: modeld publishes actual FPS (20 or 4) so downstream
  consumers can adjust frame-rate-dependent logic
- Longitudinal planner: dynamically adjusts dt and v_desired_filter based on
  ModelFps; FCW crash_cnt threshold scales with FPS to maintain consistent
  0.15s trigger window at both 20fps and 4fps
- controlsd: suppress commIssue alerts for 2s after lateral control engages
  (FPS transition from 4->20 causes transient freq check failures)
- Shutdown timer: hardcoded to 10 minutes (was 45min via FrogPilot param),
  screen taps reset the countdown via ShutdownTouchReset memory param,
  removed Shutdown Timer UI selector from ClearPilot menu

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

62 lines
2.0 KiB
Python
Executable File

#!/usr/bin/env python3
import os
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
BENCH_MODE = os.environ.get("BENCH_MODE") == "1"
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: bench mode always uses normal onroad fan range (30-100%)
if BENCH_MODE and ignition:
self.controller.neg_limit = -100
self.controller.pos_limit = -30
# CLEARPILOT: at standstill below 74°C, clamp to 0-30% (quiet)
# at standstill above 74°C, allow full 0-100% range
elif ignition and standstill and cur_temp < 74:
self.controller.neg_limit = -30
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 = -15
# CLEARPILOT: offroad but overheating (startup cooling) — full fan range
elif cur_temp >= 75:
self.controller.neg_limit = -100
self.controller.pos_limit = 0
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