feat: 4Hz fan control with gear/cruise-aware clamps; move hot signals to cereal
Fan control rework (thermald → 4Hz):
- DT_TRML 0.5s → 0.25s (thermald loop + fan PID now at 4Hz)
- New clamp rules based on (gear, cruise_engaged, standstill):
parked → 0-100%
in drive + cruise engaged (any speed) → 30-100%
in drive + cruise off + standstill → 10-100%
in drive + cruise off + moving → 30-100%
- thermald now reads gearShifter (via carState) and controlsState.enabled,
passes them to fan_controller.update()
- Removed BENCH_MODE special case — new rules cover bench automatically
- Removed ignition-based branches — gear is the correct signal
System health overlay:
- Subscribed UI to peripheralState so we can read fanSpeedRpm
- Added FAN row: actual fan% (RPM / 65) to sit alongside LAG/DROP/TEMP/CPU/MEM.
Shows the real fan output vs. what the PID is asking for.
Migrate hot signals from paramsMemory to cereal (frogpilotCarControl):
- Added latRequested @3 and noLatLaneChange @4 to FrogPilotCarControl schema
- controlsd sets FPCC.latRequested / FPCC.noLatLaneChange (send-on-change
already gates the IPC)
- modeld reads from sm['frogpilotCarControl'] (added to its subscribers)
instead of paramsMemory (saves ~20 file-read syscalls/sec)
- carcontroller reads from frogpilot_variables (set in-process by controlsd)
instead of paramsMemory (saves ~100 file-read syscalls/sec in 100Hz path).
Dropped carcontroller's now-unused Params instance and import.
- UI (ui.cc, onroad.cc) reads from sm['frogpilotCarControl'].noLatLaneChange
- Removed LatRequested and no_lat_lane_change param registrations + defaults
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -101,7 +101,7 @@ ClearPilot uses memory params (`/dev/shm/params/d/`) for UI toggles that should
|
||||
- **Python access**: Use `Params("/dev/shm/params")`
|
||||
- **Defaults**: Set in `manager_init()` via `Params("/dev/shm/params").put(key, value)`
|
||||
- **UI toggles**: Use `ToggleControl` with manual `toggleFlipped` lambda that writes via `Params("/dev/shm/params")`. Do NOT use `ParamControl` for memory params — it reads/writes persistent params only
|
||||
- **Current memory params**: `TelemetryEnabled` (default "0"), `VpnEnabled` (default "1"), `ModelStandby` (default "0"), `ScreenDisplayMode`, `DashcamState` (default "stopped"), `DashcamFrames` (default "0")
|
||||
- **Current memory params**: `TelemetryEnabled` (default "0"), `VpnEnabled` (default "1"), `ModelStandby` (default "0"), `ScreenDisplayMode`, `DashcamState` (default "stopped"), `DashcamFrames` (default "0"), `DashcamShutdown` (default "0")
|
||||
- **IMPORTANT — method names differ between C++ and Python**: C++ uses camelCase (`putBool`, `getBool`, `getInt`), Python uses snake_case (`put_bool`, `get_bool`, `get_int`). This is a common source of silent failures — the wrong casing compiles/runs but doesn't work.
|
||||
|
||||
### Building Native (C++) Processes
|
||||
@@ -311,8 +311,7 @@ The OMX encoder (`selfdrive/frogpilot/screenrecorder/omx_encoder.cc`) was ported
|
||||
|
||||
### Params
|
||||
|
||||
- `DashcamDebug` — when `"1"`, dashcamd runs even without car connected (for bench testing)
|
||||
- `DashcamShutdown` — set by thermald before power-off, dashcamd acks by clearing it
|
||||
- `DashcamShutdown` (memory param) — set by thermald before power-off, dashcamd acks by clearing it
|
||||
- `DashcamState` (memory param) — "stopped", "waiting", or "recording" — published every 5s
|
||||
- `DashcamFrames` (memory param) — per-trip encoded frame count, resets each trip — published every 5s
|
||||
|
||||
@@ -524,7 +523,7 @@ Power On
|
||||
|
||||
### ClearPilot Processes
|
||||
|
||||
- `dashcamd` — raw camera dashcam recording (runs onroad or with DashcamDebug flag)
|
||||
- `dashcamd` — raw camera dashcam recording (always runs; manages its own trip lifecycle)
|
||||
|
||||
### GPS
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ struct FrogPilotCarControl @0x81c2f05a394cf4af {
|
||||
alwaysOnLateral @0 :Bool;
|
||||
speedLimitChanged @1 :Bool;
|
||||
trafficModeActive @2 :Bool;
|
||||
# CLEARPILOT: migrated from paramsMemory to avoid file-read syscalls in modeld/UI/carcontroller
|
||||
latRequested @3 :Bool; # controlsd's request to enable lat before ramp-up delay
|
||||
noLatLaneChange @4 :Bool; # lat is temporarily suppressed during a lane change
|
||||
}
|
||||
|
||||
struct FrogPilotCarState @0xaedffd8f31e7b55d {
|
||||
|
||||
@@ -109,7 +109,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"ControlsReady", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
{"CurrentBootlog", PERSISTENT},
|
||||
{"CurrentRoute", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
{"DashcamDebug", PERSISTENT},
|
||||
{"DashcamFrames", PERSISTENT},
|
||||
{"DashcamState", PERSISTENT},
|
||||
{"DashcamShutdown", CLEAR_ON_MANAGER_START},
|
||||
@@ -201,7 +200,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"TelemetryEnabled", PERSISTENT},
|
||||
{"Timezone", PERSISTENT},
|
||||
{"TrainingVersion", PERSISTENT},
|
||||
{"LatRequested", PERSISTENT},
|
||||
{"ModelFps", PERSISTENT},
|
||||
{"ModelStandby", PERSISTENT},
|
||||
{"ModelStandbyTs", PERSISTENT},
|
||||
@@ -510,8 +508,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"WheelIcon", PERSISTENT},
|
||||
{"WheelSpeed", PERSISTENT},
|
||||
|
||||
// Clearpilot
|
||||
{"no_lat_lane_change", PERSISTENT},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -12,7 +12,7 @@ from openpilot.system.hardware import PC
|
||||
# time step for each process
|
||||
DT_CTRL = 0.01 # controlsd
|
||||
DT_MDL = 0.05 # model
|
||||
DT_TRML = 0.5 # thermald and manager
|
||||
DT_TRML = 0.25 # thermald and manager — 4 Hz
|
||||
DT_DMON = 0.05 # driver monitoring
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from openpilot.selfdrive.car.hyundai import hyundaicanfd, hyundaican
|
||||
from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CANFD_CAR, CAR
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
from openpilot.common.params import Params
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
|
||||
@@ -57,9 +56,6 @@ class CarController(CarControllerBase):
|
||||
self.car_fingerprint = CP.carFingerprint
|
||||
self.last_button_frame = 0
|
||||
|
||||
# CLEARPILOT: cache Params instance — create_steering_messages was building
|
||||
# a new one every 10ms (100Hz), causing needless allocation + file opens
|
||||
self.params_memory = Params("/dev/shm/params")
|
||||
|
||||
def update(self, CC, CS, now_nanos, frogpilot_variables):
|
||||
actuators = CC.actuators
|
||||
@@ -116,7 +112,8 @@ class CarController(CarControllerBase):
|
||||
hda2_long = hda2 and self.CP.openpilotLongitudinalControl
|
||||
|
||||
# steering control
|
||||
no_lat_lane_change = self.params_memory.get_int("no_lat_lane_change", 1)
|
||||
# CLEARPILOT: no_lat_lane_change comes via frogpilot_variables (set by controlsd in-process)
|
||||
no_lat_lane_change = int(getattr(frogpilot_variables, 'no_lat_lane_change', False))
|
||||
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_steer, no_lat_lane_change))
|
||||
|
||||
# prevent LFA from activating on HDA2 by sending "no lane lines detected" to ADAS ECU
|
||||
|
||||
Binary file not shown.
@@ -279,12 +279,12 @@ int main(int argc, char *argv[]) {
|
||||
// Check for graceful shutdown request (every ~1 second)
|
||||
if (++param_check_counter >= CAMERA_FPS) {
|
||||
param_check_counter = 0;
|
||||
if (params.getBool("DashcamShutdown")) {
|
||||
if (params_memory.getBool("DashcamShutdown")) {
|
||||
LOGW("dashcamd: shutdown requested");
|
||||
if (state == RECORDING || state == IDLE_TIMEOUT) {
|
||||
close_trip();
|
||||
}
|
||||
params.putBool("DashcamShutdown", false);
|
||||
params_memory.putBool("DashcamShutdown", false);
|
||||
LOGW("dashcamd: shutdown ack sent, exiting");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -172,9 +172,8 @@ class Controls:
|
||||
self.not_running_prev = None
|
||||
self.lat_requested_ts = 0 # CLEARPILOT: timestamp when lat was first requested (ramp-up delay + comm issue suppression)
|
||||
self.prev_lat_requested = False
|
||||
self.prev_no_lat_lane_change = None # CLEARPILOT: gate no_lat_lane_change write on change
|
||||
# CLEARPILOT: gate frogpilotCarControl send on change (3 static bools, was publishing 100Hz)
|
||||
self._prev_fpcc = (None, None, None)
|
||||
self._prev_fpcc = (None, None, None, None, None)
|
||||
self._last_fpcc_send_frame = 0
|
||||
self.steer_limited = False
|
||||
self.desired_curvature = 0.0
|
||||
@@ -702,12 +701,12 @@ class Controls:
|
||||
|
||||
# CLEARPILOT: tell modeld early so it can ramp to 20fps, then delay latActive by
|
||||
# 250ms (5 frames at 20fps) so downstream services stabilize before steering engages.
|
||||
# latRequested is now on frogpilotCarControl (cereal) — see update_frogpilot_variables.
|
||||
now_ts = time.monotonic()
|
||||
if lat_requested != self.prev_lat_requested:
|
||||
self.params_memory.put_bool("LatRequested", lat_requested)
|
||||
if lat_requested:
|
||||
self.lat_requested_ts = now_ts
|
||||
if lat_requested and not self.prev_lat_requested:
|
||||
self.lat_requested_ts = now_ts
|
||||
self.prev_lat_requested = lat_requested
|
||||
self.FPCC.latRequested = lat_requested
|
||||
CC.latActive = lat_requested and (now_ts - self.lat_requested_ts) >= 0.25
|
||||
CC.longActive = self.enabled and not self.events.contains(ET.OVERRIDE_LONGITUDINAL) and self.CP.openpilotLongitudinalControl
|
||||
|
||||
@@ -726,10 +725,10 @@ class Controls:
|
||||
no_lat_lane_change = model_v2.meta.laneChangeState == LaneChangeState.laneChangeStarting and clearpilot_disable_lat_on_lane_change
|
||||
if no_lat_lane_change:
|
||||
CC.latActive = False
|
||||
# CLEARPILOT: only write on change — per-cycle atomic writes were eating ~15% CPU
|
||||
if no_lat_lane_change != self.prev_no_lat_lane_change:
|
||||
self.params_memory.put_bool("no_lat_lane_change", no_lat_lane_change)
|
||||
self.prev_no_lat_lane_change = no_lat_lane_change
|
||||
# CLEARPILOT: noLatLaneChange now lives on frogpilotCarControl (see update_frogpilot_variables).
|
||||
# Also mirrored to frogpilot_variables so in-process carcontroller reads it without IPC.
|
||||
self.FPCC.noLatLaneChange = no_lat_lane_change
|
||||
self.frogpilot_variables.no_lat_lane_change = no_lat_lane_change
|
||||
|
||||
if CS.leftBlinker or CS.rightBlinker:
|
||||
self.last_blinker_frame = self.sm.frame
|
||||
@@ -1211,9 +1210,11 @@ class Controls:
|
||||
|
||||
self.FPCC.trafficModeActive = self.frogpilot_variables.traffic_mode and self.params_memory.get_bool("TrafficModeActive")
|
||||
|
||||
# CLEARPILOT: send only when one of the 3 fields changes, with 1Hz keepalive
|
||||
# CLEARPILOT: send only when any field changes, with 1Hz keepalive
|
||||
# Saves ~7ms/sec of capnp+zmq work (was sending 100Hz despite static contents)
|
||||
fpcc_tuple = (self.FPCC.alwaysOnLateral, self.FPCC.speedLimitChanged, self.FPCC.trafficModeActive)
|
||||
# latRequested and noLatLaneChange are edge-triggered too (rare flips)
|
||||
fpcc_tuple = (self.FPCC.alwaysOnLateral, self.FPCC.speedLimitChanged, self.FPCC.trafficModeActive,
|
||||
self.FPCC.latRequested, self.FPCC.noLatLaneChange)
|
||||
if fpcc_tuple != self._prev_fpcc or (self.sm.frame - self._last_fpcc_send_frame) >= 100:
|
||||
fpcc_send = messaging.new_message('frogpilotCarControl')
|
||||
fpcc_send.valid = CS.canValid
|
||||
|
||||
@@ -89,7 +89,7 @@ def manager_init(frogpilot_functions) -> None:
|
||||
params_memory.put("VpnEnabled", "1")
|
||||
params_memory.put("DashcamFrames", "0")
|
||||
params_memory.put("DashcamState", "stopped")
|
||||
params_memory.put("LatRequested", "0")
|
||||
params_memory.put("DashcamShutdown", "0")
|
||||
params_memory.put("ModelFps", "20")
|
||||
params_memory.put("ModelStandby", "0")
|
||||
params_memory.put("ShutdownTouchReset", "0")
|
||||
@@ -178,7 +178,6 @@ def manager_init(frogpilot_functions) -> None:
|
||||
("DisableOpenpilotLongitudinal", "0"),
|
||||
("DisableVTSCSmoothing", "0"),
|
||||
("DisengageVolume", "100"),
|
||||
("DashcamDebug", "1"),
|
||||
("TelemetryEnabled", "0"),
|
||||
("DragonPilotTune", "0"),
|
||||
("DriverCamera", "0"),
|
||||
|
||||
@@ -169,7 +169,7 @@ def main(demo=False):
|
||||
|
||||
# messaging
|
||||
pm = PubMaster(["modelV2", "cameraOdometry"])
|
||||
sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "navModel", "navInstruction", "carControl", "liveTracks", "frogpilotPlan"])
|
||||
sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "navModel", "navInstruction", "carControl", "frogpilotCarControl", "liveTracks", "frogpilotPlan"])
|
||||
|
||||
publish_state = PublishState()
|
||||
params = Params()
|
||||
@@ -245,10 +245,12 @@ def main(demo=False):
|
||||
# Full 20fps: lat requested or lane changing
|
||||
# Reduced 4fps: not lat requested, not standstill (driving without cruise)
|
||||
# Standby 0fps: standstill
|
||||
# Uses LatRequested (not carControl.latActive) so modeld ramps to 20fps BEFORE
|
||||
# Uses FPCC.latRequested (not carControl.latActive) so modeld ramps to 20fps BEFORE
|
||||
# controlsd actually engages steering — gives downstream services time to stabilize.
|
||||
lat_active = params_memory.get_bool("LatRequested")
|
||||
lane_changing = params_memory.get_bool("no_lat_lane_change")
|
||||
# CLEARPILOT: both fields migrated from paramsMemory to cereal (no per-cycle file reads)
|
||||
fpcc = sm['frogpilotCarControl']
|
||||
lat_active = fpcc.latRequested
|
||||
lane_changing = fpcc.noLatLaneChange
|
||||
standstill = sm['carState'].standstill
|
||||
calibrating = sm['liveCalibration'].calStatus != log.LiveCalibrationData.Status.calibrated
|
||||
full_rate = lat_active or lane_changing or calibrating
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from openpilot.common.realtime import DT_TRML
|
||||
@@ -7,11 +6,11 @@ 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:
|
||||
def update(self, cur_temp: float, ignition: bool, standstill: bool = False,
|
||||
is_parked: bool = True, cruise_engaged: bool = False) -> int:
|
||||
pass
|
||||
|
||||
|
||||
@@ -23,29 +22,27 @@ class TiciFanController(BaseFanController):
|
||||
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:
|
||||
def update(self, cur_temp: float, ignition: bool, standstill: bool = False,
|
||||
is_parked: bool = True, cruise_engaged: bool = False) -> int:
|
||||
# CLEARPILOT fan range rules:
|
||||
# parked → 0-100% (full, no floor)
|
||||
# in drive + cruise engaged (any speed, inc standstill) → 30-100%
|
||||
# in drive + cruise off + standstill → 10-100%
|
||||
# in drive + cruise off + moving → 30-100%
|
||||
# In the PID output, neg_limit is how negative it can go (= max fan as %),
|
||||
# pos_limit is how positive (= negative of min fan %).
|
||||
if is_parked:
|
||||
self.controller.neg_limit = -100
|
||||
self.controller.pos_limit = 0
|
||||
elif cruise_engaged:
|
||||
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:
|
||||
elif 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
|
||||
self.controller.pos_limit = -10
|
||||
else:
|
||||
self.controller.neg_limit = -30
|
||||
self.controller.pos_limit = 0
|
||||
self.controller.neg_limit = -100
|
||||
self.controller.pos_limit = -30
|
||||
|
||||
if ignition != self.last_ignition:
|
||||
self.controller.reset()
|
||||
|
||||
@@ -292,8 +292,18 @@ def thermald_thread(end_event, hw_queue) -> None:
|
||||
msg.deviceState.maxTempC = all_comp_temp
|
||||
|
||||
if fan_controller is not None:
|
||||
standstill = sm['carState'].standstill if sm.seen['carState'] else False
|
||||
msg.deviceState.fanSpeedPercentDesired = fan_controller.update(all_comp_temp, onroad_conditions["ignition"], standstill)
|
||||
# CLEARPILOT: fan rules based on gear (parked vs drive) and cruise-engaged state
|
||||
if sm.seen['carState']:
|
||||
cs = sm['carState']
|
||||
standstill = cs.standstill
|
||||
is_parked = cs.gearShifter == log.CarState.GearShifter.park
|
||||
else:
|
||||
standstill = False
|
||||
is_parked = True # default safe: assume parked, no fan floor
|
||||
cruise_engaged = sm['controlsState'].enabled if sm.seen['controlsState'] else False
|
||||
msg.deviceState.fanSpeedPercentDesired = fan_controller.update(
|
||||
all_comp_temp, onroad_conditions["ignition"], standstill,
|
||||
is_parked=is_parked, cruise_engaged=cruise_engaged)
|
||||
|
||||
is_offroad_for_5_min = (started_ts is None) and ((not started_seen) or (off_ts is None) or (time.monotonic() - off_ts > 60 * 5))
|
||||
if is_offroad_for_5_min and offroad_comp_temp > OFFROAD_DANGER_TEMP:
|
||||
@@ -422,10 +432,10 @@ def thermald_thread(end_event, hw_queue) -> None:
|
||||
if power_monitor.should_shutdown(onroad_conditions["ignition"], in_car, off_ts, started_seen):
|
||||
cloudlog.warning(f"shutting device down, offroad since {off_ts}")
|
||||
# CLEARPILOT: signal dashcamd to close recording gracefully before power-off
|
||||
params.put_bool("DashcamShutdown", True)
|
||||
params_memory.put_bool("DashcamShutdown", True)
|
||||
deadline = time.monotonic() + 15.0
|
||||
while time.monotonic() < deadline:
|
||||
if not params.get_bool("DashcamShutdown"):
|
||||
if not params_memory.get_bool("DashcamShutdown"):
|
||||
cloudlog.info("dashcamd shutdown ack received")
|
||||
break
|
||||
time.sleep(0.5)
|
||||
|
||||
@@ -79,9 +79,10 @@ void OnroadWindow::updateState(const UIState &s) {
|
||||
nvg->update(); // CLEARPILOT: force repaint every frame for HUD elements
|
||||
|
||||
QColor bgColor = bg_colors[s.status];
|
||||
if (paramsMemory.getBool("no_lat_lane_change") == 1) {
|
||||
// CLEARPILOT: read from frogpilotCarControl cereal message (was paramsMemory)
|
||||
if ((*s.sm)["frogpilotCarControl"].getFrogpilotCarControl().getNoLatLaneChange()) {
|
||||
bgColor = bg_colors[STATUS_DISENGAGED];
|
||||
}
|
||||
}
|
||||
|
||||
if (bg != bgColor) {
|
||||
bg = bgColor;
|
||||
@@ -753,6 +754,7 @@ void AnnotatedCameraWidget::drawHealthMetrics(QPainter &p) {
|
||||
auto cs = sm["controlsState"].getControlsState();
|
||||
auto ds = sm["deviceState"].getDeviceState();
|
||||
auto mv = sm["modelV2"].getModelV2();
|
||||
auto ps = sm["peripheralState"].getPeripheralState();
|
||||
|
||||
float lag_ms = cs.getCumLagMs();
|
||||
float drop_pct = mv.getFrameDropPerc();
|
||||
@@ -760,6 +762,8 @@ void AnnotatedCameraWidget::drawHealthMetrics(QPainter &p) {
|
||||
int mem_pct = ds.getMemoryUsagePercent();
|
||||
int cpu_pct = 0;
|
||||
for (auto v : ds.getCpuUsagePercent()) cpu_pct = std::max(cpu_pct, (int)v);
|
||||
// Actual fan (not commanded): scale RPM to 0-100 using 6500 RPM as full scale
|
||||
int fan_pct = std::min(100, (int)(ps.getFanSpeedRpm() * 100 / 6500));
|
||||
|
||||
auto color_for = [](float v, float warn, float crit) {
|
||||
if (v >= crit) return QColor(0xff, 0x50, 0x50); // red
|
||||
@@ -774,6 +778,7 @@ void AnnotatedCameraWidget::drawHealthMetrics(QPainter &p) {
|
||||
{"TEMP", QString::number((int)temp_c), color_for(temp_c, 75.f, 88.f)},
|
||||
{"CPU", QString::number(cpu_pct), color_for((float)cpu_pct, 75.f, 90.f)},
|
||||
{"MEM", QString::number(mem_pct), color_for((float)mem_pct, 70.f, 85.f)},
|
||||
{"FAN", QString::number(fan_pct), QColor(0xff, 0xff, 0xff)},
|
||||
};
|
||||
|
||||
p.save();
|
||||
@@ -885,7 +890,8 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
|
||||
// paint center lane path
|
||||
// QColor bg_colors[CHANGE_LANE_PATH_COLOR];
|
||||
|
||||
bool is_no_lat_lane_change = paramsMemory.getBool("no_lat_lane_change");
|
||||
// CLEARPILOT: read from frogpilotCarControl cereal message (was paramsMemory)
|
||||
bool is_no_lat_lane_change = sm["frogpilotCarControl"].getFrogpilotCarControl().getNoLatLaneChange();
|
||||
|
||||
QColor center_lane_color;
|
||||
|
||||
|
||||
Binary file not shown.
@@ -118,8 +118,10 @@ void update_model(UIState *s,
|
||||
}
|
||||
|
||||
// update path
|
||||
// CLEARPILOT: read from frogpilotCarControl cereal message (was paramsMemory)
|
||||
bool no_lat_lane_change = (*s->sm)["frogpilotCarControl"].getFrogpilotCarControl().getNoLatLaneChange();
|
||||
float path;
|
||||
if (paramsMemory.getBool("no_lat_lane_change")) {
|
||||
if (no_lat_lane_change) {
|
||||
path = (float)LANE_CHANGE_NO_LAT_PATH_WIDTH / 20; // Release: better calc for EU users
|
||||
} else {
|
||||
path = (float)CENTER_LANE_WIDTH / 20; // Release: better calc for EU users
|
||||
@@ -439,7 +441,7 @@ void UIState::updateStatus() {
|
||||
UIState::UIState(QObject *parent) : QObject(parent) {
|
||||
sm = std::make_unique<SubMaster, const std::initializer_list<const char *>>({
|
||||
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState",
|
||||
"pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2",
|
||||
"pandaStates", "peripheralState", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2",
|
||||
"wideRoadCameraState", "managerState", "uiPlan", "liveTorqueParameters",
|
||||
"frogpilotCarControl", "frogpilotDeviceState", "frogpilotPlan",
|
||||
"gpsLocation",
|
||||
|
||||
Reference in New Issue
Block a user