1 · Fahrgestell¶
1.1 Grundlagen¶
| Punkt | Wert | Beleg |
|---|---|---|
| Grundadresse | http://<ip>:8090 — reines HTTP, kein TLS |
BELEGT |
| Wurzel | GET / liefert eine Liste der Bereiche |
BELEGT |
| Anmeldung | keine. Wer das Netz erreicht, erreicht das Gerät | BELEGT |
| CORS | keine Kopfzeilen — ein Browser kann das Gerät nicht unmittelbar ansprechen | BELEGT |
| Unterbau | Django mit REST-Gerüst; Fehler kommen mal als HTML-Fehlerseite (exception_value), mal als sauberes JSON ({"map_name":["map with this map name already exists."]}) |
BELEGT |
Warning
Der Schrägstrich am Ende ist Teil der Adresse — und die Regel ist umgekehrt zur Erwartung.
- Listen verlangen ihn:
/maps/,/mappings/,/robot-params/,/services/. - Einzelabrufe vertragen ihn nicht:
/mappings/16/→ 404,/mappings/16→ 200. Gleiches gilt für/maps/<id>. BELEGT - Fehlt er bei einer Liste, antwortet Django auf GET mit
301auf die Fassung mit Schrägstrich — der Verweis kommt relativ („/maps/"). - Bei POST gibt es diese Rettung nicht. Django kann einen POST nicht umleiten, ohne den Rumpf zu verlieren, und wirft stattdessen:
RuntimeError at /maps: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set.— das war der zwei Tage lange „500 beim Karten speichern".
Warning
Zeitverhalten: langsam ist nicht kaputt. Fünf Sekunden Zeitgrenze sind für alles richtig, was im Takt abgefragt wird — aber vier Aufrufe laufen regelmässig darüber hinaus und kommen dann fälschlich als 504 zurück (BELEGT 18./19.08.2026): GET /mappings/, GET /maps/, POST /chassis/pose, POST /chassis/current-map. Für diese vier gilt im uGo-Server eine eigene Grenze von 45 Sekunden — und zwar nur beim Schreiben, damit ein hängendes Gerät die Bedienoberfläche nicht eine Dreiviertelminute blockiert.
1.2 Endpunkte — Karten¶
| Adresse | Verfahren | Zweck / Rumpf | Antwort | Fallstricke |
|---|---|---|---|---|
/maps/ |
GET | Kartenliste | JSON-Liste mit id, uid, map_name, create_time, map_version, overlays_version, image_url, url |
Schrägstrich Pflicht; langsam BELEGT |
/maps/<id>?format=json |
GET | vollständige Karte mit Zeichnungen | zusätzlich overlays, grid_origin_x/y, grid_resolution, pbstream_url, last_modified_time |
ohne Schrägstrich. overlays ist eine eingebettete Zeichenkette, kein Objekt BELEGT |
/maps/ |
POST | Karte anlegen. Rumpf: map_name, occupancy_grid (Base64), carto_map (Base64), grid_origin_x, grid_origin_y, grid_resolution |
201 mit id |
Es wird der Inhalt in Base64 erwartet, nicht die Adressen — die Annahme vom 17.08. war falsch und hat zwei Tage gekostet („Error at /maps/: Incorrect padding"). Doppelter Name → 400 BELEGT |
/maps/<id> |
PATCH | Zeichnungen oder Namen ändern. Rumpf: {"overlays": "<JSON als Zeichenkette>"} oder {"map_name": "…"} |
200 | Am Gerät nicht nachgemessen. Deshalb immer nachlesen, siehe 1.6 HINWEIS |
/maps/<id> |
DELETE | Karte entfernen | 200 | Die aktive Karte nicht löschen — ein Roboter ohne Karte nimmt keine Aufträge mehr an HINWEIS |
/chassis/current-map |
GET | welche Karte aktiv ist | nur ein Steckbrief: id, uid, map_name, create_time, map_version, overlays_version |
Keine overlays, kein Gitterursprung, keine Auflösung. Wer nur das einliest, bekommt eine Karte ohne einen einzigen Punkt — die vollständige Karte steht unter /maps/<id> BELEGT |
/chassis/current-map |
POST | umschalten. Rumpf: {"map_id": 11} |
200 | Danach steht slam_state auf inactive — die Lokalisierung läuft nicht. Ohne anschliessendes POST /chassis/pose nimmt der Roboter jeden Auftrag an und fährt keinen Zentimeter BELEGT 17.08.2026 |
1.3 Endpunkte — Kartenfahrten (Aufnahme)¶
| Adresse | Verfahren | Zweck / Rumpf | Fallstricke |
|---|---|---|---|
/mappings/ |
GET | Liste der Aufnahmen, mit state (running, finished) |
langsam; die Liste wird offenbar aus den abgelegten Karten zusammengebaut BELEGT |
/mappings/ |
POST | Aufnahme starten. Rumpf: {"start_pose_type": "zero" \| "current_pose", "continue_mapping": false} |
Ein zweites POST, während schon eine Aufnahme läuft, ergibt einen RuntimeError at /mappings/ (500). Vorher die Liste auf running prüfen und die laufende übernehmen BELEGT 18.08.2026 |
/mappings/<id> |
GET | Stand der Aufnahme, mit image_url, pbstream_url, grid_origin_x/y, grid_resolution |
ohne Schrägstrich — mit gibt es 404 BELEGT |
/mappings/<id> |
PATCH | beenden. Rumpf: {"state": "finished"} |
Danach rechnet das Gerät noch an Gitter und Bild; rund 2,5 Sekunden warten, sonst sind die Adressen leer BELEGT |
/mappings/<id> |
DELETE | Aufnahme entfernen | HINWEIS |
Die vom Gerät gemeldeten Adressen (image_url, pbstream_url) sind vollständige Adressen mit dem Rechnernamen des Gerätes. Davon wird immer nur der Pfad übernommen; der Rechner ist immer der aus der eigenen Betriebsumgebung. Sonst bestimmte derjenige, der die Antwort fälscht, welche Adresse unser Server abruft.
1.4 Endpunkte — Lage, Fahrt, Zustand¶
| Adresse | Verfahren | Zweck / Rumpf | Antwort | Fallstricke |
|---|---|---|---|---|
/chassis/pose |
GET | — | nur ein Hinweistext („use POST to set current pose") | Als Lagequelle unbrauchbar. Die Lage kommt über den WebSocket BELEGT |
/chassis/pose |
POST | Lage setzen. Rumpf: {"position": [x, y, z], "ori": <Bogenmass>} — z wird mit 0 gefüllt |
200, startet eine neue Bahn (trajectory_id) |
Bogenmass. Läuft in die 5-Sekunden-Grenze, das Gerät lokalisiert sich neu BELEGT |
/chassis/moves |
POST | Fahrauftrag. Rumpf: creator, type (standard | charge), target_x, target_y, target_ori (Bogenmass), bei Ladefahrt zusätzlich charge_retry_count |
Auftrag mit id, state, create_time (Sekunden) |
Andocken misslingt am echten Gerät gelegentlich beim ersten Versuch; der Hersteller setzt hier ebenfalls Wiederholungen (bei uns 5) BELEGT. Ein misslungenes Andocken ist an der Antwort nicht vom gelungenen zu unterscheiden: Fahrt 1943 endete mit state: cancelled nach 125 Sekunden (üblich sind 40), trug dabei aber fail_reason: 0 und fail_reason_str: "None - None" — genau wie jede gelungene Fahrt. Nur state ist auswertbar, fail_reason nicht BELEGT 21.08.2026 |
/chassis/moves/<id> |
GET | Stand einer Fahrt, vollständig | state, type, target_x, target_y, target_z, target_ori, target_accuracy, use_target_zone, is_charging, charge_retry_count, fail_reason, fail_message, rack_area_id, properties, create_time, last_modified_time |
Kein progress, kein distance_remaining. Der Fortschritt kommt über den WebSocket. Immer prüfen, ob die zurückgegebene id die abgefragte ist — im Netz kann jeder Aufträge anlegen BELEGT |
/chassis/moves |
GET | letzte Fahrten | Liste, neueste zuerst | Kurzfassung ohne Zielkoordinaten. Geliefert werden nur id, creator, state, type, is_charging, fail_reason, fail_reason_str, fail_message, create_time, last_modified_time. Wer Positionen braucht, ruft jede Fahrt einzeln ab. Ohne Schrägstrich — /chassis/moves/ ergibt 404 (Ausnahme zu Fallstrick 1) BELEGT 21.08.2026. Einzelne unlesbare Einträge überspringen, nicht die ganze Liste verwerfen — nach einem Verbindungsverlust ist sie das einzige Mittel, den eigenen Auftrag wiederzufinden |
/chassis/state |
GET | — | 404, der Pfad existiert nicht | Steht in fremden Beispielen, an diesem Gerät gibt es ihn nicht. Zustand siehe /chassis/status und WebSocket BELEGT 21.08.2026 |
/chassis/moves/<id> |
PATCH | abbrechen. Rumpf: {"state": "cancelled"} |
Auftrag | Ein Pausieren ist in der Schnittstelle OFFEN — ob {"state":"paused"} oder ein Dienst unter /services/ das kann, ist nicht belegt |
/chassis/status |
GET | Zustand | nur control_mode, emergency_stop_pressed, wheel_overloaded |
Kein slam_state, kein moving, keine current_move_id, keine Fehlerliste. Der Adapter kann all diese Felder lesen — dieses Gerät liefert sie hier nicht BELEGT |
/battery-state |
GET | Ladezustand | eine HTML-Seite, kein JSON | Existiert, ist aber maschinell nicht verwendbar. Ladezustand kommt über den WebSocket BELEGT |
/device/info |
GET | Steckbrief des Gerätes: Seriennummer, Modell, Rufname, Fassungen, Fussabdruck, Fähigkeiten (caps) |
JSON | Verschachtelt: Seriennummer/Modell/Rufname unter device, Fussabdruck unter robot, caps ganz oben. Vor dem Einlesen einmal flachklopfen BELEGT |
1.5 Endpunkte — Fahrwerte und Dienste¶
Danger
Sicherheitsaussage, und sie gehört genau so in den Vertrag mit dem Hersteller: GET /robot-params/ liefert die Fahrwerte des Gerätes, unter anderem max_forward_velocity: 1.2. Derselbe Pfad nimmt POST und übernimmt die geänderten Werte. Ohne jede Anmeldung. BELEGT
Damit kann jeder, der das Netz des Roboters erreicht, die Höchstgeschwindigkeit eines Fahrzeugs verändern, das in einem Krankenhausflur unterwegs ist. Der einzige Schutz ist heute die Netztrennung — im Gerät selbst liegt keiner. Der uGo-Server reicht /robot-params/ deshalb zwar durch (er reicht alles durch), aber jede Oberfläche, die dort schreibt, muss die Anmeldung selbst verlangen.
| Adresse | Verfahren | Zweck | Beleg |
|---|---|---|---|
/robot-params/ |
GET | Fahrwerte lesen, u. a. max_forward_velocity: 1.2 |
BELEGT |
/robot-params/ |
POST | Fahrwerte ändern — über das Netz, ohne Anmeldung | BELEGT |
/services/ |
GET | Liste der anstossbaren Dienste, darunter restart_service |
BELEGT |
/services/<name> |
POST | Dienst anstossen, Rumpf {}. Im laufenden Betrieb vertretbar: wheel_control/clear_errors, wheel_control/reset_wheels, baseboard/power_on_lidar, imu/recalibrate. Nicht auf einen Bildschirm gehören: Shutdown, Reset Occupancy Grid, Reset Wheel (hart), Neustart des Fahrdienstes |
HINWEIS |
| Uhrzeit / Zeitzone | — | Wo die Uhr des Fahrgestells steht, ist nicht bekannt. Geprüft wurden /system/settings, /system/time, /device/time, /device/timezone, /chassis/time, /services/system/set_time. Der Hersteller meldet supportsSystemSettings, nennt aber keinen Pfad |
OFFEN |
Danger
Selbst angelegte Karten überleben restart_service nicht. Zweimal gemessen am 19.08.2026: eine über POST /maps/ angelegte Karte war nach POST /services/restart_service verschwunden — auch dann, wenn ihr eine Kennung im Format der Herstellercloud (24 Hexzeichen) mitgegeben wurde. Das Format ist also nicht das Kriterium. Übrig blieben beide Male nur die Karten aus dem Cloud-Abgleich.
Ursache offen — vermutlich verwirft das Gerät beim Neustart alles, was sein Cloud-Abgleich nicht kennt; belegt ist das nicht. Gegenmittel ist gebaut: jede angelegte Karte wird örtlich mitgeschrieben (lib/server/kartenarchiv.ts, Endpunkt /api/kartenarchiv) und lässt sich zurückspielen. Die Cloud ist die zweite Ebene darüber.
1.6 Zeichnungen (overlays)¶
Punkte, Zonen und Fahrspuren liegen zusammen im Feld overlays der Karte — als GeoJSON-FeatureCollection, eingebettet als Zeichenkette. Beim Lesen also erst JSON.parse, beim Schreiben wieder JSON.stringify. Fehlt das Feld oder ist es unlesbar, ist die richtige Antwort eine leere Sammlung und kein Fehler: eine Karte ohne Zeichnungen ist ein gültiger Zustand.
| Geometrie | Was es ist | Artfeld |
|---|---|---|
Point |
Punkt (Station, Ladestation, Tür) | properties.type — Zeichenkette mit einer Zahl darin |
Polygon |
Zone | properties.regionType |
LineString |
Fahrspur | properties.lineType — belegt ist "1" mit direction 3; was die 3 bedeutet, ist OFFEN |
Weitere Felder eines Punktes: name, yaw (Grad), iconYaw (Grad, nur Darstellung), mapOverlay: true, startType, endType (Bedeutung OFFEN), deviceIds (nur Typ 9), deviceId (nur Typ 7, MAC des Türcontrollers), dockingPointId (Typ 9 und 36). Die Kennung id ist am Gerät 24 Hexzeichen.
Zwei Fassungsnummern, getrennt geführt: map_version für das Belegungsgitter, overlays_version für Punkte und Zonen. Eine verschobene Zone ändert nur die zweite — damit lässt sich der teure Bildabruf sparen. Das Gerät liefert die Nummer mal als Zahl, mal als Zeichenkette.
Warning
Schreiben ist ungeprüft — deshalb dreifach nachlesen. PATCH /maps/<id> mit einem neuen overlays ist bis 20.08.2026 nie an einem echten Gerät gemessen worden, weder für Punkte noch für Zonen. Wer dagegen programmiert, baut auf Misstrauen:
- Die Antwort auf den PATCH prüfen, nicht nur absenden.
- ~~
overlays_versionvorher und nachher lesen.~~ Am 21.08.2026 widerlegt: eine vierte Zone kam hinzu, die Fassungsnummer blieb auf 1. Die Fassungsnummer ist an diesem Gerät kein Anzeiger für Änderungen — sie darf weder als Beleg noch als Sparmassnahme beim Bildabruf verwendet werden. - Inhaltlich nachlesen, ob die Zone bzw. der Punkt wirklich da ist. Die Fassungsnummer sagt nur, dass geschrieben wurde, nicht was. Und: ob das Gerät unsere Kennung übernimmt oder eine eigene vergibt, ist OFFEN — deshalb zusätzlich über den Namen suchen, bevor ein Vorgang als gescheitert gilt.
Danger
Eine nachträglich geschriebene Überlagerung wirkt erst nach dem Kartenladen. BELEGT: derselbe Ladepunkt scheitert unmittelbar nach dem Schreiben und funktioniert, nachdem die Karte neu geladen wurde (POST /chassis/current-map). Das Gerät hält die Zeichnungen offenbar im Speicher und liest sie nur beim Kartenwechsel neu ein.
Folge für jeden Ablauf: Punkt oder Zone schreiben → Karte neu laden → erst dann darauf fahren. Wer diesen Schritt weglässt, misst nicht die Schnittstelle, sondern einen alten Stand. Nach dem Kartenladen steht slam_state auf inactive, also muss die Lage gleich mitgesetzt werden (siehe 1.4).
1.7 Punktarten¶
Die Namen aller Arten sind aus dem Herstellerportal („Edit POI") bekannt, die Zahlen nur für vier. Der Nummernraum ist lückenhaft, weil das Angebot vom eingestellten Geschäftsszenario abhängt. Vollständig samt Belastbarkeit steht das in src/lib/chassis/point-types.ts; die confidence-Angaben von dort sind hier unverändert übernommen.
| Zahl | Art | Belastbarkeit | Anmerkung |
|---|---|---|---|
| 9 | Ladestation (Charging Pile) | BELEGT | Trägt deviceIds und dockingPointId. Nie allein, siehe 1.9 |
| 36 | Andockpunkt (Docking Point) | BELEGT | Steht in keiner Auswahlliste des Portals. Zubehör der Ladestation, kein eigenes Fahrziel — gehört nicht in Auswahllisten der Bedienoberfläche |
| 7 | Tür/Schranke (Gate) | BELEGT | Feld deviceId trägt die MAC-Adresse des Türcontrollers. Achtung: „Electric Door" ist im Portal eine eigene Art neben Gate; ihre Zahl ist OFFEN und darf nicht mit 7 verwechselt werden |
| 11 | Lieferpunkt (Delivery Point) | VORSICHT | Unter der Zahl 11 liegen am Gerät die Stationen A, B, C. Dass das dem Portal-Eintrag „Delivery Point" entspricht, ist plausibel, aber nicht belegt — denkbar wäre auch „Dispatch Point" oder eine szenarioabhängige Station |
| — | Empfang, Firma, Arbeitsplatzkennung, Wartepunkt, Aufzug, Aufzug-Wartepunkt, Elektrische Tür, Verteilpunkt, Regalpunkt, Sonstiges | OFFEN | Namen bekannt, Zahlen nicht |
Regel für unbekannte Zahlen: nie verwerfen. Sie werden als Art unknown durchgereicht, behalten ihre Zahl und bekommen die Anzeige „Unbekannte Art (Nummer X)". Eine verworfene Zahl ist eine Information weniger; eine geratene ist eine Information zu viel.
1.8 Zonen¶
regionType |
Bedeutung | Belastbarkeit |
|---|---|---|
| 2 | Langsamzone | BELEGT 20.08.2026 |
| Sperrzone | Zahl unbekannt | OFFEN |
| weitere 23 Portalarten | namentlich bekannt, Zahlen unbekannt | OFFEN |
Die Messung zu regionType 2 (zwei unabhängige Fahrten, 20.08.2026):
| innerhalb | ausserhalb | |
|---|---|---|
| Median | 0,26 m/s | 0,55 m/s |
| Höchstwert | 0,36 m/s | 1,24 m/s |
Die Innenwerte beider Fahrten sind praktisch deckungsgleich (Median 0,256 und 0,268, Höchstwert 0,359 und 0,354). Damit ist regionType 2 belegt die Langsamzone.
Warning
Ein zweiter Messversuch am 21.08.2026 wurde durchgeführt und wieder verworfen. Er ist hier festgehalten, weil der Fehlschluss lehrreich ist und der Weg dorthin sonst ein zweites Mal gegangen wird.
Verfahren: Geschwindigkeit je Fahrtabschnitt aus der Fahrtenliste — Luftlinie vom vorigen
zum neuen Ziel, geteilt durch last_modified_time − create_time. Fünf Umläufe einer
vierteiligen Tour, Fahrten 1937 bis 1961. Der Reiz des Verfahrens: es braucht keine
Lagequelle, und seit GET /chassis/pose als Hinweistext entlarvt ist, ist das viel wert.
Das Ergebnis sah überzeugend aus — ein Abschnitt brauchte 6,74 Sekunden je Meter, die übrigen 3,45 bis 4,31, Verhältnis 0,53 gegen die 0,47 der Lagemessung vom Vortag.
Es war trotzdem falsch. Der Abgleich der Fahrstrecken gegen die Zonenumrisse derselben Karte zeigte das Gegenteil:
| Abschnitt | Strecke in Zonen | Zeit je Meter |
|---|---|---|
| Ladestation → A | 0,00 m von 3,94 m | 4,31 s/m |
| A → B | 1,28 m von 3,41 m (37 %) | 6,74 s/m |
| B → C | 3,02 m von 5,55 m (54 %) | 3,60 s/m |
| C → Ladestation | 3,90 m von 11,59 m (34 %) | 3,49 s/m |
Der Abschnitt mit dem grössten Zonenanteil ist der schnellste. Damit ist die Zonenwirkung
als Erklärung erledigt. Auf dem einen langsamen Abschnitt sitzt ausserdem eine Tür
(type 7) 0,12 m neben der Fahrlinie, und die ursprünglich als Gegenprobe gedachte
Rückfahrt zur Ladestation ist eine Ladefahrt mit Andockmanöver — zwei einfachere
Erklärungen, beide auf demselben Abschnitt, nicht voneinander zu trennen.
Drei Lehren, die bleiben:
- Fahrtdauern taugen nur, wenn die Strecke frei von Türen, Andockmanövern und Wartepunkten
ist. Vorher die Fahrlinie gegen alle Punkte vom
type 7und gegen die Ladestation prüfen. - Ein fester Aufwand je Fahrt — Anfahren, Ausrichten, Türhandschlag — trifft kurze Abschnitte hart und lange kaum. Zwei Abschnitte sind nur vergleichbar, wenn sie ähnlich lang sind und dieselben Hindernisse haben.
- Ein Zonenumriss ist kein Rechteck. Der umschliessende Rahmen sagt nichts darüber, ob eine Fahrlinie die Zone wirklich schneidet. Es muss gegen den Streckenzug gerechnet werden.
Massgeblich für regionType 2 bleibt allein die Lagemessung vom 20.08.2026 in der Tabelle
darüber. Sie ist davon nicht berührt: sie hat echte Positionen über die Zeit verglichen.
Offen und wichtiger als der verworfene Befund: ob die gezeichneten Zonen zum Messzeitpunkt überhaupt wirksam waren. Die Karte war seit dem Zeichnen nicht neu geladen — genau der Fallstrick aus Abschnitt 1.6. Wenn eine in der Bedienoberfläche gezeichnete Zone bis zum nächsten Kartenladen nichts tut, ist das ein Auslieferungshindernis und kein Randthema.
Success
Aufgelöst am 22.08.2026: unsere Zonen waren nie fehlerhaft — sie waren nie geladen.
Der Abend hatte den Befund geliefert, dass eine geschriebene regionType 2-Zone nicht bremst
und dass die Bedienoberfläche des Herstellers nur die beiden Zonen aus der Herstellerkarte
zeichnet, nicht unsere beiden. Zwei Vermutungen wurden geprüft und beide widerlegt:
- Die Kennung ist es nicht. Unsere Zonen tragen Kennungen, deren Zeitstempel auf 2056 und 2076 zeigt, die des Herstellers auf 2026. Aber unsere Punkte tragen ebenso unsinnige Zeitstempel (1985, 2002, 2057, 2060) und werden anstandslos gezeichnet. Eine Zone bekam testweise eine echte Kennung — ohne Wirkung.
- Das Feld
nameist es nicht. Der Zone wurde der Name entfernt — ohne Wirkung.
Die Ursache ist der eigene Fallstrick aus Abschnitt 1.6, nur schärfer als bisher formuliert: das Fahrgestell liest Zeichnungen ausschliesslich beim Kartenladen ein. Ein Neuladen derselben Karte genügt dabei offenbar nicht zuverlässig. Erst der Wechsel auf eine andere Karte und zurück brachte alle vier Zonen zur Anzeige.
Zwei Folgen, beide gross:
- Die Messung vom 21.08. abends misst einen nicht geladenen Zustand und sagt nichts über die Zonenwirkung. Die Lagemessung vom 20.08.2026 (0,26 gegen 0,55 m/s) bleibt damit unwidersprochen. Gegenprobe am selben Abend, mit geladenen Zonen — die Wirkung ist belegt. Dieselbe Tour, dasselbe Verfahren, Fahrten 1986 bis 1996:
| Abschnitt | Strecke | Zonenanteil vorher → nachher | Dauer vorher → nachher | Zeit je Meter |
|---|---|---|---|---|
| Ladestation → A | 3,94 m | 0 % → 41 % | 17 s → 30 s | 4,31 → 7,61 s/m |
| B → C | 5,55 m | 17 % → 53 % | 20 s → 25 s | 3,60 → 4,50 s/m |
| C → A | 8,82 m | 34 % → 58 % | 31 s → 40 s | 3,52 → 4,54 s/m |
| A → B | 3,41 m | 37 % → 57 % | 23 s → 23 s | 6,74 → 6,89 s/m |
Der Abschnitt, der von null auf 41 Prozent Zonenanteil kam, braucht 76 Prozent mehr Zeit.
Zwei weitere Abschnitte werden um rund ein Viertel langsamer. Nur A → B bleibt unverändert —
dort sitzt die Tür D1 0,12 m neben der Fahrlinie, und der Türhandschlag dominiert die
Dauer so stark, dass die Zone daneben nicht mehr ins Gewicht fällt.
Damit ist regionType 2 mit zwei unabhängigen Verfahren belegt: über die Lage am
20.08.2026 und über die Abschnittsdauern am 22.08.2026. Vorbedingung ist beide Male, dass die
Karte nach dem Zeichnen gewechselt und neu geladen wurde.
- Für die Bedienoberfläche ist das ein Auslieferungshindernis. Wer eine Zone zeichnet, sieht sie sofort farbig in der Karte — und sie wirkt nicht. Die Oberfläche muss den Kartenwechsel selbst auslösen oder unmissverständlich sagen, dass die Zone erst nach dem Laden gilt. Ohne das ist jede gezeichnete Zone eine Zusage, die das Gerät nicht hält.
Danger
Die Zahl der Sperrzone wird nicht geraten, und der Grund ist kein formaler. Eine Sperrzone mit falscher Nummer sieht auf dem Bildschirm richtig aus — sie liegt sichtbar in der Karte, farbig, benannt — und der Roboter fährt trotzdem in den Treppenabgang. Eine falsch gezeichnete Langsamzone kostet dagegen höchstens Tempo. Solange die Nummer nicht am Gerät belegt ist, legt das Werkzeug ausschliesslich regionType 2 an (src/lib/server/zonen-zeichnungen.ts). Wer eine Sperrzone braucht, misst sie vorher am Gerät — er rät sie nicht.
Zonenparameter. Zonen tragen ausser der Art auch Werte. Belegt ist das aus dem Portal für „Sloping Area": Voreinstellung 0,3 m/s, Bereich 0 bis 1,2 m/s (HINWEIS). Unter welchem Feldnamen der Wert im overlays steht, ist OFFEN{ .bad } — deshalb wird beim Lesen gegen mehrere Kandidaten geprüft (speed, speedLimit, maxSpeed, speed_limit). Für „Slow-moving Area" ist ein Geschwindigkeitsparameter nur VORSICHT, Grenzen und Voreinstellung sind nicht abgelesen.
1.9 Die Ladestation ist ein Paar — nie ein einzelner Punkt¶
Danger
Am Fahrgestell besteht eine Ladestation aus zwei Punkten: Typ 9 (die Station) und Typ 36 (der Andockpunkt davor), gegenseitig über dockingPointId verknüpft. Fehlt der Partner, sucht das Fahrgestell beim Ladebefehl ein Ladegerät an dieser Stelle und findet keins:
failed to find charger with pos(-1.737,2.352,89.000)
Ein von Hand angelegter Ladepunkt war immer nur ein halber. Das hat einen halben Tag gekostet.
Das gemessene, funktionierende Paar (20.08.2026, Gerät 8982504805371oD; in den Karten 10, 11, 19 und 21 identisch, weil es dieselbe Station ist):
| Punkt | Koordinaten | yaw |
iconYaw |
|---|---|---|---|
| Ladestation (Typ 9) | (-0.0283, -0.3990) | 86 | 364 — das ist 4, nur nicht gekürzt |
| Andockpunkt (Typ 36) | ( 0.0344, 0.4981) | 266 | 184 |
| Beziehung | Wert |
|---|---|
| Abstand Station → Andockpunkt | 0,899 m |
| Richtung Station → Andockpunkt | 86,0° — exakt der yaw der Station |
yaw des Andockpunktes |
266° = yaw der Station + 180 |
iconYaw |
yaw − 82 (mod 360). Wofür die 82 steht, ist OFFEN; der Wert wirkt rein auf die Darstellung |
Ehrlich dazu: das ist ein gemessenes Paar. Die vier Karten tragen identische Koordinaten — das ist dieselbe Messung viermal, nicht vier Messungen. Ob 0,899 m eine Konstante der Baureihe ist oder an der Bauform dieser Station hängt, ist OFFEN. Im Code steht die Zahl deshalb als benannte Grösse (ANDOCK_ABSTAND_METER, src/routes/service/+page.svelte) und nicht mitten im Ablauf.
deviceIds trägt die Seriennummer des ROBOTERS, nicht eine Kennung des Ladegerätes: am funktionierenden Paar steht dort ["8982504805371oD"], und das ist das Fahrgestell selbst. Das Feld sagt also „welche Roboter dürfen hier laden". Genau deshalb ist eine Ladestation keine Abhängigkeit von der Herstellercloud — alles, was hineingehört, kennt das Gerät selbst.
Formunterschied, der nachgebildet werden muss: am funktionierenden Paar ist type eine Zeichenkette, yaw bei der Station dagegen eine Zahl — anders als bei allen übrigen Punkten, wo auch yaw eine Zeichenkette ist. Beim Andockpunkt ist yaw wieder eine Zeichenkette. Warum, ist OFFEN; wir bilden es nach, statt es zu begradigen.
1.10 WebSocket /ws/v2/topics — die einzige Quelle für Zustand¶
Zustand, Ladezustand, Lage und Fahrtfortschritt gibt es an diesem Gerät ausschliesslich über die Dauerverbindung. Die REST-Endpunkte dafür liefern entweder Hinweistext (/chassis/pose), HTML (/battery-state) oder zu wenig Felder (/chassis/status, /chassis/moves/…).
Adresse: ws://<ip>:8090/ws/v2/topics. Anmeldung je Thema nach dem Verbinden, ein JSON je Thema: {"enable_topic": "/tracked_pose"}. Was nicht bestellt wird, kommt nicht.
| Thema | Wofür | Achtung |
|---|---|---|
/tracked_pose |
Lage und Ausrichtung | ori in Grad — anders als überall sonst |
/battery_state |
Ladezustand | percentage kommt je nach Fassung als 0…1 oder 0…100. power_supply_status: nur charging heisst „hängt am Strom" — full meldet das Gerät auch mitten im Raum |
/slam/state |
Lokalisierung | Nach einem Kartenwechsel inactive. Als „arbeitet" gelten nur positioning, slam, mapping, active, localizing — eine Ja-Liste, keine Nein-Liste |
/planning_state |
Fahrtfortschritt, Restweg | — |
/wheel_state |
Räder | — |
/robot/footprint, /nav_thumbnail |
bewusst nicht bestellt | Der Umriss steht schon in /device/info, das Vorschaubild braucht die Oberfläche nicht |
1.11 Fallstricke in Kurzform¶
- Schrägstrich: Listen mit, Einzelabrufe ohne. POST ohne Schrägstrich auf eine Liste ergibt einen 500er, keinen Umzug. Ausnahme, gemessen am 21.08.2026:
/chassis/moveswill keinen Schrägstrich — mit Schrägstrich kommt 404. Die Regel ist eine Faustregel, kein Gesetz; im Zweifel beide Formen probieren. - Winkel:
/tracked_poseGrad, Fahrbefehle undPOST /chassis/poseBogenmass. - Zustand nur über WebSocket. REST reicht dafür nicht.
- Kartenwechsel ohne Lagesetzen ist kein gültiger Zustand. Der Roboter nimmt sonst Aufträge an und fährt nicht.
- Geschriebene Zeichnungen wirken erst nach dem Kartenladen.
- Ladestation nur als Paar.
- Karten überleben
restart_servicenicht, wenn sie nicht aus dem Cloud-Abgleich stammen. create_timekommt in Sekunden seit 1970; manche Fassungen liefern Millisekunden. Unterscheidung an der Grössenordnung (unter 10^12^ = Sekunden).- Vollständige Adressen aus Geräteantworten (
image_url,pbstream_url) nie ungeprüft abrufen — nur den Pfad übernehmen. - Keine Weiterleitung verfolgen ausser der einen mit angehängtem Schrägstrich auf derselben Adresse. Keiner der 39 bekannten Endpunkte leitet sonst weiter.