Skip to content

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/16200. Gleiches gilt für /maps/<id>. BELEGT
  • Fehlt er bei einer Liste, antwortet Django auf GET mit 301 auf 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.typeZeichenkette 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:

  1. Die Antwort auf den PATCH prüfen, nicht nur absenden.
  2. ~~overlays_version vorher 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.
  3. 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:

  1. Fahrtdauern taugen nur, wenn die Strecke frei von Türen, Andockmanövern und Wartepunkten ist. Vorher die Fahrlinie gegen alle Punkte vom type 7 und gegen die Ladestation prüfen.
  2. 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.
  3. 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 name ist 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:

  1. 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.

  1. 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

  1. 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/moves will keinen Schrägstrich — mit Schrägstrich kommt 404. Die Regel ist eine Faustregel, kein Gesetz; im Zweifel beide Formen probieren.
  2. Winkel: /tracked_pose Grad, Fahrbefehle und POST /chassis/pose Bogenmass.
  3. Zustand nur über WebSocket. REST reicht dafür nicht.
  4. Kartenwechsel ohne Lagesetzen ist kein gültiger Zustand. Der Roboter nimmt sonst Aufträge an und fährt nicht.
  5. Geschriebene Zeichnungen wirken erst nach dem Kartenladen.
  6. Ladestation nur als Paar.
  7. Karten überleben restart_service nicht, wenn sie nicht aus dem Cloud-Abgleich stammen.
  8. create_time kommt in Sekunden seit 1970; manche Fassungen liefern Millisekunden. Unterscheidung an der Grössenordnung (unter 10^12^ = Sekunden).
  9. Vollständige Adressen aus Geräteantworten (image_url, pbstream_url) nie ungeprüft abrufen — nur den Pfad übernehmen.
  10. Keine Weiterleitung verfolgen ausser der einen mit angehängtem Schrägstrich auf derselben Adresse. Keiner der 39 bekannten Endpunkte leitet sonst weiter.