--- name: proxi-control description: Steuert den Proxi-Roboter. Nutze diesen Skill, wenn jemand will, dass Proxi etwas tut — laufen, tanzen, sich umschauen, ein Gesicht zeigen, etwas sagen, Hindernisse suchen. --- # Proxi steuern Proxi ist ein kleiner zweibeiniger Roboter mit einem micro:bit als Kopf. Du schickst ihm Textbefehle über die Brücke und übersetzt damit, was der Mensch in Alltagssprache will. ## Befehle senden Du brauchst **keine Dateien und kein Python**. Die Brücke läuft als Dienst auf dem Raspberry Pi und ist über HTTP erreichbar — `curl` genügt. Die Adresse der Brücke steht in der Umgebungsvariablen `PROXI_URL`: ```bash PROXI="${PROXI_URL:?PROXI_URL ist nicht gesetzt — Adresse der Proxi-Brücke, z.B. http://proxi.local:8080}" ``` Ist sie nicht gesetzt, sag das dem Menschen, statt eine Adresse zu raten. Sie hängt davon ab, wo die Brücke läuft — typisch ist der Hostname des Raspberry Pi plus Port 8080, notfalls dessen IP-Adresse. Ein einzelner Befehl: ```bash curl -sX POST $PROXI/command \ -H 'Content-Type: application/json' \ -d '{"command":"MOVE:FWD:1000"}' ``` Mehrere am Stück — die Brücke arbeitet sie der Reihe nach ab, inklusive der `WAIT`-Pausen. **So schickst du Choreografien:** ```bash curl -sX POST $PROXI/commands \ -H 'Content-Type: application/json' \ -d '{"commands":["FACE:HAPPY","MELODY:FUNK","TURN:LEFT:400","WAIT:450","TURN:RIGHT:400","WAIT:450","STOP"]}' ``` Nachsehen, ob Proxi überhaupt da ist: ```bash curl -s $PROXI/status # {"connected": true, ...} ``` Steht dort `"connected": false`, ist Proxi ausgeschaltet oder außer Reichweite. Sag das dem Menschen, statt Befehle ins Leere zu schicken — die Brücke verbindet sich von selbst, sobald er eingeschaltet wird. ### Nicht selbst starten `proxi_bridge.py` brauchst du nicht und sollst du **nicht** aufrufen. Das Skript liegt auf dem Pi und läuft dort bereits als Dienst. Eine zweite Instanz würde scheitern: Bluetooth LE erlaubt nur **eine** Verbindung zum Roboter, und die hält der Dienst. Alles läuft über HTTP. ## Was Proxi kann | Befehl | Wirkung | |---|---| | `MOVE:FWD[:ms]` / `MOVE:BWD[:ms]` / `MOVE:STOP` | laufen | | `TURN:LEFT[:ms]` / `TURN:RIGHT[:ms]` / `TURN:STOP` | Oberkörper drehen | | `DANCE[:n]` / `STAMP[:n]` / `SHAKE[:n]` | tanzen, aufstampfen, Kopf schütteln | | `FACE:` / `FACE:RAW:z0:z1:z2:z3:z4` | Gesicht zeigen | | `TEXT:` | Text über das Display laufen lassen | | `MELODY:` / `TONE:[:ms]` | Musik und Töne | | `SENSOR:ALL` / `SENSOR:IR_L` / `SENSOR:IR_R` | Sensoren lesen | | `CLEAR` / `STOP` / `PING` / `STATUS` | System | Die vollständige Liste aller Namen für `FACE` und `MELODY` steht in [`docs/PROTOCOL.md`](../docs/PROTOCOL.md). Rate keine Namen — nimm einen aus der Liste oder frag nach. ## Regeln **Es gibt keine Geschwindigkeit.** Die Motoren können nur an oder aus. Alles, was du steuerst, ist die *Dauer*. "Langsam" gibt es nicht — "kurz" schon. Erfinde keinen Speed-Parameter. **Realistische Zeiten.** Grobe Anhaltspunkte, jeder Untergrund ist anders: | Was | Dauer | |---|---| | ein, zwei Schritte | 800–1500 ms | | durchs Zimmer | 4000–6000 ms | | Vierteldrehung | ~700 ms | | halbe Drehung | ~1400 ms | **Zwischen Bewegungen `WAIT:` setzen.** Bewegungsbefehle kommen sofort mit `OK` zurück und laufen dann weiter — ohne Pause überschreibt der nächste Befehl die noch laufende Bewegung, und Proxi zuckt nur. `WAIT` ist eine Pause in der Brücke, kein Befehl an den Roboter. Immer etwas länger als die Bewegung davor: ``` MOVE:FWD:1200 WAIT:1400 TURN:LEFT:700 WAIT:900 ``` **Immer mit `STOP` enden**, wenn eine Bewegungsfolge fertig ist. **Ohne Dauer stoppt eine Bewegung nach 10 Sekunden von selbst.** Nutze `:0` nur, wenn wirklich bis auf Weiteres gefahren werden soll — und dann mit einem klaren `STOP` danach. **Lauf- und Drehmotor sind unabhängig.** Beide zusammen ergibt eine Kurve: `MOVE:FWD:0` plus `TURN:LEFT:800`. **Für Choreografien: `MOVE` und `TURN` laufen parallel zur Musik, `DANCE`, `STAMP` und `SHAKE` nicht.** Die drei Figuren teilen sich mit `MELODY` und `TEXT` denselben Arbeiter und kommen deshalb erst dran, wenn die Melodie fertig ist — bei `MELODY:NYAN` also 16 Sekunden später. Soll zur Musik getanzt werden, bau die Schritte aus `MOVE` und `TURN`: Wackeln ist `TURN:LEFT:220` / `TURN:RIGHT:220` im Wechsel, Stampfen `MOVE:FWD:200` / `MOVE:BWD:200`, eine Kurve `MOVE:FWD:0` plus `TURN`. `DANCE` und Co. gehören vor oder nach die Melodie, nicht mittenrein. Ein fertiges Beispiel liegt in `bridge/nyan-dance.txt`. **Aber immer nur ein Klang.** Ein neues `MELODY` oder `TONE` bricht das ab, was gerade läuft. Soll eine Melodie ausklingen, gib ihr mit `WAIT` Zeit, bevor der nächste Ton kommt. ## Kleine Choreografie Auf "Proxi, freu dich!": ```json {"commands": [ "FACE:FABULOUS", "MELODY:POWERUP", "STAMP:2", "WAIT:1200", "TURN:LEFT:600", "WAIT:800", "TURN:RIGHT:1200", "WAIT:1400", "TURN:LEFT:600", "WAIT:800", "DANCE:2", "WAIT:1500", "FACE:HEART", "STOP" ]} ``` ## Eine Choreografie zur Musik bauen Das ist die Königsdisziplin — und es gibt ein paar Regeln, ohne die es auseinanderfällt. Geschickt wird eine Choreografie als eine einzige Liste an `POST /commands`, mit `WAIT` als Taktgeber dazwischen. **Getanzt wird mit `MOVE` und `TURN`, nicht mit `DANCE`.** Nur die beiden laufen wirklich parallel zur Musik. **Melodien reihen sich von selbst aneinander.** Schickst du `MELODY:B`, während A noch läuft, startet B nahtlos danach. So baust du mehrteilige Stücke. **Rechne mit den Laufzeiten.** So lange spielt jede Melodie: | | | |---|---| | ~0,5–1 s | `BADING` `JUMPUP` `JUMPDOWN` `POWERUP` `POWERDOWN` | | ~2,5–3,5 s | `WAWAWAWAA` `PUNCHLINE` `RINGTONE` `BADDY` `ENTERTAINER` `FUNERAL` | | ~4 s | `DADADUM` `FUNK` | | ~8 s | `CHASE` `WEDDING` `PRELUDE` | | ~12 s | `BIRTHDAY` `BLUES` | | ~16 s | `ODE` `NYAN` | **`WAIT` ist rund 150 ms kürzer als die Bewegung davor** — so lange braucht die Brücke selbst zwischen zwei Befehlen. Ohne diesen Abzug läuft der Tanz der Musik davon. **Tanzschritte bestehen aus drei Bausteinen:** ``` Wackeln TURN:LEFT:220 / TURN:RIGHT:220 im Wechsel Stampfen MOVE:FWD:200 / MOVE:BWD:200 im Wechsel Kurve MOVE:FWD:0 + TURN währenddessen, danach MOVE:STOP ``` Kurze Zeiten wirken hektisch, lange gemütlich. Genau daraus entsteht Rhythmus. **Ein vollständiges Beispiel** (vier Teile, 30 Sekunden) steht kommentiert in `bridge/bigdance.txt` im Repo. Die Zeilen dort sind genau die Liste, die an `POST /commands` geht — Zeilen mit `#` sind Kommentare und werden weggelassen. **Jeder Abschnitt bekommt ein eigenes Gesicht** — das macht aus einer Bewegungsfolge eine Aufführung. **Gleich viel vorwärts wie rückwärts**, dann bleibt Proxi ungefähr da, wo er losgetanzt ist. Und am Ende immer `STOP`. ## Sensoren nutzen `SENSOR:IR_L` und `SENSOR:IR_R` liefern 0–1023, **höher heißt näher**. Am Gerät gemessen: freie Sicht 5–15, Hand in etwa 10 cm 200–600, direkt davor bis ~980. Ab 400 steht etwas im Weg — das entspricht ungefähr einer Handbreit. **Proxi kann kein Licht messen.** Der Helligkeitssensor sitzt hinter einer getönten Scheibe und ist deshalb nicht angeschlossen. Sag nicht, Proxi könne sehen, ob es hell oder dunkel ist — er kann es nicht. Soll Proxi einem Hindernis ausweichen, fahr in kurzen Etappen und miss dazwischen, statt blind eine lange Strecke zu setzen: ``` SENSOR:ALL -> SENSOR:ALL:IR_L=12,IR_R=640,... rechts ist was -> nach links ausweichen TURN:LEFT:700 WAIT:900 MOVE:FWD:1200 WAIT:1400 SENSOR:ALL ``` ## Wenn nichts passiert Kommt `OK` zurück, aber Proxi bewegt sich nicht: `SENSOR:PWR` abfragen. Steht da `0`, ist Proxis Schalter aus (der micro:bit hängt dann nur am USB-Strom). Sag das dem Menschen, statt weiter Fahrbefehle zu schicken. ## Sicherheit Proxi fährt auf dem Boden herum, oft mit einem Kind daneben. * Keine Dauerfahrten ohne Zeitlimit * Nach jeder Folge `STOP` * Taste A am Roboter ist der Not-Stopp und geht immer, auch ohne Verbindung * Wenn jemand "Stopp" sagt: sofort `STOP` schicken, Nachfragen kommen danach