diag: per-publisher valid=False logging; 30min shutdown; daylight fix; UI tweaks
Some checks failed
prebuilt / build prebuilt (push) Has been cancelled
badges / create badges (push) Has been cancelled

CLAUDE.md: added a "Logging" rule — never use cloudlog (upstream cloud
pipeline, effectively a black hole for us), always use
print(..., file=sys.stderr, flush=True). Manager redirects each process's
stderr to /data/log2/current/{proc}.log. Prefix our lines with "CLP ".

Diagnostic logging — when a publisher sets its own msg.valid=False, log
which specific subscriber tripped the check. Only fires on transition
(True→False) so we don't spam. Covers the services whose cascades we've
been chasing:
  - frogpilot_planner (frogpilotPlan)
  - longitudinal_planner (longitudinalPlan)
  - paramsd (liveParameters)
  - calibrationd (liveCalibration)
  - torqued (liveTorqueParameters)
  - dmonitoringd (driverMonitoringState)

gpsd.is_daylight: fixed a day-boundary bug where the function would flip
to "night" at UTC midnight regardless of actual local sunset. At 85W
sunset is ~00:20 UTC next day, so between local 8pm and actual sunset
the function used *tomorrow's* sunrise/sunset and said night. Now checks
yesterday/today/tomorrow windows with UTC-day offsets.

ui/onroad.cc: nightrider tire-path outline is now light blue (#99CCFF)
at 3px (was white/status-tinted at 6px); lane lines 5% thinner (float
pen width).

thermald/power_monitoring: auto-shutdown timer 10min → 30min.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-17 19:31:09 -05:00
parent cf2b3fc637
commit e86eafde15
11 changed files with 127 additions and 20 deletions

View File

@@ -20,17 +20,16 @@ from openpilot.common.time import system_time_valid
from openpilot.system.hardware.tici.pins import GPIO
def is_daylight(lat: float, lon: float, utc_dt: datetime.datetime) -> bool:
"""Return True if it's between sunrise and sunset at the given location.
Uses NOAA simplified solar position equations. Pure math, no external libs."""
def _sunrise_sunset_min(lat: float, lon: float, utc_dt: datetime.datetime):
"""Compute (sunrise_min, sunset_min) in UTC minutes since midnight of utc_dt's day.
Values can be negative or >1440 for western/eastern longitudes. Returns
(None, None) for polar night, ('always', 'always') for midnight sun."""
n = utc_dt.timetuple().tm_yday
gamma = 2 * math.pi / 365 * (n - 1 + (utc_dt.hour - 12) / 24)
# Equation of time (minutes)
eqtime = 229.18 * (0.000075 + 0.001868 * math.cos(gamma)
- 0.032077 * math.sin(gamma)
- 0.014615 * math.cos(2 * gamma)
- 0.040849 * math.sin(2 * gamma))
# Solar declination (radians)
decl = (0.006918 - 0.399912 * math.cos(gamma)
+ 0.070257 * math.sin(gamma)
- 0.006758 * math.cos(2 * gamma)
@@ -42,14 +41,41 @@ def is_daylight(lat: float, lon: float, utc_dt: datetime.datetime) -> bool:
cos_ha = (math.cos(zenith) / (math.cos(lat_rad) * math.cos(decl))
- math.tan(lat_rad) * math.tan(decl))
if cos_ha < -1:
return True # midnight sun
return ('always', 'always') # midnight sun
if cos_ha > 1:
return False # polar night
return (None, None) # polar night
ha = math.degrees(math.acos(cos_ha))
sunrise_min = 720 - 4 * (lon + ha) - eqtime
sunset_min = 720 - 4 * (lon - ha) - eqtime
return (sunrise_min, sunset_min)
def is_daylight(lat: float, lon: float, utc_dt: datetime.datetime) -> bool:
"""Return True if the sun is currently above the horizon at (lat, lon).
Handles west-of-Greenwich correctly: at UTC midnight it may still be
evening local time, and the relevant sunset is the PREVIOUS UTC day's
value (which is >1440 min if we re-ref to that day, i.e. it's past
midnight UTC). Symmetric case for east-of-Greenwich at the other end.
Strategy: compute sunrise/sunset for yesterday, today, and tomorrow (each
relative to its own UTC midnight), shift them all onto today's clock
(yesterday = -1440, tomorrow = +1440), and check if now_min falls inside
any of the three [sunrise, sunset] intervals.
"""
now_min = utc_dt.hour * 60 + utc_dt.minute + utc_dt.second / 60
return sunrise_min <= now_min <= sunset_min
for day_offset in (-1, 0, 1):
d = utc_dt + datetime.timedelta(days=day_offset)
sr, ss = _sunrise_sunset_min(lat, lon, d)
if sr == 'always':
return True
if sr is None:
continue # polar night this day
sr += day_offset * 1440
ss += day_offset * 1440
if sr <= now_min <= ss:
return True
return False
def at_cmd(cmd: str) -> str: