From 54516f29daedc67b291ef7ab8c0b098b20fca36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sun, 24 May 2026 11:00:49 +0200 Subject: [PATCH] =?UTF-8?q?GPS=20anzeige=20verbessert=20und=20planung=20f?= =?UTF-8?q?=C3=BCr=20abarbeitung=20der=20Route=20angefangen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ExoMy_Software-master/ROUTENPLANUNG_TODO.md | 234 ++++++++++++++++++++ ExoMy_Software-master/gui/app.css | 3 + ExoMy_Software-master/gui/index.html | 31 ++- 3 files changed, 263 insertions(+), 5 deletions(-) create mode 100644 ExoMy_Software-master/ROUTENPLANUNG_TODO.md diff --git a/ExoMy_Software-master/ROUTENPLANUNG_TODO.md b/ExoMy_Software-master/ROUTENPLANUNG_TODO.md new file mode 100644 index 0000000..096d498 --- /dev/null +++ b/ExoMy_Software-master/ROUTENPLANUNG_TODO.md @@ -0,0 +1,234 @@ +# Routenplanung To-do + +Stand: 24.05.2026 + +## Aktueller Stand + +- Karten-Tab in `admin.html` vorhanden +- Wegpunkte können gesetzt werden +- Wegpunkte können verschoben werden +- Wegpunkte können gelöscht werden +- Klick auf die Route fügt einen Wegpunkt zwischen zwei vorhandenen Wegpunkten ein +- Route kann unter Namen gespeichert werden +- Gespeicherte Route kann geladen werden +- Gespeicherte Route kann gelöscht werden + +## Offene Produktentscheidung + +Noch nicht final entschieden ist, wie die Fahrart zwischen zwei Wegpunkten festgelegt wird: + +- Vollautomatisch aus der Richtungsänderung ableiten +- Pro Wegpunkt manuell festlegen +- Automatik als Standard, aber pro Wegpunkt übersteuerbar + +Aktuell bevorzugte Idee: + +- Automatik als Standard +- Pro Wegpunkt optionaler Override + +## Geplante Logik für Fahrart-Vorschlag + +Beim Klick auf einen Wegpunkt soll sofort eine Empfehlung berechnet werden: + +- unter `20°`: einfach `Ackermann` +- `20° bis 60°`: engerer `Ackermann-Bogen` +- über `60°`: erst `Turn on Point`, danach `Ackermann` + +Wichtig: + +- Die Winkeldifferenz soll aus den benachbarten Segmenten berechnet werden +- Bei inneren Wegpunkten: Richtung `vorheriger Punkt -> aktueller Punkt` gegen `aktueller Punkt -> nächster Punkt` +- Beim ersten Wegpunkt: optional Richtung `Rover -> Wegpunkt` gegen `Wegpunkt -> nächster Punkt` +- Beim letzten Wegpunkt: keine automatische Weiterfahr-Empfehlung oder eigener Sonderfall + +## Geplante UI-Erweiterungen + +- Klick auf Wegpunkt zeigt Popup +- Im Popup soll zusätzlich zur Löschfunktion die berechnete Fahrart-Empfehlung stehen +- Im Popup soll klar stehen: + - berechneter Winkel + - empfohlene Fahrart + - kurze Begründung +- Später optional: + - manuelle Auswahl `Ackermann` + - manuelle Auswahl `Turn on Point` + - manuelle Auswahl `Ackermann-Bogen` + - manueller Override `Automatik` + +## Wegpunktlogik im Detail + +Für jeden Wegpunkt sind später diese Fragen wichtig: + +- Wie wird der Punkt angefahren? +- Muss am Punkt gestoppt werden? +- Muss am Punkt neu ausgerichtet werden? +- Soll direkt in das nächste Segment übergegangen werden? + +Mögliche Varianten: + +- `nur passieren` + - Punkt gilt als erreicht, wenn der Rover den Radius schneidet +- `präzise anfahren` + - Punkt gilt erst als erreicht, wenn der Rover im Radius steht und genug verlangsamt hat +- `stoppen und neu ausrichten` + - Punkt wird erreicht, dann `Turn on Point` auf gewünschte Richtung + +## Segmentlogik + +Später soll die Route nicht nur als Punktliste gesehen werden, sondern als Folge von Segmenten: + +- Segment 1: `Start -> WP1` +- Segment 2: `WP1 -> WP2` +- Segment 3: `WP2 -> WP3` + +Für jedes Segment interessant: + +- Segmentlänge +- Zielrichtung +- empfohlene Fahrart +- erlaubte Geschwindigkeit +- Abbruchbedingungen + +## Marsrover-inspirierte Denkweise + +Für den ExoMy sinnvoll: + +- nicht die ganze Route als einen Block behandeln +- sondern Abschnitt für Abschnitt +- vor jedem neuen Abschnitt bewerten: + - Zielrichtung + - Platzverhältnisse + - gewünschte Genauigkeit + - Sicherheitslage + +Das bedeutet: + +- Menschen planen die Route +- der Rover arbeitet Segment für Segment ab +- am Übergang zum nächsten Segment wird neu bewertet + +## Vorschlag für Standardregeln + +Erste Regelbasis für die spätere Automatik: + +- unter `20°`: `Ackermann` +- `20° bis 60°`: `Ackermann-Bogen` +- über `60°`: `Turn on Point`, danach `Ackermann` + +Zusätzliche mögliche Regeln: + +- wenn Wegpunkt sehr nah am nächsten liegt: + - lieber präzise neu ausrichten +- wenn Toleranzradius klein ist: + - langsamer anfahren +- wenn wenig Platz oder Hindernisse: + - eher `Turn on Point` + +## Pro-Wegpunkt-Override + +Wahrscheinlich beste spätere Lösung: + +- Standardmäßig entscheidet die Automatik +- pro Wegpunkt kann man die Entscheidung überschreiben + +Mögliche Werte: + +- `automatik` +- `ackermann` +- `ackermann_bogen` +- `turn_on_point` + +## Was noch fehlt, bevor der Rover wirklich fahren kann + +- sauberes Routenformat für den Rover +- Status je Wegpunkt: + - `offen` + - `aktiv` + - `erreicht` + - `übersprungen` + - `fehler` +- Status je Route: + - `bereit` + - `läuft` + - `pausiert` + - `abgebrochen` + - `fertig` +- Start/Stop/Pause in der GUI +- Anzeige des aktuell aktiven Wegpunkts +- Anzeige der aktuell gewählten Fahrart + +## Sensorik-Fragen + +Noch offen für die spätere echte Fahrfunktion: + +- Woher kommt das Heading? + - IMU + - GPS-Bewegungsrichtung + - Fusion aus beidem +- Wie genau ist das GPS im Zielbereich? +- Brauchen wir zusätzlich Odometrie für den Nahbereich? +- Ab welcher Geschwindigkeit ist GPS-Kurs überhaupt brauchbar? + +## Sicherheitsfragen + +Vor echter Abarbeitung der Route klären: + +- Was passiert bei GPS-Verlust? +- Was passiert bei ROS-Verlust? +- Was passiert bei großem Positionssprung? +- Was passiert, wenn ein Wegpunkt nicht erreicht wird? +- Wann wird die Route automatisch abgebrochen? +- Muss der Rover bei Fehler immer sofort stoppen? + +## Spätere Komfortfunktionen + +- Richtungspfeil oder Segmentrichtung in der Karte anzeigen +- Wegpunktnummern und geplante Fahrart direkt in der Karte +- Route duplizieren +- Wegpunktreihenfolge manuell ändern +- Route exportieren/importieren +- Routenkommentar oder Missionsname +- Toleranzradius pro Wegpunkt einstellen +- Geschwindigkeit pro Segment oder Wegpunkt einstellen + +## Späterer Unterbau für echte Rover-Route + +Wenn aus der Planungsroute später eine ausführbare Rover-Route wird, soll das Datenformat erweitert werden: + +- `name` +- `waypoints` +- pro Wegpunkt: + - `id` + - `lat` + - `lon` + - `radius_m` + - `mode` oder `mode_override` + - optional `heading_deg` + - optional `stop_at_waypoint` + - optional `arrival_action` + - optional `speed_limit` + - optional `notes` + +## Technische Folgefragen + +- Woher kommt die zuverlässige aktuelle Fahrtrichtung? + - nur GPS ist bei langsamer Fahrt oft ungenau + - später besser mit IMU oder gemittelter Bewegungsrichtung +- Wann gilt ein Wegpunkt als erreicht? + - Toleranzradius in Metern +- Soll vor jedem neuen Segment neu entschieden werden? + - wahrscheinlich ja + +## Nächster sinnvoller Schritt + +1. Winkelberechnung zwischen Routensegmenten implementieren +2. Fahrart-Vorschlag nach obiger Tabelle erzeugen +3. Vorschlag im Wegpunkt-Popup anzeigen +4. Danach entscheiden, ob wir direkt einen manuellen Override pro Wegpunkt einbauen + +## Nicht vergessen + +- Die Route soll später leicht wiederzufinden und fortsetzbar sein +- Entscheidungen nicht still im Code verstecken, sondern in der GUI sichtbar machen +- Bei kleinen Rover-Geschwindigkeiten keine Scheingenauigkeit vortäuschen +- Lieber klare, nachvollziehbare Regeln als zu frühe komplizierte Autonomie diff --git a/ExoMy_Software-master/gui/app.css b/ExoMy_Software-master/gui/app.css index 41fd846..3ff9903 100644 --- a/ExoMy_Software-master/gui/app.css +++ b/ExoMy_Software-master/gui/app.css @@ -331,6 +331,9 @@ header { line-height: 1.9; pointer-events: none; } +.gps-quality-good { color: #00ff91; } +.gps-quality-mid { color: #FFB300; } +.gps-quality-bad { color: #FF5252; } .c-tl { top: calc(13px * var(--cam-scale)); left: calc(13px * var(--cam-scale)); } .c-tr { top: calc(13px * var(--cam-scale)); right: calc(13px * var(--cam-scale)); text-align: right; } .c-bl { bottom: calc(13px * var(--cam-scale)); left: calc(13px * var(--cam-scale)); } diff --git a/ExoMy_Software-master/gui/index.html b/ExoMy_Software-master/gui/index.html index e901f46..3ac7641 100644 --- a/ExoMy_Software-master/gui/index.html +++ b/ExoMy_Software-master/gui/index.html @@ -74,7 +74,7 @@
GPS: Offline
- SAT: --
+ POS: --
LAT: --
LON: --
@@ -603,17 +603,41 @@ function updateAxesDisplay(x, y) { setText("dpy", formatAxis(y)); } +function setGpsAccuracyDisplay(valueMeters) { + var node = document.getElementById("gps-accuracy"); + if (!node) return; + + node.classList.remove("gps-quality-good", "gps-quality-mid", "gps-quality-bad"); + if (typeof valueMeters !== "number" || isNaN(valueMeters) || valueMeters <= 0) { + node.textContent = "--"; + return; + } + + node.textContent = formatNumber(valueMeters, 1) + " m"; + if (valueMeters <= 1.0) { + node.classList.add("gps-quality-good"); + } else if (valueMeters <= 3.0) { + node.classList.add("gps-quality-mid"); + } else { + node.classList.add("gps-quality-bad"); + } +} + function updateGpsOverlayFromFix(message) { if (!message) return; markGpsFresh(); var hasFix = message.status && message.status.status >= 0; if (!hasFix) { + setGpsAccuracyDisplay(NaN); setText("gps-lat", "--"); setText("gps-lon", "--"); return; } + var covariance = Array.isArray(message.position_covariance) ? Number(message.position_covariance[0]) : NaN; + var accuracyMeters = covariance > 0 ? Math.sqrt(covariance) : NaN; + setGpsAccuracyDisplay(accuracyMeters); setText("gps-lat", formatNumber(Number(message.latitude || 0), 5)); setText("gps-lon", formatNumber(Number(message.longitude || 0), 5)); } @@ -622,9 +646,6 @@ function updateGpsOverlayFromStatus(text) { var value = String(text || "Offline"); markGpsFresh(); setText("gps-state", value); - - var satMatch = value.match(/(\d+)\s*Sat/i); - setText("gps-sats", satMatch ? satMatch[1] : "--"); } function updateModeDisplay() { @@ -727,7 +748,7 @@ function clearRosLiveDisplay() { liveIndicator.classList.add("is-offline"); } setText("gps-state", "Offline"); - setText("gps-sats", "--"); + setGpsAccuracyDisplay(NaN); setText("gps-lat", "--"); setText("gps-lon", "--"); setText("overlay-speed", "--");