mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-29 02:43:47 +08:00
see sats
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""Onroad GNSS health readout.
|
||||
|
||||
Built to measure RF desense from the external GPU's USB-C link: with the eGPU unplugged the
|
||||
receiver demodulates satellite time from ~93% of tracked satellites and fixes immediately, and
|
||||
with it plugged in that collapses to 0% while the tracked satellite count actually rises. Raw
|
||||
satellite counts are therefore misleading on their own - the demodulation rate and C/No are what
|
||||
show whether a cable, ferrite or antenna placement change helped.
|
||||
"""
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.application import gui_app, FontWeight
|
||||
|
||||
WIDTH = 300
|
||||
HEIGHT = 150
|
||||
MARGIN = 30
|
||||
PADDING = 14
|
||||
TITLE_SIZE = 26
|
||||
ROW_SIZE = 32
|
||||
|
||||
_BG = rl.Color(0, 0, 0, 180)
|
||||
_LABEL = rl.Color(255, 255, 255, 140)
|
||||
_GOOD = rl.Color(34, 197, 94, 255)
|
||||
_WARN = rl.Color(234, 179, 8, 255)
|
||||
_BAD = rl.Color(239, 68, 68, 255)
|
||||
|
||||
# Demodulation rate thresholds. Anything under ~40% has never produced a fix in logged drives.
|
||||
SAT_TIME_GOOD = 60.0
|
||||
SAT_TIME_WARN = 25.0
|
||||
|
||||
# Carrier-to-noise, in the modem's raw units (~2550 average with the eGPU unplugged and a clean
|
||||
# fix; the desensed drives report 0 for every satellite, so any non-zero reading is progress).
|
||||
CNO_GOOD = 2000.0
|
||||
CNO_WARN = 800.0
|
||||
|
||||
|
||||
def _grade(value: float, good: float, warn: float) -> rl.Color:
|
||||
if value >= good:
|
||||
return _GOOD
|
||||
if value >= warn:
|
||||
return _WARN
|
||||
return _BAD
|
||||
|
||||
|
||||
class GnssHealth:
|
||||
"""Bottom-right live GNSS quality readout."""
|
||||
|
||||
def __init__(self):
|
||||
self._font = gui_app.font(FontWeight.SEMI_BOLD)
|
||||
self._sat_time_pct = 0.0
|
||||
self._cno = 0.0
|
||||
self._gps_sv = 0
|
||||
self._glonass_sv = 0
|
||||
self._has_fix = False
|
||||
|
||||
def _update(self) -> None:
|
||||
sm = ui_state.sm
|
||||
if not sm.valid.get("qcomGnss", False):
|
||||
return
|
||||
|
||||
gnss = sm["qcomGnss"]
|
||||
if gnss.which() != "measurementReport":
|
||||
return
|
||||
|
||||
report = gnss.measurementReport
|
||||
svs = list(report.sv)
|
||||
source = str(report.source)
|
||||
|
||||
if "glonass" in source:
|
||||
self._glonass_sv = len(svs)
|
||||
else:
|
||||
self._gps_sv = len(svs)
|
||||
|
||||
if svs:
|
||||
known = sum(1 for sv in svs if sv.measurementStatus.satelliteTimeIsKnown)
|
||||
self._sat_time_pct = 100.0 * known / len(svs)
|
||||
noise = [sv.carrierNoise for sv in svs if sv.carrierNoise > 0]
|
||||
self._cno = sum(noise) / len(noise) if noise else 0.0
|
||||
|
||||
if sm.valid.get("gpsLocationExternal", False):
|
||||
self._has_fix = sm["gpsLocationExternal"].hasFix
|
||||
|
||||
def render(self, bounds: rl.Rectangle) -> None:
|
||||
self._update()
|
||||
|
||||
x = bounds.x + bounds.width - WIDTH - MARGIN
|
||||
y = bounds.y + bounds.height - HEIGHT - MARGIN
|
||||
rect = rl.Rectangle(x, y, WIDTH, HEIGHT)
|
||||
rl.draw_rectangle_rounded(rect, 0.12, 10, _BG)
|
||||
|
||||
tx = int(x + PADDING)
|
||||
ty = int(y + PADDING)
|
||||
|
||||
rl.draw_text_ex(self._font, "GNSS", rl.Vector2(tx, ty), TITLE_SIZE, 0, _LABEL)
|
||||
fix_text = "FIX" if self._has_fix else "NO FIX"
|
||||
fix_color = _GOOD if self._has_fix else _BAD
|
||||
rl.draw_text_ex(self._font, fix_text, rl.Vector2(int(x + WIDTH - PADDING - 90), ty),
|
||||
TITLE_SIZE, 0, fix_color)
|
||||
|
||||
ty += 34
|
||||
rl.draw_text_ex(self._font, "time", rl.Vector2(tx, ty), ROW_SIZE, 0, _LABEL)
|
||||
rl.draw_text_ex(self._font, f"{self._sat_time_pct:.0f}%", rl.Vector2(tx + 120, ty),
|
||||
ROW_SIZE, 0, _grade(self._sat_time_pct, SAT_TIME_GOOD, SAT_TIME_WARN))
|
||||
|
||||
ty += 36
|
||||
rl.draw_text_ex(self._font, "C/No", rl.Vector2(tx, ty), ROW_SIZE, 0, _LABEL)
|
||||
rl.draw_text_ex(self._font, f"{self._cno:.0f}", rl.Vector2(tx + 120, ty),
|
||||
ROW_SIZE, 0, _grade(self._cno, CNO_GOOD, CNO_WARN))
|
||||
|
||||
ty += 36
|
||||
rl.draw_text_ex(self._font, "sats", rl.Vector2(tx, ty), ROW_SIZE, 0, _LABEL)
|
||||
rl.draw_text_ex(self._font, f"{self._gps_sv}G {self._glonass_sv}R",
|
||||
rl.Vector2(tx + 120, ty), ROW_SIZE, 0, rl.WHITE)
|
||||
@@ -16,6 +16,7 @@ from openpilot.selfdrive.ui.onroad.starpilot.stopping_point import render_stoppi
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.pause_indicators import render_lateral_paused, render_longitudinal_paused
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.pulse_glide import get_pulse_glide_border_color, render_pulse_glide
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.pip_sidecam import PipSideCamera
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.gnss_health import GnssHealth
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.favorite_radial_menu import FavoriteRadialMenu
|
||||
from openpilot.selfdrive.ui.onroad.starpilot.weather_icon import render_weather_icon
|
||||
from openpilot.selfdrive.ui.lib.starpilot_status import (
|
||||
@@ -49,6 +50,7 @@ class StarPilotOnroadView(AugmentedRoadView):
|
||||
self._avg_fps = 0.0
|
||||
|
||||
self._pip_sidecam = self._child(PipSideCamera())
|
||||
self._gnss_health = GnssHealth()
|
||||
self._favorite_radial_menu = FavoriteRadialMenu(
|
||||
ui_state.ui_params,
|
||||
ui_state.params_memory,
|
||||
@@ -143,6 +145,10 @@ class StarPilotOnroadView(AugmentedRoadView):
|
||||
|
||||
self._pip_sidecam.render(self._content_rect)
|
||||
|
||||
# Always on: this is a temporary instrument for the eGPU RF-desense testing, and gating it
|
||||
# behind a param would mean registering a new key in params_keys.h, which needs a rebuild.
|
||||
self._gnss_health.render(self._content_rect)
|
||||
|
||||
# The picker is an app-drawer modal, so it intentionally draws above
|
||||
# PiP and other on-road overlays while active.
|
||||
if self._draw_hud_controls and not self._full_alert_showing():
|
||||
|
||||
@@ -64,6 +64,7 @@ class UIState:
|
||||
"selfdriveState",
|
||||
"longitudinalPlan",
|
||||
"gpsLocationExternal",
|
||||
"qcomGnss",
|
||||
"mapdOut",
|
||||
"carOutput",
|
||||
"carControl",
|
||||
|
||||
Reference in New Issue
Block a user