206 lines
6.7 KiB
Markdown
206 lines
6.7 KiB
Markdown
# ExoMy CUNO — Software
|
|
|
|
`CUNO` steht für `Celestian Unified Navigation and Observation`.
|
|
|
|
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` |
|
|
| **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-bootstrap.service` | Wählt beim Start `4pi` oder `eskimue.de`, sonst eigener Access Point |
|
|
|
|
### WLAN-Startlogik
|
|
|
|
Beim Booten sucht der Rover genau einmal nach den bekannten WLANs `4pi` und `eskimue.de`.
|
|
|
|
- Wenn `4pi` sichtbar ist, verbindet er sich mit `4pi`.
|
|
- Sonst, wenn `eskimue.de` sichtbar ist, verbindet er sich mit `eskimue.de`.
|
|
- Wenn keines von beiden sichtbar ist, spannt er den eigenen Access Point `CUNO` auf.
|
|
|
|
Nach dieser Entscheidung bleibt die gewählte Verbindung bestehen. Es gibt kein späteres Nachscannen und kein automatisches Umschalten auf ein anderes WLAN oder auf den Access Point. Erst nach einem Neustart wird erneut gesucht.
|
|
|
|
```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://<IP>: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://<IP>: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)
|