# ExoMy CUNO — Software ExoMy Mars-Rover auf Basis eines Raspberry Pi mit ROS1 Melodic, betrieben vollständig in einem Docker-Container. --- Die Software liegt in diesem Repository direkt an der Wurzel. Nicht zur Software gehörende CAD-, Datenblatt- und Anleitungsbestände wurden bewusst entfernt. ## Zugang zum Raspberry Pi | | | |---|---| | **Modell** | `Raspberry Pi 4 Model B Rev 1.4` | | **Hostname** | `cuno` | | **Benutzer** | `pi` | | **SSH-Passwort** | `Sonneberg` | | **LAN-IP** | `192.168.1.83` | | **WLAN-IP** | `192.168.1.9` (bevorzugt) | | **Fallback-AP** | SSID `CUNO`, IP `192.168.50.1`, Passwort `astr0cun042` | ```bash ssh pi@192.168.1.9 ``` --- ## Architektur ``` Web-GUI (Port 8000) │ WebSocket (Port 9090) ▼ rosbridge_websocket ──► /joy ──► joystick_parser_node ──► /rover_command │ f710_joy_node ──────────────────────────────────────────────────┘ (Logitech F710, /dev/input/js0) /rover_command ──► robot_node ──► /motor_commands ──► motor_node ──► PCA9685 PWM ──► Motoren ``` **Software auf dem Pi:** `/home/pi/ExoMy_Software/` **ROS-Workspace im Container:** `/root/exomy_ws/src/exomy/` --- ## Systemd-Services auf dem Pi | Service | Beschreibung | |---|---| | `exomy-admin-api.service` | Admin-API (`exomy_admin_api.py`) | | `exomy-camera-stream.service` | MJPEG Kamera-Stream | | `exomy-wifi-fallback.service` | WLAN-Fallback auf eigenen Access Point | ```bash # Status prüfen systemctl status exomy-admin-api.service ``` --- ## Docker-Container Der Container `exomy_autostart` (Image: `exomy`) startet automatisch beim Booten. ```bash # Status docker ps # Logs docker logs exomy_autostart --tail=50 # Shell im Container docker exec -it exomy_autostart bash ``` ### ROS-Nodes im Container | Node | Beschreibung | |---|---| | `f710_joy_node.py` | Liest Logitech F710 von `/dev/input/js0`, publiziert auf `/joy` mit 20 Hz — **auch wenn der Joystick in Ruhe liegt** | | `joystick_parser_node.py` | Konvertiert `/joy` → `/rover_command`; priorisiert Web-GUI über physischen Controller | | `gps_node.py` | Liest den GPS-Empfänger, publiziert Fix- und Diagnosedaten und kann über die Admin-Seite gezielt neu gestartet oder per Kaltstart zur Neuinitialisierung gezwungen werden | | `robot_node.py` | Berechnet Lenkwinkel und Geschwindigkeiten aus `/rover_command` | | `motor_node.py` | Setzt PWM-Werte über PCA9685; Watchdog stoppt Motoren nach 5 s ohne Befehl | | `rosbridge_websocket` | WebSocket-Bridge für die Web-GUI (Port 9090) | | `rosapi_node` | ROS-API für die Web-GUI | ### Admin-Funktionen - Admin-Seite: `http://:8000/admin.html` - Kamera-Tab nur mit `4:3`-Profilen: - `640 x 480` - `1024 x 768` - `1296 x 972` - Systemstatus mit zusätzlicher WLAN-Signalstärke in Prozent - GPS-Aktionen: - `GPS neu starten` - `GPS-Kaltstart` für den GlobalSat `BU-353N5` ### Ports | Port | Verwendung | |---|---| | `8000` | Web-GUI | | `9090` | ROSBridge WebSocket | | `8082` | Admin-API | --- ## Deploy-Workflow Dateien lokal bearbeiten, dann auf den Pi und in den laufenden Container übertragen: ```bash # Datei auf den Pi kopieren scp src/meine_datei.py pi@192.168.1.9:/home/pi/ExoMy_Software/src/ # In den Container kopieren ssh pi@192.168.1.9 "docker cp /home/pi/ExoMy_Software/src/meine_datei.py exomy_autostart:/root/exomy_ws/src/exomy/src/" # Container neu starten ssh pi@192.168.1.9 "docker restart exomy_autostart" ``` GUI-Dateien: ```bash scp gui/index.html pi@192.168.1.9:/home/pi/ExoMy_Software/gui/ ssh pi@192.168.1.9 "docker cp /home/pi/ExoMy_Software/gui/index.html exomy_autostart:/root/exomy_ws/src/exomy/gui/" # Kein Neustart nötig — Browser-Reload genügt ``` --- ## Bekannte Probleme & Fixes ### Web-GUI: Ruckartige Bewegung bei angeschlossenem Controller **Problem:** Der `f710_joy_node` sendet permanent mit 20 Hz auf `/joy`, auch wenn der Logitech F710 in Ruhe liegt (Nullwerte). Wenn die Web-GUI gleichzeitig steuert, wechseln sich Fahr- und Stopp-Befehle im 50-ms-Takt ab — der Rover bewegt sich ruckartig. **Fix:** `joystick_parser_node.py` ignoriert Nachrichten des physischen Controllers für 2 Sekunden, sobald eine Web-GUI-Nachricht eintrifft (erkennbar an `frame_id == "webgui"`). Danach übernimmt der physische Controller automatisch wieder. ### SyntaxError in rover.py (Point-Turn-Modus) **Problem:** Überzählige schließende Klammer in `rover.py` Zeile 157 ließ `robot_node.py` beim Start abstürzen — der Rover war nicht steuerbar. ```python # Falsch: math.atan((self.wheel_rx + self.wheel_fx) / self.wheel_ry))) # Richtig: math.atan((self.wheel_rx + self.wheel_fx) / self.wheel_ry)) ``` --- ## Fahrmodi | Modus | Taste (Controller) | Taste (Web-GUI) | |---|---|---| | Ackermann | A | Schaltfläche „Ackermann" | | Point Turn (Drehen auf der Stelle) | X | Schaltfläche „Turn on Point" | | Crab (Seitwärtsfahrt) | Y | Schaltfläche „Crab" | | Motoren ein/aus | START | Schaltfläche „Motoren" | --- ## Latenz-Simulation Die Latenz-Simulation wird über die Admin-Seite eingestellt und wirkt gleichzeitig auf Steuerung und Kamerabild. - Bereich: Admin-Seite `http://:8000/admin.html` - Einstellbereich: `0` bis `10` Sekunden - Steuerbefehle: werden im ROS-Node `delay_node` gepuffert - Kamerabild: läuft über den Delay-Proxy auf Port `8083` - Rohstream: Port `8081` bleibt ohne Verzögerung für Debug und interne Vorschau - Hauptseite: nutzt bewusst `8083`, damit die eingestellte Verzögerung auch im Fahrbild sichtbar ist Signalweg: ```text Kamera -> 8081 Rohstream -> 8083 Delay-Proxy -> Web-GUI Joystick/Websteuerung -> /joy -> /delay_node -> /joy_delayed -> Rover-Steuerung ``` Damit lässt sich eine künstliche Laufzeit simulieren, ohne den eigentlichen Kameradienst umzubauen. --- ## Originales ESA-Projekt - [Wiki](https://github.com/esa-prl/ExoMy/wiki) — Bauanleitung und Dokumentation - [Website](https://esa-prl.github.io/ExoMy/) - [Dokumentations-Repository](https://github.com/esa-prl/ExoMy)