| static | ||
| .gitignore | ||
| app.py | ||
| apriltag_ws.py | ||
| calibration.py | ||
| collision.py | ||
| config.yaml | ||
| logo.png | ||
| main.py | ||
| navlogger.py | ||
| README.md | ||
| requirements.txt | ||
| serverstart.txt | ||
| tracker.py | ||
HoloDeck — AprilTag-Robotersteuerung für den Unterricht
Pädagogische Hochschule Weingarten · FrankeLab
Ein overhead-kamerabasiertes System zur autonomen Navigation physischer Differentialantriebs-Roboter in Klassenzimmern. Schülerinnen und Schüler programmieren die Roboter über eine grafische Blockly-Oberfläche.
Inhaltsverzeichnis
- Systemübersicht
- Hardware-Komponenten
- Verdrahtung & Schaltplan
- Netzwerk & Infrastruktur
- AprilTag-Layout
- Software-Architektur
- Entwicklungsgeschichte (v005–v011)
- Deployment (Server)
- Firmware flashen (ESP32)
- Konfiguration (config.yaml)
- Kommunikationsprotokoll
- Regler-Tuning
- Bekannte Probleme & Workarounds
- Roadmap
1. Systemübersicht
┌─────────────────────────────────────────────────────────────┐
│ Overhead-Kamera (HuskyLens 2) │
│ RTSP → 192.168.0.30:8554/live │
└────────────────────┬────────────────────────────────────────┘
│ RTSP (UDP, 1280×720)
▼
┌─────────────────────────────────────────────────────────────┐
│ Ubuntu-Server 192.168.0.250 │
│ /opt/robot-tracker-v010/ │
│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ tracker │ │ collision │ │ navlogger │ │
│ │ AprilTag │→ │ Potential │→ │ CSV-Logging │ │
│ │ Detektor │ │ -feld PID │ │ │ │
│ └──────────┘ └───────────┘ └──────────────┘ │
│ FastAPI / uvicorn Port 80 │
│ TCP-Server Port 8765 │
└────────────────┬────────────────────────────────────────────┘
│ TCP (JSON, newline-delimited)
▼
┌─────────────────────────────────────────────────────────────┐
│ Roboter (Freenove ESP32-S3 + MicroPython v1.23) │
│ WiFi FrankeLab → 192.168.0.250:8765 │
│ ┌──────────┐ ┌────────────┐ ┌────────────┐ │
│ │ PID-Loop │ │ Encoder │ │ Motoren │ │
│ │ 20 Hz │← │ IRQ 50ms │ │ L9110S │ │
│ └──────────┘ └────────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────────┘
2. Hardware-Komponenten
Server / Kamera
| Komponente | Details |
|---|---|
| Server | Ubuntu 24.04, statisch 192.168.0.250 |
| Kamera | HuskyLens 2 (RTSP-Modus) |
| Kamera-Mount | Overhead-Befestigung zentral über der Spielfläche |
Roboter (ein Exemplar, erweiterbar)
| Komponente | Bezeichnung / Bestellnummer |
|---|---|
| Chassis | DollaTek 2WD Roboter-Chassis-Kit |
| Mikrocontroller | Freenove ESP32-S3 WROOM Board Lite |
| Breakout-Board | Freenove ESP32-S3 Breakout Board (Schraubklemmen) |
| Motortreiber | TB6612FNG Dual DC Motor Stepper |
| Encoder-Sensoren | Optokoppler-Geschwindigkeitssensor (74HC14D-basiert, 3,3–5V) |
| Powerbank | Intenso XS5000 (USB-A + USB-C Ausgang) |
| AprilTag (Roboter) | Tag36h11, ID 91, auf Aufkleber am Roboter |
Hinweis Motortereiber-Geschichte: Zunächst wurde ein handgelöteter TB6612FNG auf Lochraster verwendet. Dieser wurde durch das deutlich handhabbarere L9110S-Schraubklemmen-Modul ersetzt.
WARNUNG: Ein früheres AZDelivery-ESP32-Board wurde wahrscheinlich durch gleichzeitigen USB+Akku-Betrieb beschädigt. Niemals gleichzeitig USB und Powerbank anlegen wenn GPIO-Pins des Motortreibers auf HIGH liegen!
3. Verdrahtung & Schaltplan
Stromversorgung — ZWEI GETRENNTE RAILS (kritisch!)
Das System verwendet zwei physisch getrennte Stromversorgungskreise, weil WiFi-Peak (200–400 mA) + zwei Motoren den 5V-Rail eines einzigen USB-Anschlusses überlasten:
┌─────────────────────┐ ┌──────────────────────────────────┐
│ Intenso XS5000 │ │ Intenso XS5000 │
│ USB-C Ausgang │ │ USB-A Ausgang │
│ 5V → ESP32 (VIN) │ │ Kabel aufschneiden: │
│ │ │ Roter Draht → VM (Motortreiber) │
└─────────────────────┘ └──────────────────────────────────┘
│ │
│ USB-C Kabel │ Modifiziertes USB-A-Kabel
▼ ▼
ESP32-S3 (USB-C) VM-Pin L9110S
Logikversorgung Motorversorgung
GND verbunden: ESP32 GND ←——→ L9110S GND (gemeinsame Masse!)
Wichtig: Das schwarze (GND) Kabel des USB-A-Kabels wird ebenfalls mit dem ESP32-GND verbunden. Die Datenleitungen (grün/weiß) bleiben unbenutzt / abgeklebt.
GPIO-Belegung ESP32-S3
| GPIO | Funktion | Verbindung |
|---|---|---|
| GPIO 17 | AIN1 (Motor A Richtung 1) | L9110S Pin IA1 |
| GPIO 18 | AIN2 (Motor A Richtung 2) | L9110S Pin IA2 |
| GPIO 8 | PWMA (Motor A Geschwindigkeit) | L9110S Pin — via Jumper oder direkt |
| GPIO 9 | BIN1 (Motor B Richtung 1) | L9110S Pin IB1 |
| GPIO 10 | BIN2 (Motor B Richtung 2) | L9110S Pin IB2 |
| GPIO 11 | PWMB (Motor B Geschwindigkeit) | L9110S Pin — |
| GPIO 6 | Encoder Links (Interrupt) | Optokoppler OUT |
| GPIO 7 | Encoder Rechts (Interrupt) | Optokoppler OUT |
| 3V3 | Encoder VCC | Optokoppler VCC |
| GND | Gemeinsame Masse | L9110S GND, Encoder GND |
Achtung GPIO 12: GPIO 12 ist am ESP32(-S3 nicht betroffen, aber klassischer ESP32) ein Strapping-Pin und verursacht Boot-Probleme. Wird hier nicht verwendet.
L9110S Motor-Treiber Anschlussschema
ESP32-S3 L9110S Modul
───────── ────────────
GPIO 17 ──────────────────→ IA1 OA1 ──→ Motor A (links) Klemme 1
GPIO 18 ──────────────────→ IA2 OA2 ──→ Motor A (links) Klemme 2
GPIO 8 ──────── (PWM) ──→ IA1 oder Jumper (je nach Modul)
GPIO 9 ──────────────────→ IB1 OB1 ──→ Motor B (rechts) Klemme 1
GPIO 10 ──────────────────→ IB2 OB2 ──→ Motor B (rechts) Klemme 2
GPIO 11 ──────── (PWM) ──→ IB1 oder Jumper
3V3 ──────────────────→ VCC (Logik)
GND ──────────────────→ GND
USB-A rot ────────────────→ VM (Motorversorgung 5V)
Hinweis: Das L9110S-Modul vereint Richtungssteuerung und PWM auf zwei Eingangspins pro Kanal (IA1/IA2). Die Drehrichtung ergibt sich aus dem Muster HIGH/LOW bzw. PWM/GND. Konkrete Zuordnung in
main.py → set_motor().
Encoder-Sensor Anschluss
Optokoppler-Modul (74HC14D) ESP32-S3
─────────────────────────── ─────────
VCC ──────────────────────→ 3V3
GND ──────────────────────→ GND
OUT (linker Sensor) ──────→ GPIO 6
OUT (rechter Sensor) ──────→ GPIO 7
Lochscheibe: 20 Löcher/Umdrehung → 20 Pulse/Rev
Befestigung
- Alle Elektronikmodule mit Heißkleber auf dem Chassis fixiert (sicher, rückbaubar)
- Encoder-Sensoren justiert auf Lochscheibe der Motorachsen
- AprilTag (ID 91) flach auf der Oberseite des Roboters aufgeklebt, muss von oben sichtbar sein
4. Netzwerk & Infrastruktur
| Komponente | IP-Adresse | Port |
|---|---|---|
| Ubuntu-Server | 192.168.0.250 (statisch) | — |
| FastAPI/Webinterface | 192.168.0.250 | 80 |
| TCP Robot-Server | 192.168.0.250 | 8765 |
| HuskyLens 2 (RTSP) | 192.168.0.30 | 8554 |
| Roboter (ESP32) | DHCP | — |
WLAN: FrankeLab (Passwort in main.py und WIFI_PSW Variable)
Python-Umgebung Server:
/opt/vision-venv/ # Virtuelle Umgebung
/opt/robot-tracker-v010/ # Aktueller Produktionsstand
5. AprilTag-Layout
Alle Tags aus der Familie tag36h11.
Kalibrierungs-Tags (Referenzpunkte)
Auf einem A4-Blatt, fixiert im Sichtfeld der Kamera:
| Tag-ID | Position (mm) |
|---|---|
| 0 | (0.0, 0.0) — Ursprung |
| 1 | (100.5, 0.0) |
| 2 | (0.0, 181.0) |
| 3 | (100.5, 181.0) |
Roboter-Tags
| Tag-ID | Bedeutung |
|---|---|
| 91 | Roboter 1 |
Hindernis-Tags
| Tag-IDs |
|---|
| 11, 12, 21, 22, 31, 32, 41, 42, 51, 52, 61, 62, 71, 72, 81, 82, 92 |
Hindernisse werden als AprilTags auf dem Boden oder an Objekten platziert. Der Server berechnet automatisch Abstoßungskräfte (Potentialfeld).
6. Software-Architektur
Server-Stack
app.py FastAPI-App, 20-Hz-Steuerungsloop, TCP-Server, WebSocket-Broadcast
tracker.py AprilTag-Detektion via pupil-apriltags, EMA-Filter, Dead Reckoning
collision.py Potentialfeld-Navigation: Zielanziehung + Hindernisabstoßung
navlogger.py CSV-Logging aller Navigationsdaten → logs/nav_YYYYMMDD_HHMMSS.csv
calibration.py Homographie-Kalibrierung (Kamerabild → Weltkoordinaten mm)
config.yaml Alle Parameter externalisiert
static/ Browser-Frontend (Live-Kamerabild + AprilTag-Overlay)
ESP32-Firmware
main.py Komplette Roboter-Firmware (MicroPython)
├── WiFi-Verbindung mit Auto-Reconnect
├── TCP-Client → Server 192.168.0.250:8765
├── Encoder-Interrupts (GPIO 6, 7)
├── PID-Loop 20 Hz (asyncio)
├── Telemetrie-Loop 10 Hz (asyncio)
└── Feedforward-Architektur (v011, aktuell deaktiviert = Option B)
7. Entwicklungsgeschichte v005–v011
v005 — Stabile Tracking-Basis (Server only)
- Kamera-I/O auf dedizierten Background-Thread via
asyncio.Queue(maxsize=1) - ffmpeg-Watchdog mit Auto-Reconnect bei Kameraausfall
- config.yaml — alle Parameter externalisiert, kein Hardcoding mehr
- Velocity-Vektor-Visualisierung im Browser-Frontend
- Bestätigt: Merklich flüssiger als v004
v006 — Grundlegende Navigation
- Erste TCP-Kommunikation mit ESP32
- Einfache Richtungs-Befehle (links/rechts/vorwärts)
- Kein Encoder-Feedback
v007 — Homographie-Kalibrierung
calibration.pyeingeführt: 4 Referenz-Tags → Kamerabild-zu-Weltkoordinaten-Mapping- Kamerakoordinaten erstmals in echte mm umgerechnet
- A4-Kalibrierblatt mit Tags 0–3 als Referenz
v008 — Erste Hindernisvermeidung
collision.pyeingeführt: Potentialfeld-Ansatz- Zielanziehung + Hindernisabstoßung
- Noch instabil: Spin-Probleme, zu aggressiv
v008_log — Navigation-Logging
navlogger.pyhinzugefügt- CSV-Logging aller Navigationsdaten für spätere Analyse
- Log-Dateien in
logs/nav_DATUM_UHRZEIT.csv
v009 — Encoder-PID + Erste stabile Navigation
Meilenstein: Erster Roboter fährt autonom zum Ziel
- Encoder-Interrupts auf GPIO 6/7
- PID-Regler für Radgeschwindigkeit:
KP=1.2, KI=0.3, KD=0.05 - Kommunikationsprotokoll auf mm/s umgestellt (server→robot:
{"speed_l": N, "speed_r": N}) - TCP statt WebSocket für Robot-Kommunikation (simpler, stabiler)
- Dead Reckoning: Bei Tag-Verlust schätzt ESP32 Position aus Encoder-Daten
- Hardware-Parameter in config.yaml:
mm_per_pulse=10.525,axle_width_mm=121.0 - PWM-Minimum 150 damit Motoren sicher anlaufen
v009_fix → v009_spin_fix → v009_goal_fix
Iterative Fixes basierend auf Log-Analyse:
- Spin-Schwelle angepasst
- Ziel-Erreicht-Erkennung verbessert
- Repulsionskraft von 5000 → 1500 (war zu aggressiv)
v010 — Stabilisierte Navigation (aktueller Produktionsstand)
Serverseitige Verbesserungen:
| Parameter | Alt | Neu | Grund |
|---|---|---|---|
FORCE_ALPHA |
0.15 | 0.35 | Zu träge → Endlos-Spin |
SPIN_THRESHOLD |
120° | 90° | 120° zu hoch, Roboter überschoss |
SPIN_STOP |
— | 35° | Sauberes Spin-Ende |
SPIN_SLOWDOWN |
— | 60° | Sanftes Abbremsen |
HEADING_DEADBAND |
— | 6° | Unter 6° kein Kurskorrektur |
repulsion_strength |
5000 | 1500 | Sanftere Abstoßung |
| Controller-Frequenz | 10 Hz | 20 Hz | Doppelte Reaktionsgeschwindigkeit |
reset_robot() |
— | ✓ | Roboter stoppt bei Verbindungsabbruch |
Bug behoben: FORCE_ALPHA=0.15 war zu träge — der geglättete Kraftvektor folgte der echten Richtung so langsam, dass der Roboter beim Drehen immer wieder die Stopp-Schwelle überschoss und neu anfing zu drehen → Endlos-Spin.
v011 — Feedforward-Architektur (aktuell auf ESP32)
Firmware-Verbesserungen:
Neue Feedforward-Architektur: u = kS·sign(v) + kV·|v| + PID(error)
- kS (Haftreibungskompensation): Fester PWM-Wert um Haftreibung zu überwinden
- kV (Kennlinien-Linearisierung): PWM proportional zur Sollgeschwindigkeit
- PID regelt nur noch den kleinen Restfehler statt alles alleine
- Gleitendes Messfenster
SPEED_WINDOW=3(150ms) für Istgeschwindigkeit — bei 20 Pulsen/Rev ist 50ms zu grob (quantisiertes Rauschen) - Anti-Windup: Integral einfrieren bei PWM-Sättigung
- Option B (aktuell aktiv):
KS=0, KV=0→ reiner PID wie v009, aber mit Messfenster und Anti-Windup
Bugs gefunden und behoben in v011:
Bug 1: Motoren drehten nicht
- Ursache: In v011 wird
current_pwm = ff + pid_out · signdirekt gesetzt statt aufaddiert - Mit
KS=KV=0gibt feedforward() 0 zurück → PWM bleibt auf der ersten Stufe, zu klein für Motoranlauf - Fix: Wenn
KS=KV=0→ aufaddieren wie v009 (current_pwm += pid_out · sign) + PWM_MIN erzwingen
if KS_L == 0.0 and KV_L == 0.0:
current_pwm_l += pid_out_l * sign_l # aufaddieren
if sign_l > 0 and current_pwm_l < PWM_MIN:
current_pwm_l = float(PWM_MIN) # Mindest-PWM
else:
current_pwm_l = ff_l + pid_out_l * sign_l # Feedforward-Modus
8. Deployment (Server)
Voraussetzungen
# Python-Umgebung
python3 -m venv /opt/vision-venv
source /opt/vision-venv/bin/activate
pip install fastapi uvicorn pupil-apriltags opencv-python-headless numpy pyyaml
Aktuellen Stand deployen
# Dateien kopieren
scp -r v010/* root@192.168.0.250:/opt/robot-tracker-v010/
# Server starten
ssh root@192.168.0.250
cd /opt/robot-tracker-v010
/opt/vision-venv/bin/python -m uvicorn app:app --host 0.0.0.0 --port 80
Schnell neu starten
ssh root@192.168.0.250 "pkill -f uvicorn; sleep 1; \
cd /opt/robot-tracker-v010 && \
/opt/vision-venv/bin/python -m uvicorn app:app --host 0.0.0.0 --port 80"
Nur collision.py neu laden (kein Neustart nötig bei Code-Änderungen)
scp collision.py root@192.168.0.250:/opt/robot-tracker-v010/
# dann Server neu starten
Logs einsehen
ssh root@192.168.0.250
ls -lt /opt/robot-tracker-v010/logs/
cat /opt/robot-tracker-v010/logs/nav_20260401_192534.csv | head -5
Log-Format
timestamp, elapsed_s, robot_x_mm, robot_y_mm, robot_theta,
goal_x_mm, goal_y_mm, dist_to_goal_mm, angle_error_deg,
cmd_speed_l, cmd_speed_r, cmd_status,
num_obstacles, nearest_obstacle_id, nearest_obstacle_dist_mm,
all_obstacle_dists
cmd_status kann sein: straight, curving, spinning
9. Firmware flashen (ESP32)
Voraussetzungen
# esptool aus Freenove-Toolchain
~/Downloads/Freenove_ESP32_S3_WROOM_Board_Lite-main/Python/Python_Firmware/
# mpremote für REPL-Zugriff
pip install mpremote
Gerät erkennen
Der ESP32-S3 erscheint unter Ubuntu als /dev/ttyACM0 (native USB, nicht /dev/ttyUSB*).
ls /dev/ttyACM*
MicroPython flashen (nur wenn nötig)
# Flash löschen
python esptool.py --chip esp32s3 --port /dev/ttyACM0 erase_flash
# MicroPython flashen (v1.23.0)
python esptool.py --chip esp32s3 --port /dev/ttyACM0 write_flash \
-z 0x0 ESP32_GENERIC_S3-SPIRAM_OCT-20240602-v1.23.0.bin
Firmware-Datei übertragen
# main.py auf ESP32 kopieren
mpremote connect /dev/ttyACM0 fs cp main.py :main.py
# Neustart
mpremote connect /dev/ttyACM0 reset
REPL für Debugging
mpremote connect /dev/ttyACM0
# Dann Ctrl+C → interaktive Python-Konsole
10. Konfiguration (config.yaml)
camera:
rtsp_url: "rtsp://192.168.0.30:8554/live"
width: 1280
height: 720
rtsp_transport: "udp"
reconnect_delay: 3.0
server:
host: "0.0.0.0"
port: 80
broadcast_hz: 30
tracker:
tag_family: "tag36h11"
detector_threads: 2
quad_decimate: 1.0
ema_alpha_pos: 0.35 # Positions-Glättung (0=träge, 1=roh)
ema_alpha_ang: 0.35 # Winkel-Glättung
ema_alpha_vel: 0.25 # Geschwindigkeits-Glättung
hold_seconds: 0.80 # Tag-Verlust Toleranz
predict_seconds: 0.25 # Prediction-Horizont
robots:
tcp_port: 8765
robot_tag_ids: [91]
goal_radius: 80 # mm — Ziel gilt als erreicht
speed_base: 160 # mm/s — Fahrgeschwindigkeit
speed_turn: 90 # mm/s — Spin-Geschwindigkeit
speed_min: 50
speed_max: 350
angle_threshold: 120 # Grad — nur noch für Spin-Trigger
calibration:
reference_tags:
0: [0.0, 0.0 ]
1: [100.5, 0.0 ]
2: [0.0, 181.0]
3: [100.5, 181.0]
obstacles:
safe_distance: 150 # mm — Abstoßungsbereich
repulsion_strength: 1500 # Stärke der Abstoßung
obstacle_tag_ids: [11,12,21,22,31,32,41,42,51,52,61,62,71,72,81,82,92]
robot_hardware:
wheel_diameter_mm: 67.0
wheel_circumference_mm: 210.5
encoder_pulses_per_rev: 20
mm_per_pulse: 10.525 # 210.5 / 20
axle_width_mm: 121.0 # Radmitte links → Radmitte rechts
pulses_per_360deg: 36.1 # π × axle_width / mm_per_pulse
11. Kommunikationsprotokoll
Server → Roboter (TCP, newline-delimited JSON)
{"speed_l": 160.0, "speed_r": 160.0}
Beide Werte in mm/s. Negativ = rückwärts. 0.0 = Stop.
Roboter → Server (alle 100 ms)
{
"robot_id": 91,
"enc_l": 1234,
"enc_r": 1235,
"speed_l": 158.3,
"speed_r": 161.1,
"pwm_l": 420,
"pwm_r": 435
}
| Feld | Bedeutung |
|---|---|
enc_l/r |
Absoluter Encoder-Zähler (monoton steigend) |
speed_l/r |
Istgeschwindigkeit in mm/s (aus gleitendem Fenster) |
pwm_l/r |
Aktueller PWM-Wert (0–950) |
12. Regler-Tuning
Serverseitig (collision.py)
| Parameter | Aktuell | Wirkung |
|---|---|---|
SPIN_THRESHOLD |
90° | Ab diesem Winkel dreht Roboter auf der Stelle |
SPIN_STOP |
35° | Unterhalb: Spin beendet, Kurvenfahrt beginnt |
SPIN_SLOWDOWN |
60° | Spin wird sanfter |
FORCE_ALPHA |
0.35 | EMA-Glättung des Kraftvektors (0=träge, 1=roh) |
HEADING_DEADBAND |
6° | Winkeltoleranz für Geradeausfahrt |
repulsion_strength |
1500 | Abstoßungsstärke von Hindernissen |
goal_radius |
80 mm | Ziel gilt als erreicht |
ESP32-seitig (main.py) — Option A: Feedforward aktivieren
Schritt 1 — kS bestimmen (Haftreibung):
→ speed_base sehr klein setzen (z.B. 20 mm/s)
→ KS_L/R erhöhen bis Räder gerade anfangen zu drehen
→ Typisch: 130–170
Schritt 2 — kV bestimmen (Kennlinie):
→ speed_base = 160 mm/s, KS bereits gesetzt
→ Log beobachten: pwm_l/pwm_r bei Geradeausfahrt ablesen
→ kV = (PWM_gemessen - kS) / 160
→ Typisch: 2.0–3.5
Schritt 3 — PID reduzieren:
→ KP von 1.2 auf ~0.4 reduzieren
→ KI von 0.3 auf ~0.08 reduzieren
→ KD bleibt ~0.02
Schritt 4 — Links/Rechts-Asymmetrie:
→ kS_L ≠ kS_R fein abgleichen bis Geradeausfahrt ohne Drift
ESP32-seitig — Option B (aktuell): Reiner PID
KS_L = KS_R = 0.0 # Feedforward aus
KV_L = KV_R = 0.0
KP = 1.2
KI = 0.3
KD = 0.05
PWM_MIN = 150 # Erzwungenes Mindest-PWM
13. Bekannte Probleme & Workarounds
| Problem | Ursache | Workaround / Fix |
|---|---|---|
| Endlos-Spin | FORCE_ALPHA zu klein, Kraftvektor folgt zu langsam |
FORCE_ALPHA=0.35, SPIN_THRESHOLD=90° |
| Motoren laufen nicht an | PWM_MIN fehlt im direkten Feedforward-Pfad | PWM_MIN=150 erzwingen wenn KS=0 |
| ESP32 bootet nicht | GPIO 12 belegt (Strapping-Pin) | GPIO 12 nicht verwenden |
| ESP32 beschädigt | Gleichzeitig USB + Powerbank + Motoren | Stets separate Stromkreise! |
| Kamera-Freeze | ffmpeg verliert RTSP-Stream | Watchdog mit Auto-Reconnect in v005+ |
| Tag nicht erkannt | Schlechte Lichtverhältnisse | Gleichmäßige Beleuchtung, möglichst kein direktes Sonnenlicht |
| Ziel nie erreicht | goal_radius zu klein, Kamera-Jitter |
goal_radius auf 100–120 mm erhöhen |
| Ziel wird weggedrückt | Hindernis-Repulsion nahe am Ziel | repulsion_strength bei kleiner dist_to_goal abschwächen (TODO) |
14. Roadmap
Kurzfristig (Tuning)
- Feedforward-Koeffizienten
kS,kVexperimentell bestimmen und aktivieren goal_radiusauf 100 mm erhöhen- Repulsion nahe am Ziel abschwächen
axle_width_mmundpulses_per_360degexakt nachmessen
Mittelfristig (Architektur)
- v/ω-Regler statt direktem Innen-/Außenrad-Schema (
collision.py) - Weiches Dead-Reckoning/Vision-Fusion (kein harter Sprung bei Tag-Wiedersehen)
- Mehrere Roboter gleichzeitig (IDs 91, 92, ...)
- Seeed Grove I2C TB6612 für einfachere Multi-Roboter-Verdrahtung
Langfristig (Unterrichts-Interface)
- Blockly-Interface für Schülerinnen und Schüler
- Ziel per Klick im Browser setzen (bereits teilweise vorhanden)
- Mehrere Ziele als Route definieren
- Begegnungs-/Kooperationsszenarien
Lizenz
Entwickelt für Unterrichtszwecke an der Pädagogischen Hochschule Weingarten.
Internes Projekt — nicht zur öffentlichen Weiterverbreitung bestimmt.
Zuletzt aktualisiert: April 2026 — v011 Firmware, v010 Server