ARBot

Třetí verze softwaru, od června 2026

Čím si projekt prošel

Co se kdy ukázalo jako problém, co se s tím udělalo a co ještě čeká. Každá položka vede do dokumentace v repozitáři, kde jsou čísla a měření.

Časová osa

Měsíc po měsíci

červenec 2026

srpen 2026

září 2026

říjen 2026

Oblast

Lokalizace a fúze senzorů

Náklon robota jde mimo fúzi (řídicí smyčka bere poslední došlé IMU)

otevřeno vada nalezeno 11. 8. 2026

Řídicí smyčka bere roll a pitch z posledního došlého IMU vzorku, který nenese identitu zdroje - při dvou IMU (VN100 a T265) může náklon mezi tiky přeskakovat mezi čidly s jinou montáží a kvalitou. Obchází to fúzi: bez gatingu, bez kovariance a bez dopředikování do času tiku, zatímco zbytek stavu robota fúzovaný je. Návrh je přidat náklon do stavového vektoru EKF jako regulérní měření; je to zásah do filtru a zatím se neudělal. Od 13. 9. 2026 je T265 z robota odpojená natrvalo (rozhodnutí v decisions.md) a od 26. 9. se v runtime ani nezakládá, takže přeskakování náklonu mezi dvěma IMU nastat nemůže. **Identitu zdroje IMUState nese už od 4. 9. 2026** (Name, formát verze 2; VN100, virtuální IMU i T265 ho vyplňují — zjištěno 30. 9., popis to do té doby tvrdil opak); ControlLoop ji ale nepoužívá, při dvou IMU by pořád vyhrávalo „poslední došlé". Zůstává obcházení fúze (bez gatingu, kovariance a dopředikování). **Autor 30. 9. 2026:** mezikrok (výběr IMU pro náklon podle jména / absolutního kurzu) zamítnut — správné řešení je dát náklony do EKF, a to **spolu s odhadem chyb senzorů** (lok-bias-senzoru-jako-stav-ekf). Do té doby zůstává otevřené.

čeká na Chyby senzorů (bias kompasu a gyra) jako stavy EKF · ekf-fusion.md, imu-and-frames.md · DevLog 2026-08-11, 2026-09-30

Chyby senzorů (bias kompasu a gyra) jako stavy EKF

otevřeno záměr nalezeno 25. 8. 2026

Podnět autora: místo přidávání dalších referencí kurzu odhadovat bias kompasu a gyra přímo ve stavovém vektoru filtru — dvě nezávislé absolutní reference (kompas, GPS kurz) na to stačí, mapa není potřeba. Úkol byl 25. 8. gatovaný potvrzením, že skutečný VN100 nějaký bias vůbec má (ten 3° v simulaci vnutil člověk). To se potvrdilo v terénu 7. 9. (kurz o 24° vedle, po kalibraci magnetometru zbývá konstanta −3,7°). Zůstává cílem; 12. 9. se místo něj sáhlo po podlaze sigmy a škrcení kompasu, „na stav EKF teď není prostor". ✅ **Potvrzení z HW 18. 9. 2026:** s kalibrovaným magnetometrem má kompas proti GPS kurzu bias −2,5 / −1,6° (sd ~4°), na protilehlých kurzech stejný, ale mezi běhy jiný — tedy reálný, malý a pomalu proměnný bias, přesně případ pro stav EKF, ne pro konstantu v konfiguraci. Brána „potvrdit na reálném HW" je tím splněná.

  • Přístroj na rozpor dvou absolutních referencí bez ground truth (ARBot.Analyze heading --nogt) 25. 8. 2026
  • Potvrdit bias kompasu na skutečném senzoru záznamem se smyčkou 7. 9. 2026
  • Bias kompasu a gyra jako stavy EKF (varianta B)
  • Spolu s tím dát do stavu EKF i náklony (pitch/roll) — rozhodnutí autora 30. 9. 2026, téma lok-ekf-pitch-roll-stav

ekf-fusion.md · DevLog 2026-08-25, 2026-09-07, 2026-09-12, 2026-09-18, 2026-09-30

Chyba GPS fixu je korelovaná ~40 s, filtr ji bere jako nezávislou

otevřeno vada nalezeno 6. 9. 2026

Nový ARBot.Analyze gps využívá, že stojící robot dává pravdu zadarmo: chyba fixu má p50 4,4 m a dekorelační čas ~40 s, takže průměrování nepomůže vůbec, a filtr přitom bere 10 fixů za sekundu jako nezávislé — odhad ujíždí 5,5 m/min s časovou konstantou 57 s a hlásí sigmu 0,074 m. Prozatímní léčba: gpsposstd je parametr a v provozním profilu je 30 m (20× ze √400 korelovaných vzorků), jen pro Pi, ne jako default. Skutečná léčba je decimace nebo offset GPS jako stav EKF; za jízdy dekorelační čas změřit nešlo, nejdelší souvislá jízda v záznamech je 45 s. 17. 9. 2026 se za jízdy změřit DAL: souvislý úsek 215 s a 96 m dal dekorelační čas ~40 s (zbytek po zarovnání proti mrtvému odhadu z kol p50 3,58 m, p90 7,58 m) — tedy stejný řád jako ze stání, ale pořád jen ~5 nezávislých vzorků, takže je to orientační číslo. Ze stání (55 s) měl fix odchylku od průměru segmentu p50 9,68 m a maximum 17,3 m, průměrovací křivka je plochá (činitel nadsazení 10,6× při N = 100) a změřené Kalmanovo zesílení 0,32/0,29 říká, že GPS odhad pořád táhne. Tím je vysvětlené, co obsluha viděla na stránce po kalibraci magnetometru — poloha o „3–4 metry ujetá": chyba fixu té velikosti drží desítky sekund, takže nevypadá jako šum, ale jako posunutá stopa. Podmínky byly toho dne slabé: 4–6 družic a DOP 6,8–12, tedy na hraně brány gpsmaxdop=10 (na startu se zamítlo 136, resp. 205 fixů po sobě).

  • ARBot.Analyze gps (drift, K, tau, autokorelace, blok A2b za jízdy) 6. 9. 2026
  • gpsposstd= jako parametr, 30 m v pi-provoz.cfg 6. 9. 2026
  • Ověřit násobek na novém záznamu ze stání (drift a tau se mají posunout 20×)
  • Souvislá jízda 5–10 minut bez zastavení pro dekorelační čas za jízdy
  • První měření za jízdy (17. 9., úsek 215 s / 96 m → T_d ~40 s); na 5–10 min to nestačí 17. 9. 2026
  • 1. 10. 2026 (gps): stání v Tracku (83 s, GPS výborná, 13–15 družic, HDOP 1,4–1,8) — odchylka fixu od průměru p50 0,17–0,47 m, T_d ~15–25 s z ~7 vzorků; kratší než tau a jiná kvalita než 6. 9., násobek 20× tím potvrdit nejde. Souvislá jízda FreeRun 583 s / 774 m: T_d ~60 s (~10 vzorků). Úsek Tracku je pro blok A2b nepoužitelný (skok enkodérů při záseku 15:15:41). ⚠️ Vady měřidla gps: nečte gpsposstd/gpsdopsigma ze záznamu (počítá s 1,5 m), A2b nedělí úsek na skoku enkodérů a kurz mrtvého odhadu bere z rozdílu kol 7. 10. 2026
  • Opravit měřidlo gps (konfigurace ze záznamu přes LogConfig, dělení A2b na skoku enkodérů, kurz z fúze/IMU) a přeměřit FreeRun 1. 10.
  • Decimace nebo offset GPS jako stav EKF

čeká na Chyby senzorů (bias kompasu a gyra) jako stavy EKF · ekf-fusion.md, configuration.md, GpsReport.cs · DevLog 2026-09-06, 2026-09-17, 2026-10-07

Chyba kurzu z GPS není bílý šum a GPS běží 10 Hz, ne 5

otevřeno vada nalezeno 12. 9. 2026

Dotaz autora na původ σ kurzu z GPS vedl k měření: sousední fixy se liší jen o ~1°, ale chyba s odstupem roste a usadí se na 8,4° / 4,1° při dekorelačním čase 10 / 5 s. Filtr bere fixy jako nezávislé, takže počtivá σ je 83° / 29°; model atan2(0,3; v) dává 23°, tedy trefuje zhruba správně, ale ze špatného důvodu (příčný šum rychlosti je ve skutečnosti 0,007 m/s). Zároveň se opravilo, že GPS chodí 10 Hz — všechny přepočty byly dvakrát vedle, frekvence se teď měří. Důsledek pro kompas: jeho bias je korelovaný na stovky sekund, počtivá σ by byla ~1 200°, takže podlaha 5° je pořád řádově málo. Léčba (podlaha v desítkách stupňů, další škrcení, nebo bias jako stav EKF) není rozhodnutá. 18. 9. 2026 s kalibrovaným kompasem: velikost biasu je 1–3,5° a sd ~4°, takže 5° sedí na velikost chyby — „řádově málo" se týká jen její časové korelace, obě tvrzení platí zároveň.

  • Korelace chyby GPS kurzu změřena (ARBot.Analyze heading) 12. 9. 2026
  • Frekvence GPS se měří (FixRateHz), tři místa s natvrdo 5 Hz opravena 12. 9. 2026
  • Rozhodnout, jak σ obou referencí kurzu narovnat
  • Přeměřeno při vyšší rychlosti 1. 10. 2026 (heading): FreeRun (v p50 1,40 m/s) σ GPS kurzu 2,21°, usazení na lagu 10 s, poctivá σ 21,9° proti modelu 12,1°; Track (1,69 m/s) σ 2,72°, usazení až na lagu 40 s, poctivá σ 54° proti modelu 10,1°. Při vyšší rychlosti model atan2(0,3; v) „náhodou sedí“ přestává platit — je 2–5× optimističtější. GPS kurz sám je spolehlivý (Doppler − směr posunu 0,2 ± 3,2–3,8°) 7. 10. 2026

čeká na Chyby senzorů (bias kompasu a gyra) jako stavy EKF · ekf-fusion.md · DevLog 2026-09-12, 2026-09-18, 2026-10-07

Při jízdě FreeRun na jih ujel kurz VN100 i odhadu o desítky až 180° (atitudové řešení senzoru přestalo brát magnetometr)

otevřeno vada nalezeno 24. 9. 2026

Autor 23. 9. 2026 na cyklostezce v Modřanech (OSM/modrany2.osm): tam (mise Track, na sever) kurz seděl, zpět (FreeRun, na jih) se kurz odhadu postupně stáčel, ačkoli robot jel stále na jih. **Rozbor záznamů 24. 9.** (records/test/20260923-144934.rec, -145648.rec; ARBot.Analyze heading bloky *DRIFT PROTI GYRU* a *SMĚR POSUNU*, vn100): robot podle GPS jel celou dobu na azimut 170–184°, ale **VN100 yaw šel 166 → 100 → 4 → 323°** (za 5 min) a ve druhém běhu 152 → 18° (za 2 min), tedy **doleva = k VÝCHODU** (autor 24. 9. potvrdil, že se spletl ve stranách — bylo to na východ; id tématu zůstává). Kurz odhadu a stopa na mapě šly s ním (azimut kurzu odhadu 177 → 73°, posun odhadu 160 → 15°), fúze se jen zpožďovala (odhad − IMU yaw −20 až −54°). **Magnetometr je v pořádku:** |B| 0,495 G konstantní, sklon 66,4° (reference 65,95°), kurz z pole − GPS kurz +4,7 ± 5,7° (≈ deklinace) — **od pole se odtrhl až yaw senzoru** (kurz z pole − yaw 1,5 → −33 → −103 → 168°), zesílení VPE k poli K ≈ 0 (−0,0035 ± 0,0013 1/s). GPS kurz je spolehlivý (Doppler − směr posunu polohy −0,3 ± 3,5°). **Proti integrálu gyra ujíždí GPS kurz** (−62° za 330 s, resp. −154° za 150 s, tj. až ~1 °/s), zatímco VN yaw se od gyra odchýlí jen o +35 až +130° — nahrávané gyro je ImuGroup.Gyro = **AngularRate, kompenzované odhadem biasu z Kalmanova filtru VN** (ICD kap. 2.4.11), takže bias ~1 °/s je nejspíš **chybný odhad biasu uvnitř VPE**, ne fyzický gyroskop (surové UncompGyro se nenahrává, takže to dokázané není). Ve stání čte gyro 126–365 °/h proti −4,6 °/h ze 7. 9. Týž den v Track (20260923-143515.rec) bylo K = 0,010 (τ ~100 s proti 28–53 s 18. 9.) a drift gyra −26° za 10 min, tedy stejná vada slabší. Po restartu aplikace (zápis registru 83 magmodel=) začal VN yaw znovu u pravdy a pak ujel rychleji. **Fúze to nezachytila**, protože IMU/gyro jde do EKF v plné kadenci (nese většinu informace o úhlové rychlosti) a GPS kurz má σ atan2(0,3; v) ≈ 21° — a koridor v Modřanech nedal ani jedno měření (lok-koridor-siroka-cyklostezka). Hypotéza „korekce z mapy táhnou kurz“ tím padá: koridor neposlal nic. ⚠️ Registry senzoru (35, 36, 38, 83, 43) v záznamu nejsou.

  • Rozbor záznamu z 23. 9.: ARBot.Analyze heading (IMU − GPS kurz podle směru, --bin=), vn100 blok 5 (železo), odhad − IMU yaw, přiřazená hrana a posílaný kurz v RoadCorridorMsg 24. 9. 2026
  • Read-only deploy/vnprobe.sh na senzoru: registr 35 (heading mode, adaptivní filtrování), 36/38 (VPE ladění mag/acc), 83, 43 (startovní bias gyra). Očekávané hodnoty z exportu ARBot2 + historie zápisů: 35 = 1,0,1,1, 36/38 jako export, 43 = (0,0,0), 83 s UseMagModel=1 (magmodel=). Registr 43 sonda do 24. 9. nečetla, doplněn. Nižší priorita než záznam s UncompGyro — registry neřeknou, proč VPE za jízdy magnetometr utlumila. Přečteno 25. 9.: 35–38 a 43 přesně podle exportu, 44 = Run (vada, hw-vn100-hsi-run-ve-flash) 25. 9. 2026
  • Nahrávat i UncompGyro (a teplotu) vedle Gyro — rozliší chybný odhad biasu ve VPE od skutečného gyra. V kódu 24. 9. (IMUState verze 5, YprRate vyřazen kvůli lince, vn100 blok 6); na zařízení neběželo 24. 9. 2026
  • Jízda se záznamem verze 5: ARBot.Analyze vn100 blok 6 — mění se bias filtru, nebo syrové gyro? ✅ 29. 9. 2026 (20260929-150844.rec Track na sever, -151634.rec FreeRun na jih, Modřany; pro srovnání 25. a 27. 9.): bias, který filtr VN odečítá v ose Z (Gyro − UncompGyro), je **3 400–4 060 °/h (~1 °/s)** a uvnitř jízdy stabilní (25. 9. 1 540–2 040, 27. 9. 1 110–1 550 °/h). **Kompenzované gyro přitom sedí:** GPS kurz − ∫gyro za ~7 min jen +9° / −30°, tedy nejvýš ~0,07 °/s. Offset ~1 °/s má tedy **syrové gyro** a VPE ho odhaduje správně — ne chybný odhad biasu jako 23. 9. Napříč pěti záznamy roste bias s teplotou senzoru (28–31 °C → 1,1–1,5 tis., 31–36 °C → 1,5–2,0 tis., 47–54 °C → 3,4–4,1 tis. °/h), uvnitř jízdy ale ne (Track: teplota klesá 54 → 52 °C, bias roste), takže je to jen podezření; 29. 9. byl senzor ohřátý dlouhým stáním na slunci (autor), viz hw-vn100-zmena-po-27-9. Velký drift z 23. 9. se nezopakoval, jen slabší podoba: ve FreeRun na jih se yaw za 7 min odtrhl od vlastního magnetometru (kurz z pole − yaw +1,3 → −22°) a IMU yaw − GPS kurz došel na +25° 29. 9. 2026
  • Měřidlo vn100 blok 6: sloupec „syrové gyro Z ve stání“ je nepoužitelný — stání pozná jen podle proudu motorů pod 0,5 A, takže zahrnuje i otáčení a doběh (29. 9. průměry po minutách skáčou o ±12 000 °/h). Stání brát z nulové rychlosti kol a GPS (ne z gyra, to by výběr zkreslilo)
  • Hypotéza FW (25. 9. 2026): senzor má FW 3.0.0.0, aktuální je v3.1.0.0 (březen 2023). Týž FW jel dobře 12. a 18. 9., takže sám drift nevysvětlí; ukáže-li jízda s UncompGyro, že ujíždí jen odhad biasu ve VPE (syrové gyro čisté), zjistit u VectorNavu (S/N 100016133), co 3.1 opravuje, a zvážit update — po něm znovu nahrát konfiguraci i kalibraci (vnrestore.sh) a ověřit vnprobe.sh. ⚠️ 29. 9. předpoklad nenastal: syrové gyro čisté není (offset ~1 °/s) a odhad biasu ve VPE seděl. Jízda ale velký drift z 23. 9. nezopakovala, takže to hypotézu nevyvrací
  • Pojistka ve fúzi: trvalý rozpor VN yaw / integrál gyra proti GPS kurzu za jízdy (Doppler je ověřeně spolehlivý) = VN přestat věřit, případně bias gyra jako stav EKF
  • Jízdy 1. 10. 2026 (záznam v5; heading --bin=60, vn100): v Tracku na jižní větvi se yaw VN100 znovu odtrhl od vlastního magnetometru, slaběji než 23. 9. — „kurz z pole − yaw“ mimo ±7° od 15:05:38 do 15:20:38, nejvíc −28,6°; IMU yaw − GPS kurz +23 až +35° (15:08:38–15:12:38), po obrátce na sever −18°; kompenzované gyro proti GPS kurzu ujelo −46° za 9 min (~0,085 °/s); bias filtru v ose Z 3 200–3 600 °/h při ~51 °C, 2 060–2 110 °/h při ~43 °C. **FÚZE TO USTÁLA:** odhad − GPS kurz nejvýš 4,2° — podle protifaktu (fusionreplay bez koridoru ujede 35–43 m od sítě) díky koridoru. FreeRun na jih bez ujetí. K hypotéze FW: syrové gyro čisté není a odhad biasu ve VPE se mýlí ~0,06–0,085 °/s, předpoklad kroku tedy znovu nenastal 7. 10. 2026

imu-and-frames.md, ekf-fusion.md, HeadingReferencesReport.cs, mission-freerun.md · DevLog 2026-09-24, 2026-09-25, 2026-09-29, 2026-10-07

Při otočení robotem rukou fúze věří kolům místo gyra — kurz zaostane o 11–13°

otevřeno vada nalezeno 7. 10. 2026

1. 10. 2026 (20261001-144638.rec, 15:27:34,5–35,2) obsluha otočila stojícím robotem o ~60° (gyro až 110 °/s). Smyčka přitom velela opačnou rotaci a kola se točila proti tělu (prokluz), fúzní ω spadlo na 5–13 °/s a kurz fúze zaostal za gyrem o 11–13°. Ve světové soustavě to PoseJumpDetector vzal jako skok kurzu a grid smazal (což náhodou ukončilo 132s RobotBlocked). ⚠️ V odometrické soustavě (localframe=odom, integruje fúzní v, ω) by grid po takovém zásahu zůstal pootočený o ~13° (obsah ve 3 m posunutý o ~0,7 m) a detektor by nic nehlásil — odvozené, na HW neověřené. V běžné jízdě se integrál gyra s kurzem fúze shoduje do ±2° za 10 s.

  • Změřeno nad 1. 10. (gyro proti kolům, příkazu a kurzu fúze kolem 15:27:35) 7. 10. 2026
  • Rozhodnout (autor): rozpor gyro / kola nad prahem = věřit gyru (prokluz), nebo aspoň hlásit

ekf-fusion.md · DevLog 2026-10-07

Koridor přiřadil 1,3 m široký chodník k ulici 4,9 m vedle a posunul pózu o 4,8 m

otevřeno vada nalezeno 7. 10. 2026

20260918-154028.rec 15:47:02,5–04,8 (binárka 9f649a0, bez corridorslew): robot na chodníku souběžném s ulicí (service 230064212, v mapě bez tagu width). Koridor změřil šířku 1,2–1,4 m; jakmile naučená šířka (1,3 m) nahradila mapové 3,0 m, prošla šířková brána. Service byla jediný kandidát (χ² 3,6), fúze přijala NIS 216 s R×1 a póza skočila o 4,8 m na osu ulice; grid se smazal a globální navigace přestala vidět, že je robot 4,9 m mimo trasu. Naučená šířka se bere jako šířka kterékoli hrany, takže úzký souběžný pás projde bránou široké ulice. Dnes by limit kroku skok rozložil na ~10 s a localframe=odom by neposunul grid; přiřazení samo by nejspíš proběhlo stejně (odvozeno, nepřehráno).

  • Nalezeno nad 18. 9. (zasek, scratch rozbor RoadCorridorMsg / MeasurementDiagMsg, snímky) 7. 10. 2026
  • Přehrát přiřazení nad 381–384 s dnešním EdgeAssociator (assocwhy / assocreplay) a rozhodnout o vazbě naučené šířky na hranu

map-correlation-localization.md · DevLog 2026-10-07

V 90° zatáčce koridor 7–14 s neměří (nejednoznačnost sousedních úseků téže cesty) a chybu pak opraví sérií korekcí 1,5–3 m

otevřeno vada nalezeno 7. 10. 2026

Jízdy 1. 10. 2026 v Modřanech (20261001-144638.rec, -152906.rec). Po léčbě assocfloorlong=3 (lok-assoc-sousedni-usek) je AmbiguousEdge na rovinkách 0–3 %, ale **do 30 m od dvou 90° zatáček 14–69 %** cyklů za jízdy: zakřivená cesta je v OSM lomená čára po 4–8 m s úseky lišícími se o 10–20° a sousední úsek téže cesty je legitimní druhý kandidát. Koridor má v zatáčce Ok jen 5–31 % cyklů (před ní 51–94 %), nejdelší mezera bez měření 7–14 s (4–16 m). Nesoulad pózy s mapou mezitím naroste na 1,5–3 m a koridor ho na výjezdu vrátí sérií korekcí (NIS 50–102). Korekce jdou správným směrem, ale grid ve světě se tím posune proti robotu (lp-uvaznuti-v-zatackach). Směr cesty z kamery je v zatáčce tětivou vychýlený o 10–24° ve směru zatáčení; když robot v zatáčce stál, stáhl tím kurz fúze o ~7° (odvozeno). Slepota sama zastavení nerozliší (FreeRun zatáčku projel s AmbiguousEdge 75 %).

  • Změřeno nad 6 průjezdy Tracku a 2 FreeRunu (corridor, assocwhy, scratch rozbor po průjezdech) 7. 10. 2026
  • Rozhodnout (autor): zakřivenou cestu přiřazovat jako jednu hypotézu (sousední úseky téže way jako polylinie / oblouk), aby v zatáčce nevycházelo Ambiguous; kurz z koridoru neposílat, když se sousední úseky liší o víc než ~5° nebo robot stojí

map-correlation-localization.md · DevLog 2026-10-07

Lokalizace z hran cesty místo z plochy

v kódu, na HW neověřeno záměr nalezeno 21. 8. 2026 vyřešeno 21. 8. 2026

Plošná korelace platí za informaci, kterou vnitřek cesty nenese; stačí najít hranici cesty, proložit ji přímkou a v místě robota změřit šířku, příčnou polohu a odchylku osy. Spike nad záznamem dal příčnou polohu na 3 cm a směr na 0,8° za 0,1 ms na snímek proti 62–104 ms plošného skenu. Vznikl CorridorFinder, mapová protistrana RoadAxis a stupeň CorridorLocalizer (corridor=), který posílá do fúze příčné a kurzové měření. Od 15. 9. běží v provozním profilu v měřicím režimu (bez vlivu na řízení); první jízda ze zařízení 16. 9. (2 256 cyklů, 424 přijatých). **18. 9. 2026 první jízdy s korekcemi naostro** (20260918-154028.rec, -155329.rec): za jízdy měření v 52–54 % cyklů (rezidua 7 cm, ~43 inlierů na stranu, úsečky 7 m), ve stání 0,6 %; do fúze odešlo 2 821 + 2 889 měření a fúze se jimi řídí (odhad − IMU yaw z ±0,06° na ±1,9°). ⚠️ Přesnost pózy tím ověřená není — s korekcemi naostro je příčný nesouhlas (p50 0,06 m) self-konzistence. Robotour 19. 9.: koridor je jediná příčná reference (za jízdu stáhl 20–28 m driftu), ale skoky pózy 0,6–4 m jdou všechny za ním (lok-koridor-skoky-pozy) — to je dnes to, co koridoru reálně chybí; tři podmínky z lok-korelace-tri-podminky-naostro se u něj obešly.

  • Spike nad záznamem z virtuálních kamer 21. 8. 2026
  • CorridorFinder, RoadAxis, CorridorLocalizer a RoadCorridorMsg v repozitáři 21. 8. 2026
  • Ověřeno během v simulaci (178 měření za 40 s, chyba polohy 0,027 m, kurzu 0,18°) 23. 8. 2026
  • Kvalita hranice na reálné D435 (18. 9.: rezidua 7 cm, ~43 inlierů, dosah 7 m; každá kamera vidí jen svou hranu — křižovatka na trati nebyla) 18. 9. 2026
  • Zapnout posílání korekcí naostro (autor, config/pi-provoz.cfg, commit a44b4f4) 17. 9. 2026
  • První běh na zařízení v měřicím režimu (20260916-164926.rec) 16. 9. 2026
  • Přesnost pózy s korekcemi — A/B na zařízení nejde (dvě jízdy nejsou srovnatelné, autor); nahrazeno dvěma kroky níž 27. 9. 2026
  • Simulace proti pravdě (ARBot.Analyze truth, provozní profil, prokluz 1,8 %, bias kompasu 3°, 2 × 2 běhy): příčná za jízdy p50 0,03 m s korekcemi proti 2,07 m bez, kurz 0,2° proti 1,4°, podélná 1,2 proti 2,3 m 27. 9. 2026
  • Přehrání fúze nad jízdami 25. 9., Kolo 3b, 18. 9. (ARBot.Analyze fusionreplay, měřidlo sedí na záznam p50 0,000 m): příčně od GPS lepší ve všech třech (1,00/1,50, 1,73/3,12, 0,46/0,83 m), podélně ve dvou ze tří mírně horší 27. 9. 2026
  • Dohledat, proč korekce zhoršují PODÉLNOU chybu proti GPS — nalezeno (fusionreplay blok 4): koridor v zatáčkách srazí podélnou σ filtru (Hviezdoslavova 2,23 → 0,39 m), s gpsposstd=30 pak GPS podélně táhne ~30× slaběji a chyba z obvodu kola (+1,8 %) zůstane; kde má malou σ i varianta bez (Kolo 3b), korekce podélně pomáhají 28. 9. 2026
  • Přeměřit podélnou chybu s opraveným obvodem kola (26. 9.) na příští jízdě; pak rozhodnout o poctivější σ GPS (gpsposstd) nebo o nejistotě mapy v corridorstd. ⚠️ 27. 9. nerozhodne: GPS byla sama 4,7 m mimo cestu (3 družice na startu), podélná odchylka od GPS je proto k ničemu. Ukázalo ale, že koridor drží pózu na cestě (od osy 0,36 proti 3,58 m bez) a opakovaný průjezd sedí 0,49 proti 5,58 m bez. ✅ 29. 9. (Modřany, obvod kola opraven, GPS 14 družic, fusionreplay --set=assocfloorlong=3, protože robot jel ještě s nejednoznačností lok-assoc-sousedni-usek): |podélně od GPS| p50 / p90 Track **0,89 / 4,16 s korekcemi proti 1,11 / 2,07 bez**, FreeRun **2,27 / 4,23 proti 1,64 / 4,70**; σ podél 0,91–1,05 proti 1,12–1,22 m (rovná cyklostezka ji nesrazí). Podélná chyba je proti 25. 9. (6–7 m) na 1–2 m a rozdíl s / bez je řádu chyby GPS bez systematického směru — rozhodnutí o gpsposstd / corridorstd tím nic netlačí. Příčně korekce jasně pomáhají: od osy sítě 0,25 / 0,59 m proti 1,75 / 4,85 m, příčně od GPS 1,49 / 0,62 proti 2,73 / 5,08 m, p90 1,97 / 2,07 proti 6,68 / 10,39 m 29. 9. 2026
  • Změřit, jak rychle póza po výpadku koridoru (stání, jedna kamera) spadne na GPS při gpsposstd=30 — ✅ 29. 9. změřeno na skutečném výpadku: Track 20260929-150844.rec poslal korekce jen v první minutě (nejednoznačnost) a |póza − GPS| pak rostl 1,8 → 9,7 m za 6 min (fusionreplay, po minutách), varianta úplně bez koridoru 1,1 → 6,9 m. **Na GPS nespadne vůbec** — póza ujíždí příčně ~0,06 m/s (kurz ~2° vedle) a GPS se σ 30 m ji nevrátí 29. 9. 2026
  • Přehrání fúze nad jízdami 1. 10. 2026 (20261001-144638.rec Track 42 min, -152906.rec FreeRun 10 min; fusionreplay, měřidlo sedí na záznam p50 0,000 m), S koridorem proti BEZ: od osy sítě p50/p90 0,11/0,39 proti 7,63/32,47 m (Track) a 1,03/1,63 proti 2,58/7,52 m (FreeRun, pravá polovina); příčně od GPS 0,82/1,72 proti 6,96/31,64 m a 0,80/1,47 proti 2,79/8,31 m; opakovaný průjezd 0,10/0,34 proti 3,26/8,13 m. Bez koridoru by póza v Tracku 15:10–15:15 ujela od sítě o 35–43 m (tehdy ujel yaw VN100, lok-freerun-kurz-staci-na-zapad) 7. 10. 2026
  • Podélná chyba s korekcemi (1. 10., binárka bez 9afb50c): póza je soustavně PŘED GPS — FreeRun p50 +6,2 m (p90 10,1), roste ~1 m/min; Track na jižní větvi do +10,9 m; bez koridoru 2,8/5,1 m. Koridor srazí podélnou σ (0,23 proti 0,98 m) a GPS se σ 30 m pak nestáhne dráhu nadsazenou o 1,3–1,4 % (lok-fuze-poza-pred-koly); protifakt --set=gpsposstd=3 růst zastaví (2,6/2,8 m). Část (~2–3 m) je zpoždění GPS. Přeměřit s binárkou ≥ 9afb50c; zůstane-li póza před GPS, rozhodnout o gpsposstd / corridorstd

čeká na Póza fúze ujede o ~1 % víc než kola, ačkoli obvod kola sedí · map-correlation-localization.md · DevLog 2026-08-21, 2026-08-23, 2026-09-15, 2026-09-16, 2026-09-18, 2026-09-20, 2026-09-27, 2026-09-28, 2026-09-29, 2026-10-07

Naučená šířka cesty jde dál do mapy — korelaci i kreslení

v kódu, na HW neověřeno záměr nalezeno 15. 9. 2026 vyřešeno 15. 9. 2026

Odhad šířky zůstával uvnitř koridoru a nedosáhl na korelaci s mapou (jediný algoritmický dopad) ani na kreslení. Teď je to neměnný překryv uzel → šířka (roadwidthmap=, výchozí false), graf sítě se nemění, protože ho drží i navigace; scéna korelátoru se atomicky zamění za prahem 0,25 m a odstupem 10 s. Scéna virtuální kamery překryv nedostane, jinak by koridor měřil sám sebe. Autor hned při prvním proklikání našel vadu: do maxima na sdíleném uzlu přispívala i nezměřená cesta svou mapovou hodnotou, takže se naučené zúžení přehlasilo prakticky na celé síti — mapová šířka nezměřené cesty je default, ne důkaz. Perzistence vědomě není; prahy jsou odhad a jdou doladit offline. Na zařízení neběželo.

  • RoadWidthOverrides, RoadWidthMapUpdater, vrstva v mapě i na půdorysu 15. 9. 2026
  • Oprava maxima na sdíleném uzlu, práh proti účinné šířce, hláška s velikostí změny 15. 9. 2026
  • Doladit RebuildThresholdM a MinRebuildPeriodSec z prvního záznamu
  • Data z první jízdy s propisem (1. 10. 2026, 20261001-144638.rec Track, -152906.rec FreeRun, roadwidthmap=true): 112 přestaveb za 42 min a 28 za 10 min, vždy 47 uzlů — jedna šířka pro celou cyklostezku (way 154101921), interval p50 13 s, |změna| p50 0,32 m. ~40 % přestaveb (45 ze 112) kmitá tam a zpět pod 0,4 m v úseku konstantní šířky, práh 0,25 m tedy leží v šumu (s 0,5 m by zbylo 28 a 5). Skutečná šířka má podle oboustranného koridoru dvě úrovně, ~3,4–3,8 a ~4,8–5,4 m, a jedno číslo na cestu mezi nimi přepíná; chybné hodnoty 1,88 a 2,37 m estimátor pustil při úniku a stání. Propis do MapMsg na zařízení běží; kreslení nikdo nekontroloval, korelace nejela (mapcorr=false) 7. 10. 2026
  • Zapnuto roadwidthmap=true v config/pi-provoz.cfg (pokyn autora) — 25. 9. 2026 autor šířku do mapy nepropsanou neviděl, ačkoli estimátor se ji naučil (Track 20260925-143643.rec: 3,68 m proti mapovým 3 m, WidthNotTrusted jen 2,3 %); všechny čtyři záznamy běžely s roadwidthmap=false (default) 25. 9. 2026
  • Ověřit na zařízení

čeká na Tři podmínky, než korekce z mapy pustit naostro · plan-naucena-sirka-do-mapy.md, map-correlation-localization.md · DevLog 2026-09-15, 2026-09-25, 2026-10-07

PoseJumpDetector skok pózy nehlásí, když přijde na snímek s časem pozadu

v kódu, na HW neověřeno vada nalezeno 21. 9. 2026 vyřešeno 1. 10. 2026

Autor z náhledu webu a z měření ví, že při skocích pózy 0,6–4 m z Robotouru 19. 9. (lok-koridor-skoky-pozy) PoseJumpDetector grid **nesmazal** — robot se skokem ocitl mimo sjízdnou oblast staré mapy a přešel do úniku. V kódu je díra, která to vysvětluje: PoseJumpDetector.Check při dt ≤ 0 pózu jen zapamatuje a skok nekontroluje (komentář: „snímky dvou kamer mají jiné časy grabu a mohou přijít přehozené"). Se dvěma D435 po 30 fps chodí snímky s přehozenými razítky běžně, takže skok, který přijde právě na takový snímek, se spolkne a další snímek se už porovnává s pózou po skoku. Ověřeno jen čtením kódu, ne nad záznamem (není na vývojovém stroji). Neopravuje se hned: s limitem kroku (corridorslew=) detektor chránit nemusí, a oprava (porovnávat i při dt ≤ 0, nebo nepřepisovat pamatovanou pózu) chce nejdřív změřit podíl snímků s dt ≤ 0 a četnost skoků, aby nevyrobila bezdůvodná mazání gridu. **Změřeno a opraveno 1. 10. 2026** (ARBot.Analyze fusionreplay, nový blok 7 — póza GetStateAt(čas snímku) v pořadí streamu, replay sedí na RobotStateMsg p50 0,000 m): díra je skutečná, ale **malá**. Snímků s dt ≤ 0 je 22–23 % (prakticky jen pravá kamera, |dt| p50 12–15 ms); spolknuté mazání gridu **2 z 21** (Kolo 3b) a **1 z 10** (Kolo 4), všechna na skutečných skocích 0,55–0,98 m, **žádné zbytečné**. Ze skoků pózy (blok 5) starý detektor grid smazal u 14 ze 14 a 8 z 10, nový u 14 a 9. Propady gridu ve snapshotech OccupancyGridMsg ze skutečné jízdy (Kolo 3b, 9 propadů) sedí časově na mazání, která replay připisuje starému detektoru — **grid se při skocích většinou mazal**, takže pozorování z 19. 9. tahle díra vysvětluje jen zčásti. Oprava: Check při dt ≤ 0 porovnává s |dt| (CheckBackwardTime, výchozí true; false = staré chování pro A/B). ⚠️ Na zařízení neběželo.

  • Změřit nad Kolo3b/Kolo4: podíl volání Process s dt ≤ 0 a kolik skoků z bloku 1 nav připadlo na takový snímek 1. 10. 2026
  • Opravit Check (kontrola posunu i při dt ≤ 0, s |v|·|dt|) a přeměřit počet mazání gridu 1. 10. 2026
  • Ověřit na zařízení (počet GridResets / propady gridu ve snapshotech proti skokům pózy)

PoseJumpDetector.cs, map-correlation-localization.md · DevLog 2026-09-21, 2026-10-01

Póza fúze ujede o ~1 % víc než kola, ačkoli obvod kola sedí

v kódu, na HW neověřeno vada nalezeno 29. 9. 2026 vyřešeno 1. 10. 2026

Vedlejší nález při ověření obvodu kola (lok-odometrie-obvod-kola, 29. 9. 2026): na přímých úsecích je kola / tětiva GPS 0,999, ale **tětiva pózy / tětiva GPS 1,011** v obou jízdách (20260929-150844.rec, -151634.rec; 25. 9. 1,018 proti 1,023). Podélně je póza před GPS o ~1 % dráhy (FreeRun +4 m za 280 s). Měřidlo dráhu z kol nepodhodnocuje (vzorky motorů po 12 ms, žádná mezera ≥ 0,1 s). Integrál V ze stavu fúze vychází o 2–3 % nad dráhou z kol, ale V proti kolům ve stejném okamžiku p50 0,94 (p10–p90 0,89–1,16) — ukazuje to spíš na časový posun mezi RobotStateMsg a MotorStateBase než na měřítko; neprověřeno. GPS s σ 30 m pózu nevrátí, takže to jde 1:1 do podélné chyby. Na rovince dlouhé 1 km je to ~10 m. **Příčina nalezena 1. 10. 2026: razítka odometrie.** SDC2160Ex.GetMeasurement bere razítko na **začátku** čtení (ts = TimeBase.Now před čekáním na řádek DI=) a rychlost počítá jako Δenkodér / Δrazítko. Kontrolér posílá v pravidelné periodě (enkodér přibude v každém vzorku o stejných ~13,8 mm), ale řádky chodí po sériové lince v dávkách, takže razítka mají vzor **12 / 12 / 9 ms** a vzorek po krátkém intervalu hlásí rychlost **1,334×** průměru sousedů (po dlouhém 0,857×). Integrál „hodnota platí zpětně" to vyruší přesně (enkodéry / integrál rychlostí 1,000 — proto posegps a měření obvodu kola sedí), **EKF ale měření drží dopředu**: integrál dopředu 1,032–1,034 × enkodéry, EKF krmený jen Odo/speed **1,0185–1,0192** ve všech čtyřech jízdách (25. 9. a 29. 9.). Rozklad (fusionreplay blok 8): fúze bez GPS i bez koridoru ujede 1,016–1,018 × kola, GPS polohu stahuje zpět na 1,00–1,01 (podle jízdy), korekce z koridoru nepřidávají nic soustavného. Měřidlo posegps (okna vybraná podmínkou na poměr pózy a kol) to nadsazovalo jen o ~0,005. **Protifakt:** rychlost z enkodérů přes okno 3 vzorků (~33 ms, celá perioda dávek) dá **1,0004–1,0008** (jízda s 1,6s mezerami 1,0022), přes 2 vzorky 1,006. Odometrická ω má tutéž vadu, ale gyro ji přehlasuje ~30 : 1. **Léčba (autor, 1. 10. 2026): čas z motorové jednotky.** Skript posílá před blokem telemetrie řádek T=<ms>, SDC2160Ex z něj bere interval pro rychlost i razítko (DeviceClock: posun hodin = minimum příchod − čas jednotky, stoupání omezené driftem, resync po restartu jednotky). Okno rychlosti ve fúzi se dělat nebude. MotorStateBase verze 4 (DeviceTimeMs). Zpětně kompatibilní oběma směry. Skript 2.1 je v jednotce (autor 6. 10. 2026); jízda s ním zatím vyhodnocená není.

  • Změřeno: tětiva pózy 1,011 proti kolům 0,999 (posegps) 29. 9. 2026
  • Najít příčinu: přehrát fúzi jen z odometrie a IMU (fusionreplay) a porovnat dráhu s integrálem kol; prověřit časová razítka stavu proti odometrii. Výsledek: razítka SDC2160Ex (vzor 12/12/9 ms) a rychlost Δenc/Δrazítko držená v EKF dopředu; fusionreplay bloky 8 a 9 1. 10. 2026
  • Rozhodnout léčbu (autor): čas z motorové jednotky (řádek T=); okno rychlosti ve fúzi se nedělá 1. 10. 2026
  • Skript s řádkem T= (Src/RoboRun/RizeniDiffPodvozku.mbs verze 2.1, kopie v komentáři SDC2160Ex.cs), DeviceClock + parsování v driveru, MotorStateBase v4, blok 9 fusionreplay umí čas jednotky; 9 testů DeviceClock, 4 testy driveru / serializace 1. 10. 2026
  • Nahrát RizeniDiffPodvozku.mbs verze 2.1 do jednotky (Roborun+) a ověřit nouzové zastavení a watchdog. **Autor 6. 10. 2026:** verze 2.1 v jednotce je. Ověření nouzového zastavení a watchdogu se přesouvá ke skriptu **2.2** (hw-motor-rampa-jednotky), který mění právě jejich rampu 6. 10. 2026
  • Jízda: fusionreplay blok 9 — čas jednotky ve všech vzorcích, interval ~11 ms, EKF z Odo/speed / enkodéry ~1,000; blok 8 — tětiva pózy / kola ~1,00. Měřit i podélnou chybu pózy na vjezdu do obou 90° zatáček v Modřanech (viz krok níž)
  • Dopad na zařízení 1. 10. 2026 (binárka ještě bez opravy; fusionreplay, posegps, rozbor zatáček): tětiva pózy / tětiva GPS 1,013–1,014, póza / kola 1,017; s korekcemi koridoru je póza soustavně PŘED GPS (FreeRun do +10,7 m, Track na jižní větvi do +10,9 m, po obrátce −9,8 m), protože koridor podélnou σ srazí a GPS se σ 30 m dráhu nestáhne. Na vjezdu do 90° zatáčky se podélná chyba převede na příčnou — u Z1 (po ~830 m rovinky) kamera proti mapě ukazuje ~5,7 m — a je jedním ze zdrojů nesouladu, který pak korekce koridoru vrátí proti gridu ve světě (lp-uvaznuti-v-zatackach) 7. 10. 2026

ekf-fusion.md, SDC2160Ex.cs, rozhodnutí 1. 10. 2026 · DevLog 2026-09-29, 2026-10-01, 2026-10-07

Přiřazení hrany vzalo ulici 15 m od pózy — veto podle rozbitého kurzu vyřadilo bližší cesty a limit 4 hran schoval soupeře

v kódu, na HW neověřeno vada nalezeno 1. 10. 2026 vyřešeno 4. 10. 2026

Vedlejší nález při přeměření lok-koridor-pricna-brana (1. 10. 2026). Přehrání 20260917-160558.rec (Hviezdoslavova, uliční síť) s dnešní konfigurací koridoru (MaxEdgeDistanceM = ∞ od 26. 9., limit kroku, 2 Hz, σ koridoru): přijato 129 cyklů, ale vítězná hrana leží p50 **14 m od pózy a 24,5 m od GPS**, kdežto GPS sedí na síti (p50 2,6 m od osy) — souběžná ulice. Příčina: nejistota polohy z fúze p50 **7,5 m** (gpsposstd=30, binárka ze 17. 9. nevyráběla měření z jedné hrany, takže koridor měřil málo), a χ² se σ 7,5 m pustí hranu do ~20 m. Azimutové veto souběžnou ulici nezastaví (má týž azimut) a odstup od druhého kandidáta jen tehdy, když projde i správná. S limitem odstupu 8 m vede přiřazení na ulici pod GPS (0,17 m, 26 cyklů). Korekce šly skrz škrcení 2 Hz a limit kroku, takže se póza za 6 min posunula jen o ≤ 3 m — na delší jízdě by ji ale táhly na špatnou ulici rychlostí 0,5 m/s. V Modřanech (25. a 29. 9., čtyři jízdy) je ∞ i 8 m totéž (GPS od osy vítěze p50 0,8–1,4 m, σ polohy 0,2–0,9 m): koridor z jedné hrany měří pořád a souběžná ulice tam není. Rozpor s rozborem 29. 9. („podélný přesah nezávisí na limitu, vítěze nezměnil") je jen zdánlivý: ten se dělal nad zaznamenanými pózami (assocwhy), kde byla σ malá. ⚠️ Rozhodčím je GPS (σ 30 m ve městě), přímá pravda k jízdě není; jedna jízda, jedna mapa. **Konkrétní případ na mapě (1. 10. 2026, dotaz autora „jak může projít 14 m vzdálená cesta, když robot po nějaké jede?")** — fusionreplay --dumpassoc=auto --svg=, cyklus 16:07:11.7, obrázky doc/media/assoc-prirazeni-20260917-160711-detail.png a -trasa.png. Podle mapy stojí póza **uprostřed bloku** mezi dvěma souběžnými ulicemi (jižní way 52464567 15,6 m, severní way 230064222 19,4 m) a nejbližší jsou **krátké spojky napříč** (5,6 / 13,2 / 14,6 m). Ty tři vyřadilo **veto azimutu** (−71 až −75° proti směru, který vidí kamery) a čtvrtou nejbližší hranou byla jižní ulice — jediný kandidát, vyhrál bez soupeře (χ² 5,55, σ polohy 8 m). Severní ulice by měla χ² 7,55, tedy rozdíl 2,0 < odstup 4 → **Ambiguous, nic by se neposlalo** — jenže byla až pátou nejbližší hranou a assock=4 počítá **segmenty**, ne cesty, takže sloty sežraly spojky. Proč veto: **kompas byl v té jízdě rozbitý** (compassab: IMU yaw proti směru posunu GPS p50 +61°, sd 74°, na východ +135° — 17. 9. odpoledne, před novou kalibrací, železo kabelů ke kamerám ze 14. 9.), takže směr koridoru převedený do světa byl jinde a veto vyhodilo cesty podle špatného kurzu. GPS se celou jízdu drží u **severní** ulice a spojky #2, tedy ne u vítěze. Dvě slabiny, které platí obecně: (a) veto stojí na kurzu, takže rozbitý kurz vyřadí správnou cestu; (b) limit 4 nejbližších **segmentů** v husté síti skryje soupeře, kvůli kterému by přiřazení správně řeklo „nejednoznačné". Limit odstupu 8 m to dřív jen náhodou zakryl.

  • Změřeno: přiřazení na souběžnou ulici 24,5 m od GPS při σ polohy 7,5 m a odstupu ∞; s 8 m 0,17 m (fusionreplay blok 2, --maxedge=, --set= s dnešním profilem) 1. 10. 2026
  • Konkrétní případ na mapě (fusionreplay --dumpassoc= --svg=): spojky napříč vyřazené vetem podle rozbitého kurzu (kompas +61°), soupeř (severní ulice) mimo 4 nejbližší segmenty — jinak by cyklus vyšel Ambiguous 1. 10. 2026
  • Rozhodnout léčbu (autor): kandidáty řadit podle χ² přes VŠECHNY hrany, bez limitu 4 (návrh autora 4. 10.) 4. 10. 2026
  • V kódu: RoadNetwork.EdgesWithin, EdgeAssociationConfig.Candidates = 0 (všechny, výchozí), assock=0 (1–16 = staré chování pro A/B); 3 nové testy (regrese 17. 9., dlouhá rovná cesta z 40 úseků = jedna hypotéza, EdgesWithin); assocwhy --k= --jelk= s výpisem změn 4. 10. 2026
  • Přeměřeno offline nad 23 jízdami (assocwhy --k=0 proti --k=4): špatně −145, správně −152; 17. 9. všech 77 špatných pryč, 27. 9. po startu 97 správných → nejednoznačné (σ pózy desítky m), 29. 9. +33 a 23. 9. +6 špatných: blízké cesty vypadnou na směru a vzdálenější vyhraje sama 4. 10. 2026
  • Rozhodnout (autor): co s vyhrou osamělé vzdálenější cesty, když blízké vypadnou na směru (29. 9. +33) — odolnost veta / χ² kurzu vůči rozbitému kurzu. **Autor 6. 10. 2026: přijme se hrana, která vyšla nejlépe** — rozbitý kurz se za jízdy poznat nedá, takže se veto ani χ² kurzu kvůli němu neoslabují. Kód beze změny (tak se chová už dnes); vědomě přijaté riziko, rozhodnutí v decisions.md 6. 10. 2026
  • Ověřit na zařízení: podíl AmbiguousEdge a vítěz u GPS (assocwhy, corridor)
  • Přeměřit nad jízdou v uliční síti z binárky s měřením z jedné hrany (Hviezdoslavova po 24. 9.), kde koridor měří častěji a σ polohy tolik neroste
  • Protifakt nad jízdami 1. 10. 2026 (assocwhy --k=0 proti --jelk=4; robot jel ještě s assock=4): neutrální — FreeRun mění 7 cyklů (Ok → Ambiguous, sousední úsek téže cesty), Track 98 Ok → Ambiguous, 24 NoCandidate → Ambiguous, 12 NoCandidate → Ok, 3 na jinou cestu (jen na startu ve stání, σ velká); vybraná cesta zůstává do 2 m od GPS ve 100 %. Souběžnou ulici modřanská trať netestuje 7. 10. 2026

map-correlation-localization.md, EdgeAssociator.cs · DevLog 2026-10-01, 2026-10-07

Korelace occupancy gridu s mapou jako oprava polohy a kurzu

odloženo záměr nalezeno 19. 8. 2026

Semantický kanál lokální mapy (co kamera vidí jako cestu) se porovnává s vozovkou podle OSM a z posunu se odhaduje chyba polohy a kurzu, která jde do fúze jako dvě osová měření a kurz. Jádro, napojení do runtime a 17 telemetrických sloupců vznikly podle dvanáctidílného plánu; první měření hlásilo cyklus 126 ms, 25. 8. se ukázalo, že stojí 1,31 s, celé jádro (Debug 5,5× pomalejší a k měření bezcenný). Ve výchozím stavu se korelátor vůbec nezakládá (mapcorr=false) — nic neřídí a stál by celé jádro (při odstupu 3 s ~40 %); naostro ho pustí až tři podmínky. Na zařízení neběželo. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Jádro, napojení do runtime a telemetrie (plán fáze 1–3) 19. 8. 2026
  • První spuštění v simulaci a naměřená doba cyklu 19. 8. 2026
  • Přepínač Enabled nevypínal výpočet, jen posílání — nový mapcorr= (výchozí false) a přejmenování na SendCorrections 20. 8. 2026
  • Přepínač mapcorrsend= pro A/B se stejnou zátěží 21. 8. 2026
  • Měření na OrangePi (fáze 5 plánu)

čeká na Tři podmínky, než korekce z mapy pustit naostro · map-correlation-localization.md, plan-map-correlation.md · DevLog 2026-08-19, 2026-08-20, 2026-08-21, 2026-09-29

Sigma korelace je slepá k množství důkazu

odloženo vada nalezeno 19. 8. 2026

Nejistota korelace se počítala ze zakřivení normalizovaného skóre, takže nevěděla, kolik buněk za ní stojí — malý oblak důkazu hlásil větší jistotu než velký a na cestě rovnoběžné s osou gridu vycházela falešná podélná jistota. Případ „malý oblak obelže hlídač volné osy" se ukázal být touž vadou a vědomě se neopravoval zvlášť. Léčba přišla 25. 8.: sigma se škáluje vahou informativního důkazu (ReferenceInformativeEvidence), měřeno proti tuze posunuté mapě. Po odečtení chyby fúze v měřidle (samostatné téma) vyšla σ naopak ~1,25× konzervativní a vědomě se neopravuje; na zařízení neběželo. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Falešná podélná jistota potvrzena za běhu (SigmaLoose konečná ve všech cyklech) 19. 8. 2026
  • Malý oblak obelže hlídač — změřeno, že je to táž vada, rozhodnuto neopravovat zvlášť 20. 8. 2026
  • Rozvaha korelace přes FFT / Fourier-Mellin — jako jiný estimátor by pomohla, odloženo do rozhodnutí o přestavbě 20. 8. 2026
  • Honestní sigma změřena nástrojem ARBot.Analyze sigma a opravena 25. 8. 2026

map-correlation-localization.md, rozhodnutí 25. 8. 2026 · DevLog 2026-08-19, 2026-08-20, 2026-08-25, 2026-09-29

Určená osa korelace je vychýlená o 6°

odloženo vada nalezeno 19. 8. 2026

Směr lépe určené osy (TightAxisAngle) vychází soustavně o −6,3° vedle kolmice na cestu, protože fit kvadratiky na skóre tvaru „stan" ho ohýbá. Kdo podle ní rozkládá hlášený posun, dostane u velké podélné nejednoznačnosti o 40 % víc; rozklad se proto převedl na kurz robota. Vada sama zůstává nedotčená. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

map-correlation-localization.md · DevLog 2026-08-19, 2026-08-25, 2026-09-29

Eskalace stavu „lokalizace nepodložená mapou" a znovunalezení po ztrátě

odloženo záměr nalezeno 20. 8. 2026

Když korelace occupancy gridu s mapou shodu nenajde, korelátor jen mlčí — stav „lokalizace nepodložená mapou" si nikdo nečte a navigace věří mrkvi dál stejně. Chybí i schopnost se znovu najít: záchytný rozsah skenu je jen ±2,5 m a ±8°, takže po delším výpadku GNSS nebo po přenesení robota hierarchický sken principiálně nedosáhne. Kandidát na hrubý inicializátor s širokým záběrem je Fourier–Mellinova transformace (jeden výstřel, nízká přesnost, sken to dojemní) — jako náhrada skenu byla 20. 8. 2026 zamítnuta, jako inicializátor sedí. Až bude z dat vidět, jak dlouhé úseky bez shody v praxi vznikají, může GlobalNavigator ubrat nebo mrkvi přestat věřit. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Změřit z dat, jak dlouhé úseky bez shody v praxi vznikají
  • Eskalace stavu do GlobalNavigator (ubrat, přestat věřit mrkvi)
  • Hrubý inicializátor pro široký záběr (kandidát Fourier–Mellin)

map-correlation-localization.md, MapCorrelator.cs, GlobalNavigator.cs · DevLog 2026-08-20, 2026-09-29

Posun mapa–GPS jako stav filtru

odloženo záměr nalezeno 20. 8. 2026

Návrh autora: kamera neměří polohu, ale vztah k cestě, takže by posun mezi rámcem GPS a rámcem mapy mohl být samostatný stav EKF krmený korelací. Týž den se závěr otočil — přímá korekce pózy stačí, protože všechny cíle robota jsou mapově relativní a absolutní přesnost je stejně omezená chybou mapy. Stav bude potřeba až pro použití nezávislé na mapě (návrat do depa podle GNSS, jiný zdroj mapy).

rozhodnutí 20. 8. 2026, map-correlation-localization.md · DevLog 2026-08-20

Tři podmínky, než korekce z mapy pustit naostro

odloženo záměr nalezeno 20. 8. 2026

Korelace s naměřenou sigmou 0,1 m přehlasuje GPS zhruba 400 : 1, takže záchyt na souběžné cestě by unesl pózu a nikdo by to nezastavil. Než se korekce pustí do řízení, musí platit tři věci: honestní sigma, rychlostní limit na aplikovanou korekci a strop na nesouhlas s GPS; k tomu měkký gating místo tvrdého zamítání. První podmínka je od 25. 8. splněná, druhá nemá naměřenou naléhavost, třetí je naměřeně nutná a chybí. Podmínka 2 od 21. 9. 2026: mechanismus (IMeasurement.MaxStep, nafouknutí R v EKF, corridorslew=) v kódu existuje, ale nastavuje ho jen koridor — MapCorrelator ho nepoužívá; naléhavost se 19. 9. změřila na koridoru v téže fúzi (skoky pózy 0,6–4 m, lok-koridor-skoky-pozy). Koridor šel 17. 9. naostro bez podmínek 2 a 3, takže tyhle podmínky dnes gatují jen mapcorr=, který na zařízení nikdy neběžel. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Podmínka 1 — honestní sigma 25. 8. 2026
  • GateMode.Soft místo Reject (tvrdý gate zahazoval právě potřebné korekce) 25. 8. 2026
  • Podmínka 2 — rychlostní limit na aplikovanou korekci (proměřit v běhu bez GPS)
  • Podmínka 3 — strop na kumulovaný nesouhlas s GPS

rozhodnutí 20. 8. 2026, map-correlation-localization.md · DevLog 2026-08-20, 2026-08-25, 2026-09-29

Cykly korelace s mapou nejsou nezávislé — odstup je dekorelační čas 3 s

odloženo vada nalezeno 25. 8. 2026

Fúze bere každé měření jako nezávislé, ale korelace čte tentýž grid s pamětí ~2,5 s, takže dva cykly po sobě říkají skoro totéž a informace se započítá dvakrát (činitel nadsazení 1,9–2,4). Dekorelační čas vyšel 2,85 / 2,93 / 3,31 s na třech bězích s periodou lišící se o 42 %, tedy je to konstanta scény, ne artefakt měření. Léčba je odstup konstrukcí: nejmenší perioda korelace 400 ms → 3 s, po změně je korelace sousedních cyklů záporná a činitel 1,00. Při tom se opravil o řádek špatný údaj o ceně — cyklus stojí 1,31 s (celé jádro), ne ~126 ms; hranice 400 ms byla v praxi mrtvá. Změřeno v simulaci, na zařízení korelace neběžela (mapcorr=false). ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Autokorelace reziduí a dekorelační čas v ARBot.Analyze sigma (tři běhy) 25. 8. 2026
  • MinPeriod 400 ms → 3 s (rozhodnutí autora), ověřeno dvěma běhy 25. 8. 2026
  • Ověřit odstup a cenu cyklu na Orange Pi (se zapnutým mapcorr=)

čeká na Tři podmínky, než korekce z mapy pustit naostro · map-correlation-localization.md, rozhodnutí 25. 8. 2026, SigmaReport.cs · DevLog 2026-08-25, 2026-09-29

Tvrdý gate korekcí z mapy zahazoval právě ty korekce, které byly potřeba

odloženo vada nalezeno 25. 8. 2026

Korekce polohy z korelace occupancy gridu s mapou se poprvé pustily naostro a změřily (ARBot.Analyze corrections): s tvrdým gatem byl výsledek horší, než když se nekorigovalo vůbec (příčná chyba p50 0,67 → 0,85 m), protože gate zamítal 42–46 % korekcí podle velikosti innovace — tedy přesně ty velké, které měly chybu stáhnout. Korelátor přitom hlásil správně. Měkký gate (GateMode.Soft) je od té doby výchozí (0,59 m), mapcorrgate=reject vrací staré chování. Zisk je ale jen 6–13 %, dokud kurz drží kompas; celá korelace je navíc ve výchozím stavu vypnutá (mapcorr=false), takže na zařízení nikdy neběžela. ⏸ **Odloženo 29. 9. 2026 (autor)** spolu s celou korelací occupancy gridu s mapou (mapcorr=false): důvodem zastavení bylo, že cykly korelace nejsou nezávislé, protože sousední cykly korelují z téhož nahromaděného oblaku bodů. Na lokalizaci podle cesty se od té doby používá koridor (corridor=).

  • Přístroj ARBot.Analyze corrections (krok pózy, gating, NIS podle zdroje, chyba proti pravdě) 25. 8. 2026
  • Změřit tvrdý proti měkkému gatu na scéně se skutečným driftem (dva běhy na variantu) 25. 8. 2026
  • GateMode.Soft výchozí 25. 8. 2026
  • Ověřit se zapnutou korelací na zařízení

map-correlation-localization.md, rozhodnutí 25. 8. 2026 · DevLog 2026-08-25, 2026-09-29

Fúze extrapoluje bez omezení — ztráta GPS i IMU robota nezastaví

odloženo vada nalezeno 15. 9. 2026

Nález V2 externího auditu: fúze nemá práh na stáří posledního měření, takže po výpadku GPS i IMU při živých kamerách jede odhad polohy dál z predikce a robot nezastaví. Autor 15. 9. 2026 rozhodl neřešit: pevný práh by robota zastavil i v legitimních případech a jeho hodnota se má vzít ze záznamu, ne odhadnout.

ekf-fusion.md · DevLog 2026-09-15

EKF senzorická fúze napsaná od nuly s asynchronním zpracováním měření

hotovo záměr nalezeno 7. 7. 2026 vyřešeno 28. 7. 2026

Původní EKF z ARBot2 nešel přeložit (vazby na WPF, chybějící matice) a měl pevný takt 10 Hz. Nová fúze v ARBot.Common/Fusion má generický Ekf (Joseph form, čisté kroky pro replay), model stavu [X, Y, θ, v, ω] s rychlostmi jako stavy (robustní vůči smyku) a AsyncFusionEngine, který zpracovává měření podle času pořízení s checkpointy a líným přepočtem — senzory s různou kadencí a latencí (kamery) se skládají správně. Druhý den přibylo NIS gating v měkkém režimu: odlehlému měření se nafoukne R místo zahození, takže se filtr z dlouhého výpadku vždy zotaví (tvrdý Reject umí filtr trvale zaseknout). Adaptivní odhad R/Q z reziduí se vědomě odložil — je stavový a kolidoval by s bezstavovým přehráváním. Od 28. 7. je engine thread-safe a řídicí smyčka z něj vzorkuje odhad přes GetStateAt.

  • Ekf, EKFModel, měřicí modely, AsyncFusionEngine, GeoReference 7. 7. 2026
  • NIS + měkký gating proti lockoutu 8. 7. 2026
  • Thread-safe engine, řízení vzorkuje odhad nezávisle na měřeních 28. 7. 2026

ekf-fusion.md · DevLog 2026-07-07, 2026-07-08, 2026-07-28

Binární driver VN100 a sjednocení souřadnicových rámců (FLU / ENU)

hotovo záměr nalezeno 10. 7. 2026 vyřešeno 10. 7. 2026

Druhý driver VN100 čte binární výstup včetně nejistoty orientace (YprU) jako zdroj kovariance pro fúzi. Zároveň se pevně stanovily rámce projektu — tělo FLU, svět ENU s matematickou orientací — a rozhodlo se, že montáž senzoru (X vzad) řeší reference frame rotation uložená v senzoru, ne softwarový offset; driver převádí jen FRD → FLU a azimut → ENU. Čtení ověřeno na skutečném senzoru: dřívější „180° na severu" byla stará konfigurace senzoru, ne chyba kódu. Pozdější potíže s kurzem (heading mode Relative, kalibrace magnetometru) jsou samostatná témata.

  • VN100IMUBinary s YprU → IMUState.OrientationUncertainty 10. 7. 2026
  • Rámce FLU / ENU, reference frame rotation diag(-1,1,-1) v senzoru 10. 7. 2026
  • Ověřeno na HW (heading OK po factory resetu) 10. 7. 2026

imu-and-frames.md · DevLog 2026-07-10

Fúze neměla žádné měření polohy ani rychlosti

hotovo vada nalezeno 11. 8. 2026 vyřešeno 12. 8. 2026

Při návrhu globální navigace se ukázalo, že mapper měření krmí filtr jen kurzem a gyrem z IMU: GPS ani odometrie do fúze netekly a referenční bod roviny nikdo nenastavoval, takže stav EKF neměl žádné měření polohy ani rychlosti. Doplnilo se mapování GPS na polohu a rychlost, odometrie na rychlost a úhlovou rychlost, počátek roviny z mapy (map=) a inicializace polohy z prvního fixu - bez ní by první fix stovky metrů od počátku prošel jen s malým ziskem a po zapnutí gatingu by ho filtr zahodil navždy. Testy přitom chytily, že GPS stav nese stupně a mapper je bral jako radiány.

  • GPS a odometrie v DefaultMeasurementMapper, GeoReference z mapy 12. 8. 2026
  • InitializePosition z prvního fixu (i start= na reálném HW) 13. 8. 2026

ekf-fusion.md, global-navigation-runtime.md · DevLog 2026-08-11, 2026-08-12, 2026-08-13

GPS stav nesl stupně, všechno ostatní radiány

hotovo vada nalezeno 12. 8. 2026 vyřešeno 26. 8. 2026

GPSState byl jediný geografický typ ve stupních (u-blox posílá 1e-7 stupně), kdežto LLA i GeoReference počítají v radiánech. První verze mapperu měření předala stupně jako radiány a chytil to až test - tichá past stejného druhu jako národní prostředí při parsování. Od 26. 8. 2026 je i GPSState v radiánech; převod na stupně patří jen na okraje (driver při parsování, zobrazení). Naostro to kouslo 26. 8.: mise Robotour z něj stavěla LLA bez převodu, body v okně fixů byly desítky radiánů od sebe a armování v depu se nikdy nedočkalo; testy vadu potvrzovaly, protože jejich pomocník převáděl stejně špatně.

  • Test Gps_IsInterpretedAsDegrees_NotRadians a převod v mapperu 12. 8. 2026
  • GPSState sjednocen na radiány 26. 8. 2026
  • Dohledat zbylé převody ze stupňů (WorldViewDocument) 27. 8. 2026

imu-and-frames.md, rozhodnutí 26. 8. 2026 · DevLog 2026-08-12, 2026-08-26, 2026-08-27

Fúze zahazovala opožděné korekce a nebylo to vidět

hotovo vada nalezeno 13. 8. 2026 vyřešeno 21. 8. 2026

Měření starší než okno historie EKF se tiše zahodilo — hláška šla jen do Debug, které v Release neexistuje, a telemetrie dál hlásila „Ok". V Debug buildu tak propadlo 51 z 55 korekcí (latence 1,4 s proti oknu 1 s), přičemž skutečná příčina byla latence, ne velikost okna. Přibylo počítadlo zahozených podle zdroje, hláška přes Trace s údajem „o kolik pozdě", verdikt měření ve zprávě MeasurementDiagMsg (do té doby mrtvé DTO) a sloupce v telemetrii. Potřeba vidět, co fúze s měřením udělala, byla zapsaná už 13. 8. jako otevřený úkol; tahle vada ji proměnila v konkrétní zprávu.

  • Zapsáno jako otevřený úkol „diagnostika EKF do streamu a záznamu“ 13. 8. 2026
  • Změřena latence korekce proti oknu (Debug vs. Release) 20. 8. 2026
  • Počítadlo DroppedTooOld a hláška přes Trace s typem, hodnotou a zpožděním 20. 8. 2026
  • MeasurementDiagMsg se publikuje (measdiag=), verdikt Accepted / GatedOut / TooOld 21. 8. 2026
  • Sloupec „zahozeno fúzí" v telemetrii pro korelaci i koridor 21. 8. 2026

map-correlation-localization.md, record-replay.md (kdy Trace a kdy Debug) · DevLog 2026-08-13, 2026-08-20, 2026-08-21

Odometrie do fúze byla dvakrát vedle - i na skutečném robotu

hotovo vada nalezeno 13. 8. 2026 vyřešeno 13. 8. 2026

Uzavřená simulační smyčka odhalila dvě vady, které platily i pro reálný hardware. Rozchod ve fúzi byl natvrdo 0,5 m proti 0,41 m z profilu, takže odometrická úhlová rychlost byla o 18 % podhodnocená. A rychlost kol se počítala z přírůstku enkodéru a doby od posledního vyzvednutí stavu - které v runtime nikdo nedělal, takže bez otevřeného okna motorů tekla do EKF trvale nula a s otevřeným závisela na překreslování UI. Rychlost je od té doby vlastní pole plněné driverem (MotorStateBase verze 2), enkodéry kumulativní.

  • FusionConfig.WheelBase z profilu, regresní test 13. 8. 2026
  • MotorStateBase verze 2: rychlost z driveru, kumulativní enkodéry 13. 8. 2026

ekf-fusion.md, virtual-hw.md · DevLog 2026-08-13, 2026-08-18

První korelace byla chybná, protože se kurz neinicializoval

hotovo vada nalezeno 19. 8. 2026 vyřešeno 19. 8. 2026

Fúze při startu inicializovala jen polohu, kurz startoval na nule a ke skutečnému kurzu dojížděl přes měření; lokální mapa se mezitím zapisovala pootočená až o 170° a první korekce z ní měla opačné znaménko. Pojistka proti skoku pózy byla o argument krátká — rotaci stojícího robota neviděla. Kurz se teď inicializuje (InitializeHeading) a detektor skoku hlídá i rotaci; první cyklus vychází správně ve čtyřech ze čtyř běhů.

  • Příčina dohledána (grid znečištěný zápisem s kurzem u nuly) 19. 8. 2026
  • PoseJumpDetector hlídá i rotaci (tolerance 5°) 19. 8. 2026
  • AsyncFusionEngine.InitializeHeading místo startovního měření 19. 8. 2026

rozhodnutí 19. 8. 2026, ekf-fusion.md · DevLog 2026-08-19

Hranová lokalizace za běhu zahazovala 77 % korekcí a hlásila měření i metr mimo cestu

hotovo vada nalezeno 22. 8. 2026 vyřešeno 20. 9. 2026

Při prvním běhu hranové lokalizace (corridor=) vyplavaly dvě vady. Tvrdý gate Reject pustil jen 65 z 280 měření, protože měření tvrdilo 3 cm jistoty a nesouhlasilo o 55 cm; přepnuto na GateMode.Soft, jak předepsalo rozhodnutí z 20. 8. Stupeň navíc hlásil platné měření i při příčné poloze 2,1 m od osy koridoru širokého 2 m — doplněn gate „jsem uvnitř koridoru" (OutsideCorridor) a počítadlo, kolik korekcí fúze skutečně přijala (DroppedByFusion), protože „poslali jsme" není totéž co „došlo to". Přitom se ukázalo, že rig dvou map ani poseerror= nemohou ověřit konvergenci — vkládají chybu do pozorování, ne do pózy. Na zařízení jde koridor naostro od 17. 9. (a44b4f4), první jízdy 18. 9.: corrections NIS p50 0,5, 0 % zamítnuto, fúzí nezahozeno nic; na Robotouru 19. 9. přijato 1 404 z 1 404 včetně NIS 443 — Soft gate na zařízení prokazatelně nezahazuje, a jeho odvrácenou stranu (skoky pózy) vede lok-koridor-skoky-pozy. Podíl OutsideCorridor v rozpadu ze zařízení samostatně vyčíslený není.

  • Počítadlo DroppedByFusion v RoadCorridorMsg 22. 8. 2026
  • Výchozí gating Soft místo Reject 22. 8. 2026
  • Gate MaxOutsideCorridorM → CorridorFixReason.OutsideCorridor 22. 8. 2026
  • Ověřit gating s korekcemi naostro na zařízení — 18. 9. NIS p50 0,5, 0 % zamítnuto, DroppedByFusion 0; 19. 9. 1 404 z 1 404 (podíl OutsideCorridor nevyčíslen) 20. 9. 2026

map-correlation-localization.md, CorridorLocalizer.cs · DevLog 2026-08-22, 2026-09-18, 2026-09-20

Hranice se s dálkou rozmazává a RANSAC ji měřil jedním metrem

hotovo vada nalezeno 22. 8. 2026 vyřešeno 24. 8. 2026

Měření 12 631 hraničních bodů proti mapě ukázalo, že medián sedí na okraji vozovky v každé vzdálenosti, ale rozptyl roste z ±5 cm na metru na −0,6/+0,4 m na deseti metrech. RANSAC měl jeden práh inlieru 0,10 m pro celou hranici, takže se u vzdálených bodů chytal náhodného zarovnání. Práh je od 23. 8. úměrný vzdálenosti (optimum 0,15 m/m, +11 % přijatých). Zbytek kandidátů neobstál a je to změřené, ne názor: vážené proložení 1/σ² (vzdálené body jediné určují směr), velikost vzorku hypotézy (bez vlivu), ortogonální regrese (numericky bezvýznamná), Huberova váha (při normalizaci tolerancí principiálně no-op) i přehradlování konsenzuální sady (RegatePasses, ráno zapnuto na kruhové referenci, večer vráceno na 0 — práh inlieru je 10× volnější než rezidua). Přepínače v kódu zůstaly. Dvě poučení: rezidua nejsou přesnost a méně přijatých při lepší geometrii není zlepšení.

  • Změřit odchylky hraničních bodů proti mapě po pásmech vzdálenosti 22. 8. 2026
  • Práh inlieru úměrný vzdálenosti (InlierThresholdPerMeter, corridortol=) 23. 8. 2026
  • Vážené proložení a velikost vzorku hypotézy zamítnuty měřením 23. 8. 2026
  • Ortogonální regrese, Huber a RegatePasses zamítnuty měřením 24. 8. 2026

map-correlation-localization.md, CorridorFinder.cs · DevLog 2026-08-22, 2026-08-23, 2026-08-24

Koridor za jízdy propadal v 92 % cyklů

hotovo vada nalezeno 22. 8. 2026 vyřešeno 24. 8. 2026

Za 40 s jízdy dalo měření jen 35 ze 411 cyklů. Rozpad ukázal tři různé věci: ~60 % cyklů nemělo snímek druhé kamery v okně 60 ms (NoPair), část byla stání v cíli na konci cesty (zamítnutí správně) a zbytek symetrické sbíhání hranic ~11° těsně nad prahem 10°. Hypotéza ohybu ze zpětné projekce padla testem BoundaryStraightnessTests. NoPair vyřešila kompenzace pohybu mezi snímky (Reproject, párování se do té doby dívalo jen dozadu): NoPair 260 → 20, přijatých 76 → 159. Sbíhání ~11° nakonec žádná vada nebyla — byla to nálevka v testovací mapě (rozšíření 1 → 3 m na 10 m dává přesně 11,42°); nad mapou s konstantní šířkou je 100 % cyklů přijato po prvních 60 s. Proložené přímky kreslené v mapě navíc ukázaly, že většina zamítnutí padá na křižovatku a slepý konec, kde koridor existovat nemá.

  • Rozpad příčin (NoPair, stání v cíli, sbíhání 11°) a diagnostika v RoadCorridorMsg v2/v3 22. 8. 2026
  • Hypotéza ohybu zpětné projekce vyvrácena testem 22. 8. 2026
  • Kompenzace pohybu mezi snímky (CorridorLocalizer.Reproject), okno 400 ms 23. 8. 2026
  • Sbíhání 11° vysvětleno jako nálevka v testovací mapě 24. 8. 2026

map-correlation-localization.md, BoundaryStraightnessTests.cs, CorridorLocalizer.cs · DevLog 2026-08-22, 2026-08-23, 2026-08-24, 2026-08-27

Korekci kurzu z koridoru přehlasuje kompas ~200:1

hotovo vada nalezeno 22. 8. 2026 vyřešeno 18. 9. 2026

Autor se ptal, proč korekce z koridoru chybu kurzu nezmenšila. Nejdřív se zjistilo, že kurz nebylo co opravovat (robot stál a virtuální IMU dává absolutní kurz s efektivní σ 0,1°). Když se chyba vnutila (imubias=5,0), koridor ji změřil správně (4,8°), ale fúze zůstala na 4,96°: informace kompasu při 100 Hz přehlasuje koridor ~200:1 a měkký gating navíc u velké chyby σ koridoru nafoukne (sebemařící). S oslabeným kompasem korekce funguje (4,76° → 0,58°). Důsledek pro robot: σ kompasu musí být podstatně větší než jeho krátkodobý šum, nebo musí bias kurzu přibýt do stavu EKF. Od 12. 9. má σ kompasu podlahu 5° a škrtí se na 1 Hz, takže 15. 9. výpočet ukázal, že poměr se překlopil na koridor ~150–1000:1 nad kompasem — je to ale výpočet, ne měření, a na zařízení to neběželo. ✅ **Změřeno na zařízení 18. 9. 2026** (první jízdy s corridorsend=true): fúze kurz z kompasu už neopisuje — odhad − IMU yaw je +0,39 ± 1,88° (dřív −0,01 ± 0,06°) a odhad je ke GPS kurzu blíž než kompas sám (v jízdních minutách −1,0 až −1,8° proti −2,7 až −4,7°). Koridor kurz reálně táhne; kolik přesně a s jakou σ, zůstává u lok-koridor-merici-rezim (σ proložení 4× optimistická, kadence 10/s).

  • Změřit poměr informace kompas : koridor v simulaci (~200:1) 22. 8. 2026
  • Důkaz, že korekce kurzu funguje se slabým kompasem 22. 8. 2026
  • Přepočet poměru po podlaze σ kompasu a škrcení na 1 Hz (koridor ~150–1000:1) 15. 9. 2026
  • Změřit korekci kurzu z koridoru na zařízení — 18. 9.: odhad − IMU yaw z −0,01 ± 0,06° na +0,39 ± 1,88°, odhad ke GPS kurzu blíž než kompas (−1,0° proti −3°) 18. 9. 2026

virtual-hw.md, map-correlation-localization.md, ekf-fusion.md · DevLog 2026-08-22, 2026-08-23, 2026-09-15, 2026-09-18

RANSAC je nedeterministický, replay hranové lokalizace není reprodukovatelný

hotovo vada nalezeno 23. 8. 2026 vyřešeno 30. 9. 2026

RANSAC.Compute používá neseedovaný new Random(), takže tentýž vstup dá pokaždé jiný výsledek (±8 přijatých ze 421 dvojic). Než se to zjistilo, vyšly z jednotlivých běhů dva závěry, které neplatily; od té doby se každá varianta estimátoru měří 12× a porovnávají se rozpětí. Jde to proti zbytku projektu (DeterministicNoise, ComparisonTarget) a je podezřelé i z jednoho nestabilního běhu testovací sady. Zaseedování je drobnost, zatím neudělaná — v kódu je pořád new Random(). ✅ **Opraveno 30. 9. 2026:** RANSAC<T>.Seed (výchozí RANSAC.DefaultSeed, null = staré chování), generátor se zakládá s pevným semínkem při každém výpočtu; koridor ho bere z CorridorConfig.RansacSeed. Tentýž vstup dá tentýž koridor nezávisle na předchozích výpočtech. corridorfit --rep= mění semínko v každém opakování (1. = runtime), takže rozpětí dál měří citlivost na losování, reprodukovatelně. Seedovaný Random je v .NET stejný na x64 i ARM64.

  • Naseedovat RANSAC (reprodukovatelný replay, jedno měření na variantu) — 2 testy (shoda bit po bitu i po jiném výpočtu; na testovacích datech na losování opravdu záleží), dva běhy corridorfit nad 20260918-154028.rec se liší jen časem; testy 1 728 / 151, build OrangePI 30. 9. 2026

map-correlation-localization.md, RANSAC.cs · DevLog 2026-08-23, 2026-08-24, 2026-09-30

Šířkový nesouhlas vyskočil na 0,23 m — měřil se proti filtru, ne proti mapě

hotovo vada nalezeno 23. 8. 2026 vyřešeno 23. 8. 2026

Po kompenzaci pohybu mezi snímky vyskočil šířkový nesouhlas z 0,046 na 0,230 m a vypadalo to jako regrese. Nebyla: MapWidth ve zprávě není šířka z mapy, ale výstup filtru šířky, který se z měření učí a za rozšiřující se cestou trvale zaostává (šířka uzlu je maximum z okolních cest, takže na styku 1m a 3m cesty se úzká rozevírá). Kamera proti mapě souhlasí na centimetry. Přejmenováno, aby číslo dál nemystifikovalo, a zapsáno poučení: osm běhů téže konfigurace dalo p50 0,028–0,259 m, rozptyl mezi běhy je větší než zkoumaný rozdíl. Filtr šířky nahradil 15. 9. estimátor s verdiktem kvality (jiné téma).

  • Rozbor po cestách, test NaRozsirujiciSeCeste_filtrTrvaleZaostava, přejmenování WidthDisagreement 23. 8. 2026

map-correlation-localization.md · DevLog 2026-08-23, 2026-08-24

Kurz z GPS jako druhá absolutní reference kurzu

hotovo záměr nalezeno 25. 8. 2026 vyřešeno 25. 8. 2026

Přijímač GPS hlásí kurz nad zemí a reálné drivery ho plnily, ale fúze ho nepoužívala vůbec a virtuální GPS ho ani nevysílala. Od 25. 8. jde GPS/heading do fúze jako druhá reference kurzu vedle kompasu (sigma roste s klesající rychlostí, jízda vzad vyloučená) a virtuální GPS ho hlásí se šumem v příčné složce rychlosti. Nový rozbor ARBot.Analyze heading měří rozpor IMU yaw − GPS kurz i bez ground truth, takže běží nad záznamy ze zařízení — právě jím se pak 7. 9. našel kurz VN100 o 24° vedle. Samo to ale chybu kurzu nezmění, dokud si kompas věří tisíckrát víc. Od 12. 9. je změřeno, že chyba kurzu z GPS není bílý šum (poctivá sigma by byla 29–83°) a že GPS jede 10 Hz, ne 5 — model sigmy trefuje realitu spíš náhodou.

  • Virtuální GPS hlásí kurz nad zemí (šum v příčné rychlosti, 12° při 0,5 m/s, 3,7° při 3 m/s) 25. 8. 2026
  • 'Mapper bere GPS/heading do fúze (varianta A: druhá reference, žádné nové stavy)' 25. 8. 2026
  • ARBot.Analyze heading i bez ground truth (--nogt), ověřeno proti známé odpovědi 25. 8. 2026

ekf-fusion.md, imu-and-frames.md · DevLog 2026-08-25, 2026-09-07, 2026-09-12

Kompas si věří 60–90× víc, než jaký je

hotovo vada nalezeno 25. 8. 2026 vyřešeno 1. 10. 2026

Senzor VN100 hlásí nejistotu kurzu 0,06°, ale proti kurzu z GPS se trvale mýlí o 3–5°. Fúze proto věřila kompasu asi 4 000× víc než GPS a žádná druhá reference kurzu (GPS kurz, korelace s mapou) neměla šanci cokoli opravit — odhad kurzu seděl na kompasu na 100 % i se zapnutými korekcemi. Jádro je v tom, co sigma kompasu popisuje: krátkodobý šum, ne bias. Od 12. 9. má sigma kurzu z kompasu podlahu 5° (imuheadingstd=) a absolutní kurz se navíc škrtí na 1 Hz (imuheadinghz=); gyro jede dál v plné kadenci. Poměr informace spadl na ~2,2 : 1, ale poctivý filtr z toho není — bias je časově korelovaný a filtr ho bere jako bílý šum. 18. 9. 2026 (kalibrovaný kompas): chyba kompasu proti GPS kurzu má bias do 3,5° a sd ~4° (včetně šumu GPS kurzu), takže podlaha 5° je správného řádu. A/B imuheadingstd=5 proti =0 pořád není. Na zařízení jely jízdy 18. a 19. 9. s výchozími 5° / 1 Hz (profil hodnoty nenastavuje, platí defaulty registru). Že fúze kompas už nepřebírá, je vidět (odhad − IMU yaw −0,01 ± 0,06° → +0,39 ± 1,88°), ale je to společný účinek s korekcemi z koridoru naostro, ne A/B podlahy. **29. 9. 2026 (autor): A/B se dělá OFFLINE nad existujícími záznamy**, ne dvěma jízdami. Dvě jízdy po sobě by účinek nerozlišily: bias kompasu se mezi běhy liší o ~2° (18. 9. −3,4 proti −1,1° za 13 min), což je řádově tolik, kolik má podlaha změnit, a jiný odhad kurzu by v uzavřené smyčce dal i jinou trajektorii. ARBot.Analyze fusionreplay přehrává fúzi ze zaznamenaných senzorů (dnes A/B koridoru), takže obě varianty uvidí přesně tatáž data. Měřítka: odhad kurzu − GPS kurz na úsecích nad prahem rychlosti (střed a rozptyl, zvlášť po směrech) a odhad − IMU yaw. Vhodné záznamy: jízdy s kalibrovaným kompasem (18. 9., 27. 9. a pozdější). **A/B změřeno 1. 10. 2026** (ARBot.Analyze compassab, 16 jízd 18.–29. 9. včetně Robotouru, referencí je nezávislý směr posunu GPS polohy, měřidlo sedí na RobotStateMsg 0,000°): **zabírá jen kombinace 5° + 1 Hz** — samotné škrcení dá totéž co kompas (≤ 0,2°), samotná podlaha skoro totéž (≤ 0,3°, jen 18. 9. 0,8–1,0°). Kde je kompas vedle, stáhne chybu na 25–45 % jeho biasu (−6,6 → −1,8°, +9,3 → +4,2°, −4,9 → −1,7°, −1,6 → −0,1°) a rozptyl většinou klesne (4,4 → 2,7°, 5,3 → 2,2°); v obou jízdách 18. 9. rozptyl o ~0,6° vzrostl. Kde je kompas v pořádku, je to skoro neutrální (střed do ±0,6°, v jedné krátké jízdě 1,4°). Táhne GPS kurz — varianta bez koridoru je do ~0,7° stejná. Zbytek biasu do 4° zůstává: bias kurzu jako stav EKF zůstává cílem. Tabulka v [ekf-fusion.md](ekf-fusion.md).

  • 'Změřit poměr informace kompas : GPS kurz (~4 000 : 1) a že odhad sedí na kompasu na 100 %' 25. 8. 2026
  • Podlaha sigmy kurzu z kompasu imuheadingstd= (výchozí 5°, skládá se kvadraticky s YprU) 12. 9. 2026
  • Škrcení absolutního kurzu z kompasu imuheadinghz= (výchozí 1 Hz, gyro neomezeno) 12. 9. 2026
  • A/B imuheadingstd=5 proti =0 OFFLINE nad existujícími záznamy (dvě varianty fúze nad toutéž jízdou, ne dvě jízdy) — nový příkaz ARBot.Analyze compassab (příprava sdílená s fusionreplay, 5/0 ° × 1/0 Hz, s koridorem i bez) 1. 10. 2026
  • Pustit A/B nad záznamy s kalibrovaným kompasem: 16 jízd (18., 19. — Kolo 3b a 4, 23., 25., 27. a 29. 9.); zabírá jen 5° + 1 Hz, chyba na 25–45 % biasu kompasu, kde je kompas v pořádku skoro neutrální 1. 10. 2026

ekf-fusion.md, rozhodnutí 12. 9. 2026, FusionReplayReport.cs · DevLog 2026-08-25, 2026-09-12, 2026-09-18, 2026-09-29, 2026-10-01

Měřidlo poctivosti σ účtovalo korelátoru vlastní chybu fúze

hotovo vada nalezeno 25. 8. 2026 vyřešeno 25. 8. 2026

Korelátor hlásí posun proti odhadu pózy, takže správná odpověď proti tuze posunuté mapě není konstantní posun mapy, ale posun mapy plus chyba fúze — a ten druhý člen (p50 0,105 m) v měřidle ARBot.Analyze sigma chyběl. Po jeho odečtení padly dvě vedené vady: „σ je 1,28–1,43× optimistická" (zbylo 1,03–1,17× a přísnější sd(z) = 0,78–0,87 říká, že je naopak ~1,25× konzervativní) a „systematické vychýlení +0,10 m" (bylo to vychýlení fúze, hlášené správně). Aby se póza nedohledávala podle razítka (nepřežije seek), nese ji zpráva MapCorrelationMsg (verze 5); rozdíl obou cest je 0–4 mm, takže dřívější závěry platí. Konzervativní σ se vědomě neopravuje — zmenšit ji znamená zvětšit autoritu korelátoru proti GPS, což gatují tři podmínky. Čistě softwarové, ověřeno testy a pěti běhy v simulaci.

  • Chyba fúze odečtena v sigma, metrika sd(z) místo poměru souhrnů 25. 8. 2026
  • MapCorrelationMsg verze 5 s pózou, proti které se korelovalo 25. 8. 2026

map-correlation-localization.md, MapCorrelationMsg.cs · DevLog 2026-08-25

Robot na mapě poskakoval, protože fúze pod nouzovým zastavením zahazovala odometrii

hotovo vada nalezeno 27. 8. 2026 vyřešeno 27. 8. 2026

Po přijetí QR kódu se poloha robota na mapě rozjela o metry. Nebyla to mise: mapper pod drženým nouzovým zastavením odometrii zahazoval, takže fúze ve stání neměla žádnou vazbu na rychlost a polohu tahal šum GPS. Autor zdůvodnění té výjimky vyvrátil (motory jsou pod stopem řízené pozičně, kola nemohou hlásit nic než nulu; odnesení robota je možné i bez stopu), výjimka byla zrušena a odometrie teče normálně. Odhalilo to zároveň, že chybový rámec motorového driveru se tváří jako měření (samostatné téma).

  • Změřit, že fúze je za jízdy zdravá (chyba pózy p50 0,16 m) a problém je jen pod stopem 27. 8. 2026
  • Zrušit výjimku pro odometrii pod stopem 27. 8. 2026

rozhodnutí 27. 8. 2026, ekf-fusion.md · DevLog 2026-08-27

Hláška fúze o zahozeném měření vinila okno historie, které za to nemohlo

hotovo vada nalezeno 1. 9. 2026 vyřešeno 1. 9. 2026

Autor si všiml, že fúze hlásí zahození odometrie „starší než okno historie", ačkoli měření bylo zpožděné jen 7 ms a okno je 3 s. Testem se potvrdilo, že chování filtru je správné: po inicializaci se zahodí každé měření starší než základ filtru, a to bez ohledu na velikost okna. Vadná byla jen hláška — vinila okno a slovem „opožděno" posílala hledání chyby do doručování měření místo k základu filtru. Hláška rozlišuje obě situace a test hlídá i její znění.

  • Rozlišit „za oknem historie" od „před základem filtru" a opravit znění 1. 9. 2026

ekf-fusion.md · DevLog 2026-09-01

Nejistota EKF tekla do záznamu od začátku, ale nikde nebyla vidět

hotovo záměr nalezeno 2. 9. 2026 vyřešeno 2. 9. 2026

Na dotaz, jak pozorovat vývoj filtru, se ukázalo, že kovariance stavu jde do streamu i do záznamu od začátku, jen z ní telemetrie nedělala ani jeden sloupec. Přibylo šest sloupců (σ polohy, σx, σy, σ kurzu, σv, σω) do tabulky i grafu; protože se nic nového neposílá, funguje to i nad staršími záznamy. Chybějící nebo rozpadlá kovariance dá prázdno, ne nulu. Zjištění od autora: EKFStepMsg není cesta k vnitřku filtru — engine je asynchronní s okny historie, „jeden krok" v něm neexistuje.

  • Šest sloupců σ, výpočet v StateSigma s testy 2. 9. 2026

ekf-fusion.md, telemetry-view.md · DevLog 2026-09-02

Fúze brala každý GPS fix s toutéž sigmou

hotovo vada nalezeno 6. 9. 2026 vyřešeno 6. 9. 2026

Na náhledu ujela poloha o 570 m, zatímco robot stál. Fúze brala každý fix s IsFixed a vždy se sigmou 1,5 m, ačkoli zpráva nese počet družic i DOP; u-blox navíc jen přetypovával fixType, takže i samotný mrtvý odhad bez družic vypadal jako platný fix. Teď se sigma násobí DOP (gpsdopsigma=) a volná brána (gpsminsat=, gpsmaxdop=) odmítne nesmysl — neznámá hodnota projde. Kvalita GPS je i na stránce náhledu. Na stojícím robotu ověřeno: dokud fix projde, odhad ujede ~1 m za 30 s; po odmítnutí zamrzne na centimetr. Příčina těch 570 m potvrzená není (robot byl v době opravy vypnutý).

  • Sigma podle DOP, brána na družice a DOP, oprava mapování fixType u u-bloxu 6. 9. 2026
  • Kvalita GPS na stránce náhledu 6. 9. 2026
  • Ověřeno na stojícím robotu (brána zastaví ujíždění) 6. 9. 2026

ekf-fusion.md, rozhodnutí 6. 9. 2026 · DevLog 2026-09-06

Deklinace se nezapočítávala nikde — model pole se teď nastaví sám

hotovo záměr nalezeno 6. 9. 2026 vyřešeno 12. 9. 2026

Yaw z VN100 byl azimut k magnetickému severu: registr 21 měl východní složku 0, model pole vypnutý a náš kód deklinaci nepřidával. Jediná metoda, která by model zapnula, nikdy nemohla fungovat (čtecí příkaz místo zápisu, oddělovač tisíců v čísle, radiány místo stupňů). Od 8. 9. MagModelInit (magmodel=) zapíše registr 83 jednorázově po prvním kvalitním fixu; deklinace i sklon reference se dopočítají z WMM. Na živém senzoru 12. 9. potvrzeno, že se deklinace aplikuje (3,42°) — vestavěný model VN je ale zastaralý o ~1,9°.

  • VnCommands + IMagneticModel, oprava tří chyb v SetModelParams 6. 9. 2026
  • MagModelInit po prvním kvalitním fixu (magmodel=) 8. 9. 2026
  • Ověřeno čtením registrů 83 a 21 na živém senzoru 12. 9. 2026

imu-and-frames.md · DevLog 2026-09-06, 2026-09-08, 2026-09-12

T265 běžela, ale její data neměla kam téct

hotovo vada nalezeno 6. 9. 2026 vyřešeno 12. 9. 2026

Kamera se zakládala, otáčela pipeline a soupeřila na USB, ale BuildSensorSources ji nikdy nedrátoval — v záznamu po ní nebyla ani stopa a na stránce vypadala jako porucha. Napojení není jednořádkové: bez magnetometru je její yaw o neznámou konstantu vedle severu, proto jde do fúze jen úhlová rychlost z rozdílu yaw na nepřekrývajícím se okně 0,5 s (IMUState.HasAbsoluteHeading, verze 3). Na robotu pak nesla 19 % informace o úhlové rychlosti. Absolutní kurz z ní nevznikne bez offsetu yaw jako stavu EKF — a od 14. 9. je to jedno, protože autor T265 kvůli výpadkům kamer odpojil natrvalo.

  • Napojení jako relativní yaw → úhlová rychlost, filtr zdrojů v ARBot.Analyze 6. 9. 2026
  • Podíl T265 na informaci změřen na záznamu z robota 12. 9. 2026

ekf-fusion.md, hardware.md, rozhodnutí 14. 9. 2026 (T265 odpojena) · DevLog 2026-09-06, 2026-09-12, 2026-09-14

Koridor v měřicím režimu — odtlumení a první měřicí jízda

hotovo záměr nalezeno 15. 9. 2026 vyřešeno 20. 9. 2026

Koridor měří snímek co snímek týž okraj cesty, takže jeho chyba je časově korelovaná — táž past jako u GPS a kompasu. Přibyly corridorstd=, corridorheadingstd= a corridorhz= (sigmy kvadraticky, škrtí se jen posílání), výchozí 0 schválně, protože dekorelační čas koridoru změřený nebyl; provozní profil měl běžet s corridor=true, corridorsend=false — plná zátěž, nulový vliv na řízení. Řádek corridorsend=false v profilu byl od 15. 9. (commit 0e34771) a měřicí jízda 16. 9. s ním jela; 17. 9. ho autor v přípravě na Robotour odstranil (8bf1081) a týž den zapsal corridorsend=true (a44b4f4) — od té doby se korekce posílají vědomě; viz lok-koridorsend-nebyl-vypnuty. První měřicí jízda 16. 9. (první záznam ze zařízení, kde koridor vůbec běžel) dala první střízlivé číslo: koridor je dobrá reference kurzu (+0,42° proti GPS, robustní sd 2,30°), ale proložení hlásí 0,50°, tedy je ~5–9× optimističtější. Poloha byla celou jízdu mimo mapovanou vozovku (3–5 m), takže do fúze neodešlo 0 ze 424 přijatých měření — a report to do té doby neuměl říct (Ok znamenalo „prošlo branami“, ne „došlo do fúze“). 18. 9. 2026: corridorsend=true je v profilu vědomě od 17. 9. a první jízdy naostro ho potvrdily; σ kurzu z proložení je potřetí ~4× optimistická (robustní sd 2,4–2,6° proti 0,6°), takže číslo pro corridorheadingstd= je ~2,5°, ale pořád nenastavené. **18. 9. večer, pro soutěž:** autor chtěl koridor „trošku“ oslabit; v profilu je corridorstd=0.1, corridorheadingstd=2.5, corridorhz=2 (~15× méně příčné informace, ~90× méně o kurzu než dnes), podloženo A/B v simulaci s pravdou (příčně 0,018 m, kurz 0,41° proti 0,84 m / 2,4° bez korekcí). S těmi hodnotami jel robot na Robotouru 19. 9. (profil z da82549); rozbor 20. 9.: koridor přijat 1 404 z 1 404 (NIS p90 3,1, max 443), odtlumení mechanicky funguje, ale skokům pózy nebrání — to vede lok-koridor-skoky-pozy.

  • Parametry odtlumení a měřicí profil pi-provoz.cfg 15. 9. 2026
  • Měřicí jízda na zařízení (20260916-164926.rec) 16. 9. 2026
  • Report corridor — trychtýř ztrát, „došlo to do fúze?“, neuťatá příčná statistika, koridor jako reference kurzu 16. 9. 2026
  • Nastavit corridorheadingstd= z měření — 18. 9.: 2,5° (robustní sd koridor − GPS kurz 2,4–2,6°), s corridorstd=0.1 a corridorhz=2 v profilu pro soutěž; A/B v simulaci příčně 0,003 → 0,018 m, kurz 0,13 → 0,41° 18. 9. 2026
  • Ověřit odtlumené hodnoty na zařízení — Robotour 19. 9. (Kolo3b, Kolo4, rozbor 20. 9. ARBot.Analyze nav + corridorstd): 1 404 z 1 404 přijato, NIS p90 3,1, max 443; skoky pózy to neodstranilo → lok-koridor-skoky-pozy 20. 9. 2026
  • Rozvolnit příčnou bránu — vyřešeno zrušením brány, viz lok-koridor-pricna-brana 18. 9. 2026
  • corridorsend=true v profilu — autor 17. 9. (commit a44b4f4) po kalibraci kompasu 12. 9. a přiřazení hrany 16. 9.; první jízdy 18. 9. 17. 9. 2026

map-correlation-localization.md, pi-provoz.cfg · DevLog 2026-09-15, 2026-09-16, 2026-09-18, 2026-09-20

Šířková brána koridoru se ptala dřív, než se bylo z čeho učit

hotovo vada nalezeno 15. 9. 2026 vyřešeno 18. 9. 2026

Porovnání naměřené šířky cesty s odhadem běželo před jeho aktualizací a při prvním kontaktu s hranou vracelo mapovou šířku — u cest bez tagu width jen default 3 m. Na cestě širší než 4,5 m se první měření nepřijalo nikdy a hrana zůstala němá navždy; v ostré mapě nemá tag width ani jedna z 412 cest, takže na vozovce by koridor nezměřil nic a vypadalo by to jako porucha detektoru. RoadWidthEstimator běží bez brány (okno, medián, kvalita z MAD) a dokud si měření nesednou, řekne „nevím“; šířka na póze nezávisí, takže kvalitu měří shoda měření mezi sebou, ne shoda s mapou. Při měřicí jízdě 16. 9. na zařízení šířka seděla (nesouhlas p50 0,057 m); prahy zůstávají odhad. 18. 9. naostro: WidthNotTrusted jen 5,4 % / 4,4 % cyklů za jízdy, šířka p50 3,20 m proti filtru 3,22 m — vada „hrana němá navždy" je na zařízení pryč, doladění prahů nemá naléhavost; uzavřeno rozhodnutím autora 21. 9. 2026.

  • RoadWidthEstimator s verdiktem kvality, důvod WidthNotTrusted 15. 9. 2026
  • Rozpad FixReason nad měřicí jízdou (16. 9. šířka sedí, nesouhlas p50 0,057 m) 16. 9. 2026
  • Prahy kvality — 18. 9. naostro WidthNotTrusted 4–5 % za jízdy, doladění bez naléhavosti 18. 9. 2026

map-correlation-localization.md · DevLog 2026-09-15, 2026-09-16, 2026-09-18

Polovina cyklů koridoru se párovala na příčnou ulici

hotovo vada nalezeno 16. 9. 2026 vyřešeno 7. 10. 2026

Koridor bral nejbližší hranu sítě podle vzdálenosti, kurz do výběru nevstupoval — při chybě pózy 3–4 m vyhrála u křižovatky příčná ulice (1 114 z 2 256 cyklů nad měřicí jízdou) a šířková brána ji nechytila, protože v té mapě mají všechny cesty tutéž šířku. Teď vybírá EdgeAssociator přes χ² (Mahalanobis z příčné odchylky a azimutu, každá dělená svou σ — váhy se neodhadují, měří se), s podlahou na σ (bez ní by hlášená σ kurzu 1,1° proti skutečné chybě 15–20° zamítla všechno — počtvrté táž past), tvrdým vetem ±45° na azimut a odstupem od druhého kandidáta; při nejednoznačnosti se neposílá nic. Kandidáti se sbírají jako hypotézy, ne hrany, jinak by kolineární segment téže cesty zamítl každou rovnou cestu. Přitom se opravila živá vada: Send() odečítal směr přímky bez rozhodnutí o smyslu, takže u cesty kolmé na kurz šel do fúze kurz otočený (9,4 % přijatých cyklů); cena je, že koridor už nikdy neřekne „jsi otočený o 180°“. Ověřeno testy a simulací, na zařízení neběželo. 18. 9. 2026 po kalibraci kompasu: chyba kurzu odhadu proti GPS je sd 8–11° včetně stání a ~2–4° za jízdy, takže assocfloorhdg jde stáhnout spíš na **5°** než na 3°; před soutěží nezměněno. Robotour 19. 9. byla první jízda přes skutečné křižovatky (830 m městem). Rozbor z 27. 9. (ARBot.Analyze assocreplay, přepočet přiřazení nad záznamem, ověřený shodou 100 % verdiktů): na příčnou ulici se nepárovalo nic, hlavní ztráta je **nejednoznačnost** (~37 % proložených koridorů). Podlaha kurzu 5° místo 10° přidá ~10 % přijatých cyklů a všechny nové jsou u GPS; 3° přidá +28 %. Změněný vítěz (5 cyklů na 5°, 68 na 3°) je vždy tatáž cesta, jen správnější úsek zakřivené cesty — podle GPS dráhy i podle kurzu z GPS k lepšímu (3°: 64 : 0 směrem), ale jen z jednoho místa. Nově přijaté nemíří na příčnou ulici (osa proti kurzu z GPS nad 30° 0,0 %) — ta je za vetem 45° a do soutěže nevstupuje.

  • Nález nad 20260916-164926.rec a podklad pro přiřazení (χ² s hlášenými σ zamítne vše) 16. 9. 2026
  • EdgeAssociator, parametry assoc*, RoadCorridorMsg verze 6 se skóre 16. 9. 2026
  • Oprava orientace kurzu v Send() (složení na ±90°, smysl podle kurzu) 16. 9. 2026
  • Přeměřit nad měřicí jízdou — nahrazeno: odhad „2× víc měření“ ze 16. 9. ověřit nejde (spolu s ním padla příčná brána, zisky nejdou oddělit); místo něj přepočet nad Robotourem, kde nový kód skutečně jel 27. 9. 2026
  • Po opravě magnetometru snížit assocfloorhdg z 10° na 5° — výchozí od 27. 9. (autor); přepočtem: 5° = +10 % / +9 % Ok, 3° = +28 % / +24 %; nové cykly 100 % u GPS, změněný vítěz jen jiný úsek téže cesty a podle GPS k lepšímu (5°: 2 : 0, 3°: 28 : 0, zbytek nerozhodnutý) 27. 9. 2026
  • Ověřeno na zařízení 1. 10. 2026 (20261001-144638.rec Track, -152906.rec FreeRun, binárka f848fdf, assocfloorhdg=5): za jízdy AmbiguousEdge 7,9 % a 6,6 %, EdgeMismatch 1,0 % a 0,9 % cyklů (z 1 906 EdgeMismatch v Tracku je 66 % ve stání při zastaveních v zatáčkách); χ² vítěze p50 0,085 a 0,073. Trasa vede přes T-křižovatky a obě místa Tracku leží na křižovatkách: na jinou cestu se přiřadilo 12 cyklů (3 odeslány), všechny v prvních 9 s na startu; za jízdy na příčnou ulici nic. Vybraná cesta do 2 m od GPS ve 100 % přiřazených cyklů 7. 10. 2026
  • Ověřit na zařízení — 18. 9.: běží (χ² vítěze p50 0,004, nejednoznačných 3 z 3 147), ale trať je jediná OSM cesta, takže křižovatku to neotestovalo 18. 9. 2026
  • Vyčíslit nad Kolem 3b / 4: AmbiguousEdge 3 153 / 1 208 (38 / 37 % proložených), EdgeMismatch 6 / 3, χ² vítěze p50 0,058 / 0,040; nástroj ARBot.Analyze assocreplay 27. 9. 2026

map-correlation-localization.md · DevLog 2026-09-16, 2026-09-18, 2026-09-27, 2026-10-07

MinInliers=25 škrtí koridor 1,4–4× a proti čemu vznikl, to nechytá

hotovo vada nalezeno 17. 9. 2026 vyřešeno 21. 9. 2026

MinInliers je největší ztrátová brána proložení koridoru (17. 9. zahodila 3 987 z 6 173 cyklů). Práh 25 vznikl na starším záznamu odjinud a jeho zdůvodnění je konkrétní: bez něj se do statistiky míchaly přímky proložené 3–6 body, které vyjdou **kolmo na cestu** (šířka až 10 m, směr −88°), a šířka měla sd 3,3 m místo 0,45 m. Změřeno ze záznamů (nový blok *PRAH INLIERU* v ARBot.Analyze corridor, který dopočítá geometrii z uložených úseček, takže **nový výjezd netřeba**): nad 20260917-160558.rec by práh 15 dal **2 513 koridorů místo 635 (4,0×)** a podíl nesmyslné šířky (mimo 1–8 m) by šel 0,0 → 2,0 %; nad 20260916-164926.rec by dal **3 399 místo 2 354 (1,4×)** a podíl nesmyslné šířky 2,0 → 2,6 %. ⚠️ **Podstatné je to druhé číslo: při dnešním prahu 25 už je nesmyslná šířka 2,0 %**, a při prahu **20 je jen 1,7 %**, tedy MÉNĚ než při 25. Ta závislost je nemonotónní, což znamená, že **práh tu vadu neřídí** — případy s kolmou přímkou nejsou soustředěné v cyklech s málo inliery. Rozdělení šířky je přes všechny prahy prakticky stejné (p50 3,00–3,16 m). Druhý signál týmž směrem: cykly, které by práh navíc pustil, procházejí testem rovnoběžnosti **častěji** než ty dnes přijaté (65 % proti 47 % nad 17. 9.) — přesný opak toho, co by „málo inlierů = šum" předpovídalo. ⚠️ **Neříká to, že by se tím něco spravilo.** Měří se jen stupeň *proložení*; jestli by ty koridory navíc prošly přiřazením hrany a příčnou bránou, se z těchto záznamů říct nedá — 17. 9. byl rozbitý kurz a póza 2,5–4,5 m mimo mapovanou vozovku, takže tam se stejně ztrácelo všechno až dál. A „šířka v 1–8 m" je slabé měřítko kvality: přímka proložená na špatnou hranu (obrubník místo trávy) dá věrohodnou šířku taky. ✅ **Od 17. 9. 2026 je to parametr corridormininliers=** (výchozí 25, tedy beze změny chování), takže A/B na zařízení jde pustit z profilu. Výchozí hodnota se ZÁMĚRNĚ nemění, dokud se neprojede na robotu: měření výš je jen o stupni proložení, ne o tom, co doteče do fúze. Spodní mez validátoru je 3 — dvěma body jde přímku proložit vždy, takže 2 by bránu fakticky vypnulo. 18. 9. 2026 s kalibrovaným kompasem: zisk prahu 20 je jen **+6–7 %** koridorů (17. 9. při rozbitém kurzu 4×) a nesmyslná šířka roste — ztráty už nesedí na tomhle prahu. Výchozích 25 zůstává; A/B na zařízení tím ztrácí naléhavost. Škrcení 1,4–4× z názvu tedy platilo jen při rozbitém kurzu; s dobrým kurzem je to ~7 %. **Rozhodnutí autora 21. 9. 2026: přísnějších 25 zůstává**, A/B na zařízení se nedělá — měření z 18. 9. říká, že 20 přinese jen ~7 % koridorů navíc za horší nesmyslnou šířku, a parametr corridormininliers= je k dispozici, kdyby se to mělo někdy přeměřit.

  • Blok *PRAH INLIERU* v reportu (geometrie z uložených úseček; měřidlo ověřené proti známé odpovědi) 17. 9. 2026
  • Změřeno na dvou záznamech (17. 9. a 16. 9.), nemonotónní závislost potvrzena 17. 9. 2026
  • Vystavit MinInliers jako parametr corridormininliers= (validátor 3–500, guard test hlídá, že se čte) 17. 9. 2026
  • Rozhodnout výchozí hodnotu — autor 21. 9.: zůstává 25, A/B na zařízení se nedělá (18. 9. změřeno, že 20 dá jen ~7 % navíc za horší šířku) 21. 9. 2026
  • Změřit s dobrým kurzem — 18. 9.: práh 20 dá jen +6 / +7 % koridorů (3 414 proti 3 221; 3 426 proti 3 211) při horší nesmyslné šířce (1,7 → 2,5 %; 0,6 → 0,9 %); přiřazení hrany pouští 98–99 %, takže by skoro všechny došly do fúze — zisk malý, 25 zůstává 18. 9. 2026

map-correlation-localization.md, CorridorConfig.cs, CorridorReport.cs · DevLog 2026-09-17, 2026-09-18

Měřicí režim koridoru nebyl měřicí — corridorsend v profilu chybí

hotovo vada nalezeno 17. 9. 2026 vyřešeno 18. 9. 2026

lok-koridor-merici-rezim i CLAUDE.md tvrdí, že provozní profil běží s corridorsend=false, tedy „plná zátěž, nulový vliv na řízení", a týž úkol vede jako OTEVŘENÝ krok „corridorsend=true — až po opravě magnetometru a přiřazení hrany". V config/pi-provoz.cfg ale ten řádek 17. 9. **nebyl**, takže platil default true a korekce se posílaly do fúze. Potvrzuje to i účinná konfigurace v záznamech ze 17. 9. (corridorsend=true (default)) a report: *poslana pricna korekce 16 z 16 Ok, poslana korekce kurzu 16 z 16 Ok*. Upřesnění z gitu (audit 21. 9.): řádek corridorsend=false v profilu **byl** od 15. 9. (0e34771) a měřicí jízda 16. 9. s ním jela (corridorsend=false (profil) v účinné konfiguraci); odstranil ho autor 17. 9. v přípravě na Robotour (8bf1081, zakomentováno) a týž den zapsal true (a44b4f4). Měřicí režim tedy platil jeden den, ne „nikdy". ⚠️ **Podstatné je, co tím prošlo:** těch 16 korekcí kurzu odešlo v běhu, kde měl koridor abs nesouhlas kurzu p50 **23,4°** (nezkalibrovaný kompas, viz hw-zelezo-od-kabelu-kamer) — tedy přesně ta situace, kvůli které měla brána zůstat zavřená. GateMode.Soft je nezahodí, jen odtlumí. Je to vada **dokumentace proti skutečnosti**, ne v kódu: chybí jeden řádek v profilu. ⚠️ A ukazuje na obecnější past — „výchozí hodnota je bezpečná" tu neplatí, protože default corridorsend je true; bezpečný stav se musí do profilu napsat, ne předpokládat. ✅ **Uzavřeno 18. 9. 2026 opačně, než nález navrhoval:** bezpečný stav se do profilu nezapsal — zapsal se ostrý. Autor corridorsend=true zapnul vědomě 17. 9. (a44b4f4) a první jízdy 18. 9. ukázaly, že koridor za jízdy dává měření v každém druhém cyklu a fúze se jím řídí (viz lok-koridor-hranova-lokalizace). Odstavec v CLAUDE.md o „měřicím režimu" přepsán.

  • Nález (účinná konfigurace v záznamu proti tvrzení v úkolu i v CLAUDE.md) 17. 9. 2026
  • Vyřešeno OPAČNĚ: autor 17. 9. zapsal do profilu corridorsend=true vědomě (commit a44b4f4); dokumentace (CLAUDE.md, registr) srovnána 18. 9. 17. 9. 2026
  • Projít profil, jestli takhle „nezapsaným defaultem" nevisí i jiná brána — 18. 9.: mapcorr v profilu není a jeho default je false (bezpečný), corridorstd/headingstd/hz 0 = bez odtlumení (zapsané jako komentář); jediná brána s ostrým defaultem byla corridorsend 18. 9. 2026

pi-provoz.cfg, map-correlation-localization.md · DevLog 2026-09-17, 2026-09-18

Příčná brána koridoru zahazovala 81,8 % cyklů — zrušena bez náhrady

hotovo vada nalezeno 18. 9. 2026 vyřešeno 1. 10. 2026

Z dotazu autora „na kolik je nastaven parametr ovlivňující příčnou bránu?“ nad 20260917-160558.rec. MaxLateralDisagreementM = 1,5 m byla hardcoded konstanta bez klíče — a hlavně testovala doslova tutéž veličinu jako EdgeAssociator o pár řádků výš (dLat = corridor.Lateral − axis.Lateral), jen pevným pravítkem místo χ² škálovaného kovariancí pózy, a stála až ZA ním. Nad tím záznamem zahodila 81,8 % cyklů, které dostaly hranu, při σ polohy z fúze 3,73 m — tedy brána na 0,4 σ vlastní nejistoty. Je to táž vada, jaká se u MapCorrelatoru změřila 25. 8. 2026 (tvrdý Reject dělal výsledek horší než nekorigovat vůbec): tvrdý strop na innovaci zahazuje právě ty velké korekce, které jsou potřeba, takže chyba pózy zůstane nad stropem navždy a hrana je němá. Zrušeno, ne přenastaveno: rozsah dLat je omezený konstrukcí (≲ 10 m), takže práh „jen jako pojistka“ by byl mrtvý kód a nižší řeže do živého. Odemklo to i učení šířky (widths.Add stálo až za branou) — týž zámek, jaký se 15. 9. odstraňoval o patro níž. Hodnota enumu LateralDisagreement = 6 zůstává kvůli čtení starších .rec. Na zařízení od 19. 9. (binárka nasazená ráno na Robotouru): do fúze došly inovace 36× nad 2 m, max 6,1 m, které by brána 1,5 m nepustila — a právě ty vyrobily skoky pózy (lok-koridor-skoky-pozy); to je cena zrušení, kterou má zaplatit limit kroku, ne vrácená brána. **Přeměřeno 1. 10. 2026** nad 20260917-160558.rec (fusionreplay, uzavřená smyčka): záznam 198 cyklů s hranou, brána zahodila 162 (81,8 %), prošlo 16. Bez brány s tehdejší konfigurací Ok 73, z bráněných 53 → Ok (83 → NoEdge, 26 → WidthNotTrusted), χ² vítěze p50 0,91 / p90 6,61 (max 9,17 pod prahem 9,21); pomohlo to v minutě 2 (0,68 proti 2,02 m od osy sítě), ale bez limitu kroku přišel skok 3,65 m a v minutě 4 póza 11 m od sítě (s bránou 2,4 m). S dnešními pojistkami skoky od koridoru zmizely (3 → 0) a póza je do ~1 m varianty bez koridoru. Vedlejší nález: při neomezeném odstupu hrany a nejistotě polohy ~7,5 m bere přiřazení souběžnou ulici 24,5 m od GPS → lok-assoc-velka-sigma-soubezna-ulice. Tabulka v [map-correlation-localization.md](map-correlation-localization.md).

  • Nález — brána testuje tutéž veličinu jako EdgeAssociator a stojí za ním 18. 9. 2026
  • Brána i MaxLateralDisagreementM odstraněny, tři testy otočené/nové 18. 9. 2026
  • Report corridor — „nad bývalou branou“ + varování u starších záznamů 18. 9. 2026
  • Přeměřit nad 20260917-160558.rec (kolik cyklů projde, rozdělení AssocChi2): 16 → 73 Ok, χ² p50 0,91 / p90 6,61; fusionreplay blok 2 tiskne nově χ², odstup, σ polohy a |GPS − osa vítěze| 1. 10. 2026
  • Ověřit na zařízení — Robotour 19. 9.: inovace do 6,1 m došly do fúze, brána prokazatelně pryč; cena = skoky pózy 20. 9. 2026

map-correlation-localization.md, decisions.md · DevLog 2026-09-18, 2026-09-20, 2026-10-01

Skoky pózy 0,6–4 m na rovných úsecích přicházejí všechny hned po přijatém měření koridoru

hotovo vada nalezeno 20. 9. 2026 vyřešeno 7. 10. 2026

Robotour 19. 9. 2026 (Kolo3b, Kolo4): 14 z 14 a 9 z 9 skoků pózy (posun mezi RobotStateMsg o 0,6–4 m nad |v|·dt) přišlo do 0,1 s po přijatém měření Corridor, často v sériích jedním směrem (14:25:05–07 čtyři skoky −59° o 5,8 m; 15:42:32–34 pět skoků o 4 m) — koridor táhl pózu k jiné hraně nebo poloze, ne šum. Koridor byl přijat 1 404 z 1 404 (0 % zamítnuto, NIS p90 3,1, max 443): GateMode.Soft nezahodí nic, jen odtlumí, a corridorstd=0,1 / corridorhz=2 z 18. 9. tomu nezabránily. Po skoku typicky EscapingBlocked (robot je najednou v blokované části gridu). Ve FreeRun (Kolo3-navrat) 3 skoky, všechny také za koridorem. Měří to blok 1 ARBot.Analyze nav. Léčba je od 21. 9. v kódu: rychlostní limit kroku uvnitř filtru (corridorslew= m/s, corridorheadingslew= °/s, výchozí 0 = dnešní chování); hodnota vybraná týž den večer z Kola 3b/4 (ARBot.Analyze corridorstd --slew= --hslew=): corridorslew=0.5, corridorheadingslew=3 v pi-provoz.cfg. „−59°" u skoků je směr posunu, ne otočení — korekce kurzu z koridoru jsou max 2°, limit kurzu je pojistka. Na zařízení neběželo.

  • Změřit: skoky pózy vs. přijatá měření koridoru (blok 1 nav) 20. 9. 2026
  • Proměřit corridorstd= protifaktickým 1-D replayem (ARBot.Analyze corridorstd): 0,5–1,0 m odstraní kroky > 0,3 m (21 → 1 → 0 v Kolo3b), 5 m nepřidá nic a srazí informaci koridoru na 6× GPS; cena je pomalejší stažení driftu (odchylka p50 0,8–1,3 m, p90 2,4–2,6 m); inovace p50 0,06 m, ale 36 nad 2 m v sériích na téže hraně (změna hrany jen 6 ze 78); koridor za jízdu stáhl 20–28 m driftu 20. 9. 2026
  • Rozhodnout léčbu: rychlostní limit korekce (autor souhlasí s principem; návrh PoseSlew na výstupu fúze 20. 9. zamítl kvůli dvěma pózám v systému — varianta uvnitř filtru se má nejdřív probrat), nebo corridorstd 0,5–1,0 v profilu 21. 9. 2026
  • Mechanismus v kódu: IMeasurement.MaxStep + nafouknutí R v Ekf.UpdateStep (krok = přesně limit, P konzistentní, měření se nezahazuje), corridorslew= [m/s] a corridorheadingslew= [°/s] s Δt od předchozího odeslání (0,02–1 s), MeasurementDiagMsg v3 (RInflation, StepLimited), ARBot.Analyze corridorstd --slew= (blok 4), blok „limit kroku" v ARBot.Analyze corrections; výchozí 0 = dnešní chování; 16 testů; řetěz ověřen 45s simulací (StepLimited v záznamu, blok 4 stropuje krok přesně na limit) 21. 9. 2026
  • Zvolit hodnotu z dat: ARBot.Analyze corridorstd Kolo3b.rec / Kolo4.rec --slew= --hslew= (blok 4 příčně, nový blok 4b kurz): corridorslew=0.5 = největší hodnota, při které v obou záznamech nezbyde kalibrovaný krok nad 0,3 m (bez limitu 21 / 16, 1,0 m/s nechá v Kole 4 23 kroků do 0,46 m), cena p50 odchylky 0,21 / 0,19 m (0,3 m/s by dalo 0,37 / 0,77 m); corridorheadingslew=3 jen pojistka — korekce kurzu z koridoru max 2,0 / 0,6° (K p50 0,07), replay bez rozdílu; zapsáno do config/pi-provoz.cfg 21. 9. 2026
  • Měřidlo: K_eff v corridorstd je z okna 50 ms po měření a krok PODCEŇUJE — skok 14:25:05 (inovace 6,13 m, K·ν 5,83 m) je v nav bloku 1 vidět jako čtyři dílčí skoky 2,47 + 1,64 + 1,06 + 0,64 = 5,81 m za 1,6 s, fúze krok rozkládá, ne tlumí; přeměřit kalibraci přes delší okno (pořadí variant to nemění, jen výši ceny) — ❌ VYVRÁCENO 29. 9. 2026 (fusionreplay blok 6, Kolo 3b): čtyři dílčí skoky jsou ČTYŘI SAMOSTATNÁ měření koridoru po ~0,5 s, každé posune aktuální pózu o svůj vlastní krok (14:25:05.1 → 2,45 m, .6 → 1,63 m, 06.1 → 1,04 m, 06.7 → 0,61 m; nav blok 1: 2,47 / 1,64 / 1,06 / 0,64 m). Fúze krok nerozkládá — už první měření udělalo 2,45 m, ne 5,83 m, takže okno 50 ms měřilo krok jednoho měření SPRÁVNĚ a kalibrace podhodnocená není. Přeměřovat netřeba; volbu corridorslew jde dnes zkoušet přímo nad skutečným filtrem (fusionreplay --set=corridorslew=…) 29. 9. 2026
  • Ověřeno na zařízení 1. 10. 2026 (binárka f848fdf; 20261001-144638.rec Track 42 min / 3 260 m, -152906.rec FreeRun 10 min / 792 m; corridorslew=0.5, corridorheadingslew=3, corridorseekback=1, corridorposlimit=true z profilu — první jízdy s celou léčbou): skoků nad 0,5 m (nav) 0 a 0, StepLimited 29 z 6 512 a 6 z 1 886 měření, žádné uzavření ani penalizace hrany. Krok pózy mimo predikci nejvýš 0,54 m, tedy přesně na toleranci PoseJumpDetector — grid se proto nemaže a místo skoků vznikají SESUVY (1,5–2,2 m za 5–10 s); jejich důsledek v gridu vede lp-grid-posun-pomalou-korekci / lp-uvaznuti-v-zatackach 7. 10. 2026
  • Změřeno 29. 9. nad 12 jízdami s limitem (23.–29. 9., corridorslew=0.5): limit zasahuje (StepLimited 0,5–18 % měření), skoků je méně a menší (0–11 na jízdu, většinou 0,6–1 m; Kolo 3b bez limitu 14 až 2,5 m), ale NEZMIZELY — a fusionreplay blok 5 ukázal, že **všechny** udělal koridor (ve variantě bez koridoru žádný). Blok 6 (účinek jednoho odeslání na aktuální pózu) našel DVA úniky: (a) **kolmé skoky 0,6–0,85 m** = dvě odeslání v jednom 100ms intervalu pózy, každé v limitu: VydatMerenie i LimitDt berou JAKÝKOLI skok času zpět jako seek — škrcení se vynuluje a Δt dostane strop 1 s (limit 0,5 m); čas fixu jde zpět ve 22–26 % zpráv (párování dvou kamer, o 10–20 ms, max 0,17 s), u odeslání ve ~25 % (25. 9.: 927 z 2 924). (b) **podélné skoky 1–4 m** (27. 9. 17:26:01 jedno odeslání posunulo pózu 3,98 m podél hrany a 0,18 m kolmo): limit omezuje krok jen podél osy měření, podélná složka jde přes vazbu v kovarianci (typicky po inicializaci z GPS) 29. 9. 2026
  • Léčba (autor, obojí): (a) corridorseekback= (1 s, SeekBackSec) — menší skok zpět je Δt ≈ 0; (b) IMeasurement.MaxPositionStep + Ekf.PositionIndices, corridorposlimit=true — limit normy posunu polohy u příčného i kurzového měření. 8 nových testů (premisy se starým chováním padají), testy 1 719 / 148 / 129. Přehrání 7 jízd se zapnutou léčbou: skoků od koridoru 0 (dřív 2–11 na jízdu), přesnost stejná nebo lepší, měření o 25–35 % méně. Starší záznamy přehrávání pouští se starým chováním (klíče v logu nejsou) 29. 9. 2026

global-navigation-runtime.md, map-correlation-localization.md, rozhodnutí 21. 9. · DevLog 2026-09-20, 2026-09-21, 2026-09-29, 2026-10-07

Na široké cyklostezce (Modřany) koridor nedal ani jedno měření — Track se podle něj nekorigoval a FreeRun jel „rovně“

hotovo vada nalezeno 24. 9. 2026 vyřešeno 7. 10. 2026

Všechny čtyři záznamy z 23. 9. 2026 (records/test/20260923-*.rec, mapa OSM/modrany2.osm): **0 přijatých měření koridoru**, koridor se proložil v 0,2–0,3 % cyklů (18. 9. na Hviezdoslavově ~52 %). Za jízdy vadí TooFewInliers a OneSideOnly; přímky obou hran existují v ~50 % cyklů, ale s mediánem **21–25 inlierů** proti prahu corridormininliers=25 (18. 9. 39–43), v Track na pravé straně jen 10 (rezidua 0,116 m). FreeRun proto měl mrkev z koridoru jen v 18 z 6 632 cyklů a jinak držel kurz — ten ujíždějící (lok-freerun-kurz-staci-na-zapad); na cestě ho držela lokální mapa. Segmentace sítě je na asfaltu čistá (backproject --compare), jde tedy o proložení hran na široké cestě (hrana daleko, řídké body). Mapa nemá u cyklostezky tag width (síť počítá s roadwidth=3). V Track navíc 34 % NoPair kvůli dvěma zamrznutím barvy (pravá 14:38:44, levá 14:40:53, obě zotavené). Kód detekce se od 21. 9. neměnil. **Léčba 24. 9. 2026: měření z JEDNÉ hrany** (corridorsingle=, výchozí true): kurz ze směru hrany (na šířce nezávisí), příčná poloha přes naučenou šířku, jinak mapovou s nejistotou corridorsinglewidthstd= (1 m) v σ — rozhodnutí autora. ARBot.Analyze singleedge nad týmiž záznamy: jedna hrana v 48–80 % snímků, kurz z ní proti GPS kurzu p50 −1,3 až +1,2°, robustní sd 2,4–4,9°; ve FreeRun drží u nuly, zatímco odhad fúze ujel na 30°+. RoadCorridorMsg verze 7. ⚠️ Chyba mapové šířky je bias příčné polohy (Modřany: mapa 3 m).

  • Měření z jedné hrany v kódu + ARBot.Analyze singleedge + testy 24. 9. 2026
  • Jízda na cyklostezce s corridorsingle=true: kurz odhadu proti GPS kurzu (heading), podíl přijatých z jedné hrany (corridor). ⚠️ 29. 9. (20260929-150844.rec, -151634.rec) NEROZHODNE: přijato z jedné hrany jen **135 (1,6 %) a 306 (4,6 %)** cyklů, a to hlavně v první ~2 min; zbytek zamítlo přiřazení hrany (AmbiguousEdge 4 171 / 2 159, EdgeMismatch 1 121 / 1 932) — regrese opravená týž den (lok-assoc-sousedni-usek). Kurz odhadu − GPS kurz −3,3 ± 6,5° / +4,3 ± 11,2°, ale ten určoval kompas (hw-vn100-zmena-po-27-9), ne koridor. Přeměřit s assocfloorlong=3. ✅ **1. 10. 2026** (20261001-144638.rec Track, -152906.rec FreeRun; binárka f848fdf s assocfloorlong=3, corridorsingle=true a od 30. 9. s branou inlierů 10 % řádků): Ok 62,3 % a 77,8 % cyklů, z jedné hrany 7 571 a 3 231 cyklů (převážně pravá), do fúze 3 262 a 943 snímků, z toho 31 / 38 % z jedné hrany. Kurz odhadu − GPS kurz nad 0,8 m/s 0,13 ± 3,32° a 0,79 ± 3,55° (|.| p50 1,2 / 1,3°) — drží i v době, kdy yaw VN100 ujel o +15 až +35° (Track 15:07–15:13). Proti 29. 9. 11–56× víc měření z jedné hrany; podíl na nárůstu má i nová brána inlierů 7. 10. 2026
  • Změřit skutečnou šířku cyklostezky (nebo doplnit width do mapy) — příčná poloha z mapové šířky je jinak posunutá. Z koridoru při prahu ≤ 15 vychází 4,85–5,3 m (mapa 3 m). **Autor 6. 10. 2026:** cca **5 m**, mírně kolísá, od určitého místa jen **3 m**; do mapy se width **doplňovat nebude**. Na 5m úseku tedy příčná poloha z jedné hrany s mapovou šířkou ujede o ~1 m (polovina rozdílu), dokud se šířka nenaučí z oboustranného koridoru (RoadWidthEstimator, roadwidthmap=); na 3m úseku mapa sedí 6. 10. 2026
  • Snížit corridormininliers — autor 26. 9. 2026: **20** v config/pi-provoz.cfg (FreeRun 20260925-144658.rec: 2,7 → 28 % snímků, šířka p50 3,61 m, mimo 1–8 m 1,6 %; 12–15 by pustilo víc, ale s nesmyslnými šířkami) 26. 9. 2026
  • 29. 9. 2026 (20260929-150844.rec, -151634.rec, corridormininliers=20): oboustranný koridor jen v **1,6 % a 1,2 %** snímků (135 a 78 cyklů), ne 28 % jako nad 25. 9. — a šířka z nich p50 **1,36 / 0,40 m** (mimo 1–8 m 24 / 88 %), tedy převážně nesmysl; při prahu 10 by jich bylo 2 432 / 1 051 se šířkou p50 **5,04 / 4,79 m**. Do přiřazení došlo jen 89 a 20 oboustranných cyklů, takže **naučená šířka nevznikla** (odhad se učí jen z oboustranného koridoru po přiřazení hrany) a roadwidthmap=true neměl co propsat. Jedna hrana 86 % a 70 % cyklů (převážně pravá) 29. 9. 2026

map-correlation-localization.md, mission-freerun.md · DevLog 2026-09-24, 2026-09-29, 2026-10-07

Po zatáčce je póza 12 m vedle cesty a koridor ji neopraví — hranu hledá jen do 8 m (NoEdge)

hotovo vada nalezeno 26. 9. 2026 vyřešeno 30. 9. 2026

Track 25. 9. 2026 (20260925-142428.rec): podélná chyba 12,9 m z rovinky (lok-odometrie-obvod-kola) se v první zatáčce (~460 s) změnila na **příčnou**: na cestě k východu je póza 12,0–13,0 m severně od GPS, odstup pózy od sítě 11–12 m, GPS od sítě 0,4–1,5 m (robot fyzicky jel po cestě, lokální plán Ok, 1,5–1,6 m/s). Koridor po celou dobu (490–570 s) hlásí **NoEdge** (119–198 cyklů za 10 s) a nepošle nic: přiřazení hledá hranu jen do CorridorLocalizerConfig.MaxEdgeDistanceM = **8 m** od pózy. Oboustranný koridor přitom měřil jen v úseku 290–440 s (way 154101921), jinde jen z jedné hrany. Jakmile se ~580 s dostala do 8 m nějaká hrana, jednohranová měření s inovacemi −2,7 / +3,2 / +2,0 m (p50 za 10 s) stáhla pózu limitem corridorslew=0,5 za ~30 s o ~10 m zpět k GPS (odchylka 12,6 → 2,3 m). Která hrana to byla (správná, nebo příčná), z toho vidět není. Koridor je tak slepý právě tehdy, když je chyba největší — a GPS s σ 30 m pózu nevrátí. ✅ **Uzavřeno 30. 9. 2026 (autor):** příčina (obvod kola) je opravená — 29. 9. potvrzeno, kola / tětiva GPS 0,999 — takže podélná chyba, ze které se v zatáčce stává příčná, bude menší, a 8m brána je zrušená (MaxEdgeDistanceM = ∞). Podlaha χ² přiřazení (assocfloorlat=3) zůstává, jak je.

  • Změřeno: NoEdge po zatáčce, odstup pózy od sítě 11–12 m, pozdní korekce ~10 m za 30 s (ARBot.Analyze posegps, corridor) 26. 9. 2026
  • Příčina opravena (lok-odometrie-obvod-kola) a 8m limit vypnut (autor): MaxEdgeDistanceM = ∞ 26. 9. 2026
  • Rozhodnout (autor): χ² přiřazení s podlahou assocfloorlat=3 pořád zamítne 12 m (χ² ≈ 16 > 9,21 → EdgeMismatch) — nechat, nebo podlahu vázat na skutečnou nejistotu pózy (filtr hlásí 0,1 m při chybě 12 m). Autor 30. 9.: nechat — s opraveným obvodem kola bude chyba menší 30. 9. 2026

map-correlation-localization.md · DevLog 2026-09-26, 2026-09-30

Obvod kola je o ~1,8 % větší, než robot ujede — póza na rovince utíká dopředu (12,5 m na 740 m)

hotovo vada nalezeno 26. 9. 2026 vyřešeno 29. 9. 2026

Pozorování autora z Track 25. 9. 2026 (records/test/20260925-142428.rec, Modřany, rovinka k severu 0–450 s): odhad fúze se postupně vzdaluje od GPS. Změřeno ARBot.Analyze posegps: póza je před GPS podélně o 0,06 m v 10 s, 5,7 m ve 100 s a **12,5 m ve 440 s** (~740 m jízdy), příčně jen ~1 m (kurz sedí, IMU − GPS −1,2°). Na přímých úsecích (okno 30 s, změna směru < 3°) je dráha z kol / tětiva GPS **1,018** (p10–p90 1,00–1,03, n = 63) a Doppler / kola ve stejných oknech 0,982 — dvě nezávislé cesty, stejné číslo. Profile.WheelRadius = 0,085944 · 0,94 (0,94 = „změřené zmáčknutí pneumatiky") je tedy o ~1,8 % velký; odpovídal by činitel ~0,923. S gpsposstd=30 určuje podélnou polohu téměř jen odometrie (σ 0,05 m/s, ~91 Hz), takže chyba měřítka jde 1:1 do pózy — a **po zatáčce se změní na příčnou** (lok-koridor-noedge-po-zatacce). Jedna jízda, jeden povrch; zmáčknutí závisí na zatížení, tlaku a povrchu.

  • Změřeno: kola / tětiva GPS 1,018, Doppler / kola 0,982 (ARBot.Analyze posegps) 26. 9. 2026
  • Autor opravil konstantu Profile.WheelRadius: činitel 0,94 → 0,923 26. 9. 2026
  • Ověřit na další jízdě: posegps, blok PŘÍMÉ ÚSEKY → kola / tětiva GPS ~1,00. ⚠️ 27. 9. (binárka s 0,923, Track a FreeRun Hviezdoslavova) NEPOUŽITELNÉ: po jednom 30s přímém okně (kola / tětiva 1,018 a 1,022, n = 1), GPS startovala na 3 družicích a ležela p50 4,7 m od cesty, jízdy 163 a 120 m. ✅ 29. 9. (Modřany, 20260929-150844.rec Track a -151634.rec FreeRun, 425 a 405 m): kola / tětiva GPS **0,999** (p10–p90 0,96–1,02, n = 58) a **0,999** (0,98–1,00, n = 28), Doppler / kola 1,003 a 0,990. Obvod sedí. Vzorky motorů jsou bez mezer ≥ 0,1 s, měřidlo tedy dráhu z kol nepodhodnocuje. ⚠️ Póza přitom jede o 1,1 % dál než kola — to není obvod, viz lok-fuze-poza-pred-koly 29. 9. 2026

ekf-fusion.md · DevLog 2026-09-26, 2026-09-29

Přiřazení hrany je „nejednoznačné“ se sousedním úsekem TÉŽE cesty — koridor na dlouhé rovince nepošle nic

hotovo vada nalezeno 29. 9. 2026 vyřešeno 7. 10. 2026

Pozorování autora z jízd 29. 9. 2026 v Modřanech (20260929-150844.rec Track, -151634.rec FreeRun): korekce z koridoru se neaplikovaly. Změřeno: AmbiguousEdge **51 % a 33 %** cyklů, do fúze za celou Track jízdu (430 s) šly jen desítky měření z jedné hrany v první minutě, pak nic; póza mezitím ujela od GPS příčně až o **10 m** (FreeRun 16 m), tempem ~0,06 m/s, tedy ~2° kurzu. Nový ARBot.Analyze assocwhy (rozklad na hypotézy, přepočet sedí na záznam v 99,3 / 100 %): druhým kandidátem je ve **99 %** nejednoznačných cyklů **jiný úsek téže cyklostezky** (way 154101921; sousední 67–75 %, vzdálenější 23–32 %), jiná cesta jen 0,4–1,4 %. Ten úsek je od pózy p50 **46–51 m** (p90 106–119 m) a robot vedle něj vůbec nestojí — RoadAxis.Relate počítá příčnou polohu z **nekonečné přímky** úseku, takže ohyb 1,7° (p50) dá v té vzdálenosti osu ~0,8–1,0 m vedle: víc než SameHypothesisLateralM (0,5 m), a při podlaze příčné sigmy 3 m je rozdíl χ² ~0,1 proti požadovanému odstupu 4. NearestEdges přitom kandidáty řadí podle vzdálenosti k ÚSEČCE, ale skóre ji nepoužije vůbec. OSM rovinka je lomená čára po 20–180 m, takže to platí na celé její délce; slučování kolineárních úseků (16. 9.) chytí jen přímou návaznost. **Protifakt** (měření, ne změna kódu): k χ² přičíst (podélný přesah / σ)², kde přesah je, o kolik póza leží za koncem úsečky, a σ = max(póza podél hrany, podlaha 3 m). Nejednoznačných 4 289 → 357 a 2 161 → 81, přiřazeno Ok 137 → 4 053 a 306 → 2 333, vybraná cesta do 2 m od GPS **99,9 % a 94,6 %** (dnes 97,8 % a 51,6 %). Příčný nesouhlas těch přiřazených p50 4,3 / 2,7 m je z velké části právě nashromážděný drift pózy. ⚠️ Za přiřazením jsou ještě brány šířky a „robot na cestě“, takže do fúze by šlo méně; ⚠️ příčná poloha z jedné hrany jde přes mapovou šířku 3 m proti skutečným ~5 m (lok-koridor-siroka-cyklostezka), tedy s biasem ~1 m.

  • Změřeno: druhý kandidát = úsek téže cesty 46–51 m daleko, protifakt s podélným přesahem (ARBot.Analyze assocwhy) 29. 9. 2026
  • **Je to regrese z 26. 9.** (d193c12, MaxEdgeDistanceM 8 m → ∞ kvůli lok-koridor-noedge-po-zatacce): s limitem 8 m se úsek 50 m daleko do kandidátů vůbec nedostal. Přepočet s --maxedge=8 sedí na starší záznamy 99,6–99,9 % (s ∞ jen 41–73 %), a dnešní Track by s 8 m měl Ok 3 779 cyklů místo 137. Oprava 26. 9. přitom získala jen pás 8–~9 m: nad ním zamítne kandidáta χ² s podlahou 3 m (EdgeMismatch). Protifakt s podélným přesahem na 13 záznamech (Hviezdoslavova, Robotour, Modřany): **nezávisí na limitu** (Ok s 8 m i ∞ v rozmezí ±6 %), **nezměnil vítěze ani jednou** mezi cykly přiřazenými dnes, ztráta ≤ 0,4 %, a navíc spraví nejednoznačnost sousedních úseků v zatáčkách, která existovala i s 8 m (Robotour Kolo 3b +780 a Kolo 4 +817 cyklů, vybraná cesta u GPS 100 %) 29. 9. 2026
  • Léčba (autor): podélný přesah do χ², assocfloorlong=3 m (0 = nepočítá se), MaxEdgeDistanceM zůstává ∞. RoadAxisMatch.OverhangM, EdgeAssociator, 4 nové testy; EdgeAssociator dává nad 8 záznamy (39 871 cyklů) tentýž verdikt jako protifakt v měřidle ve 100 %. Změněná cesta jen v 9 cyklech 27. 9. (GPS 4,7 m mimo, nerozhodne). FusionReplayReport bere hodnotu z logu (starší záznam = 0) 29. 9. 2026
  • Ověřeno na zařízení 1. 10. 2026 (20261001-144638.rec Track, -152906.rec FreeRun, binárka f848fdf s assocfloorlong=3): AmbiguousEdge 8,2 % a 6,5 % cyklů proti 51 % a 33 % 29. 9.; na rovinkách (dál než 30 m od dvou 90° zatáček) jen 3,2 % a 0,0 % cyklů za jízdy. Do fúze odešlo 3 262 a 943 snímků, póza − GPS příčně p50/p90 0,77/1,64 m a 0,73/1,35 m. Zbylá nejednoznačnost leží skoro celá v zatáčkách (21–69 %), kde je sousední úsek téže cesty legitimní druhý kandidát — podélný přesah to neléčí, vede se jako lok-koridor-slepy-v-zatacce 7. 10. 2026

map-correlation-localization.md, rozhodnutí 29. 9. 2026 · DevLog 2026-09-29, 2026-10-07

Šířka koridoru vychází o 18 mm větší — nejmenší kvadráty sledují průměr, medián sedí

zamítnuto vada nalezeno 24. 8. 2026 vyřešeno 18. 9. 2026

Nad rovnou mapou proti pravdě vyšla šířka 2,018 m místo 2,000 (filtr šířky tu odchylku schovával devítinásobně). Surové body chybu nemají — medián sedí na okraji — ale rozdělení je zešikmené s dlouhým chvostem ven z cesty, a proložení nejmenšími kvadráty sleduje průměr. Příčinou je drsnost trávy v simulaci: bez ní je vychýlení −1,7 mm, při 0,12 m už +54 mm. Proložení cílící medián (LineFitMode.OrthogonalL1) srazí vychýlení na 1,4 mm (−92 %) a klesne i rozptyl; Huber s MAD je slabší, Tukey nestabilnější. Nezapnuto — autor 27. 8. rozhodl počkat na měření na reálné kameře, protože to zešikmení je artefakt simulace a na skutečné trávě se může ztratit v šumu. Zapínat léčbu vady, o které se neví, jestli na železe existuje, by znamenalo ladit simulaci. ❌ **Zamítnuto 18. 9. 2026:** na reálných datech (20260918-155329.rec, 10 340 dvojic) dávají všechny varianty proložení týž výsledek v rámci rozpětí opakování; pravda k dispozici není, ale rozdíl, který by šlo obhajovat, nevzniká. LeastSquares zůstává. Otevře se znovu jen se záznamem s pravdou.

  • Nález proti pravdě (corridorfit --truewidth --axisy) 24. 8. 2026
  • Příčina dohledána (edgebias, zešikmení z drsnosti trávy) 24. 8. 2026
  • OrthogonalL1 / OrthogonalHuber / OrthogonalTukey naměřeny, LeastSquares zůstává 24. 8. 2026
  • Rozhodnutí autora odložit do měření na HW 27. 8. 2026
  • Změřit na záznamu ze skutečné kamery — 18. 9.: corridorfit --limit=0 --rep=3 nad 10 340 dvojicemi, LS/L1/Huber/Tukey nerozlišitelné (Ok 3 176–3 232, rezidua 0,076–0,079 m, vychýlení proti filtru −0,006 až −0,010 m u všech) 18. 9. 2026

map-correlation-localization.md, LineFit.cs, EdgeBiasReport.cs · DevLog 2026-08-24, 2026-08-27, 2026-09-18

Oblast

Navigace po mapě

Oblast

Lokální mapa a plánování

Výkon řetězu hloubka → grid → EDT → A* na ARM není změřený

otevřeno záměr nalezeno 10. 8. 2026

Occupancy grid, distanční transformace a A* běží v řídicí smyčce každý takt (10×/s). Při návrhu 10. 8. 2026 se ověření výkonu na cílové desce zapsalo jako zbývající krok a od té doby se řetěz měřil jen na Windows. Na Orange Pi je změřená vizuální část (zpracování snímku, síť na CPU i NPU) a obsazenost taktu se sleduje souhrnně (PerfMsg), ale rozpad na integraci + EDT + A* jako čísla z ARM chybí — takže se neví, kolik z periody 100 ms tam ten řetěz bere.

  • Změřit integraci + EDT + A* na Orange Pi (doba na takt, podíl periody)

occupancy-and-local-planning.md, perf-monitoring.md, LocalPathPlanner.cs, ClearanceField.cs · DevLog 2026-08-10

Koridor trasy jako měkká cena v lokálním A*

otevřeno záměr nalezeno 12. 8. 2026

Lokální plánovač dostane z trasy po síti cest jen jediný bod (mrkev), takže tvar cesty do ceny A* nevstupuje. Původní obava „robot sjede z cesty všude, kde je vedle geometricky volno" se 27. 8. 2026 ukázala lichá — cesty se drží sám díky sémantickému kanálu z vize (mimo cestu = blokováno) a ceně neznáma, a přibyly testy, které to přibíjejí. Otevřený zbytek je užší: kde vize okraj cesty nevidí, mapa se ho nezastane — měkká preference blízkosti osy cesty (šířka z Node.Width) by to doplnila. Nikdo to zatím nepotřeboval. Pomohlo by na široké zpevněné ploše (náměstí, parkoviště, cyklostezka ~5 m), při nízkém kontrastu okraje, mimo zorné pole a při výpadku kamery. ⚠️ **Podmínka (autor, 25. 9. 2026): nesahat na to před vyřešením driftu kurzu** (lok-freerun-kurz-staci-na-zapad) — cena se počítá v souřadnicích mapy, takže při ujeté póze (23. 9. kurz o desítky stupňů, 19. 9. skoky 0,6–4 m) by táhla robota k ose, která leží jinde. I pak jen jako slabá preference, kterou vidění přebije tam, kde okraj vidí.

  • Ověřeno testy, že plán drží cestu díky sémantice a nebere zkratku přes neznámo 27. 8. 2026
  • Měkká cena podle vzdálenosti od osy cesty v A* (jen kde vize okraj nevidí)

čeká na Při jízdě FreeRun na jih ujel kurz VN100 i odhadu o desítky až 180° (atitudové řešení senzoru přestalo brát magnetometr) · global-navigation-runtime.md, occupancy-and-local-planning.md, LocalPathPlanner.cs · DevLog 2026-08-27, 2026-09-25

Zapisovat pod půdorysem robota důkaz „volno" do kanálu hloubky

otevřeno záměr nalezeno 18. 8. 2026

Původně krok 3 návrhu úniku z blokované buňky, vyčleněný 26. 9. 2026 (autor). Pomohl by jen tehdy, když robot stojí na zdánlivé překážce z HLOUBKY (posunutý grid po korekci pózy, šum těsně u robota) a ta pokrývá celý půdorys — únik smí z výchozí buňky odjet, ale do další geometricky blokované nevjede. Případ z 18. 8. by nevyřešil (tam blokovala barva a do semantického kanálu se psát nesmí), pomalý rozjezd po startu už řeší sjízdný půdorys v obálce (3. 9.). Riziko: zápis podle chybné pózy smaže skutečnou překážku ve slepé zóně kamer, kde ji nic hned nepřepíše. Posunutý grid se má řešit u příčiny (lp-grid-posun-pomalou-korekci). Vrátit se k tomu, až se v záznamu objeví RobotBlocked kvůli hloubce pod půdorysem. **Ta podmínka nastala 1. 10. 2026** (20261001-144638.rec, lp-uvaznuti-v-zatackach), proto znovu otevřeno (7. 10.) — rozhoduje autor. Varianta bez zápisu do gridu: únik bere jako průjezdný celý půdorys (dnes jen startovní buňku). Protifakt nad 319 snímky gridu ve stavu RobotBlocked: poloměr 0,3 m najde východ do 1,5 m ve 246, 0,4 m ve 306, 0,6 m ve všech; stejnou výjimku musí dostat kontrola kolize únikové dráhy (lp-unik-kontrola-kolize-startu). Příčinu (posun gridu) řeší localframe=odom, na HW neověřené.

  • Spouštěč nastal 1. 10. 2026: RobotBlocked 132,4 s a 42,0 s na zdánlivé překážce z HLOUBKY pod půdorysem — buňka pod robotem B:G ve 42/42 a 77/78 snímcích gridu, v r ≤ 0,3 m 98 ze 110 resp. 87 ze 112 buněk geometrických, sémantika tam říkala „cesta“ nebo nic; únik pravidly PlanEscape bez východu do 8 m, bez zákazu geometrie 0,53–0,90 m vpředu (ARBot.Analyze zasek) 7. 10. 2026
  • Rozhodnout (autor): zápis volna / únik přes půdorys, nebo nejdřív ověřit localframe=odom na zařízení

occupancy-and-local-planning.md · DevLog 2026-09-26, 2026-10-07

Obtížně sjízdný povrch (hrbol, prasklina) jako rychlostní strop v lokální mapě

otevřeno záměr nalezeno 22. 9. 2026

Sjízdnost z hloubkové kamery je dnes dvoustavová: buňka je buď volná, nebo překážka (práh výškové odchylky 3 cm + 2 cm na metr dosahu). Hrbol nebo kořen pod prahem projde jako hladká cesta a robot přes něj jede plnou rychlostí; nad prahem je z něj zeď. Inspirace: kořeny a hrboly na Robotouru 19. 9. 2026, kde se robot jen těsně nepřeklopil. Nebezpečí přitom není ráz hnaných kol, ale klopení dopředu, když na hrbol najede ZADNÍ pasivní kolo — o rozvor později než přední náprava; brzdění v tu chvíli klopný moment zvětšuje. Záměr: vést spojitou míru drsnosti (výška schodu a rozptyl výšek, které polární grid už měří, ale do kartézského gridu nepřenáší) jako třetí kanál lokální mapy a odvodit z ní rychlostní strop VSurface, který se skládá s ostatními stropy obálky. Strop musí platit od hrbol − brzdná dráha po hrbol + rozvor a uvnitř být PLOCHÝ (zpomalit před, projet konstantně, zrychlit až za) — mapa si ho tedy musí pamatovat i pod robotem a za ním. Spodní mez strop nemá: kolo regulované na polohu kolečko přes schod protlačí (na asfaltu bez prokluzu), cena nízké rychlosti je jen čas. Riziko: šum hloubky roste s r² (reference 1 cm + 0,4 cm/m², ve 3 m 4,6 cm), takže drsnost je čitelná asi do 1,5 m, brzdná dráha z 1 m/s je řádově metr — horizont stačí jen tak tak a praskliny v asfaltu budou nejspíš pod rozlišením. Proto nejdřív měření ze záznamů, ne kód: bez toho by třetí strop mohl robota přibrzdit všude, jako to 7. 9. udělal VAlong. ZMĚŘENO 22. 9. 2026 (ARBot.Analyze bumps nad records/Robotour2026/, Kolo3b 799 m): drsnost JE vlastnost úseku, ne bodu — nejhorší pětimetrové okno je 2,5× drsnější než medián a podobnost dvou míst klesá pomalu (r = 0,80 na 5 m, 0,65 na 10 m, 0,44 na 20 m, 0,19 na 30 m). Záměr se tím posouvá: nemusí se předpovídat JEDEN kořen z hloubky na 1,5 m (kde šum 4,6 cm ve 3 m sotva stačí), stačí poznat HRBOLATÝ ÚSEK a strop postavit z IMU podle toho, po čem robot už projel. Podmínkou je normalizace na jednotku dráhy — viz kroky.

  • Měřidlo ARBot.Analyze bumps nad záznamy z Robotouru 22. 9. 2026
  • Go/no-go ZMĚŘENO — a odpověď záměr PŘEFORMULOVALA: jednotlivý hrbol z kamery předpovídat netřeba, protože drsnost drží přes desítky metrů (r = 0,80 na 5 m, 0,44 na 20 m, dekorelační délka ~20 m; nejhorší okno 2,5× nad mediánem). Strop jde postavit z IMU, z toho, po čem robot UŽ projel — dosah hloubky 1,5 m přestává být překážkou 22. 9. 2026
  • Normalizovat drsnost na jednotku DRÁHY, ne času: dnešní RMS rychlosti klopení koreluje s rychlostí okna r = 0,134 nad Kolem 3b, ale 0,822 nad Kolem 4. Bez toho by mapa drsnosti byla zčásti mapou rychlosti a strop by se honil za vlastním ocasem (zpomal → vypadá hladce → zrychli)
  • Rozhodnout ZDROJ drsnosti: z IMU po projetí, nebo z polárního gridu dopředu. ZMĚŘENO 22. 9. 2026 (bumps --depth=): grid JE v záznamu uvnitř CameraFrame (dřívější 'neposílá se, chce replay' byl omyl), ale na místě, kde robot později zakopl, se od obyčejné vozovky NELIŠÍ — StdZ p90 poměr hrbol/kontrola 0,95 / 0,98 / 0,91 / 1,68 / 1,02 na 0,5–3,0 m, bez trendu a s odporujícími si ukazateli. Cesta 'z IMU po projetí' je tedy zatím jediná změřeně nosná 22. 9. 2026
  • Vysvětlit rozpor: z náklonu plyne, že kola stoupla o ~6 cm během ~0,13 m dráhy, a to by v hloubce vidět být MĚLO. Buď je párování místa hrubší, než se zdá (chyba dráhy, boční posun, buňka ~7 x 9 cm ve 2 m), nebo to StdZ nezachytí, protože útvar leží uvnitř jedné buňky a proložení roviny ho pohltí. Rozhodne pokus se ZNÁMOU překážkou
  • Třetí kanál gridu (drsnost, byte, spíš max s rozpadem než log-odds), hodnota přežije pod půdorysem robota a za ním; nahradit skrytou vazbu fRough (drsná buňka dnes jen slaběji Free)
  • VSurface v LocalPlannerConfig: plochý strop, sloučení do ceny A* i stropu uzlu, rozpad obálky EnvVSurface
  • Kalibrační jízda přes známé hrboly a ověření na zařízení

traversability-grid.md, occupancy-and-local-planning.md, path-following.md · DevLog 2026-09-22

Reflex proti překlopení při najetí zadního kola na hrbol (nebrzdit, případně přidat)

otevřeno záměr nalezeno 22. 9. 2026

Druhá vrstva k rychlostnímu stropu z mapy, nezávislá na kameře: hrbol se ohlásí rázem předních hnaných kol ve VN100 (100 Hz) a zadní pasivní kolo na něj najede o rozvor / v později — první špička tedy OHLAŠUJE druhou předem a řídicí smyčka si může naplánovat okno kolem ní. V okně platí dolní mez příkazu v_aktuální + k · rampa · Δt: k = 0 zakáže brzdění z obálky, k = 1 na okno přidá (rampy jsou obě 0,50 m/s², takže brzdění působí jednu rampu v neprospěch a zrychlení jednu ve prospěch). Zákaz pomůže jen tehdy, když by robot v tu chvíli brzdil; přidání zabere vždy, ale je to aktivní zásah proti plánovači. Podpis dvou špiček v odstupu daném rychlostí filtruje falešné spouštěče (samotný náklon vzniká i při brzdění a na svahu). Meze: smyčka posílá příkaz jen 10×/s (Profile.Ts = 100 ms, scheduler má změřené zpoždění až 108 ms), takže okno musí být 2–3 takty, ne jeden; nouzové, držené i kolizní zastavení vyhrávají vždy; jen jízda vpřed nad minimální rychlostí (při couvání jede kolečko první). Zapadá vedle StopHold jako jeho protějšek („teď nezpomaluj" proti „smím jet"), oba stojí vedle regulátoru, ne v něm. Který k má smysl, rozhodne měření: náklon při druhé špičce rozdělený podle znaménka derivace příkazu v tu chvíli (zrychloval / držel / brzdil) — přirozený experiment, který se za čtyři kola Robotouru odehrál mnohokrát. ZMĚŘENO 22. 9. 2026 (ARBot.Analyze bumps nad records/Robotour2026/), ve dvou kolech: nejdřív přes celý záznam (záporně), pak — na upřesnění autora, KDY se na trati zakoplo o kořeny pod asfaltem (Kolo3b 14:12:20–14:13:00) — i nad tím oknem, a tam vyšlo něco jiného. (a) SPOUŠTĚČ: ANI POTVRZEN, ANI VYLOUČEN. Přes 799 m žádná dvojice špiček (autokorelace jen klesá, průměr přes 521 rázů bez hrbolku, 91,3 % spárovaných je POD náhodou 93,7 %). Autor pak doplnil geometrii (ostruha MEZI hnanými koly, rozvor ~0,35 m při přímé jízdě, mění se při manévrování; příčné defekty ale zasáhnou všechna kola), z čehož plyne ostrá předpověď: ozvěna na 0,35 m u PŘÍČNÝCH defektů a při PŘÍMÉ jízdě. Měřeno (--rozvor=, --straight=, dělení podle odezvy do strany) a NEPOTVRDILO SE: ve třech drsných úsecích Kola 3b je hodnota na 0,35 m u podmnožiny „příčný + rovně" 1,18 / 0,80 / 0,54 proti pozadí 1,50 / 0,92 / 1,72, tedy nikde nad pozadím, a vrchol putuje mezi 0,28 a 1,70 m. ⚠️ ODVOLÁN mezitímní závěr „v úseku s kořeny druhý vrchol JE na 0,25–0,30 m" — vyšel z jednoho okna na jedné ose dráhy a se změnou okna nebo osy mizí. Data to ale ani nevyvracejí: po podmínce zbývá 6–12 událostí na úsek, osa dráhy je PRÁVĚ v okamžiku události nespolehlivá (odometrie se integruje z kol, která prokluzují; náhradní osa „rychlost před událostí × čas" nepočítá se skutečným zpomalením — obě dávají jinou odpověď, 0,28 proti 0,23 m), rozvor sám není konstanta (ostruha se vytáčí) a ostruha je lehce zatížená, takže její ráz může být prostě slabý. (b) BRZDĚNÍ KLOPENÍ NEZHORŠUJE — p50 1,54° při brzdění proti 1,42° při držení, jenže tentýž rozdíl vyjde i u PRVNÍCH špiček (1,55 / 1,41) a na gyrem měřené veličině není rozdíl žádný (2,60 / 2,64°). Je to „na hrbolaté zemi se častěji brzdí", ne „brzdění klopí"; Kolo3a i Kolo4 souhlasí. Smyčka navíc v okamžiku druhé špičky brzdí jen v 6,8–11,5 % případů. (c) ALE KLOPENÍ MALÉ NENÍ. První verze tohohle záznamu tvrdila „gyrem potvrzené maximum ~6°, velké výchylky jsou artefakty" — bylo to OBRÁCENĚ, vadná byla kontrolní veličina: integrace gyra přes celé okno vyrušila fázi nosem nahoru proti fázi dolů. Po opravě (integrál se při změně smyslu nuluje) je maximum klopení dopředu 18,06°, gyrem potvrzeno 14,09°, rozkmit vrchol-vrchol 19,78°, celozáznamové maximum z gyra 19,32°. Zakopnutí 14:12:52: robot se předními koly vyhoupne na +9,7°, za 0,75 s se sklopí na −9,9°. (d) ČAS NA REFLEX JE — od prvního znatelného pohybu k nejhoršímu sklopení 0,5–0,75 s, tedy 5–7 taktů; obava „okno musí být 2–3 takty" vycházela z odstupu špiček, na velkých událostech je času víc. ZŮSTÁVÁ OTEVŘENÉ, ale s jinou otázkou než na začátku: ne „naprogramovat reflex", nýbrž „existuje spouštěč?". Bez rozvoru a bez odpovědi, jestli zadní kolečko jezdí ve stopě hnaných kol, se dál nehne.

  • V měřidle sloupec: znaménko derivace příkazu při druhé špičce a náklon po skupinách zrychloval / držel / brzdil 22. 9. 2026
  • Ověřit ze záznamů, jestli se dvojice špiček vyskytuje — přes celý záznam NE, v úseku s kořeny ANO, druhý vrchol na 0,25–0,30 m (dvě nezávislé metody) 22. 9. 2026
  • Geometrie podvozku zjištěna od autora: ostruha mezi hnanými koly, rozvor ~0,35 m při přímé jízdě, mění se při manévrování; příčné defekty zasáhnou všechna kola 22. 9. 2026
  • ZÁMĚRNÝ POKUS místo dolování ze závodních dat: přejet JEDNU známou příčnou překážku (lať, práh) několikrát rovně při 0,4 a 1,1 m/s. Poměr rychlostí 2,75 oddělí ozvěnu (pevná vzdálenost) od kmitu karoserie (pevný čas) jednoznačně — v Robotouru byl poměr jen 1,38 a předpovědi se lišily o 0,09 m. Zároveň dá opakované události se známou geometrií, kterých je dnes po podmínce jen 6–12 na úsek
  • Reflex v ControlLoop — až bude potvrzený spouštěč; brzdění klopení prokazatelně nezhoršuje, takže k = 0 odpadá a smysl by měl jen k = 1 (přidat)

path-following.md, plan-drive-hold.md · DevLog 2026-09-22

AlreadyAtGoal hlásí i nedosažitelnou mrkev 7 m daleko — detektor záseku se odzbrojí a robot stojí potichu

otevřeno vada nalezeno 7. 10. 2026

LocalPathPlanner přepíše Partial, jehož nejbližší dosažitelná buňka je ta pod robotem (plán < 2 uzly), na AlreadyAtGoal bez ohledu na vzdálenost mrkve. GlobalNavigator bere jako platný plán jen Ok/Partial/GoalBlocked/GoalUnsafe, takže detektor A je při AlreadyAtGoal vynulovaný. 18. 9. 2026 (20260918-154028.rec) tak robot stál 388–466 s a 575–737 s ve slepém konci chodníku: 4 168 plánů AlreadyAtGoal, ve všech mrkev 6,6–7,3 m daleko. Detektor A zabral jen ve vložené fázi Partial (zavřel hrany v 556,6 s). Táž past jako 3. 9. u mrkve v trávě (tam vzniklo GoalBlocked).

  • Nalezeno nad 18. 9. (zasek, localplan, kód f848fdf / 9f649a0) 7. 10. 2026
  • Rozhodnout (autor): stav pro nedosažitelnou mrkev při plánu nulové délky (GoalBlocked / nový) a reakci globální navigace

occupancy-and-local-planning.md, global-navigation-runtime.md · DevLog 2026-10-07

Smazání gridu po skoku pózy nezanechá v Trace stopu

otevřeno vada nalezeno 7. 10. 2026

LocalNavigator při skoku pózy (PoseJumpDetector) grid smaže a zvýší jen počítadlo GridResets — do Trace nejde nic. Ve Tracku 1. 10. 2026 se grid smazal 7× (skoky kurzu při výpadku kamer a ručním otočení, 15:15:43 při záseku procesu) a v logu záznamu o tom není ani řádek; smazání v 15:27:35, které jako jediné ukončilo 132s RobotBlocked, se dalo dohledat jen z propadu známých buněk ve snapshotech. Pravidlo „Diagnostika poruch jde do Trace" (CLAUDE.md) — hlášení se škrcením přes PoruchaHlasic (důvod: posun / kurz, velikost, dt).

  • Hláška do Trace přes PoruchaHlasic, test

occupancy-and-local-planning.md · DevLog 2026-10-07

Kontrola kolize únikové dráhy nevyjímá startovní buňku — falešné „NOUZOVE ZASTAVENI – kolize 0,00 m“

otevřeno vada nalezeno 7. 10. 2026

LocalPathPlanner.PlanEscape pustí z buňky pod robotem i tehdy, když ji blokuje geometrie (robot na ní stojí), ale LocalNavigator.PathCollides pro únikovou dráhu kontroluje geometrii **bez výjimky pro start** (f848fdf i HEAD). Když po EscapingBlocked z geometricky blokované buňky přijde cyklus bez nového plánu (RobotBlocked), stará úniková dráha „koliduje v 0,00 m", regulátor se zahodí a v logu je „NOUZOVE ZASTAVENI - kolize 0.00 m", které vypadá jako skutečná kolize. 1. 10. 2026 (20261001-144638.rec) 3× (15:06:57, 15:27:51, 15:27:52), 18. 9. 4×. Kdyby se únik rozšířil na celý půdorys (lp-zapis-volna-pod-robotem), musí stejnou výjimku dostat i tahle kontrola.

  • Nalezeno a přehráno nad záznamem (replika PathCollides nad poslední únikovou dráhou 15:27:51/52 našla G v 0,00 m) 7. 10. 2026
  • Výjimka pro startovní buňku (resp. půdorys) v PathCollides pro únikovou dráhu, test

occupancy-and-local-planning.md · DevLog 2026-10-07

Track 1. 10.: robot 7,4 min stál v 8 epizodách, všechny ve dvou 90° zatáčkách — korekce koridoru posunula pózu proti gridu ve světě ke krajnici

otevřeno vada nalezeno 7. 10. 2026

records/test/20261001-144638.rec (Track Modřany, 42 min, binárka f848fdf — grid ještě ve SVĚTĚ, localframe=odom v ní nebyl): robot kvůli lokální mapě stál v 8 epizodách, celkem 445 s (17,7 % mise); 6 skončilo samo únikem, 2 (RobotBlocked 132,5 s a 42 s na konci) ne. **Všech 8 je ve dvou ~90° zatáčkách** cyklostezky (way 154101921), jediných ostrých ohybech trasy; jinde ani jedna. FreeRun hned potom zatáčky projel bez úniku. **Mechanismus (ověřen dvěma skeptiky):** v zatáčce koridor 7–14 s nic neměří (lok-koridor-slepy-v-zatacce) a nesoulad pózy s mapou naroste na 1,5–3 m — z podélného driftu pózy (lok-fuze-poza-pred-koly, na vjezdu až +5,7 m) nebo z chyby vzniklé až uvnitř zatáčky. Pak přijde série korekcí (|inovace| 1,3–3,3 m, limit kroku je rozloží na 0,07–0,53 m na měření, tedy pod toleranci PoseJumpDetector) a grid kotvený ve světě se proti robotu posune — robot se ocitne u (nebo v) vnitřní krajnici zapsané předtím. **29 z 32 začátků úniku přišlo do 0,2 s po odeslaném měření koridoru.** Plán v zatáčce vede robot s odstupem 0,42–0,74 m od vnitřní hrany, práh úniku je 0,35 m, takže rezerva je malá. Na konci (15:25:22 a 15:27:52) leželo pod robotem 87–102 ze ~110 buněk půdorysu blokovaných HLOUBKOU (krajnice zapsaná 1–4 s předtím), kamera je během stání ani jednou neviděla (hodnota beze změny 134 s; grid časový rozpad nemá) a únik (PlanEscape) přes geometrii nesmí — východ do 8 m neexistoval, bez zákazu geometrie by ležel 0,53–0,90 m vpředu. Kamery přitom ukazovaly volný asfalt. Couvnutí ani otočka na místě neexistují (nav-recovery-manevr, odloženo) a nic stání neohlásilo (nav-uvaznuti-neohlasene). První stání ukončilo jen smazání gridu po skoku kurzu, když obsluha robotem otočila (lok-fuze-rucni-otoceni). ⚠️ Hypotéza „mrkev 6 m po trase padá v zatáčce do krajnice" je **vyvrácená** — stála na GPS jako na pravdě, a ten má na místě bias, který se mezi průjezdy mění až o 2,8 m. ⚠️ Že localframe=odom odstraní spouštěč u všech 8 epizod, je hypotéza (korekce by posunula cíl, ne robota) — protifaktické přehrání plánovače nebylo.

  • Rozbor (ARBot.Analyze zasek, localplan, nav, fusionreplay; dva nezávislí skeptici): mechanismus, čísla a snímky v occupancy-and-local-planning.md, sekce „Uváznutí na konci Tracku 1. 10. 2026“ 7. 10. 2026
  • Ověřit localframe=odom na zařízení na TÉMŽE místě (obě zatáčky way 154101921 v Modřanech, 3× každým směrem): EscapingBlocked/RobotBlocked po korekci koridoru (localplan, zasek, nav)
  • Rozhodnout druhou linii (autor): únik smí přes geometrii v půdorysu (r ≤ 0,3–0,45 m, viz lp-zapis-volna-pod-robotem), časový rozpad JEN nepozorovaných buněk geometrie (poločas 10 s by konec Tracku vyřešil, 30 s jen umožnil únik, 60 s ne; za jízdy by zasáhl ~10 % vzorků), rezerva/hystereze mezi odstupem plánu a prahem úniku, nebo zotavení (nav-recovery-manevr)

čeká na Lokální vrstva v odometrické soustavě (localframe=odom) — odometrická póza (x, y, θ) jako vedlejší integrátor ve snapshotu fúze · occupancy-and-local-planning.md, ZasekReport.cs · DevLog 2026-10-07

První FreeRun na železe ve stísněném prostoru skončil nárazem

v kódu, na HW neověřeno vada nalezeno 2. 9. 2026 vyřešeno 3. 9. 2026

Rozbor 417 s záznamu novým ARBot.Analyze localplan: koridor se detekoval jen ve 2 % cyklů, mrkev ležela 3 m rovně vpřed a v 97 % plánů byla nedosažitelná. Fallback pak dělal detour 8–24 m skrz neznámo nebo pahýl k čelu překážky — a přesně ten robot jel. Eskapovací zóna 0,5 m kolem robota byla ve stísněném prostoru trvale aktivní a dovolila plánovat pod bezpečným odstupem (min 0,00 m). Druhý den se zóna zrušila (těsný start = únik s hysterezí), nedosažitelný cíl dostal stavy GoalBlocked / GoalUnsafe a odstup je parametr safedist=. Reakce mise na nedosažitelnou mrkev zůstala otevřená a vyřešila se 14. 9. cílem jako zónou. Ověřeno jen testy.

  • Rozbor záznamu, příkaz ARBot.Analyze localplan, zadání průzkumu 2. 9. 2026
  • Eskapovací zóna zrušena, stavy GoalBlocked / GoalUnsafe, parametr safedist= 3. 9. 2026
  • Přeměřit FreeRun ve stísněném prostoru na zařízení
  • Regresní kontrola na široké cestě (FreeRun 1. 10. 2026, 20261001-152906.rec, koridor p50 3,68 m): Ok 97,1 %, EscapingBlocked / RobotBlocked / NoRoute 0, dráha pod SafeDist 0 z 11 204 plánů, robot pod SafeDist 0 % taktů. Stísněný prostor to nebyl, vlastní krok zůstává 7. 10. 2026

plan-freerun-stisnene-podminky.md, occupancy-and-local-planning.md, rozhodnutí 3. 9. 2026 · DevLog 2026-09-02, 2026-09-03, 2026-10-07

Klín mezi zornými poli barevných kamer brzdí robota

v kódu, na HW neověřeno vada nalezeno 13. 9. 2026 vyřešeno 13. 9. 2026

Barva D435 má při 640×480 jen 55° zorného pole a kamery jsou pootočené o ±29,3°, takže přímo před robotem zbývá mezera 3,7° (0,19 m ve 3 m), kde hloubka vidí, ale barva ne — buňka tam zůstává neznámá a rychlostní obálka na ni brzdí. Nad záznamem z 12. 9. byl klín příčinou 72,6 % zastavení paprsku a robot byl pod 0,6 m/s ve 40,5 % vzorků (proti 3,3 % bez semantiky); první měření nad jiným záznamem dalo jen 20 %, dva běhy téhož robota se liší čtyřnásobně. Léčba WedgeFiller (wedgefill=, výchozí 6°) buňku doplní interpolací z buněk příčně vlevo a vpravo, ne konstantou „sjízdné“; pětkrát ji vypnula vlastní opatrnost a pokaždé to našlo až měření. Vrátí asi pětinu ztráty (40,5 → 33,9 %), zbytek je řetěz dalších děr — hlavní brzda je dosah a hustota hloubky.

  • Měřidlo ARBot.Analyze wedge (zorná pole z intrinsik, rozpad příčin, simulace léčby) 13. 9. 2026
  • WedgeFiller se čtyřmi pojistkami a pěti opravami z měření 13. 9. 2026
  • Přeměřit nad více záznamy (dva běhy se liší 4×) — 1. 10. 2026 s opraveným měřidlem (wedge četl všechny snímky a počítal s 1,2 místo 1,7 m/s ze záznamu): Track VBrake pod stropem 1,7 m/s v 14,7 % vzorků, s doplněním klínu 14,4 %, bez sémantiky 13,4 %; FreeRun 3,0 % ve všech variantách (12. 9.: 40,5 % pod 0,6 m/s). Díra v sémantice leží p50 ve 4,2 m, kde strop už neváže (volno 3,61 m stačí na 1,7 m/s) — klín na těchto jízdách rychlost nesráží. Gridy ze záznamu jsou už po WedgeFiller, takže simulace léčby ho aplikuje podruhé 7. 10. 2026
  • Dopad ceny neznámých buněk (UnknownCostFactor) na tvar dráhy — neměřený
  • Běh na zařízení — od 18. 9. (binárka s bc08c06 nese i WedgeFiller, profil wedgefill= nepřepisuje, platí 6°); účinek nezměřen, ARBot.Analyze wedge nad 20260918-* neběžel 18. 9. 2026

occupancy-and-local-planning.md, record-replay.md · DevLog 2026-09-13, 2026-10-07

Robot cuká — kvantovaný příkaz rotace kmitá a přes vazbu na rotaci trhá i dopřednou rychlost

v kódu, na HW neověřeno vada nalezeno 25. 9. 2026 vyřešeno 25. 9. 2026

Pozorování autora z FreeRun 25. 9. 2026: robot nejede plynule. Rekonstrukce regulátoru (ARBot.Analyze drive nad 20260925-144658.rec): příkaz rychlosti se mezi takty (10 Hz) mění o víc než 0,1 m/s ve **40,5 %** taktů (4 skoky za sekundu), a **84 %** těch skoků nedělá obálka, ale **vazba dopředné rychlosti na dobu dorovnání rotace** (SpeedLimit, d/(4·T_rot)). Rotace přitom kmitá: znaménko příkazu ω se mění **3,1× za sekundu** při úhlu na cíl p50 jen 1°, |ω| fúze p50 0,14 rad/s. Příčina je v diskrétním profilu (TrapezoidMotionProfile.Compute, převzatý z ARBot2): počet kroků ne se nad 2 zaokrouhluje dolů a výsledek násobí 0,9, takže příkaz skáče po kvantech — rychlost po **0,045 m/s** (0,810 / 0,855 / 0,900…), rotace po **0,220 rad/s** (= 0,045 / polovina rozchodu; přesně tahle hodnota je ve 24,6 % taktů, 0,440 ve 4,1 %). Malý úhel tak dostane celé kvantum, přestřelí, a protože T_rot počítá i s dobrzděním aktuální ω, kmitání zvedá T_rot a srazí rychlost. Ve FreeRun je to vidět víc než v Track (tam je d ~5,6 m místo 1,4 m, vazba váže v 11 % taktů, skoků je 14,5 %), rotace ale kmitá i tam (2,1 změny znaménka za sekundu). **Rozbor příčiny (25. 9. 2026):** akční člen je rychlý — model „mrtvá doba + 1. řád" proložený ze záznamu dává τ 0,04–0,06 s, T 0,07–0,08 s, K 1,1–1,15 (gyro i kola shodně). Kmitání tedy nedělají motory, ale zákon a jeho buzení: Rot2RotSpeed má u malých úhlů zesílení ~6 s⁻¹ (1° → 0,106 rad/s), mezi ~2,5° a 10° plochý schod 0,22 rad/s (relé) a T_rot nikdy pod 0,2 s. Buzení je **přeplánování**: s novým plánem skočí úhel na cílový uzel mezi takty o p50 1,1°, p90 4,5° (se starým plánem 0,7 / 1,8°, což je jen vlastní rotace) — uzly leží ve středech buněk 5 cm a plán se mění 16×/s. Simulace uzavřené smyčky s naměřeným akčním členem, terénní poruchou a rozptylem cíle 5 cm reprodukuje realitu (dnešní zákon 3,14 změny znaménka/s proti naměřeným 3,1); bez rozptylu cíle jen 0,7. Tamtéž: mrkev 3 m srazí kmitání na 2,15/s a skoky rychlosti z vazby na rotaci zmizí; zákon „sqrt s lineární zónou" (k = 2,5 s⁻¹, mimo zónu tentýž časově optimální √(2α|β|)) dá 1,24/s při 1,4 m a **0,19/s při 3 m**, za cenu příčné odchylky rms 2 → 3 cm (ε je 10 cm). Spojitý √ bez lineární zóny je horší než dnešek (2,7/s). Simulace je zjednodušená (přímka, konstantní v), ověřit to musí jízda. **Rozbor Compute (25. 9.):** diskrétní vzorec plánuje trojúhelník z aktuální rychlosti a vrací jeho vrchol, ačkoli rampu dělá motorová jednotka. Důsledky: pevný bod při stálé vzdálenosti cíle (1,4 m → 0,855 m/s = medián FreeRun, 3 m → 1,305) hluboko pod √(2ax), kvantování 0,045 m/s a hlavně **žádné plné brzdění, když už robot nestihne zastavit** (vrací ~0,6–0,9·vs; rotace 1° při 0,5 rad/s k cíli → 0,204 rad/s). Oprávněné je jen držení příkazu po takt, spojitě v = −a·L + √((a·L)² + 2a·x + ve²); u nuly dává zesílení 1/L. **Simulace profilu se zpožděním L (25. 9.)** nad skutečnými PathPlanner/PathResult, s naměřeným akčním členem (dopředně rampa 0,5 m/s², rotace τ 0,05 / T 0,08 / K 1,1), T_rot nového profilu = 2·√(|β|/α). FreeRun, mrkev 3 m (5 běhů, šum): dnes 1,305 m/s a 1,83 změny znaménka ω/s; L = 0,3 1,59 m/s / 0,44; **L = 0,4 1,54 m/s / 0,20**; L = 0,5 1,50 / 0,08. Mrkev 1,4 m: dnes 0,855 / 2,59, L = 0,4 0,99 / 1,05. Cena: příčná odchylka rms 2,5 → 4,2 cm (L = 0,4, mrkev 3 m). Dojezd na cíl 5 m: L ≥ 0,2 bez přejetí, L = 0,1 přejede 8 cm (potvrzuje, že člen se zpožděním je nutný). Zatáčka 90°: L ≥ 0,3 bez změny znaménka ω, L = 0,4 odchylka 0,42 m a překmit kurzu 9° proti dnešním 0,51 m / 11,8°; L ≤ 0,15 horší než dnes. Simulace nemodeluje zpoždění fúze (stav je pravda) — to mluví spíš pro větší L.

  • Změřeno: kvantování příkazu, změny znaménka rotace, podíl skoků z vazby na rotaci (ARBot.Analyze drive) 25. 9. 2026
  • Změřena dynamika akčního členu a buzení přeplánováním (drive, bloky DYNAMIKA ROTACE a |d beta|), simulace zákonů uzavřené smyčky 25. 9. 2026
  • Simulace profilu se zpožděním pro L 0,1–0,5 s (FreeRun, dojezd, zatáčka) 25. 9. 2026
  • Léčba (autor): LatencyMotionProfile se zpožděním L = 0,4 s, výchozí (motionprofile=latency, motionlatency=; trapezoid = původní), PathResult beze změny; testy zákona a uzavřené smyčky (LatencyMotionProfileTests) 25. 9. 2026
  • Ověřit jízdou A/B (motionprofile=trapezoid proti výchozímu): změny znaménka rotace, skoky |dv|, rychlost a příčná odchylka v drive
  • Před/po na zařízení bez A/B (drive): Track Modřany 25. 9. s trapezoid (20260925-142428/-143643/-144200.rec) 1,5–2,3 změny znaménka ω/s, skoky |dv| 9,0–16,8 %, odchylka p99 3,9–4,5 cm; s latency 29. 9. a 1. 10. (20260929-150844.rec, 20261001-144638.rec) 0,71 a 0,26/s, 39,0 a 11,3 %, p99 5,9 a 7,5 cm. Kmitání rotace kleslo 6–9×, jak simulace slibovala; skoky dopředné rychlosti v Tracku NE (11,3 % je uvnitř rozpětí trapezoid — popis výš cituje jen -143643), odchylka vzrostla z ~4 na 6–9 cm. FreeRun 25. 9. (3,1/s) proti 1. 10. (0,47/s) je zmatený změnou freerunlook 1,5 → 5. Na HW poprvé latency už 29. 9. 7. 10. 2026

path-following.md, rozhodnutí 25. 9. 2026 · DevLog 2026-09-25, 2026-10-07

Postupná korekce pózy (limit kroku) nesmaže grid — robot se ocitne v „historicky" nesjízdných buňkách

v kódu, na HW neověřeno vada nalezeno 26. 9. 2026 vyřešeno 5. 10. 2026

Track 25. 9. 2026 (20260925-142428.rec): korekce z koridoru posunuly pózu za ~30 s o ~10 m (lok-koridor-noedge-po-zatacce), ale po krocích ~2 cm na snímek (corridorslew=0,5 m/s). PoseJumpDetector porovnává posun s |v|·dt + 0,5 m, takže nezasáhl ani jednou (report nav: jediný skok 0,59 m ve stání) a world-kotvený grid zůstal namalovaný v rámci špatné pózy. Robot se po korekci ocitl v buňkách, které tam dřív zapsala tráva viděná z posunuté pózy: EscapingBlocked 14:34:18–14:34:28 (167 plánů za 10 s) a GoalUnsafe. Limit kroku byl navržen právě tak, aby detektor nespouštěl (21. 9.) — to platí pro malé korekce, ne pro součet 10 m. Totéž se dá čekat u každé velké, ale postupné opravy pózy. **Únikový manévr to zvládl** (autor: „to by měl řešit únikový manévr"): v obou epizodách (první zatáčka 14:32:22–28, po korekci 14:34:18–28) robot z blokované buňky vyjel za 6–10 s a pokračoval (Ok, v 1,66 resp. 0,22 m/s → pak přerušení timeoutem). Únik ale řeší jen „stojím v blokované buňce", ne „celá okolní mapa je posunutá" — posunutý grid se přepisuje až tím, co kamery znovu uvidí. S opraveným obvodem kola by velké korekce neměly vznikat. **Zastavení na konci ale způsobil jiný důvod:** 14:34:39 Track: mise PRERUSENA - timeout jizdy k mistu 1/2 (limit 600 s) (mise-track-timeout-delka-useku). ⚠️ **„Únik to zvládne" neplatí obecně — 1. 10. 2026 nezvládl** (20261001-144638.rec, lp-uvaznuti-v-zatackach): korekce koridoru posunuly pózu za 5 s o 1,51 m a za 9 s o 1,92 m (kroky 0,12–0,24 m, pod tolerancí detektoru skoku) a robot se ocitl uprostřed pásu krajnice, kterou hloubka zapsala 1–4 s předtím — pod půdorysem 87–102 ze ~110 buněk blokovaných geometrií. Únik smí přes geometrii jen ze startovní buňky, takže RobotBlocked 132,4 s a 42,0 s; kamery přitom ukazovaly volný asfalt. Grid časový rozpad nemá, buňky pod robotem se během stání nezměnily (134 s).

  • Změřeno: EscapingBlocked hned po korekci ~10 m, detektor skoku nezasáhl (posegps, nav) 26. 9. 2026
  • Rozhodnout léčbu (autor): hlídat SOUČET korekcí (posun pózy proti odometrii za okno) a při překročení gridu věřit méně / smazat, nebo grid při korekci posouvat. Rozhodnuto: grid v odometrické soustavě (lp-grid-odometricka-soustava) — od 4. 10. 2026 v kódu jako localframe=odom, od 5. 10. 2026 výchozí 5. 10. 2026
  • Ověřit na zařízení: po velké postupné korekci pózy žádné EscapingBlocked/GoalUnsafe z posunutého gridu (ARBot.Analyze localplan, nav, zasek) — nejlépe na místě, kde se to 1. 10. stalo 8×: obě 90° zatáčky way 154101921 v Modřanech
  • Další případ z HW, ještě s gridem ve světě (1. 10. 2026, 20261001-144638.rec): 29 z 32 začátků úniku do 0,2 s po korekci koridoru, na konci RobotBlocked 132,4 + 42,0 s (viz popis a lp-uvaznuti-v-zatackach) 7. 10. 2026

čeká na Lokální vrstva v odometrické soustavě (localframe=odom) — odometrická póza (x, y, θ) jako vedlejší integrátor ve snapshotu fúze · occupancy-and-local-planning.md · DevLog 2026-09-26, 2026-10-07

Lokální vrstva v odometrické soustavě (localframe=odom) — odometrická póza (x, y, θ) jako vedlejší integrátor ve snapshotu fúze

v kódu, na HW neověřeno záměr nalezeno 2. 10. 2026 vyřešeno 4. 10. 2026

**Problém:** occupancy grid se zapisuje pózou z fúze, takže každá korekce z GPS, koridoru nebo korelace (skokem, nebo postupně přes corridorslew=) posune obsah gridu vůči robotu, ačkoli se robot nepohnul (lp-grid-posun-pomalou-korekci: o 10 m za 30 s → EscapingBlocked). Kotvit grid „na robota" místo do světa samo nepomůže — robot-centrický grid se musí posouvat o pohyb robota a ten by se bral z téže pózy; rozhoduje, **z jaké pózy se počítá pohyb mezi snímky**. Lokální vrstva přitom globální pravdu nepotřebuje: grid kreslený z „posunuté" pózy je lokálně správně, korekce ho lokálně rozbije. **Návrh (rozprava s autorem 2. 10. 2026):** dvě soustavy jako v ROS (REP-105, odom / map), ale **bez druhého systému výpočtu pózy** — autorova varianta: fúze nese navíc odometrickou pózu xOdom, yOdom, θOdom a GetStateAt(t) vrací obě, každý si vezme, co potřebuje. Výhoda proti dvěma systémům: **jedna časová osa** — transformace globální → odometrická se počítá z téhož snapshotu téhož běhu filtru, replay zpožděných měření (okno 3 s) obslouží obojí, záznam jen rozšíří zprávu stavu. Liší se od zamítnutého PoseSlew (20. 9.): nejde o dvě pózy téže věci, ale o dvě soustavy s pevnou rolí a nic se k ničemu nedotahuje. **Podmínka 1 — NE jako stavy EKF s kovariancí:** sdílí v a θ s x/y, predikce by vyrobila korelaci a každý update GPS/koridoru by přes Kalmanův zisk posunul i xOdom skokem. Musí to být **deterministický integrátor** v predikci, mimo P a mimo update (raději mimo stavový vektor, jen součást snapshotu historie, než vynulované řádky zisku). **Podmínka 2 — i θOdom, ne jen poloha:** grid má osy pevně ve světě, korekce kurzu o dθ otočí obsah kolem robotu (5 m · 2° = 17 cm); bez θOdom by zmizel posun, ale zůstalo kroucení. **Integruje se z rychlostí po fúzi** (v, ω), ne ze syrových kol a gyra: korekce rychlostí jsou spojité (integrál neskáče) a fúze přitom potlačí prokluz i bias gyra — jako robot_localization v soustavě odom. **Podmínka 3 — korekce nesmí protéct přes rychlosti (rozprava 2. 10. 2026):** měření polohy posune přes kovarianci P_pv i v (K_v·ν) a integrátor by tu změnu načítal — ne skok, ale drift, dokud v nestáhne další měření rychlosti. v je skalár ve směru kurzu, takže **příčná** korekce do ní přímo neteče; teče ale přes P_xθ do θ a ω, a změna ω jde do θOdom (tam ji vrací gyro 100 Hz a Odo/rate). Odhad na 1D modelu se šumem EKFModel (SigmaAccel 1, OdoSpeedStd 0,05; odometrie předpokládaná 20 Hz — **skutečně chodí ~91 Hz**, interval 11 ms, změřeno 1. 10. 2026 při rozboru razítek odometrie (fusionreplay blok 9, lok-fuze-poza-pred-koly), takže odhad je konzervativní: změnu v stáhne další měření rychlosti ~4,5× dřív), podíl kroku polohy, který proteče do xOdom: **s odometrií kol pod 1 %** (σ polohy 0,1 / 0,5 / 1,5 m → 0,5 / 0,1 / 0 %), **bez ní, jen s GPS rychlostí (σ 0,3 m/s), až 27 %** (→ 27 / 8 / 3 %). U postupné korekce se podíly sčítají: o 10 m za 30 s s odometrií centimetry, bez ní metry. Rizikem jsou tedy úseky, kdy odometrie do fúze nechodí — výpadek motorů (zástupné rámce s HasMeasurement = false mapper zahazuje). Prokluz to není: SlipDetector se v mapperu ani ve fúzi **nikde nevolá** (ověřeno v kódu 4. 10. 2026; dřív tu stálo „nejspíš zahazování odometrie SlipDetectorem"), odometrie se při prokluzu nezahazuje ani neodtlumuje. A z kol by ho ani nepoznal: měřená kola jsou hnaná a ve zpětné vazbě, takže sledují rampu příkazu bez ohledu na trakci (postřeh autora). Prokluz dopředu tedy do xOdom proteče celý — na horizontu paměti gridu je ale zanedbatelný (doc/ekf-fusion.md, „Prokluz kol fúze nepozná"). Pojistka, kdyby to vadilo: absolutní měření (poloha, kurz) mají **vynulované řádky zisku pro v a ω** — v dál opravuje GPS rychlost a odometrie, jen ne přes korelaci s polohou; hlavní filtr je pak formálně o chlup méně optimální. Nezapínat naslepo, nejdřív změřit. **Rozdělení konzumentů:** odometrickou pózu bere LocalNavigator (grid, plánovač, obálka, regulátor) a FreeRunMission; globální GlobalNavigator a mise; přes transformaci jde mrkev, zóny a cíle — skok korekce se projeví skokem mrkve (A\* přeplánuje), ne překážek. CorridorSource a MapCorrelator by měřily nad gridem nerozmazaným vlastními korekcemi a přirozeně by měřily chybu transformace (odpadne kruh „grid kreslený pózou, kterou z něj opravujeme"). lok-skok-pozy-nedetekce by tím ztratil většinu významu. **Známé důsledky:** (a) replay zpožděného měření zpětně o kousek změní minulé xOdom, grid už je zapsaný — centimetry, šum, ne skok; (b) reset/inicializace fúze (první fix, seek): odometrie buď běží dál přes reset (lepší, ale stav přežívající reinicializaci), nebo se nuluje a grid se musí smazat zároveň. Cena: přestavba všech volajících GetStateAt (LocalNavigator, FreeRunMission, CorridorSource, MapCorrelator, ControlLoop) a verze zprávy stavu. Zamítnuté levnější varianty: posouvat obsah gridu o součet korekcí (u rotace převzorkování — cena, kvůli které se natočený grid zamítl 10. 8.), smazat grid při velkém součtu korekcí (zahodí paměť právě když je potřeba). **Rozhodnutí autora 4. 10. 2026:** (1) při resetu / inicializaci fúze odometrická póza **běží dál** (inicializace přepíše jen globální pózu, grid se nemaže); (2) zapíná se **parametrem** localframe=world|odom, výchozí world — odometrická póza se ale počítá a nahrává vždy, aby šla změřit nad záznamy dřív, než se výchozí hodnota přepne; (3) **po fázích**. **Návrh implementace (4. 10. 2026, z čtení AsyncFusionEngine):** odometrická póza (xo, yo, θo) je součástí každého checkpointu — Node (vedle X, P) i báze (xBase/pBase → oBase). V EnsureValid se mezi uzly integruje z v, ω **předchozího posteriorního** stavu (táž, kterou používá predikce), stejným vzorcem jako EKFModel.PredictState (střední orientace θo + ω·dt/2); update ji nemění. GetStateAt(t) ji dopredikuje z uzlu do t týmž vzorcem. Prune ji předá do báze (oBase = n0.O, u nespočteného uzlu dointegrovat). InitializeAxesLocked (InitializePosition/-Heading) vezme oBase = odometrie v čase t z dosavadní historie (běží dál); první inicializace enginu začne na (0, 0, 0). Přehrání zpožděného měření ji přepočítá spolu se vším (jedna časová osa). RobotState dostane OdomX/OdomY/OdomTheta, RobotStateMsg novou verzi (vzniká v ControlLoop.cs:304). Fáze 2 musí převést i **ControlLoop/regulátor** (dráha z lokální vrstvy je v odometrické soustavě, póza regulátoru taky), cíl SetGoal (světový → odometrický transformací v čase snímku) a **zobrazení** gridu a plánu (web, UI, ARBot.Analyze) — OccupancyGridMsg a LocalPlanMsg ponesou transformaci odom → svět.

  • Rozprava s autorem: dvě soustavy; odometrická póza jako vedlejší integrátor ve fúzi (x, y, θ), mimo kovarianci, z fúzovaných rychlostí 2. 10. 2026
  • Rozhodnout chování při resetu fúze: odometrie BĚŽÍ DÁL (autor 4. 10.); zapínání parametrem localframe=world|odom, výchozí world; po fázích 4. 10. 2026
  • Fáze 1: integrátor v checkpointech AsyncFusionEngine (Node, báze, Prune, inicializace běží dál), GetStateAt vrací obě pózy, RobotState + nová verze RobotStateMsg; testy (bez korekcí odom = globální posun; skok GPS/koridoru odom nepohne; inicializace odom nepřeruší; out-of-sequence měření a Prune konzistentní). Hotovo: Fusion/OdomPose.cs, RobotState.OdomX/OdomY/OdomTheta + OdomToWorld(), RobotStateMsg verze 2 (HasOdom), ComparisonTarget porovnává i odometrii, telemetrie odom X/Y/theta a korekce posun/kurz; OdomPoseTests (14 testů) 4. 10. 2026
  • Fáze 1 — měření v fusionreplay: kolik korekcí se dnes promítá do gridu (rozdíl posunu globální a odometrické pózy na oknech 5/10 s) a únik přes rychlosti (odometrická póza plné fúze proti variantě jen z kol + gyra). Hotovo, blok 10, tři jízdy (Track 25. 9. 20260925-142428.rec, Track 29. 9. 20260929-150844.rec, FreeRun 29. 9. -151634.rec; všechny před skriptem 2.1, tedy s biasem kol +1,9 %). **(a) Posun obsahu gridu proti robotu bez pohybu, za jízdy, S koridorem:** za 5 s p50 0,10–0,23 m, p90 0,36–0,85 m, **p99 1,4–2,1 m, max 2,5–4,3 m**, nad 0,5 m v 7–23 % vzorků; za 10 s p99 2,8–3,0 m, max 3,1–5,2 m. Pootočení za 5 s p50 0,35–0,60°, p90 0,9–2,4° (FreeRun za 10 s p90 5,4°, max 15°). BEZ koridoru jsou chvosty poloviční (5 s: p99 0,4–1,2 m, max 0,5–1,3 m) — velké skoky dělá koridor. ⚠️ **Medián NENÍ zisk:** posun / dráha p50 je 2,1–3,4 % S koridorem a 2,5–5,0 % BEZ, tedy řádově drift odometrie (bias +1,9 %, 25. 9. ještě obvod kola) — tu část by odometrická soustava jen vyměnila za zkreslení gridu driftem. Zisk je ve chvostech (skoky korekcí). **(b) Únik přes rychlosti:** posun odometrické pózy plné fúze proti „jen kola + gyro“ za 10 s p50 2–4 mm, p90 6–9 mm, max 14–23 mm; otočení p90 0,001–0,002°, max 0,003° — **~1 % p90 posunu gridu**, a to je horní mez (obsahuje i GPS rychlost). Pojistka (vynulované řádky zisku) na těchto jízdách potřeba není; úseky s výpadkem motorů zvlášť změřené nejsou (viz krok níž). Měřidlo ověřeno: replay proti záznamu p90 ≤ 3 mm 4. 10. 2026
  • Fáze 2 (až po posouzení fáze 1 autorem): parametr localframe=, LocalNavigator (grid, plán, SetGoal přes transformaci, PoseJumpDetector), ControlLoop/regulátor, FreeRunMission, transformace odom → svět v OccupancyGridMsg/LocalPlanMsg pro web, UI a ARBot.Analyze. Hotovo: LocalFrame + FrameTransform, RobotState.InFrame/ToWorldTransform; LocalNavigator.Frame (světový cíl převáděn u každého snímku transformací v jeho čase, SetLocalGoal pro cíl vůči robotu, teleport v odom grid smaže, inicializace ne) a ControlLoop.Frame z jednoho parametru localframe=world|odom (výchozí world); FreeRun mrkev pózou téhož snímku přes ILocalGoalSink.SetLocalGoal; OccupancyGridMsg v2 / LocalPlanMsg v3 s Frame + transformací a InWorldFrame() (grid převzorkovaný nejbližším sousedem) — web, World pohled, EvidenceCloud (korelace) a ARBot.Analyze (RecordFile.LocalLayerInWorld; drive přehrává regulátor v soustavě plánu). Testy (LocalNavigatorTest +5, LocalFrameTests 12) a simulace: FreeRun 40 s v každé soustavě, v odom proti pravdě stejně (konec −0,444 m proti −0,462 m, cíl −0,5 m), plány 100 % Ok, grid na webu sedí na mapu 4. 10. 2026
  • Přepnout výchozí hodnotu na localframe=odom (pokyn autora; world = původní chování). Podnět: simulace 20261005-075416.rec — v world dva skoky gridu 0,37 / 0,40 m od prvního měření koridoru po naučení šířky 5. 10. 2026
  • Jízda na zařízení s localframe=odom (Track / FreeRun): grid po korekcích koridoru, EscapingBlocked/GoalUnsafe proti world, drift odometrie v gridu; podle toho potvrdit výchozí odom, nebo vrátit world (autor)
  • Změřit nad záznamy drift odometrické pózy na horizontu paměti gridu (sekundy, 12,8 m) a kolik korekcí se do gridu dnes promítá. ⚠️ Do nahrání RizeniDiffPodvozku.mbs 2.1 (čas z motorové jednotky) nese rychlost z kol ve fúzi bias +1,9 % (lok-fuze-poza-pred-koly) — v záznamech před tím ho drift odometrické pózy obsahuje
  • Odhad úniku korekcí přes rychlosti na 1D modelu: s odometrií kol pod 1 % kroku, bez ní až 27 % 2. 10. 2026
  • Změřit v replayi únik přes rychlosti: změna v a ω u každého měření polohy/kurzu, součet do xOdom/θOdom; zvlášť úseky s výpadkem motorů (frekvence Odo/speed už změřena: ~91 Hz; SlipDetector se nevolá, prokluz odometrii nevyřazuje). ✅ 1. 10. 2026 (fusionreplay blok 10 nad 20261001-144638.rec, výpadek motorů 15:15:41,8–43,4 = 1,6 s): v oknech přes výpadek unikla odometrická póza proti variantě „jen kola + gyro“ za 5 s p50 0,026 / max 0,035 m, za 10 s max 0,037 m — maximum celé 42min jízdy, ale pod 4 cm a ~1 % p90 posunu gridu (mimo výpadek p50 0,002 m). Posun gridu korekcemi (první jízdy s corridorseekback/corridorposlimit) za 5 s p99 1,09 m (Track) a 0,78 m (FreeRun) proti 1,4–2,1 m dřív 7. 10. 2026
  • Podle měření rozhodnout pojistku: vynulované řádky zisku pro v a ω u absolutních měření (podklad z fáze 1: únik za jízdy ~1 % posunu gridu, p90 ≤ 9 mm / 10 s — autor)

occupancy-and-local-planning.md, decisions.md · DevLog 2026-10-04, 2026-10-07

V úzkém průjezdu plán „schoduje“ po buňkách 45° a regulátor kvůli tomu jede ~0,1 m/s, ačkoli obálka plánu dovoluje 0,6–0,9

v kódu, na HW neověřeno vada nalezeno 5. 10. 2026 vyřešeno 5. 10. 2026

Simulace 20261005-124937.rec (SyntetickyKoridor + posunutá vizuální mapa, localframe=odom), zúžení way 103 (šířka 1 m; ve vizuální mapě skloněné ~17° k osám gridu), 12:50:35–12:50:55: v0 plánu (rychlostní profil ve World pohledu) **0,6–0,9 m/s**, příkaz regulátoru **0,04–0,10 m/s**, robot ujede ~1,2–1,6 m za 10 s. **Dva různé stropy:** graf kreslí RegulatorWayPoint.Speed, tedy obálku occupancy plánovače (odstup od překážek, hranice potvrzeného). PathResult k ní přidá **strop rohu** ω_max · r, kde poloměr plyne z tolerance uzlu ε = d_min − SafeDist (tady 0,06–0,11 m), a zpětným průchodem ho roztáhne dopředu — log draha: uzlu=20–30 vLimit[0]=0,18–0,24 vLimitMin=0,03 nejostrejsiRoh=45–53° minPolomer=0,06 m; vazba na dobu rotace s cílovým uzlem 0,2 m před robotem pak dá vCmd 0,06–0,09. **Příčina rohů:** při SafeDist 0,4 m zbývá v cestě široké 1 m pás d ≥ SafeDist jen ~0,2 m; šikmá přímka se do něj nevejde, takže string-pulling nechá schody po jedné buňce (5–7 cm, střídavě ±45°) — odchylka takového schodu od jeho střední přímky je ~2 cm, tedy pod ε. Plánovač (cena = čas) o ceně rohů v regulátoru neví, takže schodům nijak nebrání. **Není to vlastnost localframe=odom:** ve world (20261005-075416.rec, 70–100 s) totéž (v0 0,74–0,80, vCmd 0,08–0,10, nejostrejsiRoh=45°). **Léčba (autor zvolil „vyhlazování s tolerancí", 5. 10. 2026):** přehrání plánovače nad gridem ze záznamu ukázalo, že tvrdý odstup zkratku **nezamítá** — zamítala ji časová kontrola, která neviděla rohy, a rampa vázaná na vjezdovou rychlost; tolerance kolem buněk by tedy nepomohla. V kódu je proto druhý průchod vyhlazování MergeCorners (smoothcorners=, výchozí true): uzly prvního průchodu se sloučí do úsečky jeté nejvyšší rychlostí pod obálkou, když ji regulátor odjede rychleji než původní lomenou čáru i s jejími rohy (PathPlanner.CornerSpeed). Nad gridem ze záznamu 15 → 4 uzly, nejnižší VLimit 0,03 → 0,38 m/s; simulace s cílem za zúžením dojela o ~18 s dřív, odstup nikde pod SafeDist, ale p50 0,427 proti 0,474 m. Detail doc/occupancy-and-local-planning.md, „Druhý průchod"; rozhodnutí decisions.md 5. 10. 2026.

  • Rozbor záznamu 20261005-124937.rec: dva stropy (obálka plánu vs. rohy v PathResult), schody 45° v pásu ~0,2 m; totéž ve world 5. 10. 2026
  • Rozhodnout léčbu (autor): vyhlazování s tolerancí 5. 10. 2026
  • Druhý průchod MergeCorners (smoothcorners=), sdílený PathPlanner.CornerSpeed; testy šikmého koridoru + šikmá scéna v invariantu rampy; přehrání nad gridem ze záznamu a A/B simulace 5. 10. 2026
  • Jízda na zařízení úzkým průjezdem: ARBot.Analyze localplan (v0 vs. vCmd) a odstup od okraje proti smoothcorners=false

occupancy-and-local-planning.md, path-following.md · DevLog 2026-10-05

Po uvolnění holdu chodí plán až za 9–13 s a zastaralý regulátor mezitím točí robotem na místě

v kódu, na HW neověřeno vada nalezeno 5. 10. 2026 vyřešeno 5. 10. 2026

Nalezeno rozborem držených zastavení (ARBot.Analyze hold, lp-drzene-zastaveni-stophold). Po uvolnění holdu, který vzalo zotavení kamer, přišel první LocalPlanMsg až za **13,1 s** (20260923-143515.rec) a **8,7 s** (20260929-151634.rec). Do té doby je regulátor zastaralý (ControlLoop: déle než PathControlTimeOut bez nového plánu) — dopředný příkaz se dobrzďuje rampou z nuly, tedy zůstává 0, ale **rotace z regulátoru jde dál**. Pod holdem ji smyčka u stojícího robotu nuluje, po uvolnění už ne: 29. 9. šlo do motorů −0,48 až −0,52 rad/s a gyro naměřilo −0,47 až −0,55 rad/s, tedy robot se točil na místě za dráhou naplánovanou před holdem; 0,5 s nato obsluha stiskla nouzové zastavení a po jeho uvolnění se točil znovu (−0,52 rad/s, 1 s). 23. 9. to byly jen záchvěvy do ±0,13 rad/s. Totéž platí pro každou zastaralou dráhu, nejen po holdu: dobrzdění „po poslední trase" má smysl za jízdy, ale u stojícího robotu je to otáčení k dráze, která už neplatí. Proč plány 9–13 s nechodí, když kamery jsou podle supervizoru zpátky, z těchto dat vidět není. ✅ **V kódu 5. 10. 2026 (rozhodnutí autora):** u zastaralé dráhy se rotace nuluje, jakmile dopředný příkaz dobrzdil na nulu a kola stojí (neznámý stav motorů = stání) — ControlLoop, testy ZastaralaDraha_*. Platný plán s nulovou rychlostí (otočení na místě z plánovače) se netýká. Po uvolnění nouzového zastavení přichází plán do 0,05–0,4 s, takže tam to nehrozí.

  • Změřeno ze záznamu: plán za 13,1 / 8,7 s po uvolnění, rotace na místě −0,5 rad/s (gyro) při nulovém dopředném příkazu 5. 10. 2026
  • Rozhodnout (autor): u zastaralé dráhy nulovat rotaci, jakmile dopředný příkaz dojde na nulu / robot stojí (jako pod holdem), nebo jinak. Autor: ano — „plán je starý a robot zastavil, nevidím důvod, proč by měl rotovat“; v kódu (ControlLoop, 5 testů) 5. 10. 2026
  • Ověřit na zařízení: po uvolnění holdu robot stojí (gyro ~0) do prvního nového plánu (ARBot.Analyze hold)
  • Zjistit, proč po zotavení kamer 9–13 s nevzniká plán (snímky, grid, cíl?)

plan-drive-hold.md, ControlLoop.cs · DevLog 2026-10-05

Izolované skvrny Blocked do 4 buněk brzdí robota jako zeď

odloženo vada nalezeno 7. 9. 2026

Rozbor rychlostní obálky nad venkovním záznamem ze 7. 9. 2026 (ARBot.Analyze envelope) ukázal, že ve 41,5 % plánů drží robota u odstupu izolovaná skvrna blokovaných buněk do 4 buněk (0,01 m²), která ho zbrzdí stejně jako zeď. Morfologický filtr takových skvrn je nasnadě, ale vědomě se neudělal: dokud je kurz z VN100 vedle, nejde rozlišit šum klasifikace od rozmazání gridu chybou pózy, a filtr by ve druhém případě jen zamaskoval příčinu. Rozhodne přeměření obálky po opravě kurzu. 18. 9. 2026 přeměřeno s dobrým kurzem: za jízdy obálku neváže nic, takže izolované skvrny robota aktuálně nebrzdí. Zůstává odložené.

  • Přeměřit envelope po opravě kurzu — 18. 9.: za jízdy neváže rychlost nic (VAlong 0 % v jízdních oknech, Blocked p50 26,5 %), VAlong váže jen ve stání u překážky; rozlišit šum od rozmazání tak není z čeho — filtr není naléhavý 18. 9. 2026
  • Filtr izolovaných buněk — jen když přeměření ukáže šum klasifikace

occupancy-and-local-planning.md, EnvelopeReport.cs · DevLog 2026-09-07, 2026-09-18

Regulátor sledování dráhy z waypointů

hotovo záměr nalezeno 2. 8. 2026 vyřešeno 7. 9. 2026

Robot má projíždět dráhu z waypointů tak, aby každý uzel minul v toleranci a přitom nezastavoval. Místo proporcionálního řízení (v tomto uspořádání kmitá) vznikl plán s geometrií rohů a zpětnou brzdnou obálkou a exekuce s feedforwardem a lookaheadem (IPathPlanner, PathResult, IMotionProfile); bodový PointRegulator nahradil oba staré regulátory. Řídicí smyčka dostala atomickou výměnu regulátoru a watchdog. Venku s ním robot poprvé jel 7. 9. 2026 (FreeRun). Otevřené zůstává ladění na zařízení: MaxAllowedRotationSpeed 30°/s je nízké, sweep τ_look se nikdy neudělal.

  • Fáze 1–5: profil, plán rohů a obálky, exekuce, výměna dráhy v ControlLoop 2. 8. 2026
  • Sjednocení regulátorů na jedno IRegulator a PointRegulator 2. 8. 2026
  • První jízda venku (FreeRun, 20260907-170728.rec) 7. 9. 2026

path-following.md, rozhodnutí 2. 8. 2026 · DevLog 2026-08-02, 2026-08-14, 2026-09-03, 2026-09-07

Occupancy grid a lokální plánování nad ním

hotovo záměr nalezeno 10. 8. 2026 vyřešeno 7. 9. 2026

Sjízdnost z hloubky a z barvy se slévá do kartézského gridu 5 cm kotveného ve světě (dva log-odds kanály, kruhový buffer), nad ním vzdálenostní pole, A* s cenou v čase a vyhlazení na waypointy. Bezpečnost drží invariant „nejeď rychleji, než z čeho zastavíš na hranici potvrzeně průjezdného". LocalNavigator to zapojil do runtime 11. 8. a hned se přidalo hlídání rozjeté dráhy proti aktuální mapě (díra objevená při review). Diagnostika ze 14. 8. (rozpad zápisu snímku, koridor, obálka, regulátor) pak našla vady v projekci i v regulátoru. Venku robot s touto vrstvou poprvé jel 7. 9. 2026; co se tam ukázalo (plazení, klín, zóna cíle), jsou samostatná témata.

  • Návrh (9 fází) a rozhodnutí 10. 8. 2026
  • Jádro: grid, integrátor, EDT, A* a vyhlazení; azimut přes sloupec obrazu 10. 8. 2026
  • LocalNavigator v runtime, zprávy do záznamu, hlídání dráhy proti mapě 11. 8. 2026
  • Diagnostika řetězu a test celého řetězu bez GUI 14. 8. 2026
  • První jízda venku (FreeRun, 20260907-170728.rec) 7. 9. 2026

occupancy-and-local-planning.md, rozhodnutí 10. 8. a 11. 8. 2026 · DevLog 2026-08-10, 2026-08-11, 2026-08-14, 2026-09-07

Robot by zatáčel dvakrát rychleji, než regulátor chce

hotovo vada nalezeno 12. 8. 2026 vyřešeno 21. 9. 2026

Převod úhlové rychlosti na příkaz motorům bral dif jako rozdíl rychlostí kol, jenže driver ho k jednomu kolu přičítá a od druhého odečítá - je to offset na kolo, správně s polovinou rozchodu. Shodly se na tom tři nezávislé zdroje (předchozí generace robotu, profil pohybu, skript řadiče); dva existující testy starý faktor kódovaly. Znaménko rotace je jiná otázka a z kódu se rozhodnout nedá (asymetrická negace ve skriptu, záleží, které kolo je motor 1) - mělo se změřit na robotu malým +ω ve stoje. Samostatná zkouška nakonec nebyla potřeba: robot od 7. 9. 2026 opakovaně jezdí venku po dráze (FreeRun, Track, Robotour) a s otočeným znaménkem by zatáčel od dráhy místo k ní a regulátor by divergoval, takže znaménko je jízdou prokázané. Uzavřeno rozhodnutím autora 21. 9. 2026.

  • Faktor 1/2 v ControlLoop, test RotationSpeed_ToDif_IsHalfWheelBase 12. 8. 2026
  • Znaménko odometrického ω potvrzeno předchozí generací 12. 8. 2026
  • Znaménko příkazové rotace: odvozeno z jízd na zařízení (robot sleduje dráhu od 7. 9. 2026), samostatné měření +ω ve stoje zrušeno 21. 9. 2026

path-following.md · DevLog 2026-08-12

Robot jel 0,1 m/s, i když bylo povoleno 1,2 m/s

hotovo vada nalezeno 14. 8. 2026 vyřešeno 18. 9. 2026

Mapa, obálka i plánovač pouštěly plnou rychlost, ale regulátor vydával 0,05 m/s. Omezovač váže dopřednou rychlost na vzdálenost k lookahead bodu a dobu dorovnání rotace - a lookahead se počítal z aktuální rychlosti, takže při nízké rychlosti seděl na podlaze 0,15 m a strop zůstával nízký: západka, ze které se soustava sama nedostane. Dvě dřívější hypotézy padly, protože stály na offline testu místo na měření za běhu. Podle návrhu autora se teď míří na nejbližší uzel dráhy před robotem (uzly blíž než lookahead se přeskakují); bez opravy dosáhne test 0,19 z 0,80 m/s. Venku 7. 9. se to samostatně nepotvrdilo, protože robota brzdil jiný omezovač (odstup od překážky, lp-robot-se-plazi-vyhlazovani). Potvrzeno venku 18. 9. 2026 s opraveným kurzem (20260918-155329.rec): příkazovaná rychlost p50 1,0 m/s při stropu maxspeed=1 v provozním profilu, tedy robot jede na povoleném stropu; a článek regulator-sledovani-drahy 20. 9. ukázal, že podlaha západky d_min/(k·T_rot) = 0,048 m/s je přesně to, co se 14. 8. naměřilo.

  • Diagnostika po stupních (grid, obálka, plánovač, regulátor) 14. 8. 2026
  • Cíl řízení = nejbližší uzel dráhy, přeskok blízkých uzlů, dva regresní testy 14. 8. 2026
  • Potvrdit na zařízení, že robot dosáhne povolené rychlosti — 18. 9. 2026 venku vCmd p50 1,0 m/s při maxspeed=1 (ARBot.Analyze localplan, envelope) 18. 9. 2026

path-following.md · DevLog 2026-08-14, 2026-09-07, 2026-09-18, 2026-09-21

Únik z blokované buňky pod robotem

hotovo záměr nalezeno 18. 8. 2026 vyřešeno 26. 9. 2026

Robot v záznamu 5 s hlásil RobotBlocked, ačkoli stál na okraji cesty, ne u překážky — buňka pod ním byla podle barvy jistě mimo cestu a nejbližší průjezdná ležela 5 cm vedle. Relaxace gridu se zamítla (kamera buňku pod sebou nikdy neuvidí). Únik vede přes semanticky blokované buňky, přes geometricky blokované nikdy, nejvýš 1,5 m, a uváznutí není selhání plánu, aby nezavřelo hranu, která je v pořádku. Od 3. 9. řeší týmž únikem i robota stojícího blíž k překážce, než je SafeDist. Na robotu zabral 25. 9. 2026 (Track, 20260925-142428.rec): po posunu gridu korekcí pózy dvakrát vyjel z blokované buňky za 6–10 s a pokračoval. Zápis „volno" pod půdorysem je vyčleněný jako samostatné odložené téma (lp-zapis-volna-pod-robotem).

  • Návrh a implementace úniku s testy 18. 8. 2026
  • Těsný start u překážky řešen únikem místo eskapovací zóny 3. 9. 2026
  • Ověřeno na robotu: Track 25. 9. (20260925-142428.rec), dvě epizody EscapingBlocked, obě vyjel 25. 9. 2026

occupancy-and-local-planning.md · DevLog 2026-08-18, 2026-09-03, 2026-09-26

Rychlostní obálka lokálního plánovače v přímé jízdě vůbec neřídila

hotovo vada nalezeno 2. 9. 2026 vyřešeno 5. 10. 2026

Strop rychlosti z odstupu od překážek a z hranice potvrzeného terénu platil jen v uzlu, do kterého se přijíždí, ne podél úseku — a u dvoubodového plánu robot → mrkev (100 % plánů FreeRunu) se strop startovního uzlu nikdy nečetl. Změřeno: strop 0,30 m/s, robot jel 0,86 m/s. Po opravě obálka poprvé skutečně řídila — a hned bylo vidět další dvě věci: robot po startu 10 s lezl 0,05 m/s, protože grid před ním nic nepotvrdil (léčba: půdorys robota je pro obálku sjízdný), a radiální rampa brzdila i podél okraje trávy (léčba: směrový model, envelope=directional). Nový graf rychlostního profilu v pohledu World tu vadu odhalil. Na zařízení obálka řídí od 7. 9. 2026 (ARBot.Analyze envelope: VAlong vázal v 77 % plánů — právě ona robota zpomalila na 0,05 m/s, viz lp-robot-se-plazi-vyhlazovani); 18. 9. za jízdy neváže nic při 1,0 m/s. Směrový model a půdorys robota z jízdy rozlišit nejdou.

  • Strop uzlu, ze kterého se odjíždí, platí podél celého úseku 3. 9. 2026
  • Půdorys robota sjízdný pro brzdnou obálku (FootprintRadiusM) 3. 9. 2026
  • Směrový model stropu z odstupu (envelope=directional) 3. 9. 2026
  • Přeměřit šířku pásma podél překážky a příčnou chybu sledování na zařízení. Hotovo (ARBot.Analyze drive, nový blok; jízdy 18. 9. -154028, -155329, 29. 9. -150844, -151634): odchylka od dráhy, kterou regulátor jel, p50 1–9 mm, p99 2,6–9,3 cm (rovně i v zatáčce podobně), nad EdgeMarginM 0,15 m v 0,02–0,44 % taktů — **0,15 m stačí** a zůstává. Pod SafeDist byl robot v 0,19–0,70 % taktů s odchylkou p50 0–6 mm, tedy kvůli změně mapy pod ním, ne sledování. Plán se obnovuje po ~0,12 s, proto je odchylka malá; s plánem starým 0,3–0,6 s FreeRun 29. 9. p50 53 mm 5. 10. 2026

occupancy-and-local-planning.md, path-following.md, rozhodnutí 3. 9. 2026 · DevLog 2026-09-02, 2026-09-03, 2026-09-07, 2026-09-18, 2026-10-05

Robot se venku plazil rychlostí 0,05 m/s — může za to vyhlazování dráhy

hotovo vada nalezeno 7. 9. 2026 vyřešeno 18. 9. 2026

Rozbor venkovní jízdy (ARBot.Analyze envelope, rozpad po uzlech): medián příkazované rychlosti 0,05 m/s a v 53 % plánů je na podlaze už první uzel; váže odstup od překážky přesně na SafeDist, brzdná obálka skoro nikdy — padla hypotéza „plazí se skrz neověřený prostor". Cesta je přitom široká (3,8 m). Příčina: vyhlazení dráhy přijme zkratku podle tvrdého d ≥ SafeDist a zahodí odstup, který A* koupil cenou. Léčba smooth=time: zkratka se přijme, jen když se pod obálku vejde rampa, kterou regulátor odjede, a nezhorší jízdní čas; strop uzlu je obálka v uzlu. Brzdný zákon se sjednotil do IMotionProfile.Dist2MaxSpeed a opravil se vadný Speed2Dist. Na realistické scéně rychlost 0,05 → 0,49 m/s. Přeměření na HW čekalo na opravu kurzu. ✅ **18. 9. 2026 přeměřeno venku s dobrým kurzem:** robot za jízdy neleze — plány na podlaze už v prvním uzlu **1 %** proti 53 % ze 7. 9., příkazovaná rychlost p50 1,0 m/s (ARBot.Analyze localplan, envelope). Na podlaze zůstává jen stání u překážky (lp-zasek-v-blokovane-mape).

  • ARBot.Analyze envelope po uzlech, LocalPlanMsg verze 2 7. 9. 2026
  • Mechanismus doložen rozhodujícím experimentem (cena nemá na dráhu vliv) 8. 9. 2026
  • smooth=time, Dist2MaxSpeed, oprava Speed2Dist, 9 testů 8. 9. 2026
  • Přeměřit v terénu po opravě kurzu — 18. 9. (20260918-155329.rec, jízda 180–560 s): 1. uzel na podlaze 1 % (7. 9.: 53 %), vCmd p50 1,0 m/s, za jízdy obálku neváže nic; uzlů a cena na Pi neměřeny 18. 9. 2026

occupancy-and-local-planning.md, path-following.md, rozhodnutí 8. 9. 2026 · DevLog 2026-09-07, 2026-09-08, 2026-09-18

Řídicí smyčka umí držené zastavení (StopHold)

hotovo záměr nalezeno 13. 9. 2026 vyřešeno 5. 10. 2026

Robota šlo zastavit jen tím, že mu mise odebrala regulátor — jenže táž vlastnost nese „kam jet" i „smím jet" najednou, takže jakmile chce robota podržet někdo jiný než mise (zotavení kamer, servisní okno), začne se o ni přetahovat a vyhraje ten, kdo psal poslední. StopHold je druhý, nezávislý a počítaný vstup: robot stojí, dokud drží kdokoli, brzdí rampou místo tvrdé nuly, důvod držení je povinný a jde do DriveCommandMsg (verze 3) i na stránku náhledu; detektor záseku se pod drženým stopem odzbrojí a po uvolnění zase ozbrojí. Držení se na robotu potvrdilo při zotavení kamer (13. 9. za 29 s, podruhé 18. 9. za 32 s), ale robot u toho pokaždé stál — brzdění pod holdem za jízdy je zatím jen z testů. ✅ **Ověřeno ze záznamů 5. 10. 2026** (ARBot.Analyze hold): ze čtyř epizod (16., 18., 23. a 29. 9., vždy zotavení pravé D435, 1,6–6,2 s) dvě padly do jízdy a robot pod holdem brzdil **rampou** a zastavil za 0,27–0,35 s na 3–5 cm. Rozjezd po uvolnění rampou **není** a na jízdě se ukázaly dvě nové vady — vedou je samostatná témata lp-zastaraly-regulator-toci-na-miste a lp-prikaz-rychlosti-bez-rampy.

  • Mechanismus StopHold v řídicí smyčce, brzdění rampou, příznak ve zprávě 13. 9. 2026
  • Odzbrojení detektoru záseku pod drženým stopem (a opětovné ozbrojení) 13. 9. 2026
  • Řádek „zastaveno: důvod“ na stránce náhledu 13. 9. 2026
  • Ověřit brzdění pod holdem za jízdy na zařízení (mise + přirozený výpadek kamery). Ze záznamu (ARBot.Analyze hold): 23. 9. 20260923-143515.rec z 0,47 m/s (kola 0,60), příkaz po 0,050 m/s za takt (tehdejší MaxDecceleration 0,50), kola stojí za 0,35 s, dráha 5 cm; 29. 9. 20260929-151634.rec z 0,13 m/s, příkaz po 0,040 m/s za takt, kola stojí za 0,27 s, 3 cm. Žádný skok, kola sledují příkaz se zpožděním ~0,1 s 5. 10. 2026
  • Hold vzatý supervizorem na robotu při skutečné poruše kamery (robot stál) 13. 9. 2026
  • Rozjezd po uvolnění holdu rampou, ne skokem — ověřit měřením (rampu má dělat profil pohybu). Změřeno: rampou NENÍ. Po uvolnění přišel první plán až za 13,1 s (23. 9.) a 8,7 s (29. 9.), do té doby je regulátor zastaralý a dopředný příkaz zůstává 0 (lp-zastaraly-regulator-toci-na-miste); s prvním plánem skočí příkaz 0 → 0,57 m/s za jeden takt a za 1 s na 1,53 m/s, zrychlení omezí až motorová jednotka (lp-prikaz-rychlosti-bez-rampy) 5. 10. 2026

plan-drive-hold.md, path-following.md · DevLog 2026-09-13, 2026-09-18, 2026-10-05

Cíl lokálního plánovače je zóna, ne jediná buňka

hotovo vada nalezeno 14. 9. 2026 vyřešeno 18. 9. 2026

Robot nedokázal dojet k prvnímu bodu trasy: k 44 m jel 9,5 minuty. Cílem A* byla jediná buňka, takže mrkev v trávě nebo u překážky byla nedosažitelná jako celek — plán skončil na nejbližší bezpečné buňce, stav GoalBlocked a robot tam zastavil a čekal, ačkoli jiná část cílové zóny dosažitelná byla (nad záznamem ze 14. 9. GoalBlocked 24 %, mrkev nedosažitelná v 52 % plánů). Globální vrstva v zónách myslela už od 12. 9., lokální ne. Teď je cíl zóna (carrotradius=; průjezdní mrkev je bod, při dojezdu se použije dojezdový poloměr zmenšený o rezervu 0,5 m), heuristika se měří k okraji zóny a A* vrací nejlevnější buňku na dojetí. Není to lék na špatnou mapu — blokovaných buněk bylo p50 27,7 % při rozbitém kurzu, takže část nedosažitelnosti může být chyba gridu, kterou zóna zakryje. ✅ **18. 9. 2026 na zařízení:** GoalBlocked 24 → 2 %, GoalUnsafe 19 → 2 %, mrkev nedosažitelná 52 → 33 % — zároveň s opraveným kurzem, takže podíl zóny a podíl kurzu se z jednoho záznamu nerozdělí. Zóna tedy na zařízení běžela 18. 9. i na Robotouru 19. 9. Rozbor gridu v okamžicích nedosažitelnosti (kolik je chyba mapy) je věcně táž otázka jako lp-zasek-v-blokovane-mape a vede se tam; téma uzavřeno rozhodnutím autora 21. 9. 2026.

  • Měření ARBot.Analyze localplan nad záznamem ze 14. 9. 14. 9. 2026
  • Zóna jako cíl A*, poloměr jako vlastnost cíle, tři pasti hlídané testy 14. 9. 2026
  • Podívat se na grid v okamžicích nedosažitelnosti — přesunuto do lp-zasek-v-blokovane-mape (táž otázka) 21. 9. 2026
  • Přeměřit localplan po nasazení — 18. 9. (20260918-155329.rec): GoalBlocked 2 % / GoalUnsafe 2 % (14. 9.: 24 / 19 %), mrkev nedosažitelná 33 % (52 %), s dobrým kurzem 18. 9. 2026

occupancy-and-local-planning.md · DevLog 2026-09-14, 2026-09-18, 2026-09-21

Tabulky v path-following.md počítají se starými limity (0,8 m/s a 0,2 m/s²)

hotovo vada nalezeno 18. 9. 2026 vyřešeno 25. 9. 2026

Našlo se při psaní webového článku o regulátoru, kde se čísla nepřebírala z dokumentu, ale počítala znovu z Profile.cs. Dokument uvádí u tabulek „hodnoty z Profile“, ale ty hodnoty tam dnes nejsou: MaxAllowedSpeed je 1,2 m/s (provozní profil 1 m/s) a MaxAcceleration 0,5 m/s², kdežto tabulky oblouk-vs-klotoida i lookahead počítají s 0,8 a 0,2. Důsledky nejsou kosmetické — úhlové zrychlení vychází 2,44 rad/s² místo 0,98, náběh rotace 3,2° místo 8° a nejhorší případ (kde se potkává limit otáčení s v_max) leží na ~32°, ne na ~40°. Závěry tím nepadají (náběh je pořád malý proti běžné zatáčce, chyba oblouku hluboko pod rezervou 1 cm), ale konkrétní čísla v obou tabulkách neplatí. Je to táž třída vady jako maxspeed=1 v pi-freerun.cfg, kde komentář popisoval počáteční hodnotu, ačkoli se strop mezitím zvedl — autoritativní je kód, dokument se zapomněl přepsat. **Vyřešeno 25. 9. 2026 jinak, než se plánovalo (autor):** parametry jízdy se mění podle schopností robotu i podmínek soutěže, takže tabulky se na aktuální nastavení **nepřepisují**. U obou je teď výslovně sada parametrů, pro kterou jsou spočtené, a pod nimi vzorce pro nejhorší případ, ze kterých jde číslo přepočítat. Aktuální limity má ukázat pohled v aplikaci (nast-limity-jizdy-view). Při přepočtu vyšlo, že při maxspeed=1.7 dá seříznutí + oblouk ~11,7 mm, tedy o málo víc než rezerva PathEpsilonMargin (10 mm).

  • Označit u obou tabulek sadu parametrů (0,8 m/s, 0,2 m/s², π/6, rozchod 0,41 m, ε 0,1 m) a doplnit vzorce pro nejhorší případ — místo přepočtu na dnešní Profile.cs 25. 9. 2026
  • Hlídat tabulky testem — nepotřeba, tabulky už netvrdí aktuální hodnoty 25. 9. 2026

path-following.md, Profile.cs · DevLog 2026-09-18, 2026-09-25

Robot 18. 9. dvakrát stál minuty před blokovanou lokální mapou — vysvětleno, slepý konec chodníku

hotovo vada nalezeno 18. 9. 2026 vyřešeno 7. 10. 2026

20260918-154028.rec: po dvou celých kolech Tracku robot na cestě k bodu 1/3 od ~320 s zpomalil na 0,05–0,12 m/s a od 388 s stál ~6 minut do konce záznamu — plán délky 5 cm, potvrzeně volno 0,00 m, Blocked ~50 % buněk, stavy AlreadyAtGoal/EscapingBlocked, 4× „NOUZOVE ZASTAVENI - kolize 0,00 m“, hraniční body z kamer 1,7–2,8 m před robotem (něco tam bylo). 20260918-155329.rec: po volbě mise 52–117 s EscapingBlocked, pak se rozjel. Vedlejší efekt pro koridor: ve stání nevzniká (0,6 % cyklů), takže celkové procento Ok v záznamu je číslo o stání, ne o koridoru. **Vysvětleno 7. 10. 2026** (ARBot.Analyze zasek, nav, snímky kamer): **NENÍ to mechanismus z 1. 10. 2026** (lp-uvaznuti-v-zatackach) — RobotBlocked v obou záznamech 0×, překážky skutečné. Globální navigace poslala ve 3. kole robota k místu 1/3 objížďkou 266 m místo 44 m (nejspíš po penalizaci way 230064222 chybou φ, nav-phi-obracena-hrana; neověřeno). Na konci footway 230064222 robot nesjel přes obrubník na ulici (OSM ji spojuje přímo s osou ulice, fyzicky je mezi nimi chodník a obrubník), ~8 m se plazil po 1,2–1,4 m širokém chodníku souběžně s ulicí (offRoute 0 → 4,9 m) do slepého rohu (obrubník, sloupky, svah). V 382 s koridor přiřadil chodník k ulici 4,9 m vedle a póza skočila o 4,8 m (lok-koridor-chodnik-k-ulici); PoseJumpDetector smazal grid a grid se postavil znovu z TÝCHŽ skutečných překážek. Od 388 s AlreadyAtGoal s mrkví 6,6–7,3 m daleko (lokální minimum, lp-alreadyatgoal-lokalni-minimum), detektor záseku odzbrojený, nic nehlásilo (nav-uvaznuti-neohlasene). V 155329 (restart na tomtéž chodníku) póza z GPS 3–5 m vedle, mrkev do svahu, únik s východem 5 cm se 65 s nerealizoval; ukončila to obsluha tlačítkem stop a otočením rukou. Opravy původního popisu: grid se mazal v 382,1 s detektorem skoku pózy, ne při zotavení kamer (to grid nemaže); „nouzové zastavení 59–85 %" v 155329 bylo HW tlačítko obsluhy.

  • Nález (ARBot.Analyze localplan --from=320, corridor, log) 18. 9. 2026
  • Snímky z kamer 320–400 s (ARBot.Analyze zasek --png=): robot na úzkém chodníku za obrubníkem (ulice vlevo, svah a strom vpravo), na konci slepý roh se sloupky; překážky skutečné, ne artefakt gridu 7. 10. 2026
  • Rozhodnuto: ani lp-unik-z-blokovane-bunky (pod robotem blokovaná buňka nebyla), ani lp-filtr-izolovanych-bunek (souvislé plochy obrubníku a svahu). Nové vady: lp-alreadyatgoal-lokalni-minimum, lok-koridor-chodnik-k-ulici, nav-uvaznuti-neohlasene 7. 10. 2026

map-correlation-localization.md (sekce 18. 9. 2026), occupancy-and-local-planning.md · DevLog 2026-09-18, 2026-10-07

ARBot.Analyze drive přehrával regulátor napevno s lichoběžníkovým profilem

hotovo vada nalezeno 5. 10. 2026 vyřešeno 5. 10. 2026

Rozbor drive stavěl regulátor vždy s TrapezoidMotionProfile, ačkoli od 25. 9. 2026 je výchozí motionprofile=latency. U jízd z 29. 9. proto rekonstrukce příkazu neseděla se záznamem (p50 0,09–0,12 m/s, p90 0,34–0,43 m/s) a celý rozpad rychlosti popisoval jiný regulátor, než který jel. Našlo se při měření příčné chyby sledování (lp-rychlostni-obalka-neridila). Report teď bere motionprofile= a motionlatency= z konfigurace v záznamu (bez klíče = lichoběžník); shoda 99,7–99,9 % taktů do 0,02 m/s. Závěry dřívějších rozborů drive nad jízdami od 25. 9. je potřeba brát s touto výhradou.

  • Profil z konfigurace v záznamu, ověřeno nad 20260929-150844.rec a -151634.rec 5. 10. 2026

record-replay.md · DevLog 2026-10-05

Příkaz dopředné rychlosti skáče bez rampy — zrychlení omezuje až motorová jednotka

zamítnuto vada nalezeno 5. 10. 2026 vyřešeno 5. 10. 2026

Nalezeno při ověřování rozjezdu po uvolnění holdu (ARBot.Analyze hold). Předpoklad byl, že rampu rozjezdu udělá profil pohybu regulátoru. Neudělá: s prvním plánem po uvolnění skočil příkaz za jeden takt z 0 na **0,57 m/s** (23. 9.) resp. **0,51 m/s** (29. 9.) a za další sekundu na 1,53 / 1,70 m/s, tedy krok až 0,9 m/s za takt proti MaxAcceleration·Ts 0,04. Za jízdy totéž (29. 9. 0,28 → 1,69 m/s v jednom taktu). Profil (LatencyMotionProfile) dává nejvyšší rychlost, ze které se ještě stihne zastavit, a na **současnou** rychlost se neohlíží; MaxAcceleration v něm brání jen brzdné křivce. Kola zrychlila přibližně o 1,9 m/s² (23. 9.: 0,05 → 0,61 m/s za 0,3 s) — to je rampa motorové jednotky, ne naše. Důsledky: DriveCommandMsg neříká, jak rychle robot pojede, a regulátor počítá s rychlostí, kterou robot ještě nemá. ⚠️ Rychlost kol z jednotlivých vzorků je zašuměná (razítka odometrie, lok-fuze-poza-pred-koly); číslo zrychlení je orientační. ❌ **Zamítnuto jako vada 5. 10. 2026 (autor):** robot smí vydat příkaz „jeď maximální rychlostí", rozjezd reálně omezí motorová jednotka. Po uvolnění nouzového zastavení je obraz týž (příkaz skočí až o 1,5–1,6 m/s za takt, kola zrychlují plynule). Měření přitom ukázalo, že rampa jednotky **není** Profile.MaxAcceleration — vede hw-motor-rampa-jednotky.

  • Změřeno ze záznamu: skok příkazu 0 → 0,51–0,57 m/s za takt, kola ~1,9 m/s² 5. 10. 2026
  • Rozhodnout (autor): omezit nárůst příkazu v řídicí smyčce na MaxAcceleration·Ts, nebo nechat na motorové jednotce a jen to zdokumentovat. Autor: nechat na motorové jednotce 5. 10. 2026

path-following.md, plan-drive-hold.md, rozhodnutí 5. 10. 2026 · DevLog 2026-10-05

Oblast

Vidění

Prahy klasifikace a šumový model gridu sjízdnosti nejsou laděné na reálných datech

otevřeno vada nalezeno 30. 7. 2026

Geometrie a klasifikátor polárního gridu jsou ověřené syntetickým testem a na živé kameře grid ukazuje data, ale prahy (RoughRef, MaxSlope, škálování MaxHeightDev), šumový model a radiální hrany z reálného podílu platných pixelů se nikdy neladily nad záznamem z terénu. Grid dnes plní occupancy mapu, nad kterou plánuje lokální navigace — a podle té mapy robot od 7. 9. 2026 venku jezdí; co z chování v terénu jde na vrub prahů gridu a co chyby kurzu nebo vyhlazování, změřené není (viz lp-zasek-v-blokovane-mape, lp-robot-se-plazi-vyhlazovani).

  • Ladění prahů a šumového modelu nad záznamem ze zařízení

traversability-grid.md, occupancy-and-local-planning.md · DevLog 2026-07-30

Okluzní pravidlo zahazuje většinu barevných vzorků

otevřeno vada nalezeno 14. 8. 2026

Při zápisu barvy do occupancy gridu se za první překážkou v daném azimutu stíní celý zbytek paprsku, i místa, kam kamera zjevně vidí. Nad virtuálním HW to zahodilo ~5 200 z ~12 000 kandidátů, takže semantický kanál dostává řádově míň dat než geometrický a plocha mimo cestu se potvrzuje pomalu. Záměr pravidla je správný, míra ne; k rozmyšlení je stínit jen do jisté vzdálenosti nebo vzorek jen zeslabit. Neřešeno. 1. 10. 2026 (autor): nejdřív změřit nad skutečnými záznamy, až budou k dispozici — číslo ze 14. 8. je ze simulace. Rozhodne mezi stínem podle výšky překážky (d·H/(h−H), výpočetně zanedbatelné, PolarCell.MaxZ je k dispozici) a ignorováním malých skvrn v hloubce.

  • Změřit podíl zahozených barevných vzorků nad skutečným záznamem (offline přehráním snímků, ColorShadowed) a kolik z nich stíní skvrny do pár buněk

occupancy-and-local-planning.md · DevLog 2026-08-14, 2026-10-01

Chybná kalibrace kamer je bias, který lokalizace integruje

otevřeno vada nalezeno 20. 8. 2026

Chyba v montáži kamery (yaw o 1° při dohledu 3–6 m) posune celý bodový oblak o 5–10 cm — o řád víc, než je vlastní šum korelace (5 mm). Filtr bere měření jako nezávislá, takže bias vyhraje vahou počtu a póza se drží posunutá s falešnou jistotou. Kalibrace je tedy pravděpodobně dominantní chybový člen. Extrinsiky reálných D435 neměřené (v Profile.cs mají sklon a náklon změřené hodnoty, yaw je kulatých ±29,0°, tedy nejspíš nominál). **Upřesněno 1. 10. 2026 (s autorem):** „bias se s kurzem otáčí" platí jen pro POLOHU vzdálených bodů (posun d·δ vždy na stranu robota, při otočce se v rámci světa překlopí), ne pro KURZ — chyba yaw kamery dá kurz z koridoru chybný o δ v obou směrech jízdy, a přesně totéž dá hrana mapy pootočená o ε. Na jedné rovné cestě se to rozlišit nedá. Rozliší to: (1) víc cest různých směrů — bias kamery je stejný na všech hranách, chyba mapy se liší hranu od hrany; (2) směr GPS stopy proti azimutu hrany v OSM dá chybu mapy bez kamery; (3) nerovnoběžnost levé a pravé hrany dá rozdíl chyb kamer (δ_L − δ_R), chyba mapy ji způsobit nemůže. Data: **Robotour 19. 9. 2026** (jezdilo se různými směry, po nové kalibraci kompasu; mapa Robotour2026-ver1.osm je ručně upravená v JOSM); Hviezdoslavova a Modřany jsou většinou rovné úseky jednoho směru. Přiřazení k hraně brát podle GPS polohy, ne podle pózy, aby do toho nevstoupila lokalizace.

  • Chyba azimutu hran mapy: směr GPS stopy po úsecích proti azimutu hrany v OSM (Robotour 19. 9.)
  • Zbytek kurz z koridoru − GPS kurz napříč hranami: stejný na všech = kamera, různý = mapa (Robotour 19. 9.)
  • Nerovnoběžnost levé a pravé hrany koridoru přes záznamy — změřeno 7. 10. 2026 (dirL − dirR, cykly Ok, v > 1 m/s): Modřany 1. 10. −1,57° (n 23 560) / −2,00°, v místech projetých oběma směry tělesová složka −1,36°; Hviezdoslavova 18. 9. +0,33 / −0,05°, 27. 9. +2,71°; Robotour 19. 9. +0,06 / +0,72°. Hodnota se mezi záznamy mění o ~4° a uvnitř 1. 10. závisí na změřené šířce (−0,7° při 3 m → −2,3° při 5 m), takže to NENÍ rozdíl yaw kamer. Zbývá rozložit: souměrná chyba průmětu (sklon/výška kamer), nebo vazba směru a šířky v proložení
  • Výška, sklon a náklon obou D435 z roviny země: robot stojí na rovné podlaze doma, krátký záznam, proložení roviny hloubkou (autor 1. 10. 2026; kamery jsou pevně přidělané, takže stačí jednorázově, průběžný hlídač není potřeba)
  • Změřit extrinsiky skutečných D435 — zbývá yaw (rovina země ho neurčí)

map-correlation-localization.md, traversability-grid.md · DevLog 2026-08-20, 2026-08-23, 2026-10-01, 2026-10-07

Lepší model Model96.2 dává 96,7 %, ale půlí snímkovou frekvenci

otevřeno záměr nalezeno 7. 9. 2026

Model96.2 je 34× dražší než Model61.1; na CPU 637 ms (nepoužitelné), na NPU 44 ms s přesností 96,66 % / IoU 0,953 a falešně přidanou cestou 2,0 % místo 7,9 %. Za běhu runtime ale spadne frekvence z 29 na 16,5 snímků/s a int8 kvantizace ho rozbije (37,8 %), takže musí běžet fp16. Přibyl parametr camerafps=, který nastavuje frekvenci přímo na kameře. Jestli poloviční frekvence řízení vadí, se neví — nikdy s tím nejelo; v provozním profilu zůstává Model61.1 a blok pro Model96.2 je jen připravený.

  • Změřit Model96.2 na NPU (čas, přesnost, int8 vs fp16) 7. 9. 2026
  • camerafps= a připravený blok v pi-provoz.cfg 7. 9. 2026
  • Rozhodnout provozní bod jízdou — jestli 16 snímků/s řízení stačí

semantic-segmentation.md · DevLog 2026-09-07, 2026-09-09

Trénink segmentace se dnes nedá zopakovat jedním kliknutím

otevřeno vada nalezeno 7. 9. 2026

Trénovací notebook z roku 2022 stahuje data přes legacy LabelBox API, které je na serveru vypnuté (label_generator() neexistuje), a dnešní Colab má Keras 3, kde se staré .h5 váhy nenačtou. Export testovací sady je přepsaný na dnešní project.export(), ale část labelů se nevyexportuje (anotace nástrojem, který už není v ontologii projektu) — opravit to jde jen v LabelBoxu. Referenční float model s pevnými tvary v repu není; export z Kerasu s tím správným checkpointem má připravený notebook ExportFloatModel.ipynb.

  • Export sady přepsat na dnešní API a rozlišit id labelů od data rows 7. 9. 2026
  • Připojit chybějící nástroje k ontologii v LabelBoxu, aby se sada exportovala celá
  • Zprovoznit trénink (nebo aspoň export float modelu) v dnešním Colabu

semantic-segmentation.md, SemanticSegmentation.ipynb, ExportTestSet.ipynb · DevLog 2026-09-07, 2026-09-09

U Model96.2 chybí float checkpoint lepších vah, optimalizace je nevyužitelná

otevřeno vada nalezeno 9. 9. 2026

Dokumentace vedla Model96.2.rknn jako převod z .h5 větve (95,35 %), ale naměřeno měl 96,66 %, tedy víc než údajný zdroj. Měřením se rozhodlo, že vznikl z .tflite větve (96,80 %, −0,14 p. b. za fp16). Ta větev je ale dynamic-range kvantovaná, takže na ní optimalizace grafu nenajde nic; optimalizovat jde jen horší .h5 větev za ztrátu 1,31 p. b. přesnosti. Model96.2 proto zůstává beze změny a −45 % času půjde vytěžit teprve s float checkpointem těch lepších vah, který v repu není. Int8 ten model dál rozbíjí.

  • Zjistit, z čeho dnešní Model96.2.rknn vznikl 9. 9. 2026
  • Sehnat float checkpoint lepších vah Model96.2

čeká na Trénink segmentace se dnes nedá zopakovat jedním kliknutím · semantic-segmentation.md, models/README.md · DevLog 2026-09-09

Zpětná projekce pixelu ignorovala hloubku

v kódu, na HW neověřeno vada nalezeno 21. 8. 2026 vyřešeno 21. 8. 2026

Převod pixelu barevného obrazu na bod v prostoru byl mrtvý na všech platformách: Windows volal nativní ColorPixel23D, které v knihovně není, ARM vyhazoval výjimku, a báze tiše promítala na rovinu země — u horizontu body na stovky metrů. Extrinsiky color–depth kamera znala, ale ARM varianta je zahazovala. Nově managed ColorPixelTo3D, extrinsiky protažené HALem až do záznamu a podtřídy projekce zrušené. Na reálné D435 neověřeno.

  • ColorPixelTo3D a oprava báze CameraProjection.TransformBack 21. 8. 2026
  • Extrinsiky color–depth přes HAL a do záznamu (CameraFrame layout v5) 21. 8. 2026
  • Ověřit extrinsiky a body hranice na skutečné D435

map-correlation-localization.md, traversability-grid.md · DevLog 2026-08-21

Nativní knihovna měla chybějící exporty na x64 a špatnou volací konvenci na ARM

hotovo vada nalezeno 3. 7. 2026 vyřešeno 3. 7. 2026

První NUnit testy nad P/Invoke vrstvou NativeComputeUnit odhalily, že čtyři funkce (TransformPoint4DImpl, Depth2XYZImpl, XYZ2PlaneImpl, ClearAggregateImpl) v x64 DLL vůbec nebyly exportované (latentní EntryPointNotFound i v projekci kamery) a že ARM64 assembler byl psaný x86 stylem místo AAPCS64 (floaty v jiných registrech), plus chyba offsetu ×32. Opraveno a ověřeno na x64, přes Docker/QEMU i na skutečném Orange Pi. Cesta Segment padá na x64 (AccessViolation), v produkci se nepoužívá, její testy zůstávají ignorované.

  • NUnit testy NativeComputeUnit 3. 7. 2026
  • Doplnění exportů v asm_win_x64.asm, ochrana singularity v CalcPlaneParams 3. 7. 2026
  • Oprava AAPCS64 a offsetů v asm_linux_arm64.S, ověřeno QEMU + Orange Pi 3. 7. 2026

build-and-platforms.md, rozhodnutí 25. 7. 2026 (nativní knihovna se staví CMakem) · DevLog 2026-07-03

Polární grid sjízdnosti z hloubkové kamery s robot-centrickým pohledem

hotovo záměr nalezeno 29. 7. 2026 vyřešeno 1. 8. 2026

První vrstva vnímání terénu: hloubka → point cloud → polární grid kolem robota, per kamera, s klasifikací buněk a důvěrou. Zapojený do runtime (v Run se počítá, ve View jen přehrává — živé intrinsics se nezaznamenávají, přepočet ze záznamu je odložený), s ptačím pohledem a overlayem přes hloubkový obraz. Ověřeno na živé kameře 30. 7. Převod hloubky na body jede nativní SIMD cestou (3× levnější), 1. 8. se výpočet přesunul na vlákno kamery přímo do CameraFrame a buňky se kreslí jako mezikruhové výseče místo překrývajících se čtverců. Dnes je vstupem kartézského occupancy gridu.

  • Návrh, implementace, syntetický test geometrie a klasifikace 29. 7. 2026
  • Zapojení do runtime, RobotCentricDocument, overlay přes hloubku, ověřeno na živé kameře 30. 7. 2026
  • Nativní depth → pointcloud (DepthTransform2Impl) s ověřenou ekvivalencí 30. 7. 2026
  • Grid součástí CameraFrame (verze 2), výpočet synchronně na vlákně kamery 1. 8. 2026
  • Buňky jako mezikruhové výseče 1. 8. 2026

traversability-grid.md, rozhodnutí 29. 7. 2026 · DevLog 2026-07-29, 2026-07-30, 2026-08-01

Vizuální cesta se každých ~5 s zasekla na 200–450 ms kvůli GC

hotovo vada nalezeno 30. 7. 2026 vyřešeno 1. 8. 2026

Na zařízení skákalo stáří gridu mezi 30 a 500 ms. CSV diagnostika ukázala, že vlastní výpočet trvá 16–50 ms, ale ~8–13 % snímků zasáhne periodická pauza gen2 GC z alokací velkých obrazových bufferů. Server GC to zhoršil (zamítnuto měřením), nativní transform snížil CPU 3×, ale ocas nezmizel. Řešením byla architektura: kamery pullované řídicí smyčkou, výpočet na vlákně kamery, poolované buffery — a hlavní viník se našel až na HW: MessageWriter serializoval každou zprávu přes novou MemoryStream (~90 MB/s do LOH), k tomu odpojené UART senzory alokovaly stack-trace v těsné smyčce. Po opravách self-test na zařízení: gen2 = 0, žádný snímek nad 100 ms.

  • CSV diagnostika, diagnóza GC, Server GC zamítnut měřením 30. 7. 2026
  • Nativní depth → pointcloud bez alokací (CPU −3×, ocas beze změny) 30. 7. 2026
  • Pull kamer řídicí smyčkou, pooling bufferů a kopií per odběratel 1. 8. 2026
  • MessageWriter bez alokací na zprávu, backoff a škrcení logu v SensorBase 1. 8. 2026
  • Ověřeno na HW self-testem (gen2 = 0, 0 % snímků nad 100 ms) 1. 8. 2026

traversability-grid.md, plan-camera-vision-refactor.md, selftest.md, rozhodnutí 1. 8. 2026 · DevLog 2026-07-30, 2026-08-01

Hranice cesty se počítaly a výsledek se zahazoval

hotovo vada nalezeno 9. 8. 2026 vyřešeno 7. 9. 2026

Kamerový driver volal nativní výpočet hran cesty a výsledek odjakživa zahodil; navazující hledač hran si je počítal podruhé sám. Výpočet se přesunul do procesoru snímku, hrany se nesou v CameraFrame a serializují se se snímkem (formát 3), mrtvá větev v driveru se odstranila. Na zařízení výkon potvrdilo až A/B měření 7. 9. 2026, kde PathEdges běží v runtime za jízdy (a nad sítí dokonce nad 24× menším obrazem).

  • Přesun do CameraFrameProcessor, hrany v CameraFrame formát 3 9. 8. 2026
  • Úklid mrtvé větve BackProject v D435Camera 9. 8. 2026
  • Výkon na zařízení (A/B na Orange Pi za běhu runtime) 7. 9. 2026

rozhodnutí 9. 8. 2026, record-replay.md · DevLog 2026-08-09, 2026-09-07

Projekce kamery měla čtyři skryté chyby

hotovo vada nalezeno 10. 8. 2026 vyřešeno 21. 8. 2026

Při stavbě occupancy gridu se v CameraProjection postupně našly čtyři chyby: promítaly se i body za kamerou (chyběla kontrola Z > 0, bod 4 m za robotem vyšel jako pixel před ním), záměna přetížení ToDistort nechala celou cache nulovou, posunutí kamery se v Transform započítalo dvakrát (plocha mimo cestu se pak neoznačovala jako nesjízdná, chyba ~95 px, platí i pro reálný hardware) a zpětná projekce TransformBack ignorovala hloubku. Testy to nechytly, protože měly vlastní referenční projekci bez postranního posunutí. Poslední kus se opravil 21. 8. přepsáním báze, aby hloubku používala.

  • Kontrola Z > 0 a oprava ToDistort 10. 8. 2026
  • Dvojí odečet posunutí v Transform + round-trip test proti rendereru 14. 8. 2026
  • Čtvrtá vada (zpětná projekce bez hloubky) je samostatné téma, opraveno 21. 8. 21. 8. 2026

imu-and-frames.md, virtual-hw.md · DevLog 2026-08-10, 2026-08-14, 2026-08-21

Sjízdnost z RGB neuronovou sítí místo histogramu barev

hotovo záměr nalezeno 6. 9. 2026 vyřešeno 7. 9. 2026

Druhá implementace „cesty z RGB" (backproject=nn): U-Net Model61.1 z ARBot2 přes ONNX Runtime, který nese nativní knihovnu pro Windows i ARM, takže v simulaci i na robotu běží týž kód. Kvantizace je schovaná uvnitř modelu a předzpracování je replika tréninku, ne naše volba. Změřeno na Orange Pi: síť stojí 10,2 ms (na ARM vyhrává int8, na x86 float — opačně), za běhu runtime přidá jen 6–7 ms, protože odpadne histogram přes plný snímek. Proti sadě s pravdou dává síť 88,2 % / IoU 0,846 proti 78,0 % / 0,752 u histogramu a hlavně vymýšlí cestu, kde není, 2,6× méně často. S histogramem robot jel 7. 9., se sítí na NPU od 12. 9. (provozní profil backproject=npu); dopad na řízení proti histogramu změřený není.

  • Rozbor modelu, převod TFLite → ONNX a OnnxBackProject s testy 6. 9. 2026
  • Měřidlo ARBot.Analyze backproject (čas, shoda s histogramem, srovnávací obrázky) 6. 9. 2026
  • Změřit inferenci a A/B za běhu runtime přímo na Orange Pi 7. 9. 2026
  • Měření proti pravdě (--truth=, sada 50 snímků z LabelBoxu, SegmentationMetrics) 7. 9. 2026
  • Modely do gitu, aby šla síť spustit na čerstvé kopii 7. 9. 2026

semantic-segmentation.md, testset/README.md · DevLog 2026-09-06, 2026-09-07

Dopad výpočtu ve 128×128 na hustotu dat pro grid a hranice cesty

hotovo záměr nalezeno 6. 9. 2026 vyřešeno 7. 10. 2026

Síť počítá sjízdnost ve 128×128 (snímek 4:3 se přitom stlačí na čtverec), kdežto histogram barev pracoval nad plným snímkem 640×480 — hranice cesty a zápis do occupancy gridu tak dostávají řádově řidší data. Jaký to má dopad na hustotu gridu a přesnost hranic, naměřené není. Není to věc konfigurace: vyšší rozlišení vstupu znamená síť přetrénovat, takže stlačení i zvětšení nejbližším sousedem jsou replika tréninku a neopravují se. **Změřeno 29. 9. 2026** (ARBot.Analyze probres, pět záznamů 18.–29. 9., tentýž histogram na plném a zmenšeném snímku + síť ze záznamu, kontrola měřidla proti zapsaným hranám 0,000): hraničních bodů je ~4× méně a **oboustranný koridor na široké cestě zabíjí pevná brána corridormininliers=20 v počtu bodů, ne kvalita bodů** — Modřany 29. 9.: Ok 43,0 / 20,6 % na plném snímku, 4,8 / 3,8 % ve 128×128, síť 1,6 / 0,4 %; s branou přepočtenou na řádky (20 × 128/480 = 5) histogram 41,6 / 20,8 % a síť 33,1 / 26,5 %. Na úzké Hviezdoslavově brána skoro nevadí (26,5 → 24,7 %). Přesnost z řidších bodů skoro netrpí (šířka p50 4–9 cm, příčně 2–4 cm, směr 0,4–0,7° proti plnému snímku). Grid: jeden řádek 128×128 ve 3–5 m pokrývá 0,06–0,24 m, tedy až ~5 buněk 5 cm; hustota zápisu se nemění. Detail a tabulka: semantic-segmentation.md, sekce „Síť mění rozlišení".

  • Změřit dopad 128×128 proti plnému snímku na hranice cesty a occupancy grid — ARBot.Analyze probres nad pěti záznamy 29. 9. 2026
  • Rozhodnout bránu koridoru pro síť 128×128 (autor): corridormininliers (a SingleEdgeMinInliers, dnes pevných 25) snížit, nebo je vyjádřit na 480 řádků a přepočítat podle výšky pravděpodobnostního obrazu. Navazuje na dřívější měření brány, se kterými probres souhlasí a vysvětluje je (počet bodů je vázaný na 128 řádků): Hviezdoslavova 18. 9. 25 → 20 jen +6–7 % (lok-koridor-prah-inlieru-prisny, inlierů je tam 40–50); Modřany 25. 9. 25 → 20 2,7 → 28 % (profil od 26. 9.; hrany tam měly 20–25 inlierů, tedy těsně nad 20); Modřany 23. 9. práh 12–15 bezpečný (šířka ~5 m), pod 10 roste NotParallel i rozptyl šířky a kurzu (map-correlation-localization.md); Modřany 29. 9. při 20 jen 1,6 / 1,2 % s nesmyslnou šířkou, při 10 tisíce se šířkou ~5 m (lok-koridor-siroka-cyklostezka). Brána 5 z probres je tedy přepočet, ne doporučená hodnota. Nižší brána zvedne i NotParallel; kvalita cyklů, které projdou jen s nižší branou, změřená není. ⚠️ fusionreplay bere proložení koridoru hotové z RoadCorridorMsg, takže --set=corridormininliers= na něj NEÚČINKUJE — pro dopad na pózu by musel proložení přepočítat ze snímků (jako probres). Rozhodnuto 30. 9. (autor): přeškálovat, v procentech řádků, i bránu jedné hrany 30. 9. 2026
  • Léčba (autor 30. 9.): brána v PROCENTECH ŘÁDKŮ pravděpodobnostního obrazu, corridorinliers= a nový corridorsingleinliers=, obojí 10 % (síť 13 bodů, plný snímek 48, účinně ≥ 3); corridormininliers= zanikl, CorridorSource bere výšku obrazu ze snímku, bez ní platí absolutních 25. probres s branou 10 %: histogram plný vs. 128×128 dává totéž (Modřany 29. 9. 27,0 / 26,3 % a 11,5 / 11,5 %), síť 1,6 → 14,8 % a 0,4 → 7,2 %, Modřany 25. 9. 29,6 → 56,5 %, Hviezdoslavova 25,1 → 29,4 % a 23,4 → 28,1 %. Simulace FreeRun 75 s: 96,5 % Ok proti 95,5 % s absolutní branou. 6 nových testů; testy 1 725 / 151 / 129, build x64 i OrangePI 30. 9. 2026
  • Ověřeno na zařízení 1. 10. 2026 v Modřanech (20261001-144638.rec Track, -152906.rec FreeRun, corridorinliers=10 = 13 bodů): oboustranné PROLOŽENÍ koridoru v 59,9 / 62,0 % cyklů (za jízdy 70,8 / 61,7 %) proti 1,5 / 0,3 % 29. 9. a 2,7 % 25. 9. s pevnou branou 20; přijato oboustranně 45,2 / 49,0 %, z jedné hrany 17,1 / 28,8 %. Šířka za jízdy p50 3,89 / 3,69 m (p10–p90 3,41–5,21 m), mimo 1–8 m 2,8 % (při 25 bodech 0,4 %); koridor − GPS kurz p50 +1,17 / +2,25° (robustní sd 1,74 / 1,80°), NotParallel 12,2 / 5,3 %. Kvalita cyklů, které projdou jen s nižší branou, zvlášť změřená není 7. 10. 2026

semantic-segmentation.md, OnnxBackProject.cs, ProbResolutionReport.cs, CorridorConfig.cs, rozhodnutí 30. 9. 2026 · DevLog 2026-09-06, 2026-09-07, 2026-09-29, 2026-09-30, 2026-10-07

Síť dává 88 %, ačkoli notebook tvrdí 95 %

hotovo vada nalezeno 7. 9. 2026 vyřešeno 7. 9. 2026

První měření proti pravdě vyšlo o 7,3 procentního bodu hůř, než uvádí trénovací notebook. Šest hypotéz padlo měřením (kvantizace, jiný checkpoint, naše rekonstrukce sady, pořadí kanálů, vzorkování při zmenšení, „novější snímky jsou těžší"). Vysvětlení podal autor: trénovací sada se v čase měnila, takže Model61.1 z února 2021 byl trénován i testován na jiných datech než dnešní sada — sedí to s tím, že Model96.2 mezeru nemá. Je to vysvětlení, ne důkaz; autor rozhodl nedohledávat to v LabelBoxu. Důsledek platí: u Model61.1 se nesmí tvrdit, že dává 95 %.

  • Zamítnout hypotézy měřením (float, BGR, originální sada, vzorkování) 7. 9. 2026
  • Vysvětlení jinou trénovací sadou, rozhodnutí nedohledávat 7. 9. 2026

semantic-segmentation.md · DevLog 2026-09-07

Síť běží na NPU Orange Pi (backproject=npu)

hotovo záměr nalezeno 7. 9. 2026 vyřešeno 7. 9. 2026

Inference přes P/Invoke na librknnrt.so, převod modelu models/onnx2rknn.py; každá kamera má vlastní jádro NPU. Síť stojí 3,3 ms místo 10,2 ms na CPU a za běhu runtime jen +1,2–1,5 ms proti histogramu, přesnost prakticky stejná. Padlo dřívější doporučení psát C++ shim — stačí pět volání API. Cestou se opravil chybný návod na ověření driveru (RKNPU je DRM node, ne /dev/rknpu*) a nasazení posílá modely i knihovnu. Od 7. 9. je NPU v provozním profilu pi-provoz.cfg a ověřené na robotu — obě kamery startují na NPU bez ztráty snímků.

  • Zjistit stav NPU driveru na Pi a opravit návod 7. 9. 2026
  • RknnBackProject + převod modelu, tři pasti RKNN (float zdroj, NCHW, normalizace na NPU) 7. 9. 2026
  • Nasazení modelů a librknnrt.so, zapnutí v pi-provoz.cfg, ověřeno na Pi 7. 9. 2026

semantic-segmentation.md, onnx2rknn.py, pi-provoz.cfg · DevLog 2026-09-07

Polovina výpočtu segmentační sítě byla zbytečná

hotovo záměr nalezeno 9. 9. 2026 vyřešeno 9. 9. 2026

Rozbor grafu Model61.1 ukázal dvě exaktní úpravy (konvoluce 1×1 se spočítá před zvětšením obrazu a dvě sousední 1×1 konvoluce bez nelinearity se sloučí), které uberou 49 % násobení při nezměněném rozhodnutí na všech 819 200 pixelech testovací sady. Nástroj models/onnxopt.py ověřuje shodu rozhodnutí, ne čísel. Optimalizovaný model je výchozí pro CPU (nnmodel=, −54 % času na x86, jen −8 % na ARM) i pro NPU (npumodel=, 3,27 → 2,72 ms na Orange Pi, přesnost beze změny); z ubraných násobení NPU využilo jen třetinu, takže se muselo měřit, ne extrapolovat. Existenci výchozích modelů i shodu rozhodnutí hlídají testy. Nevysvětlené zůstává, proč je varianta _int8_deq_opt o 27 % rychlejší než _float_opt s týmž grafem.

  • Rozbor grafu a onnxopt.py s kontrolou shody rozhodnutí 9. 9. 2026
  • Optimalizovaný model jako výchozí nnmodel=, kryto dvěma testy 9. 9. 2026
  • Převod do RKNN, měření na Orange Pi a přepnutí npumodel= 9. 9. 2026
  • Přeměření CPU cesty na ARM (pořadí variant je tam jiné než na x86) 9. 9. 2026

semantic-segmentation.md, onnxopt.py, models/README.md · DevLog 2026-09-09

Trénovací notebook validoval na testovací sadě a měl další chyby

hotovo vada nalezeno 9. 9. 2026 vyřešeno 9. 9. 2026

Rozbor Model61.1 a trénovacího notebooku ze zadání „co by šlo vylepšit". Nejvážnější nález je validační sada shodná s testovací (udávaných 95,5 % je výběrové maximum přes ~1000 epoch, ne nezávislý odhad); dál sigmoid se špatnou ztrátou, dropout v každém bloku, dvakrát definovaná třída modelu a uložení datové sady, které z masky „všechno je cesta" udělá „nic". Mrtvých neuronů je jen 0,7 %, ale z 16 vstupů poslední vrstvy stačí jeden; flip-TTA a softmax jsou zamítnuté měřením. Notebook je opravený (oddělená validace, správná ztráta, GenericModel27 s residuály), ale žádný nový model se z něj nenatrénoval — na vývojovém stroji TensorFlow nejde spustit.

  • Mrtvé neurony a redundance kanálů změřeny 9. 9. 2026
  • Postprocessing přeměřen (softmax, flip-TTA, práh) 9. 9. 2026
  • Chyby v notebooku sepsané a opravené, architektura v GenericModel27 9. 9. 2026

semantic-segmentation.md, SemanticSegmentation.ipynb · DevLog 2026-09-09

Pravděpodobnost cesty 128×128 se kreslila jen přes střed snímku

hotovo vada nalezeno 10. 9. 2026 vyřešeno 26. 9. 2026

Síť počítá ve 128×128 a pokrývá celý snímek 640×480, ale panel Obrázky držel poměr stran každé vrstvy zvlášť, takže překryv kryl jen prostředních 75 % šířky, a odečet hodnoty pod kurzorem platil jen v levém horním rohu a i tam pro jiný bod. Řídicí cesta byla v pořádku, zkreslení bylo jen v zobrazení. Vrstva teď nese rozměr scény, kterou pokrývá, a každá osa se škáluje zvlášť; tutéž vadu měl webový náhled (?layer=prob), kde se pravděpodobnost natahuje na rozměr barvy. Panel ověřen za běhu v simulaci, webový náhled na zařízení potvrdil autor 26. 9. 2026.

  • Překryv a odečet kurzoru v panelu Obrázky 10. 9. 2026
  • Webový náhled natahuje pravděpodobnost na rozměr snímku 10. 9. 2026
  • Ověřit webový náhled na zařízení (autor) 26. 9. 2026

Views/README.md, semantic-segmentation.md · DevLog 2026-09-10, 2026-09-26

Kvalita segmentační sítě na dnešních snímcích D435 je bez ground truth neznámá

zamítnuto záměr nalezeno 7. 9. 2026 vyřešeno 1. 10. 2026

Segmentační síť má proti histogramu barev naměřenou výhodu (88,2 % proti 78,0 % per-pixel) jen na sadě 50 snímků z ARBot2 — jiné scény, data z let 2019–2022. Na dnešních záznamech z D435 dává síť zjevně čistší obraz cesty, na zarostlé ploše je ale nerozhodná, zatímco histogram tvrdí 80 % sjízdné — a bez ground truth k našim záznamům je to jen rozpor dvou metod, ne verdikt. Chybí anotovaná sada snímků z D435 z roku 2026; s ní by šlo říct, která metoda má pravdu a jestli síť za jízdy (rozmazání, expozice, stíny) drží. ❌ **Uzavřeno 1. 10. 2026 (autor):** tvrzení „jiná kamera" bylo chybné — robot jezdí se **stejnými kusy D435**, ze kterých je i testovací sada, takže se liší jen scénami a obdobím. Rozpor mezi sadou a dnešními záznamy tím odpadá a nová anotovaná sada se pořizovat nebude. Viz decisions.md, 1. 10. 2026.

semantic-segmentation.md, models/testset (sada z ARBot2), OnnxBackProject.cs, decisions.md · DevLog 2026-09-07, 2026-10-01

Oblast

Mise

Kalibrace magnetometru se po zápisu sama znehodnotí — kolektor sbírá dál

otevřeno vada nalezeno 17. 9. 2026

Mise magcal došla do verdiktu HOTOVO v 48. s (podmíněnost 330, sd|B| 0,0026 G) a HOTOVO držela 88 s. V 16:20:16 obsluha ťukla na zápis, v 16:20:20 se kalibrace zapsala do registru 23 i do flash — a v 16:20:19, tedy uvnitř toho zápisu, se proložení zhroutilo: sd|B| 0,0026 → 0,0073 → 0,0276 G, měřítko osy z 1,03 → 2,46 a verdikt spadl na „NEPOUZITELNE: pole je porad nekonzistentni. Postav robota na JEDNO misto dal od kovu a zacni znovu." Ta rada je opačná než skutečnost — pole konzistentní bylo a přestalo být právě tím zápisem. Příčina je v kódu, ne v poli. MagCalMission.Consume přidává každý IMUState do kolektoru bez ohledu na fázi, MagCalCollector.Add žádnou bránu nemá a proložení se počítá přes celou nasbíranou sadu. MagnetometerRaw (UncompMag) je přitom podle měření z 12. 9. 2026 pole KOMPENZOVANÉ — právě proto si mise registr 23 před sběrem sama maže. Po zápisu už vymazaný není, takže od té chvíle padají do téže sady vzorky měřené přes novou kompenzaci a fit míchá dvě různé soustavy. Zapsaná kalibrace je přitom v pořádku — zapsalo se to, co platilo v okamžiku ťuknutí (1,092364 … −0,109534, tedy dobrá první půlka dat), ne ten rozpadlý výsledek; gate Usable ve WriteToSensor() drží. Vada je v tom, co obsluha uvidí PO úspěšném zápisu: „NEPOUŽITELNÉ" a pokyn začít znovu, tedy zahodit kalibraci, která právě vyšla.

  • Nález a důkaz ze záznamu (časová shoda zhroucení se zápisem do registru 23) 17. 9. 2026
  • Po MagCalPhase.Written přestat sbírat; další měření začíná s prázdnou sadou
  • Test, že zápis sám verdikt nezmění

plan-vn100-kalibrace.md, MagCalMission.cs, MagCalCollector.cs · DevLog 2026-09-17

FreeRun u jedné hrany bere šířku z mapy bez naučené šířky (vždy výchozí 3 m)

otevřeno vada nalezeno 7. 10. 2026

FreeRun 1. 10. 2026 (20261001-152906.rec, roadwidthmap=true): ve všech 3 285 cyklech mrkve z jedné hrany se šířkou z mapy byla šířka přesně 3,00 m (výchozí roadwidth, mapa tagy width nemá), ačkoli oboustranný koridor měřil p50 3,69 m a naučená šířka se do mapy propisovala. FreeRunMission.MapWidthAt čte RoadNetwork bez překryvu naučené šířky (ARBotRuntime, f848fdf i HEAD). Cílová čára tak ležela 0,75 m od pravého kraje místo ~0,92 m (W/4). Závažnost nízká.

  • Nalezeno při ověření mise-freerun-jedna-hrana 7. 10. 2026
  • Předat FreeRunu šířku s překryvem naučené šířky

mission-freerun.md · DevLog 2026-10-07

Mise by se v depu nezarmovala nikdy — práh rozptylu fixů byl pod šumem GPS

v kódu, na HW neověřeno vada nalezeno 26. 8. 2026 vyřešeno 26. 8. 2026

Armování v depu čeká na okno kvalitních fixů GPS. Navržený práh 1,0 m byl pod nominálním šumem přijímače (σ 1,5 m) a statistika brala největší odchylku, která s délkou okna roste — delší čekání kritérium přitvrzovalo. Teď se měří RMS s prahem 2,5 m; tatáž veličina jde filtru jako sigma jednoho vzorku. Práh je z úsudku, panel naměřený rozptyl vypisuje, takže se má nastavit z prvních běhů na zařízení. Zároveň panel říká, PROČ se nepokračuje (fix nedorazil / nesplňuje kritéria / fixy jsou rozházené). Na Robotouru 19. 9. 2026 armování prošlo pětkrát za 5–6 s (9:29 při 16 družicích a HDOP 1,36; Kolo3a/3b při HDOP 2,71 / 2,15) — práh RMS 2,5 m nebránil, jediné selhání (158 s) bylo HDOP (mise-robotour-depothdop). Naměřený rozptyl (MissionMsg.FixSpreadM, ARBot.Analyze mission tiskne spread=) z těch záznamů zatím nikdo nevyčetl.

  • RMS místo maxima, práh 2,5 m 26. 8. 2026
  • Kvalita fixu a rozptyl okna ve MissionMsg a v panelu 26. 8. 2026
  • Nastavit práh z naměřeného rozptylu na zařízení (vyčíst spread= z Kolo3a/3b)
  • Spodní kotva prahu za volného nebe (gps nad 20261001-144638.rec, stání 83 s, 13–15 družic): odchylka fixu od průměru p50 0,17 m, p90 0,37 m, max 0,56 m — RMS o řád pod prahem 2,5 m; dekorelační čas ~15 s, takže 5s okno armování vidí skoro jedinou realizaci. Podmínky depa mezi budovami to nenahrazuje 7. 10. 2026

robotour-mission.md, rozhodnutí 26. 8. 2026 · DevLog 2026-08-26, 2026-09-19, 2026-10-07

Změna pravidel Robotour 2026 — po vykládce další nakládka místo jízdy do depa

v kódu, na HW neověřeno záměr nalezeno 19. 9. 2026 vyřešeno 19. 9. 2026

Pravidla Robotour dovolují po úspěšné vykládce rozhodnout se pro další nakládku místo návratu do depa, po ní následuje další vykládka a opět volba — dokola. V automatu je to jediný rozdíl: servisní okno u vykládky má zapnutý skener a kód, který tam projde strojovými kontrolami, je místo další nakládky (nextPickupChosen); uvolnění stopu bez kódu znamená „žádná další nakládka, do depa“. Rozlišuje se CodeExpected (kód se přijímá na každém stanovišti) a CodeRequired (bez něj se neodjede — depo a nakládka vrací na AwaitingEStop). Stránka náhledu i UI panel u vykládky hlásí „vyloženo: QR kód DALŠÍ nakládky, nebo uvolnění stopu bez kódu = jízda do depa“ (MissionWait.QrCodeOrRelease, MissionStatusText.WaitFor(phase, stop)); „kód nevidím“ se u vykládky nehlásí. MissionMsg je verze 7 (Deliveries = počet vykládek, NextPickupChosen); PickupLatDeg/DropLatDeg jsou od té doby poslední nakládka/vykládka. Limit vzdálenosti od depa platí i pro další nakládky. Binárka s tím jela ve 4. kole Robotouru 19. 9. (nahraná před startem kola), ale robot k nakládce nedojel (nav-phi-obracena-hrana), takže větev vykládka → další nakládka na zařízení nikdy nenastala; ve 3. kole to software ještě neuměl.

  • Automat: skener u vykládky, kód = další nakládka, uvolnění bez kódu = depo; MissionMsg v7 19. 9. 2026
  • Hlášení na stránce a v UI panelu (QrCodeOrRelease), 3 nové testy, 2 přepsané (Common 1 601, Runtime 140) 19. 9. 2026
  • Průchod vykládka → kód další nakládky → nakládka → vykládka → depo proklikán autorem v Avalonii na virtuálním HW 19. 9. 2026
  • Ověřit na robotu (skutečné kamery, stop tlačítko, stránka náhledu)

robotour-mission.md · DevLog 2026-09-19

Nouzové zastavení v řídicí smyčce a ve firmwaru motorů

hotovo záměr nalezeno 11. 8. 2026 vyřešeno 30. 8. 2026

Stav tlačítka nouzového zastavení tekl do řídicí smyčky už dřív, jen se zahazoval. Smyčka teď pod stopem posílá nulovou rychlost a rotaci nuluje až ve stoje (dobrzdění zůstává řízené), ostatní smyčky běží dál, takže po uvolnění robot plynule pokračuje; do záznamu jde příznak, proč byla nula. Stejné pravidlo se zapsalo i do MicroBasic skriptu řadiče SDC2160 (dřív nuloval rotaci hned, takže brzdil vždy rovně). Skript je zdroj, ne kompilovaný kód, takže se do jednotky nahrává zvlášť — nahrán 30. 8. (značka Version 2.0) a podle autora na robotu ověřen.

  • IsEmergencyStop v ControlLoop, DriveCommandMsg verze 2 12. 8. 2026
  • Skript řadiče upraven na totéž pravidlo (v repu) 12. 8. 2026
  • RizeniDiffPodvozku.mbs dosynchronizován ze skriptu v komentáři 18. 8. 2026
  • Nahrát skript do jednotky (Version 2.0) 30. 8. 2026
  • Ověřeno na zařízení (sdělení autora 17. 9. 2026) 17. 9. 2026

robotour-mission.md, path-following.md · DevLog 2026-08-11, 2026-08-12, 2026-08-18, 2026-08-30

Mise Robotour jako stavový automat s QR kódy

hotovo záměr nalezeno 11. 8. 2026 vyřešeno 19. 9. 2026

Soutěžní scénář depo → nakládka → vykládka → depo: robot dojede, obsluha drží nouzové zastavení, z pravé kamery se přečte QR kód s cílem a po uvolnění stopu se jede dál. Návrh z 11. 8. prošel třemi revizemi (mrkev až na okraj mapy, počátek roviny z mapy, nouzové zastavení řeší řídicí smyčka). Dekodér je nakonec ZXing.Net místo ZBar, potvrzování cíle obsluhou se zrušilo (mise běží bez operátora) a cíl z kódu se přichycuje na cestu. Celý průchod je proklikaný v simulaci a na Robotouru 19. 9. 2026 (Kolo3b) robot poprvé odjel depo → nakládka → vykládka naostro, s čtením QR v každém kole; do depa nedojel kvůli penalizaci hran (nav-phi-obracena-hrana) a nálezy ze soutěže mají vlastní témata mise-robotour-*.

  • Návrh a revize zadání 11. 8. 2026
  • Fáze 2–5: skener QR, parser geo:, automat, MissionMsg, panel UI 26. 8. 2026
  • Průchod misí v simulaci, přichycení cíle na cestu 27. 8. 2026
  • Ověření na zařízení (fáze 7): Robotour 19. 9. 2026, Kolo3b — depo → nakládka (Arrived 14:15:56) → vykládka (14:27:45) → jízda do depa; do depa nedojel (penalizace hran, nav-phi-obracena-hrana) 19. 9. 2026

čeká na Globální navigace po síti cest v runtime, Nouzové zastavení v řídicí smyčce a ve firmwaru motorů · robotour-mission.md, rozhodnutí 26. 8. 2026 (ZXing, bez potvrzování) · DevLog 2026-08-11, 2026-08-12, 2026-08-26, 2026-08-27, 2026-09-20

Mise FreeRun — jízda v pravé polovině koridoru bez mapy

hotovo záměr nalezeno 25. 8. 2026 vyřešeno 7. 9. 2026

Jednodušší mise před Robotourem, pro homologaci a přesun mezi stanovišti: držet se v pravé polovině detekovaného koridoru, překážkám se vyhýbat lokální mapou, bez mapové navigace; když koridor není, držet kurz. Je to jen producent „mrkve" pro existující lokální vrstvu, takže je malá — musela se ale vytáhnout mapově nezávislá část hledání koridoru (CorridorSource). V simulaci se usadí na −0,503 m proti požadovaným −0,500. Mise se vybírá selektorem mission=none|freerun|robotour, protože mise se vylučují. Venku poprvé jela 7. 9. (452 s, ~105 m); robot se přitom plazil, ale to bylo lokální plánování a chybný kurz, ne mise.

  • Implementace, extrakce CorridorSource, měření proti pravdě (dva běhy) 25. 8. 2026
  • Profil config/pi-freerun.cfg pro Orange Pi 1. 9. 2026
  • První jízda venku na zařízení (20260907-170728.rec) 7. 9. 2026

mission-freerun.md · DevLog 2026-08-25, 2026-09-01, 2026-09-07

Zkouška dosažitelnosti cíle z QR kódu nebyla důvěryhodná

hotovo vada nalezeno 26. 8. 2026 vyřešeno 5. 10. 2026

Dvě vady v tom, jak mise posuzuje cíl z kódu. Zkouška byla pesimističtější než jízda: cíl na téže cestě za robotem hlásila jako nedosažitelný, protože mapmatching vybral orientovanou hranu podle pořadí, ne podle kurzu — teď zkouší obě orientace. A dosažitelnost neověřovala vzdálenost cíle od sítě; hůř, navigace měří dojezd proti surovému cíli, takže cíl odsazený od osy cesty víc než o 3 m by nikdy neohlásil dojezd a mise by uvízla napořád. Cíl se proto přichycuje na cestu a co je dál než MaxTargetOffRoadM (15 m, z úsudku) je nedosažitelné; odstup jde do záznamu. Tatáž past se 12. 9. znovu řešila u mise Track. Na Robotouru 19. 9. 2026 dojezd na přichycený cíl z kódu nastal dvakrát (Kolo3b: nakládka 14:15:56, vykládka 14:27:45), takže vada „Arrived by nenastalo nikdy" je na zařízení vyvrácená; cíle byly přesně uzly mapy, k limitu 15 m data nedaly. Zamítnutí NoRoute z Probe na náměstí je jiná věc než NoRoute za jízdy — vede mise-robotour-mapa-ostrov. ✅ **Uzavřeno 5. 10. 2026 (autor: „už není aktuální"):** obě vady jsou opravené a dojezd na přichycený cíl z kódu na zařízení nastal. Dosažitelnost se zkouší **už při čtení kódu** (Probe → zamítnutí s důvodem, obsluha ukáže kód znovu), takže NoRoute za jízdy zbývá jen pro síť změněnou mezitím (uzavřené hrany) a ten misi dál přeruší. Limit 15 m zůstává.

  • Zkouška bere minimum přes hranu i její reverzní (cíl za robotem) 27. 8. 2026
  • Přichycení cíle na cestu, limit MaxTargetOffRoadM, MissionMsg verze 6 27. 8. 2026
  • NoRoute na cíl z QR = neplatný cíl, číst znova (dnes přerušení mise) — neaktuální (autor): nedosažitelný cíl se zamítne už při čtení kódu a čte se znova; NoRoute za jízdy přerušuje dál 5. 10. 2026
  • Nastavit 15 m z odstupů naměřených na zařízení — neaktuální (autor): cíle z kódů na Robotouru byly uzly mapy, limit 15 m zůstává 5. 10. 2026

robotour-mission.md, rozhodnutí 27. 8. 2026, track-mission.md · DevLog 2026-08-26, 2026-08-27, 2026-09-12, 2026-09-20, 2026-10-05

Čtení QR kódů z kamery (ZXing.Net místo ZBaru)

hotovo záměr nalezeno 26. 8. 2026 vyřešeno 19. 9. 2026

Cíl mise Robotour zadává člověk QR kódem. Dekodér je čistě managed ZXing.Net — binding ZBaru z ARBot2 nebyl k dispozici, a tím celá plánovaná fáze „nativní libzbar na obě platformy" zmizela. Skener je samostatný stupeň, který mise zapíná jen pod drženým stopem; převod na šedou se zobecnil na Image<T>.ToGray. Aby šel průchod misí projít v simulaci, umí virtuální kamera postavit svislou desku s kódem (jen do barvy, ne do hloubky). Z 1,2 m se kód nepřečetl, staví se na 1,0 m. Testy dokazují cestu, ne čitelnost, protože kód kóduje týž ZXing. Na skutečném stanovišti se četlo poprvé na Robotouru 19. 9. 2026 — až po opravě jména kamery (mise-qr-jmeno-kamery): 20260919-100414.rec 2 QrCodeMsg a kód přijat, -101057 535, -101903 195, kódy z mobilu, notebooku i papíru; offline živý dekodér čte 725 z 3 957 snímků. Doba dekódování se neměří (QrScanner čas nebere, QrCodeMsg ho nenese) — pod drženým stopem je z velké části mimo hru.

  • QrScanner + QrCodeMsg, dekodér ZXing.Net, převod BGR32 → Y800 26. 8. 2026
  • QR kód do virtuální kamery (SyntheticBillboard), test scéna → render → dekodér 26. 8. 2026
  • Deska kolmo na pohled kamery a na 1,0 m (z 1,2 m se nepřečte) 27. 8. 2026
  • Úspěšnost čtení na skutečném stanovišti (Orange Pi, D435) — Robotour 19. 9.: kód čten a přijat v každém kole 19. 9. 2026
  • Doba dekódování na Orange Pi — škrtnuto rozhodnutím autora 21. 9. (pod drženým stopem nerozhoduje) 21. 9. 2026

robotour-mission.md, rozhodnutí 26. 8. 2026, virtual-hw.md · DevLog 2026-08-26, 2026-08-27, 2026-09-19

Mise Robotour běží bez operátora — potvrzování cíle zrušeno

hotovo záměr nalezeno 26. 8. 2026 vyřešeno 19. 9. 2026

Úloha je simulace autonomního doručení: s robotem interagují jen odesílatel a odběratel, a to pouze QR kódem a stop tlačítkem. Potvrzovací tlačítko v panelu modelovalo někoho, kdo v úloze není, proto se zrušilo. Uvolnění stopu je od té doby plnohodnotný signál („vyloženo", nebo „člověk odešel" bez přečteného kódu); robot nikdy neodjede bez cíle a zamítnutý kód má viditelný důvod. Celý průchod misí autor proklikal v simulaci 27. 8.; na Robotouru 19. 9. 2026 (Kolo3b) robot odjel depo → nakládka → vykládka bez operátora: kód v depu i na nakládce, uvolnění stopu po vykládce jako signál „vyloženo".

  • Zrušit potvrzování, uvolnění stopu jako signál, MissionMsg verze 5 26. 8. 2026
  • Důvod zamítnutí kódu ve zprávě a v panelu (nesrozumitelný / daleko / bez trasy) 26. 8. 2026
  • Průchod misí v simulaci proklikán autorem 27. 8. 2026
  • Celý průchod bez operátora na zařízení (Robotour 19. 9. 2026, Kolo3b) 19. 9. 2026

robotour-mission.md, rozhodnutí 26. 8. 2026 · DevLog 2026-08-26, 2026-08-27, 2026-09-20

Panel mise Robotour a nouzové zastavení v simulaci

hotovo záměr nalezeno 26. 8. 2026 vyřešeno 27. 8. 2026

Ovládací panel mise (fáze, na co se čeká, přečtený kód s odvozeným cílem, čítače, Start / Přerušit) čte stav ze zpráv, takže funguje i při přehrávání záznamu. Bez nouzového zastavení ve virtuálních motorech se servisní okno v simulaci nedalo projít vůbec — přibylo červené tlačítko stopu. Autor panel používal a během dvou dnů nahlásil řadu vad: panel tvrdil „mise neběží" (runtime si stupeň uložil dřív, než vznikl), čas mise 6·10¹⁰ s, deska s kódem mizela hned po postavení, kód zkosený, nečitelná tlačítka, kamera zmizela dokumentům mimo hlavní dok (obecná vada IsActive). Vše opraveno a 27. 8. proklikáno („vše funguje jak má").

  • Panel *Tools → Mise Robotour*, stop tlačítko ve virtuálních senzorech 26. 8. 2026
  • 'Opravy z používání: stupeň hledat znovu, čas mise, deska s kódem, náhled kamery, styl tlačítek' 26. 8. 2026
  • IsActive pro dokumenty mimo DocumentDock, tlačítka s hotovými kódy, stop jako červené tlačítko 27. 8. 2026

robotour-mission.md, Views/README.md · DevLog 2026-08-26, 2026-08-27

Robot si kalibraci magnetometru změří sám z telefonu (mission=magcal)

hotovo záměr nalezeno 8. 9. 2026 vyřešeno 12. 9. 2026

Místo notebooku v poli: robot stojí, obsluha s ním otáčí rukou, stránka náhledu říká, co ještě chybí, a po ťuknutí pod drženým nouzovým zastavením se kalibrace zapíše do registru 23 a do flash. Práh podmíněnosti byl odhadnut o pět řádů mimo, náklony musí být na obě strany, sklon se počítal ve špatném rámci, a proložení všech vzorků by misi po minutě zadusilo (plná SVD) — vyřešeno ředěním na 1 500 vzorků. První výjezd 10. 9. našel tři vady (verdikt byl diagnóza, ne pokyn; koše podle velikosti odklonu; chyběla mapa pokrytí), druhý týž den dal použitelnou kalibraci, zapsanou 11. 9. a ověřenou 12. 9. Od 12. 9. si mise registr 23 před sběrem sama vymaže, jinak by druhé spuštění dobrou kalibraci přepsalo — to na senzoru neběželo. Vymazání registru 23 před sběrem (12. 9.) je samostatné téma a na senzoru ještě neběželo.

  • Fáze 1 — MagCalFit, pokrytí, kolektor, mise, registry, ARBot.Analyze magcal 8. 9. 2026
  • Výkon proložení (ředění na MaxFitSamples, podmíněnost invariantní) 8. 9. 2026
  • První výjezd — tři vady opraveny (koule, mapa pokrytí 24×5, verdikt jako pokyn) 10. 9. 2026
  • Sklon vyřazen z brány (rozhodnutí autora), kalibrace použitelná 10. 9. 2026
  • Zápis do senzoru a ověření venku 12. 9. 2026

plan-vn100-kalibrace.md, plan-vn100-kalibrace-kroky.md, imu-and-frames.md, rozhodnutí 10. 9. a 12. 9. 2026 · DevLog 2026-09-08, 2026-09-10, 2026-09-11, 2026-09-12

Mise Track — objezd míst ze souboru

hotovo záměr nalezeno 8. 9. 2026 vyřešeno 29. 9. 2026

mission=track track=<cesta>: řádek = místo ve stupních, repeat = jezdit dokola. Každé místo se přichytí na nejbližší bod sítě cest — a to je oprava vady, ne kosmetika, protože dojezd se měří proti surovému cíli a mise by jinak u prvního bodu uvízla navždy. Bod dál než trackoffroad= misi přeruší, nesrozumitelný řádek je chyba, mezi body se nezastavuje a volba mise robota nerozjede (čeká na stisk a uvolnění nouzového zastavení). V simulaci objela tři místa a začala druhé kolo. Od 13. 9. se všechna místa přichycují předem při odjezdu, seznamy leží u map v OSM/. Na zařízení odjela 12. a 14. 9. (13 min, k prvnímu bodu 44 m za 9,5 minuty, běh z 17:06 skončil NoRoute); celý seznam neobjela. 17. 9. 2026 poprvé DOJELA na místo: trasa 147 m k bodu 1/3 za 3 minuty (16:06:51 → 16:09:53), pak si vzala cíl 2/3 (trasa 37 m) a obsluha ji v 16:11:37 zastavila ze stránky. Přichycení všech tří míst předem proběhlo (největší odstup 2,1 m z limitu 50 m). Jelo se to ale s rozbitým kurzem (viz hw-zelezo-od-kabelu-kamer), takže o chování mise po kalibraci to neříká nic. Druhý běh téhož dne zatuhl 4 s po odjezdu (prov-zatuhnuti-za-behu-mise). ✅ **18. 9. 2026 seznam poprvé objetý celý, i s repeat** (20260918-154028.rec: 3 místa za 5 min, druhé kolo za 2,5 min, s korekcemi z koridoru naostro); třetí kolo skončilo stáním před blokovanou mapou (lp-zasek-v-blokovane-mape). Druhý běh (-155329.rec): 5 míst za 8 min, k prvnímu bodu 93 m za 4 min, z toho 130 s stání po startu. Jízdy 18. 9. jely ještě s chybou φ (nav-phi-obracena-hrana, opraveno 20. 9.); dopad na Track měřený není. Mise sama je na zařízení hotová; poslední dva drobné kroky uzavřeny 29. 9. 2026: trackoffroad=50 je volba autora (neměří se) a nezaložená mise se hlásí na stránce (ověřeno v headless simulaci; autor: ověření na Pi není potřeba).

  • TrackPlan, TrackMission, TrackMsg, parametry, 36 testů 8. 9. 2026
  • Projeto v simulaci (tři místa + druhé kolo) 8. 9. 2026
  • Seznamy *.track přesunuty k mapám do OSM/ 12. 9. 2026
  • Projet celou misi na zařízení — 18. 9.: dvě celá kola (6 míst za 5 min) včetně repeat, ve druhém běhu 5 míst za 8 min 18. 9. 2026
  • První dojezd na místo na zařízení (17. 9., bod 1/3 po trase 147 m za 3 min) 17. 9. 2026
  • První jízdy na zařízení (12. 9., 14. 9.) — k prvnímu bodu dojela, seznam neobjela 14. 9. 2026
  • trackoffroad= nastavit z naměřených odstupů (údaj je v záznamu), ne z úsudku — autor 29. 9. 2026: 50 m je jeho volba, není co měřit 29. 9. 2026
  • Hláška na stránce, když je mission=track bez track= (dnes se mise tiše nezaloží). Reprodukováno v headless simulaci (výběr track ze stránky → 200 „mise track spustena“, runtime se přestavěl se záznamem, stránka „mise: žádná“ a volbu už nenabízela). Léčba: výběr ze stránky se bez použitelného track= odmítne hned (409 s důvodem, ARBotRuntime.MissionPickProblem, sdílí kontrolu se Start); nezaložená mise z příkazové řádky / profilu se na stránce ukáže červeně „NEZALOŽENA — důvod“ (MissionNotCreatedReason, JSON missionFailed, platí pro všechny mise). Opraveno i nenulování TrackMission při přestavbě runtime. 3 nové testy; ověřeno v headless obě cesty včetně vykreslení stránky; na Pi ověřovat netřeba (autor) 29. 9. 2026

track-mission.md · DevLog 2026-09-08, 2026-09-12, 2026-09-13, 2026-09-14, 2026-09-17, 2026-09-18, 2026-09-29

Mise Track přichycuje všechna místa na síť předem, při odjezdu

hotovo záměr nalezeno 13. 9. 2026 vyřešeno 17. 9. 2026

Mise Track přichycovala místa na síť cest až ve chvíli, kdy na ně přišla řada — se seznamem, jehož druhé místo leží mimo síť, robot odjel na první a misi přerušil daleko od člověka. Teď se všechna místa přichytí a zkontrolují při odjezdu (ne už při volbě mise: tam bez pózy kontrola vracela nuly a tiše prošla i pro bod 372 m od cesty), TrackMsg verze 3 nese přichycené souřadnice a zóny na půdorysu se kreslí z nich, ne ze surových bodů. Autorem hlášený zásek po uvolnění nouzového zastavení se v simulaci nereprodukoval; reprodukoval se jiný — simulace nad velkou mapou (3 771 uzlů) vyčerpá CPU renderem virtuální kamery a stránka umlkne, takže simulace není měřítko výkonu robota. Na zařízení přichycení proběhlo 17. 9. (tři místa, největší odstup 2,1 m z limitu 50 m) a 18. 9. při dvou celých kolech. Hlášený zásek se 17. 9. reprodukoval na zařízení (týž příznak: stránka odpovídá, čas v ní neběží) a má vlastní témata prov-zatuhnuti-za-behu-mise a prov-deadlock-mise-webstatus — s přichycením nesouvisí.

  • Přichycení všech míst v Depart, rozlišení „odstup 0“ od „nepřichyceno“ 13. 9. 2026
  • TrackMsg verze 3 s přichycenými místy; zóny kreslené z nich 13. 9. 2026
  • Hlášený zásek po uvolnění stopu — 17. 9. reprodukován na zařízení, vede prov-zatuhnuti-za-behu-mise / prov-deadlock-mise-webstatus 17. 9. 2026
  • Ověřit na zařízení — 17. 9. tři místa přichycena (odstup ≤ 2,1 m), 18. 9. dvě celá kola 17. 9. 2026

track-mission.md, headless.md · DevLog 2026-09-13, 2026-09-17, 2026-09-18

Skener QR na robotu nedostal jediný snímek — jméno kamery „Right" vs. „Right 740112071021"

hotovo vada nalezeno 19. 9. 2026 vyřešeno 19. 9. 2026

Na soutěži 19. 9. 2026 robot v misi Robotour kód nepřečetl (records/test/20260919-092933.rec): automat byl 239 s ve fázi Servicing pod drženým stopem, skener zapnutý, a v záznamu není ani jedna QrCodeMsg. Kód přitom v obraze BYL — offline dekodér nad týmiž snímky ho čte v 725 z 3 957 (obě kamery, dva různé geo: texty). Příčina: skutečná D435 se jmenuje Right 740112071021 (driver skládá název a sériové číslo), kdežto QrScannerConfig.CameraName je Right a porovnávalo se celé jméno — virtuální kamera vrací holý název, takže simulace i všech 19 testů procházely a na robotu skener nikdy nedostal snímek. Druhá past téhož dne: stránka náhledu kreslila PRVNÍ kameru ve slovníku (levou), takže obsluha podle telefonu ukazovala kód levé kameře, zatímco se četlo z pravé. Léčba: jméno kamery se bere jako první slovo (QrScanner.CameraMatches), stránka kreslí tu kameru, ze které se čte QR, a říká to v řádku „na obrázku (čte QR)". Nouzové obejití bez nové binárky: qrcamera= (prázdné = všechny kamery) v profilu. Měří to nový ARBot.Analyze mission. Oprava byla nasazená před 1. kolem a od 10:04 se kód na robotu čte (535 čtení v 10:11 proti 2 v 10:04 říká, že obsluha od té doby ukazovala kód správné kameře); řádek „na obrázku (čte QR)" autor na stránce v terénu viděl (potvrzeno 21. 9.).

  • Rozbor ARBot.Analyze mission: časová osa fází a stopu, servisní okna, snímky živým dekodérem 19. 9. 2026
  • QrScanner.CameraMatches — shoda na první slovo jména (2 testy, 21 QR testů zelených) 19. 9. 2026
  • Stránka náhledu kreslí kameru, ze které se čte QR (WebStatus.PreferredCameraName), a hlásí ji 19. 9. 2026
  • Čtení kódu na robotu: 20260919-100414.rec 2 QrCodeMsg a kód přijat, -101057 535, -101903 195 19. 9. 2026
  • Ověřit na robotu, že stránka kreslí kameru, ze které se čte QR — autor řádek „na obrázku (čte QR)" na soutěži viděl 19. 9. 2026

robotour-mission.md, headless.md · DevLog 2026-09-19

Mise se v depu nezarmovala — práh HDOP 2,0 mezi budovami nesplnitelný

hotovo vada nalezeno 19. 9. 2026 vyřešeno 19. 9. 2026

Na soutěži 19. 9. 2026 stála mise Robotour 158 s v ArmingAtDepot (20260919-101546.rec), stránka ukazovala „sigma 60–70 m“. Ta sigma je gpsposstd × HDOP, tedy nejistota pro fúzi, ne kritérium mise: to je fix + ≥ 6 družic + HDOP ≤ 2,0 nepřerušeně 5 s, pak RMS rozptyl ≤ 2,5 m. Mezi budovami byl HDOP 1,74–2,95 (p50 2,30, p90 2,50) při 12–16 družicích, prahu 2,0 vyhovovalo 4,7 % fixů a nejdelší nepřerušená série byla 3 s; s prahem 3,0 vyhovuje 100 % fixů obou ranních záznamů. Práh je teď parametr depothdop= (default 2,0 z RobotourConfig se nemění), provozní profil pi-provoz.cfg má 3,0 — rozptyl polohy hlídá MaxSpreadM dál. Měří to blok 1b ARBot.Analyze mission (percentily HDOP, % vyhovujících fixů, nejdelší série pro 2,0 / 2,5 / 3,0 / 4,0).

  • Blok 1b v ARBot.Analyze mission: kvalita fixu v ArmingAtDepot proti kritériu mise 19. 9. 2026
  • Parametr depothdop= (registr, runtime, pi-provoz.cfg = 3,0) 19. 9. 2026
  • Ověřeno na robotu (Robotour, Kolo3a/Kolo3b): armování prošlo za 5 s s HDOP 2,71 (6 družic) a 2,15 19. 9. 2026

robotour-mission.md, configuration.md · DevLog 2026-09-19

Kód se četl a mise ho zamítala „nevede trasa“ — robot stál na náměstí spojeném se sítí jen schody

hotovo vada nalezeno 19. 9. 2026 vyřešeno 6. 10. 2026

Na soutěži 19. 9. 2026 (20260919-101057.rec, -101903.rec) se QR kód četl (535 a 195 QrCodeMsg), ale mise ho pokaždé zamítla hláškou „na cíl nevede po síti žádná trasa (je mimo mapu?)“ — a stránka náhledu dál psala „čeká se na QR kód“, takže obsluha myslela, že se kód nečte. Cíl 50.1038082,14.4240751 je přitom přesně uzel mapy na živé footway. Rozbor proti MapMsg a GlobalNavMsg ze záznamu: síť Robotour2026-ver1.osm má pod profilem Robot 2 komponenty souvislosti; ostrov je jediná cesta 956523901 (highway=pedestrian + area=yes, dlážděné náměstí, 40 uzlů, 139 m) spojená se sítí jen highway=steps (uzly 8852424426 a 8852424425, 0,9 m od sebe) — a schody profil Robot nepouští. Robot při zamítnutí stál 3–4 m od uzlu ostrova. Probe odpověděl podle grafu správně, ale hláška posílala člověka hledat chybu jinam a stránka ji neukázala. V 10:04 týž kód projel, protože robot stál o 50 m dál na chodníku. Léčba v kódu: řádky „QR kódy“ a „kód ZAMÍTNUT“ na stránce, hláška „z místa, kde robot stojí … síť rozpojená“, nový ARBot.Analyze route a blok 1c v mission. Ostrov je podle autora skutečný (robot tam nevyjede, GPS ho tam jen posadila), takže se neopravuje mapa, ale načtení: mapprune= (výchozí true, NetworkIslands) zahodí všechny komponenty kromě té s největší délkou cest v metrech (ne podle počtu uzlů, ne podle toho, kde robot stojí — právě ta póza je z chybné GPS). Offline z pózy na náměstí se póza přichytí na chodník 2,4 m vedle a cíl je dosažitelný (393 m). Co se zahodilo, jde do Trace; mapprune=false vrátí síť. Nasazeno před 2. kolem (11:37): robot startoval ze servisní zóny, kde se v 10:11 a 10:19 kódy zamítaly, a kód přečetl a přijal — stejně ve 3. a 4. kole. Je to nepřímý důkaz, že mapprune na zařízení účinkoval; Trace „ZAHOZENO 1" z Kolo2.rec nikdo nevyčetl a GPS mohla robota posadit jinam. Zobrazení zamítnutí na stránce ověřit nešlo — po nasazení žádné zamítnutí nenastalo. **Uzavřeno 6. 10. 2026 (autor):** ostrovy se při načtení zahazují, takže tuhle situaci už ani nejde vyzkoušet; zobrazení zamítnutí na stránce zůstává na zařízení neověřené.

  • Rozbor ARBot.Analyze route (komponenty, cesty ostrova, nejbližší dvojice uzlů) a blok 1c v mission 19. 9. 2026
  • Stránka náhledu ukazuje počet přečtených/zamítnutých kódů a důvod zamítnutí 19. 9. 2026
  • Hláška zamítnutí říká, že trasa nevede z místa, kde robot stojí, a že síť může být rozpojená 19. 9. 2026
  • Ostrovy sítě zahodit při načtení mapy (mapprune=, NetworkIslands, 5 testů); route z náměstí: dosažitelné 393 m 19. 9. 2026
  • Přijetí kódu z náměstí po nasazení — 2., 3. a 4. kolo kód přijat ze servisní zóny (Trace „ZAHOZENO 1“ v Kolo2.rec nevyčteno) 19. 9. 2026
  • Zobrazení zamítnutí na stránce na robotu (po nasazení žádné zamítnutí nenastalo) — uzavřeno bez ověření (autor 6. 10. 2026): ostrov se dnes při načtení odstraní, takže to už nejde vyzkoušet 6. 10. 2026

robotour-mission.md, osm-nav.md · DevLog 2026-09-19, 2026-09-20

FreeRun jede ~0,8 m/s při povolených 1,7 — plán končí v mrkvi 1,5 m před robotem a regulátor k ní brzdí

hotovo vada nalezeno 25. 9. 2026 vyřešeno 30. 9. 2026

Pozorování autora z FreeRun 25. 9. 2026 (records/test/20260925-144658.rec, 23 min, Modřany): robot jede výrazně pomaleji, než je maxspeed=1.7. Potvrzeno měřením: příkaz p50 **0,81 m/s**, rychlost fúze 0,78 m/s. Mrkev leží vždy freerunlook= = **1,5 m** před robotem a plán končí v ní; plánovač bere konec dráhy jako hranici potvrzeně sjízdného (BuildWayPoints: frontier se inicializuje na konec dráhy, poslední uzel má strop 0), takže obálka VBrake váže 97,4 % plánů na √(2·0,5·1,5) = **1,22 m/s**. Regulátor z toho udělá ještě méně: Dist2Speed k poslednímu uzlu (diskrétní profil s rezervou 0,9) dá p50 0,855 m/s, a vazba dopředné rychlosti na dobu rotace d/(4·T_rot) má ve jmenovateli tutéž krátkou vzdálenost, takže srazí rychlost v 35 % taktů (p50 o 0,17 m/s). Protifakticky bez brzdění na konci plánu by příkaz byl p50 0,90, p90 1,35 m/s. Pro srovnání Track téhož dne (20260925-143643.rec): mrkev ~5,6 m, příkaz p50 **1,70 m/s**, vazba na rotaci jen v 11 % taktů. Měří ARBot.Analyze drive (rekonstrukce PathResult.Control sedí na záznam v 99,9 % taktů) a envelope. Ve FreeRun navíc vznikl oboustranný koridor jen ve 3 % cyklů, zbytek jel „rovně“ (lok-koridor-siroka-cyklostezka).

  • Změřeno: obálka VBrake k mrkvi 1,5 m + Dist2Speed k poslednímu uzlu + vazba na rotaci přes krátkou vzdálenost (ARBot.Analyze drive, envelope) 25. 9. 2026
  • Léčba (autor): freerunlook=3 v config/pi-provoz.cfg (strop obálky ~1,73 m/s, ale pevný bod Compute při 3 m je ~1,3 m/s — viz lp-regulator-kmitani-rotace); prodloužení hranice potvrzeného za průjezdní mrkev v kódu zatím ne 25. 9. 2026
  • Jízda FreeRun s léčbou: drive / envelope / localplan nad záznamem — autor 30. 9.: ověřeno OK. FreeRun 29. 9. (20260929-151634.rec, freerunlook=5, profil latency): mrkev p50 5,09 m, příkaz p50 **1,67 m/s** (drive, takty za jízdy; 25. 9. 0,81), rychlost fúze p50 1,49 m/s, strop obálky p50 1,44 m/s, vazba na rotaci srazila rychlost ve 27 % taktů (25. 9. 35 %) 30. 9. 2026

mission-freerun.md, path-following.md · DevLog 2026-09-25, 2026-09-30

FreeRun jel 97 % času rovně podle kurzu — koridor z obou hran skoro nevznikal, jednu hranu mise ignorovala

hotovo vada nalezeno 26. 9. 2026 vyřešeno 7. 10. 2026

Pozorování autora z FreeRun 25. 9. 2026 (records/test/20260925-144658.rec, Modřany): mrkev byla ve směru robotu, ne v koridoru. Změřeno: mrkev z koridoru jen u 578 z 22 646 cyklů (3 %), zbytek NoCorridor / NoPair. Oboustranný koridor vznikl ve 2,7 % snímků (corridormininliers=25; při 20 by to bylo 28 % se šířkou p50 3,61 m), **jedna hrana v 86 %** (pravá 65 %, levá 21 %) a její směr proti GPS kurzu p50 0,24°, p90 5° (ARBot.Analyze singleedge). CorridorSource jednu hranu poznal (SingleEdgeUsable), ale FreeRun ji záměrně nebral s tím, že z ní nevznikne šířka ani příčná poloha. **Léčba (autor):** příčná poloha vůči hraně je změřená; se šířkou z mapy (blízká a rovnoběžná cesta) mrkev do středu pravé poloviny jako u koridoru, bez ní ve směru hrany se zachovaným odstupem. freerunsingle= (výchozí true), FreeRunMsg verze 2, 13 testů.

  • Změřeno: 3 % mrkví z koridoru, jedna hrana v 86 % snímků (freerun, corridor, singleedge) 26. 9. 2026
  • Mrkev z jedné hrany (šířka z mapy / zachovaný odstup), freerunsingle=, FreeRunMsg v2, rozpad v ARBot.Analyze freerun 26. 9. 2026
  • Jízda FreeRun na zařízení: podíl mrkví z koridoru / jedné hrany / rovně (freerun), jestli robot drží pravou polovinu. Částečně 29. 9. (20260929-151634.rec, Modřany na jih, 395 s): mrkev **z jedné hrany v 70 %** cyklů (4 603, z toho 2 764 se šířkou z mapy), rovně podle kurzu 30 %, z koridoru 12 cyklů (25. 9.: 3 % koridor, 97 % rovně). Měření koridoru z jedné hrany jsou převážně z pravé (285 z 306 přijatých). Zbývá pravá polovina: freerun hodnotí odchylku od požadované čáry jen u mrkví z koridoru (12 cyklů), pro jednu hranu to neměří. ✅ **1. 10. 2026** (20261001-152906.rec, Modřany, 602 s, binárka f848fdf): mrkev z koridoru 60,7 %, z jedné hrany 30,1 % (pravá 3 174, levá 195), rovně 9,2 %. Robot drží pravou polovinu: u koridoru příčně p50 −0,99 m od osy při šířce 3,69 m (odchylka od čáry p50 −0,10 m, vlevo od osy jen 0,3 %), u pravé hrany p50 0,79 m od pravého kraje (v pravé polovině 99,3 % cyklů). Měřeno toutéž kamerou, která mrkev klade (scratch nad FreeRunMsg v2), nezávislá pravda chybí; mapová šířka u jedné hrany byla vždy výchozích 3,00 m (mise-freerun-sirka-bez-naucene) 7. 10. 2026
  • corridormininliers=20 v config/pi-provoz.cfg (autor): oboustranný koridor 2,7 → 28 % snímků v témž záznamu 26. 9. 2026

mission-freerun.md · DevLog 2026-09-26, 2026-09-29, 2026-10-07

Timeout jízdy k místu Tracku (600 s) je kratší, než trvá první úsek v Modřanech

hotovo vada nalezeno 26. 9. 2026 vyřešeno 30. 9. 2026

Track 25. 9. 2026 (20260925-142428.rec, OSM/modrany2.track): mise skončila 14:34:39 „timeout jizdy k mistu 1/2 (limit 600 s)". Trasa k prvnímu místu měla na startu **1 118 m**; při ~1,66 m/s je to ~670 s, tedy přes limit i bez jediného zdržení. TrackConfig.DrivingTimeoutSec je pevných 600 s (a jako parametr nejde nastavit), kdežto délka úseku se mezi seznamy liší řádově.

  • Timeout vypnut (autor): TrackConfig.DrivingTimeoutSec = 0, stejně jako u Robotouru; zaseknutí hlídají detektory GlobalNavigator 26. 9. 2026
  • Ověřeno na zařízení (autor 30. 9. 2026) 30. 9. 2026

track-mission.md · DevLog 2026-09-26, 2026-09-30

Vizuální dojezd posledních metrů podle QR kódu

zamítnuto záměr nalezeno 12. 8. 2026 vyřešeno 5. 10. 2026

Mise Robotour jede na cíl z GPS, jejíž chyba ±2 m je pro „zastav u kódu" na hraně použitelnosti — stanoviště se proto bere jako zóna o dojezdovém poloměru 3 m, ne bod. Poslední ~3 m by šly řídit podle vidění: rohy QR kódu v obraze dávají směr i vzdálenost a robot by dojel ke kódu, ne k místu, kde ho GPS tuší. Zapsáno při návrhu globální navigace a mise Robotour v srpnu 2026 jako budoucí rozšíření; kód ani měření nevznikly. ❌ **Zamítnuto 5. 10. 2026 (autor): takhle Robotour nefunguje.** QR kód při příjezdu v obraze není — obsluha ho ukazuje (z mobilu nebo vytištěný na papíře) až **zastavenému** robotu, a mise ho v souladu s tím čte jen ve stavu Servicing pod drženým nouzovým zastavením. Není tedy k čemu dojíždět. Kdyby se ukázalo, že stanoviště je menší než chyba dojezdu, léčbou je přesnější lokalizace, ne vidění kódu.

global-navigation-runtime.md, robotour-mission.md, RobotourMission.cs, rozhodnutí 5. 10. 2026 · DevLog 2026-10-05

Oblast

Provoz na zařízení

Měření výkonu řízení — stíhá řídicí smyčka svou periodu?

otevřeno záměr nalezeno 1. 9. 2026

Do té doby nešlo z běhu poznat, jestli řídicí smyčka stíhá svých 10 taktů za sekundu. Měření sedí ve scheduleru (jediné místo, které zná plánovaný i skutečný čas taktu): obsazenost periody, zpoždění a zameškané takty, fronty a zahozené zprávy stupňů, CPU procesu — jednou za sekundu jako PerfMsg do proudu, tedy do UI i do záznamu, a panel Tools → Výkon (perf=, práh perfwarn=). První měření hned našlo zameškané takty na Windows (samostatné téma). Na zařízení PerfMsg chodí do záznamu od 4. 9. Fáze 3 (teplota, frekvence, CPU stroje přes HAL) se nezačala; perfwarn je pořád odhad. **Fáze 4 hotová 7. 10. 2026 (ARBot.Analyze perf) a první rozbor ze zařízení:** Track 1. 10. obsazenost periody AVG p50 3,4 %, MAX p99 12,8 % (max 25,3 %), žádná sekunda ≥ 50 %, takže perfwarn=70 nikdy nedoběhne; červený verdikt dělají výhradně zameškané takty (48 % sekund v Tracku, 25 % ve FreeRunu, 19 % 29. 9.) a ty nejsou z práce taktu, ale z fáze časovače (prov-zameskane-takty-windows). CPU procesu p50 20,5 %, max 31,6 %. LocalNavigator zahodil 83 snímků (0,09 %), avg 9,9 ms. Blok „mezery v proudech" našel zásek celého procesu (prov-zasek-procesu-1s) a souběžné výpadky obou kamer (hw-d435-vypadky-za-provozu). RoadWidthMapUpdater zahodil 1 295 zpráv (0,18 %) — neověřeno, jestli je to záměr.

  • Fáze 1–2 — měření ve Scheduleru, PerfCollector, PerfMsg, panel Výkon, 23 testů 1. 9. 2026
  • PerfMsg v záznamu ze zařízení (headless, Orange Pi) 4. 9. 2026
  • Fáze 3 — teplota, frekvence, CPU stroje, CPU čas taktu (přes HAL)
  • Fáze 4 — ARBot.Analyze perf nad záznamem (souhrn, po minutách, nejhorší intervaly, stupně, jádra, mezery v proudech z indexu a souběžné výpadky kamer); spuštěno nad 1. 10. a 29. 9. 7. 10. 2026
  • Nastavit perfwarn z měření na Orange Pi (dnes odhad 70 %). Data jsou: obsazenost MAX p99 12,8 %, max 25,3 % (Track 1. 10.), FreeRun max 17,0 % — rozhodnutí autora

perf-monitoring.md, plan-perf-monitoring.md · DevLog 2026-09-01, 2026-09-04, 2026-09-05, 2026-10-07

Řídicí smyčka zamešká takty (Windows 3–4/s, Orange Pi ~1/s), ačkoli práce trvá pod 1 ms — fáze časovače proti mřížce plánu

otevřeno vada nalezeno 1. 9. 2026

První měření nového panelu Výkon hned něco našlo: v simulaci na Windows scheduler nestihne 3–4 takty za sekundu a zpoždění jde až na 108 ms při periodě 100 ms, přestože vlastní práce taktu trvá pod milisekundu. Brzdí tedy časovač, ne řídicí kód. Padla tím podmínka, kterou si spec kladla pro dva odložené nálezy (dohánění zameškaných taktů, krok rampy dobrzdění z periody). Nic se neopravuje: číslo je z Windows, kde hrubé rozlišení časovače stačí jako vysvětlení; první krok je přeměřit totéž na Orange Pi a podle toho nastavit perfwarn. **Přeměřeno na Orange Pi 7. 10. 2026 a vysvětlení „hrubý časovač Windows" neplatí:** Track 1. 10. má zameškaný takt v 48 % sekund, FreeRun ve 25 %, 29. 9. v 19 %, vždy při obsazenosti periody p99 ≤ 13 %. Mechanismus (z T_in/T_out DriveCommandMsg): Scheduler kotví mřížku na první pumpu a System.Threading.Timer se stejnou periodou tiká ±2 ms kolem jejích bodů, takže takt vyjde buď za ~3 ms, nebo o celou periodu (~100 ms) pozdě — a fáze mezi oběma režimy přeskakuje (v Tracku cyklus ~4 min). Po záseku procesu 15:15:43 se fáze posunula na +32 ms a do konce (12,7 min) nebyl zameškaný ani jeden takt. **Skutečný dopad není „zameškaný takt", ale latence:** ve FreeRunu běželo 94,5 % taktů ~100 ms pozdě (řízení ze stavu GetStateAt(tk) o 0,1 s staršího), ačkoli červených sekund bylo jen 25 % — MissedTicks a verdikt to nevystihují, DelayAvg ano.

  • Změřit v simulaci na Windows 1. 9. 2026
  • Přeměřit totéž na Orange Pi (ARBot.Analyze perf, 20261001-144638.rec, -152906.rec, 20260929-150844.rec; mechanismus z T_in/T_out DriveCommandMsg): fáze časovače proti mřížce, viz popis 7. 10. 2026
  • Rozhodnout (autor): kotva mřížky s odsazením nebo tolerance v PumpDue, dohánění zameškaných taktů; případně do PerfMsg přidat fázi pumpy proti mřížce

perf-monitoring.md, plan-perf-monitoring.md · DevLog 2026-09-01, 2026-10-07

Nativní pád (SIGSEGV) při zastavování runtime je častý

otevřeno vada nalezeno 14. 9. 2026

V reprodukčním testu (32 kol volba mise → stop → restart) proces 12× spadl nativně při Stop(); dvě další SIGSEGV při Stop() přišly týž den za provozu. CrashLog nativní pád nezachytí, takže po něm nezůstane stopa. Příčina se nehledala; s vypnutým start-limitem je důsledek restart služby, ne trvalé odstavení, ale pád při každém druhém zastavení zůstává.

headless.md · DevLog 2026-09-14

Runtime zatuhl 4 s po odjezdu mise Track a hlídač ho nechytil

otevřeno vada nalezeno 17. 9. 2026

Runtime naběhl, senzory i řídicí smyčka běžely, v 16:12:38 obsluha uvolnila nouzové zastavení, mise Track odjela (přichytila 3 místa, cíl 1/3, trasa 50 m) — a do 20 ms po té hlášce přestaly proudit všechny zprávy najednou: IMU v 4,074 s záznamu, motory 4,078, GPS 4,068, obě kamery, řídicí smyčka i koridor. Dál žilo jediné vlákno — dotazování odpojené T265, jehož hlášky tekly do záznamu ještě 140 s. Stránka podle obsluhy odpovídala, ale čas v ní neběžel, což s tím sedí: web i zapisovač záznamu byli naživu, produkce dat ne. Zásek NENÍ v ovladačích, a je to změřené: vlákno T265 je taky SensorBase a běželo dál. Jediné, čím se od ostatních liší, je, že nic nepublikuje (dotaz vždy selže a jen loguje) — všechna vlákna, která publikují, stojí. Info z TraceInfoBridge jde přímo na Stream, kdežto měření jdou navíc přes RoleRouter do processing (RelaySource, fan-out na vlákně producenta), a právě ta větev je společná všemu, co umlklo. Konkrétní blokující odběratel ze statického čtení vidět není (stupně mají vlastní frontu DropOldest, RecordingTarget je DropNewest, takže žádný Post blokovat nemá), takže dál se pohne až ze zásobníků vláken. HangWatchdog nevystřelil, protože hlídá jen Start(Mode.Run) — ten skončil o 4 s dřív a token byl zahozen. Minidump proto neexistuje a jediný důkaz je záznam. ⚠️ **Není to totéž co zásek o devět minut později** (16:21, prov-deadlock-mise-webstatus), ačkoli spouštěč je stejný (volba mise track ze stránky). Ten je deadlock mezi zámky TrackMission a WebStatus, oba na fan-outu do Stream — jenže kdyby byl držený zámek WebStatus, zastavil by se i most Trace → Info, protože WebStatus je na Stream připojený jako PRVNÍ (v ARBot.Headless/Program.cs, mimo connections, tedy před záznamem). A Info teklo dál 140 s. Tenhle zásek je tedy na větvi processing, ne na Stream, a zůstává neurčený. V ~10 bězích 18.–19. 9. (dva Tracky, Robotour) se neopakoval; příčina tím určená není.

  • Rozbor záznamu — kdy to umlklo, co přežilo a co mají umlklá vlákna společného 17. 9. 2026
  • Hlídač i na běžící smyčku (tep ze Scheduleru), aby zásek za jízdy vyrobil minidump
  • Ze zásobníků vláken určit blokujícího odběratele na větvi processing
  • 1. 10. 2026 (20261001-144638.rec, 15:15:41,8) se celý proces zastavil na 1,19 s a sám se rozběhl — JINÝ jev (stál i zápis záznamu, Trace a časovač PerfMsg; tady tekl Trace 140 s a zásek byl trvalý), veden zvlášť jako prov-zasek-procesu-1s. Hlídač tepu s prahem ~1,5 s by ho nechytil 7. 10. 2026

headless.md, RelaySource.cs, MessageSource.cs · DevLog 2026-09-17, 2026-10-07

Celý proces na zařízení stál 1,19 s — dohnané takty, skok kurzu, smazaný grid a ztracená data ze sériových linek

otevřeno vada nalezeno 7. 10. 2026

Track 1. 10. 2026 (20261001-144638.rec) 15:15:41,819–43,010: mlčely VŠECHNY proudy včetně Info, kamer, zápisu záznamu a vlastního časovače PerfMsg (interval 1,43 s, 11 zameškaných taktů, CPU procesu 11,4 % ≈ jedno jádro), pak se proces sám rozběhl. Důsledky: host 1,23 s neposlal příkaz a watchdog motorové jednotky začal brzdit (1,73 → 0,95 m/s); fúze přes zásek extrapolovala a po příchodu dat skočil kurz o 7,1° → PoseJumpDetector smazal grid → plán 0,9 s velel 0,51 m/s; přetečení sériových bufferů dalo chybu CRC VN100 a ztrátu ~0,29 m enkodéru; UartMotor vyhodil TimeoutException, ačkoli jednotka vysílala (hw-motor-davka-po-zaseku). Za 42 + 10 min jediný případ. Je to jiný jev než prov-zatuhnuti-za-behu-mise (tam trvalý zásek, Trace tekl dál). Hypotéza blokující GC (sedí na ~1 vytížené jádro) neprokázaná; hlídač tepu s prahem ~1,5 s by ho nechytil.

  • Změřeno (ARBot.Analyze perf blok 6, scratch rozbor T_in/T_out všech zpráv) 7. 10. 2026
  • Sbírat v PerfMsg pauzy GC (GC.GetTotalPauseDuration, počet kolekcí gen 2) a čas zápisu záznamu, aby příští zásek šel přiřadit

perf-monitoring.md · DevLog 2026-10-07

Služba se po pěti restartech v pěti minutách vzdá a robot je mrtvý

v kódu, na HW neověřeno vada nalezeno 14. 9. 2026 vyřešeno 15. 9. 2026

Systemd má výchozí StartLimitBurst=5 / StartLimitIntervalUSec=5min: šestý start v okně skončí start-limit-hit, jednotka zůstane failed a Restart=always ji už nevrátí — crash loop odstaví robota v terénu natrvalo do ručního reset-failed. Našlo se to na reprodukčním testu 14. 9., kdy počítadlo restartů došlo na 4 z 5. Limit vypnut (StartLimitIntervalSec=0) a přidán rostoucí RestartSec; je to bezpečné, protože se robot bez výběru mise sám nerozjede a deterministické příčiny (návratové kódy 2, 3) dál odfiltruje RestartPreventExitStatus. Na zařízení neběželo.

  • Nález na reprodukčním testu (restart counter 4 z 5) 14. 9. 2026
  • StartLimitIntervalSec=0 + rostoucí RestartSec v jednotce 15. 9. 2026
  • Ověřit na zařízení (jednotku nasadit a vyvolat opakovaný pád)

headless.md, deploy/README.md · DevLog 2026-09-14, 2026-09-15

Externí audit, druhá dávka — tichý senzor, zatuhlý Stop, razítka kamer, CI, licence

v kódu, na HW neověřeno vada nalezeno 15. 9. 2026 vyřešeno 15. 9. 2026

Zbytek nálezů auditu: po odpojení USB převodníku se senzor tvářil jako zdravý (V4, nově „nic neměřím“ je chyba); Stop() mohl zatuhnout navždy na UARTu bez dat — běh testů s vypnutou opravou nedoběhl vůbec (V5); razítka T265 a D435 běžela mimo TimeBase, u D435 se teď kotví jen počátek, aby šel dál poznat zamrzlý stream (V6); datový závod na cíli navigace mezi stupněm a misí (V7); softwarová porucha vize se přičítala k výpadkům kamery (V8); čistý klon nešel postavit a chybělo CI (V10); profil FreeRun rozjížděl robota sám po startu (V11); vnrestore.sh zapisoval do flash bez ptaní (V12); nevyplněná licence a chybějící soupis cizích součástí (V13). Nález V2 (fúze extrapoluje bez omezení) autor rozhodl neřešit; ze středních nálezů (HeadVeh čte špatný offset, FixTime z ITOW, driver motorů nekontroluje prefixy řádků) se nesáhlo na nic; FixTime má od 17. 9. vlastní téma hw-gps-fixtime-rozbity. Binárka s opravami jela 16.–19. 9., ale žádný z nálezů by se bez vyvolané poruchy neprojevil; V13 má v THIRD-PARTY-NOTICES.md u tří binárek dál „(ověřit)".

  • V4 + V5 — SilentTimeout, StopTimeout, konečný ReadTimeout UARTu 15. 9. 2026
  • V6 — razítka kamer v TimeBase (DeviceClockAnchor), CasZTimeBaseTests 15. 9. 2026
  • V7 + V8 — cyklus navigace pod zámkem, CameraVisionStep 15. 9. 2026
  • V10 — build čistého klonu, přeskakování testů bez nativní knihovny, CI workflow 15. 9. 2026
  • V11 + V12 — autorun=false v profilu, potvrzení zápisu do flash, set -euo pipefail 15. 9. 2026
  • V13 — ověřit podmínky tří proprietárních binárek, atribuce OSM (ODbL)
  • Střední nálezy (PVTMessage.HeadVeh, prefixy řádků SDC2160Ex; FixTime z ITOW → hw-gps-fixtime-rozbity)
  • Ověřit V6 na zařízení — 1. 10. 2026 (20261001-144638.rec): T_out − T_in snímků p50 26–36 ms po 5 min, 42 min bez trendu, žádný snímek pozpátku ani z budoucnosti, i po restartu levé pipeline 15:21:57; zamrzlá barva se dál pozná (15:21:44) 7. 10. 2026
  • Ověřit V4/V5 na zařízení (odpojit převodník za běhu, systemctl stop). 1. 10. jen zčásti: konečný ReadTimeout motorů vystřelil 15:15:43,4 a vlákno čte dál, ticho ale nezpůsobila linka (jednotka vysílala, 111 rámců v bufferu), nýbrž zásek celého procesu (prov-zasek-procesu-1s); Stop() na tichém UARTu ani SilentTimeout 5 s se nevyzkoušely

THIRD-PARTY-NOTICES.md, build-and-test.yml, deploy/README.md, record-replay.md · DevLog 2026-09-15, 2026-10-07

V terénu není poznat, jestli se běh nahrává a kam

v kódu, na HW neověřeno vada nalezeno 17. 9. 2026 vyřešeno 6. 10. 2026

Po jízdě 17. 9. 2026 (track po kalibraci magnetometru, podle obsluhy s dobrým kurzem) se nenašel žádný *.rec — a proč, to ze záznamů dohledat nejde, protože chybí právě ten záznam. Při hledání se ukázalo, že o nahrávání nemluví nic, co má obsluha v terénu po ruce, a u robota je jen mobil: RecordPathFromParams() napíše „beh se zaznamenava do …" do Trace PŘED tím, než runtime stojí, takže ta hláška skončí jen v journalu a do záznamu se z principu dostat nemůže — táž past jako s účinnou konfigurací, opravená 5. 9. 2026 zopakováním po připojení mostu. Když je record= prázdné nebo false, vrátí se null MLČKY, takže neexistuje ani ta jedna řádka. ARBotRuntime.RecordPath se plní jen ve WireView, v Run zůstává null, tedy runtime ani sám neví, kam píše. A stránka náhledu o nahrávání nemá ani slovo. Běh, který se nenahrál, je proto v terénu k nerozeznání od běhu, který se nahrál. Dohledáno na zařízení týž den — a jsou to DVA různé běhy, ne jeden. Pokus v 16:21:22 (20260917-162122.rec) se do souboru nedostal vůbec: Start(Run) uvízl na deadlocku (prov-deadlock-mise-webstatus) o kus dřív, než se FileStream vůbec zakládá, takže hláška „beh se zaznamenava do …" v journalu je, ale soubor nikdy nevznikl. Ta hláška se totiž tiskne v RecordPathFromParams(), tedy PŘED WireRun — **říká záměr, ne výsledek**, a to je samo o sobě matoucí. Druhý pokus je v následujícím bootu (16:22:52) a **robota skutečně řídil** — obsluha má snímky stránky z **16:26** (běží true, kurz 0,355 rad, rychlost **0,905 m/s**, trasa, plán i mrkev) a z **16:29**. Hodiny přitom sedí na sekundy: snímek z 16:20 zachycuje dialog o zápisu kalibrace (journal 16:20:16–20) a snímek z 16:21 ukazuje **vlastní čas stránky 16:21:22**, tedy přesně okamžik POST /mission?m=track v journalu. ⚠️ **Po tom běhu ale nezůstalo NIC — ani záznam, ani journal — a to je pořád neurčené.** Journal toho bootu končí v **16:23:24** (zatímco robot jel ještě aspoň 6 minut), služba arbot v něm nevypsala **ani řádek**, ačkoli jádro ve stejné chvíli hlásí enumeraci kamer (tedy aplikace běžela), a v datovém adresáři není mezi 16:22 a 18:28 zapsaný ani bajt. Plný disk to nebyl (366 GB volných), record=true platilo všude a hodiny jsou z RTC. ⚠️ **Prověřeno na zařízení 17. 9. večer a nic z toho to nevysvětluje** — vyloučeno je: plný disk (366 GB volných), chyba disku nebo errors=remount-ro (v journalu žádná chyba ext4/NVMe), ztráta přes armbian-ramlog (/var/log sice JE na zramu, ale journal je symlink na /var/log.hdd, tedy na disk), záznam odložený vedle binárek (~/arbot-headless-run/records/ neexistuje), škrcení journaldem (žádné „Suppressed"), posun hodin (snímky stránky sedí s journalem na sekundy) a jiný boot (výpis všech 18 bootů mezi 16:23:24 a 18:28:13 žádný nemá). **Co zbývá jako holý fakt:** v tom bootu služba arbot nastartovala v 16:23:00, jádro v 16:23:16–24 enumeruje obě D435 (tedy aplikace běžela a otevírala kamery) — a služba přitom do journalu nevypsala **ani jeden řádek**, ani úvodní verzi, ani výpis konfigurace, ani „Ceka se na vyber mise". Chybí zároveň **výstup do journalu i záznam**, tedy obojí, co aplikace zapisuje, ačkoli podle snímků jela a řídila robota rychlostí 0,9 m/s. Další krok je **reprodukce**: pustit touž misi znovu a sledovat, jestli se výpis do journalu objeví. Nezávisle na tom dává smysl odstranit spouštěč celé té epizody — deadlock (prov-deadlock-mise-webstatus). ⚠️ **Hypotéza „tvrdé vypnutí to spolklo" NESTAČÍ** a je poctivé to říct: /etc/fstab má kořen na commit=120 a RecordingTarget.OnFlush dělá jen spravovaný Flush() do stránkové cache (**nikdy fsync**), takže se ztratí nanejvýš ~2 minuty — jenže mezi posledním řádkem journalu a snímkem obrazovky je **5,5 minuty**. ✅ **Hodiny robota ale z podezřelých vypadly, a to měřením ZE ZÁZNAMU** (ARBot.Analyze gps, nový blok A0): GPS nese ITOW, tedy absolutní čas, který nepochází z hodin Pi. Po rekonstrukci (viz hw-gps-fixtime-rozbity) vychází den v týdnu **4 = čtvrtek** a systémový čas je proti GPS **+3,9 s** v jednom záznamu a **+4,0 s** v druhém — tedy hodiny jdou a ty ~4 s jsou konstantní zpoždění řetězu, ne drift. Časová osa v záznamech i v journalu je proto skutečná a v 16:29 byl robot podle vlastních hodin **vypnutý**. Čas 16:29 tedy pochází z jiných hodin než robotových; rozhodne obsah toho snímku. Nezávisle na tom platí, že chybějící fsync je vada sám o sobě: záznam nemá přežít odpojení napájení jen náhodou. **V kódu 6. 10. 2026:** hláška o záznamu říká výsledek a je v .rec, stránka ukazuje cestu a rostoucí velikost (nebo důvod, proč se nenahrává), fsync po založení, každých 5 s a při zastavení. Proč 17. 9. chybí běh z 16:23–16:29, to kód nevysvětlí — zůstává otevřené.

  • Nález — proč to nejde dohledat (žádná stopa mimo journal, stránka mlčí) 17. 9. 2026
  • RecordPath plnit i ve WireRun a dát na stránku řádek „nahrává se do …" / „BEZ ZÁZNAMU" — hlavička: „záznam: cesta (N MB)" s rostoucí velikostí, oranžově „BEZ ZÁZNAMU — důvod", červeně „ZÁZNAM SELHAL"; NoRecordReason, RecordFailed, RecordBytes 6. 10. 2026
  • Hlásit i případ record=false a hlášku zopakovat po připojení TraceInfoBridge — hláška jde z WireRun až po založení souboru, kdy most stojí, takže je i v .rec (ověřeno ARBot.Analyze log) 6. 10. 2026
  • Na zařízení dohledat, proč záznam ze 17. 9. po kalibraci chybí — pokus 16:21 vysvětlen, běh v 16:29 NE
  • Záznam přežije odpojení napájení: fsync (Flush(true)) v OnFlush, nebo aspoň hned po založení souboru — obojí: hned po založení (data i index) a pak nejvýš jednou za 5 s (RecordSyncInterval) a při zastavení; po každé dávce ne (~19 MB/s) 6. 10. 2026
  • Hláška „beh se zaznamenava do …" má říkat výsledek, ne záměr (dnes se tiskne před WireRun) — „ZAZNAM: beh se nahrava do …" / „BEZ ZAZNAMU" / „SELHAL" až po založení souboru; soubor, který nejde založit, už neshodí Start 6. 10. 2026
  • Ověřit na zařízení: hlavička s cestou a rostoucí velikostí po volbě mise, „BEZ ZÁZNAMU" ve fázi čekání; po vytažení napájení za jízdy zůstane .rec čitelný (chybí nanejvýš ~5 s)

record-replay.md, ARBotRuntime.cs, WebStatus.cs · DevLog 2026-09-17

Napětí baterie není na stránce náhledu a nic na něj nevaruje

v kódu, na HW neověřeno vada nalezeno 19. 9. 2026 vyřešeno 6. 10. 2026

Ve 2. kole Robotouru 2026 robot po 27 s jízdy zastavil s vybitou baterií (byl zapnutý od rána, při opravách po 1. kole se nepřipojil na nabíječku). V záznamu to bylo vidět, jen to nikdo nečetl: medián napětí z MotorStateBase dopoledne 12,1 V (9:29) → 11,8 V (10:19) při stání, v Kolo2.rec 10,6 V a poslední vzorek 10,0 V, po nabití 12,5 V. Stránka náhledu napětí neukazuje a žádný práh na něj nehlídá — jediné místo, kde je, je záznam. Jednotlivé vzorky z motorové jednotky jsou hlučné (5–17 V), takže se musí brát medián nebo filtr, ne poslední hodnota. Léčba: řádek s napětím (mediánem za pár sekund) v tabulce senzorů na stránce a varování pod prahem (batwarn=), případně odmítnout start mise pod tvrdším prahem. **V kódu 6. 10. 2026:** BatteryMonitor (medián 5 s, zahazuje zprávy bez měření, hystereze 0,2 V, do Trace jen přechod stavu) jako stupeň runtime; stránka čte tentýž objekt — řádek „baterie [V]" v tabulce a pod batwarn= (výchozí **11,6 V**, v údajích jednotky; 4 články LiFePO4) červený řádek v hlavičce. **Start mise se neblokuje** (autor). Virtuální motory hlásí nastavitelné napětí (panel *Virtuální senzory*, výchozí 12,8 V místo natvrdo 24 V).

  • Napětí baterie (medián) do stránky náhledu vedle kvality GPS 6. 10. 2026
  • Práh varování a hlášení do Trace — batwarn= 11,6 V, hlášení jen při přechodu stavu (škrcení PoruchaHlasic netřeba); 6 testů monitoru, 3 testy stránky, ověřeno headless se simulací (batwarn=13) 6. 10. 2026
  • Ověřit na zařízení: napětí v tabulce sedí na Roborun+, varování se neobjevuje za jízdy s plnou baterií (pokles pod zátěží); případně doladit batwarn= podle skutečného napětí na svorkách
  • Přehrání BatteryMonitor nad 1. 10. 2026 (ARBot.Analyze battery; binárka robota monitor ještě neměla): Track medián 5 s za jízdy p50 12,00 V, ve stání 12,40 V, nejnižší 11,30 V; při batwarn=11,6 by varování pod zátěží ke konci 42min jízdy 2× krátce bliklo (15:23:07–25 a 15:27:21–25), ačkoli při stání bylo 12,4 V; FreeRun hned potom 1× (15:34:38–40). Podklad pro rozhodnutí o prahu / delším okně / kompenzaci proudem (autor) 7. 10. 2026

robotour-2026.html, headless.md · DevLog 2026-09-20, 2026-10-07

Ujetá dráha a průměrná rychlost mise na stránce náhledu

v kódu, na HW neověřeno záměr nalezeno 6. 10. 2026 vyřešeno 6. 10. 2026

Přání autora: na webu headless vidět, kolik metrů robot v misi ujel a jakou průměrnou rychlostí, a okamžitou rychlost tam, kam obsluha s mobilem kouká (dřív jen řádek v tabulce dole). **V kódu 6. 10. 2026:** řádek „jízda:" v hlavičce — teď, ujeto, průměr přes dobu mise a průměr v pohybu (doba mise zahrnuje stání). Odometer (ARBot.Common/Diagnostics) sčítá dráhu z **odometrické** pózy (fúzovaná skáče při korekcích), práh 5 cm proti šumu při stání, nespojitost nad 5 m/s se nepočítá; začátek mise = poslední vzorek − Elapsed, proto historie kontrolních bodů po 2 s na 12 h. **Do fúze ani do záznamu to nejde** (autor): ∫|v|dt ve fúzi by při stání sčítal šum a začátek mise by neznal; pro rozbory by patřilo spíš do MissionMsg.

  • Odometer + řádek „jízda:“ v hlavičce stránky; 8 testů počítadla, 2 testy stránky, ověřeno headless se simulací (FreeRun 19 m za 31 s, sedí na půdorys) 6. 10. 2026
  • Ověřit na zařízení: ujetá dráha sedí na skutečnou (např. proti délce trasy Tracku), stání v servisním okně nepřidává metry
  • Přehrání Odometer nad 1. 10. 2026 (ARBot.Analyze odometer; záznam bez odometrické pózy, takže integrál fúzovaných v, ω): Track 3 249,5 m za 2 157 s v pohybu (1,51 m/s); úsek k místu 1 1 176,7 m proti trase 1 151 m (+2,2 %), k místu 2 1 150,9 m proti 1 143 m (+0,7 %); proti GPS +2,4 % (nadsazená dráha z kol, lok-fuze-poza-pred-koly). Stání 83 s přidalo 0,0 m (práh 5 cm funguje). FreeRun 794,9 m. Měří algoritmus, ne stránku 7. 10. 2026

headless.md · DevLog 2026-10-06, 2026-10-07

Síť robota pro soutěž — vlastní WiFi AP a kabel bez routeru

hotovo záměr nalezeno 29. 8. 2026 vyřešeno 30. 8. 2026

Na soutěži není router, ale k robotu je potřeba se dostat z notebooku i z mobilu a stahovat velké záznamy. Robot vysílá vlastní AP arbot (na hostapd, protože AP režim wpa_supplicant s tímhle Broadcom čipem klienta nepřipojil) a po kabelu vezme adresu ze sítě, nebo když DHCP do 12 s nepřijde, sám rozdá adresu notebooku (eth-direct). Ověřeno rebootem: AP je k dispozici 9,8 s po startu. Cena: v síti s pomalým DHCP může robot spadnout na přímé spojení. Druhý den se opravilo, že sdílené připojení bralo notebooku internet (posílalo výchozí trasu přes robota); účinek se ověří až při dalším přepojení kabelu. Postup je v setup-orangepi.sh, ověřený jen staticky — celý běh ověří až reinstalace.

  • AP arbot na hostapd, ethernet eth-dhcp → eth-direct, ověřeno rebootem 29. 8. 2026
  • Pád na přímé spojení zkrácen ze 74 s na 12 s (ipv6.method ignore) 29. 8. 2026
  • setup-orangepi.sh přepsán podle nové konfigurace (ověřeno staticky) 29. 8. 2026
  • Sdílené připojení neposílá notebooku výchozí trasu ani DNS (no-default-route.conf) 30. 8. 2026

OrangePi5Ultra/POSTUP.md (kroky 3 a 4), setup-orangepi.sh, rozhodnutí 29. 8. 2026 · DevLog 2026-08-29, 2026-08-30

Na Orange Pi šel čas aplikace 100× rychleji

hotovo vada nalezeno 31. 8. 2026 vyřešeno 1. 9. 2026

První běh aplikace na Pi: kamera hlásila 0,3 Hz, ale snímky přibývaly desítkami za sekundu, a čas snímku v overlayi byl po pěti minutách o osm hodin napřed. TimeBase.Now sčítalo surové tiky Stopwatch (na Linux/ARM64 1 GHz) s tiky DateTime (100 ns); na Windows je frekvence shodou okolností 10 MHz, takže se to nikdy neprojevilo. Z TimeBase se razítkuje na 45 místech, takže dt mezi měřeními bylo 100× větší — záznamy z Pi před opravou nejsou použitelné. Motor kvůli tomu „blikal napětím" (rozpočet 500 ms byl reálně 5 ms). Opraveno, změřeno na zařízení izolovaně a 1. 9. potvrzeno v běžící aplikaci. Následně se čas v celé aplikaci sjednotil na TimeBase (pravidlo v CLAUDE.md).

  • TimeBase sčítá Elapsed.Ticks; táž záměna v Performance.ToString(); testy 31. 8. 2026
  • Ověřeno v běžící aplikaci na Pi 1. 9. 2026

rozhodnutí 31. 8. 2026, record-replay.md · DevLog 2026-08-31, 2026-09-01, 2026-09-04, 2026-09-15

Profil pro FreeRun na Pi — a profily na zařízení vůbec nefungovaly

hotovo vada nalezeno 1. 9. 2026 vyřešeno 2. 9. 2026

Při psaní prvního provozního profilu config/pi-freerun.cfg se ukázalo, že na zařízení profil nešlo vůbec načíst: v adresáři aplikace na Pi není config/ ani OSM/, takže config= ukazovalo na neexistující soubor a start skončil chybou — dokumentace přitom tvrdila opak. Léčba: build kopíruje profily i mapy k binárkám a strážný test hlídá, že každý profil v repu projde registrem. Přibyly tři parametry na přání autora: record= (záznam bez klikání v UI), autorun= (Run po startu) a maxspeed= (strop rychlosti); při tom se zjistilo, že FreeRunConfig.MaxSpeedMps byl mrtvé pole, které nikdo nečetl. Profil na Pi zabral hned 2. 9. (první FreeRun na železe); audit 15. 9. pak v profilu vypnul autorun, protože robot, který se po startu rozjede sám, projekt zakazuje.

  • Kopírovat config/*.cfg a OSM/*.osm do výstupu buildu, test ProfilyVRepuTests 1. 9. 2026
  • Parametry record=, autorun=, maxspeed=; odstraněno mrtvé MaxSpeedMps 1. 9. 2026
  • Profil načten na Pi a FreeRun s ním jel 2. 9. 2026
  • Audit: autorun=false v profilu, ProfilyBezpecnostTests 15. 9. 2026

configuration.md, mission-freerun.md, config/pi-freerun.cfg · DevLog 2026-09-01, 2026-09-02, 2026-09-15

Diagnostika senzorů šla do Debug, takže v Release na zařízení nezůstala žádná stopa

hotovo vada nalezeno 2. 9. 2026 vyřešeno 2. 9. 2026

Na snímku panelu Debug output nebyl o nefunkčních kamerách ani řádek — drivery hlásily přes Debug.WriteLine, které se v Release buildu vykompiluje pryč, a právě Release běží na robotu. Příčina výpadku kamer se tak hodinu hledala měřením zvenčí místo pár sekund čtení logu. Převedeno 31 hlášení v obou HAL a v obecné chybové cestě všech senzorů, ověřeno přímo na Pi z Release knihoven; pravidlo je v CLAUDE.md a hlídá ho strážný test. Audit 15. 9. našel totéž mimo drivery (výjimky stupňů, LocalNavigator, UART) a přidal škrcení hlášek na horké cestě.

  • Drivery kamer a SensorBase do Trace, test DiagnostikaSenzoruTests 2. 9. 2026
  • Ověřeno na Pi z Release buildu 2. 9. 2026
  • Audit: stupně, navigace a UART do Trace, škrtič PoruchaHlasic, DiagnostikaPoruchTests 15. 9. 2026

CLAUDE.md, hardware.md · DevLog 2026-09-02, 2026-09-15

Robot běžel po bootu 20 hodin pozadu kvůli fake-hwclock

hotovo vada nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

Systémový čas na Pi ukazoval včerejší večer, ačkoli hardwarové RTC sedělo na sekundy. Jádro čas z RTC nastavilo správně a hned poté ho přepsal fake-hwclock-load posledním uloženým časem z doby před vybitím baterie — balík pro stroje bez RTC, který na této desce nemá co dělat, a robot k NTP běžně cestu nemá. Služba zamaskovaná, ověřeno rebootem, krok přidán do instalačního skriptu. Záznamy z doby před opravou mají včerejší jméno i razítka.

  • Zamaskovat fake-hwclock, čas z RTC, krok v instalačním skriptu 3. 9. 2026

OrangePi5Ultra/POSTUP.md, setup-orangepi.sh · DevLog 2026-09-03

Vzdálená plocha na Pi „vytuhla" — zamykal ji spořič KDE, ne RustDesk

hotovo vada nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

RustDesk třikrát skončil černou obrazovkou bez možnosti přihlášení. Sezení na Pi běží headless na Waylandu a KDE má výchozí zámek po 5 minutách nečinnosti — v obou bootech se zamykací obrazovka objevila přesně 5 minut po přihlášení a RustDesk ji na Waylandu neumí zobrazit ani ovládat. Na pokyn autora zámek vypnut, krok v instalačním skriptu. Že tím freezy zmizely, se do DevLogu nezapsalo; další zmínka o problému není.

  • Vypnout automatický zámek obrazovky KDE 3. 9. 2026

OrangePi5Ultra/POSTUP.md · DevLog 2026-09-03

Pády aplikace na Pi nešly dohledat — teď po nich zůstane stopa

hotovo záměr nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

Aplikace na robotu „chvíli běžela a zmizela" a nikde nic: journal v RAM zmizel s vybitou baterií, výjimka .NET šla na stderr terminálu, core dumpy nevznikaly. Na robotu je teď trvalý journal, hlášení fatálních signálů jádrem a spouštěcí skript s logem a minidumpem; v aplikaci CrashLog, který neošetřenou výjimku zapíše do logs/crash-*.log a pokusí se dopsat záznam. Vyplatilo se týž večer (pád rozebraný do řádku kódu) a 5. 9. crash log na Pi skutečně vznikl. Nativní pád (SIGSEGV) CrashLog nezachytí — zůstává journal a core dump. Sourozenec pro zatuhnutí, HangWatchdog, přibyl 14. 9.

  • Trvalý journal, print-fatal-signals, skript run-arbot.sh 3. 9. 2026
  • CrashLog v aplikaci 3. 9. 2026
  • Crash log vznikl na zařízení 5. 9. 2026

OrangePi5Ultra/POSTUP.md, headless.md · DevLog 2026-09-03, 2026-09-05, 2026-09-14

Runtime bez UI a provoz na robotu jako služba

hotovo záměr nalezeno 4. 9. 2026 vyřešeno 5. 9. 2026

Řídicí runtime se vyčlenil do vlastního projektu ARBot.Runtime a konzolový ARBot.Headless ho spouští bez Avalonie (Ctrl+C / SIGTERM → Stop(), návratové kódy). Druhý den z toho vznikl provoz jako služba: systemd jednotka arbot, dvoufázový běh (bez zadané mise robot nastartuje senzory a stojí, dokud mu člověk nevybere misi), dataroot= a zámek jedné instance kvůli nasazení stínovou kopií, verze binárky v crash logu i v záznamu. Ověřeno na Orange Pi: služba, SIGTERM za 7 ms, zámek, CPU 6,2 % při čekání; při ověřování se našlo sedm vad, mimo jiné že se konfigurace do záznamu nikdy nedostávala. Celý průchod misí ze stránky proběhl 14. 9. Start po skutečném rebootu se dosud nezkoušel; limit pěti restartů, který službu v crash loopu trvale odstavil, se opravil 15. 9.

  • Projekt ARBot.Runtime a konzolový ARBot.Headless (fáze 1–2) 4. 9. 2026
  • Služba systemd, dvoufázový běh, dataroot=, zámek instance, verze binárky (fáze 4) 5. 9. 2026
  • Ověřeno na Orange Pi (služba, SIGTERM, zámek, CPU) 5. 9. 2026
  • Mise vybraná ze stránky odjela na zařízení 14. 9. 2026

headless.md, plan-headless-provoz.md, plan-runtime-headless.md, deploy/README.md, rozhodnutí 4. a 5. 9. 2026 · DevLog 2026-09-04, 2026-09-05, 2026-09-14, 2026-09-15

Webový náhled robota z mobilu — půdorys, kamera, senzory, stop

hotovo záměr nalezeno 4. 9. 2026 vyřešeno 5. 9. 2026

Stránka nad vlastním HTTP serverem (web=<port>): půdorys s occupancy gridem a sítí cest, snímek kamery včetně vrstvy „cesta z RGB", stav senzorů se stářím poslední zprávy a tlačítko Zastavit. Kreslí se líně — bez publika se nic nekreslí ani nekopíruje (13,9 % CPU bez publika proti 14,3 % s ní). Cestou se opravila zamrzlá stránka (pool kopií snímků měl kapacitu 2 pro dvě kamery) a geometrie sítě cest (rozšiřující se cesta je trychtýř). 5. 9. přibyl výběr mise pod drženým nouzovým zastavením a ověření na Pi včetně textu měřítka a živého snímku z D435. Stránka od té doby rostla dál (GPS kvalita, Power off, zóny míst, řádek zastavení).

  • Kreslení v Common/Rendering, HTTP v Runtime/Web, stránka a JSON 4. 9. 2026
  • Pool kopií snímků 2 → 4, hláška při vyčerpání 4. 9. 2026
  • Výběr mise z webu, jednořádková hlavička, tlačítka v liště 5. 9. 2026
  • Ověřeno na Orange Pi (fonty, živý snímek) 5. 9. 2026

headless.md, plan-headless-web.md, rozhodnutí 4. 9. 2026 · DevLog 2026-09-04, 2026-09-05

Start služby po skutečném rebootu Orange Pi se nezkoušel

hotovo záměr nalezeno 5. 9. 2026 vyřešeno 17. 9. 2026

Služba arbot je enabled s Restart=always, restart služby i SIGTERM jsou ověřené, ale nikdo ještě nenechal desku nabootovat od studena a nezkontroloval, že runtime nastartuje, rozjede senzory a stojí, dokud mu člověk nevybere misi. Souvisí s tím i kamery, které se po bootu občas vyčtou jen na USB 2.0. Prošlo provozem: 17. 9. 2026 obsluha robota vypnula a zapnula (boot 16:22:52), služba nastartovala v 16:23:00, jádro enumerovalo obě D435 a v 16:26 robot podle snímků stránky řídil (trasa, plán, mrkev); na Robotouru 19. 9. byl robot zapnutý od rána a po nabití baterie znovu, pokaždé senzory po bootu žily. Výhrada: journal právě toho bootu ze 17. 9. je anomální (služba nevypsala ani řádek, vede prov-zaznam-nevidet-ze-nebezi), takže z něj je vidět jen start služby. Sérii startů na baterii kvůli USB 2.0 nikdo nepočítal (hw-kamery-usb2-po-bootu zůstává vlastní téma).

  • Reboot desky a kontrola journalu, náhledu a senzorů po startu — 17. 9. (vypnutí a zapnutí obsluhou): služba naběhla za 8 s, kamery enumerovány, robot řídil; potvrzeno provozem 19. 9. 17. 9. 2026

headless.md, deploy/README.md · DevLog 2026-09-05, 2026-09-17, 2026-09-19

Otevřená záložka náhledu běží po nasazení dál se starou stránkou

hotovo vada nalezeno 6. 9. 2026 vyřešeno 6. 9. 2026

Z hlášení „chybí tlačítko Power off": náhled je jednostránková aplikace, po nasazení tedy v otevřené záložce běží starý skript, zatímco hlavička ukazuje novou verzi (čte se ze stavu). Chybějící funkce pak vypadá jako nenasazená a hlavička u toho lže. Léčba: do stránky se otiskne verze binárky, která ji poslala; skript ji porovnává s verzí ze stavu a při neshodě se jednou sám přenačte (pojistka proti zacyklení). Přibyly dva strukturální testy, že každé getElementById má své id a každý onclick svou funkci.

  • Verze stránky ve skriptu, varování a jednorázové přenačtení 6. 9. 2026
  • Strukturální testy nad vygenerovanou stránkou 6. 9. 2026

headless.md · DevLog 2026-09-06

Nasazení posílá i profily, mapy a modely

hotovo záměr nalezeno 6. 9. 2026 vyřešeno 7. 9. 2026

nasad.ps1 do té doby nasazoval jen binárky; profily a mapy se kopírovaly ručně a poznalo se to až tím, že se změna v profilu na robotu neprojevila. Teď jdou config/, OSM/ a modely (*.onnx, *.rknn) do datového adresáře, odkud je aplikace čte, a librknnrt.so vedle binárek. Repo vyhrává, ale skript před kopií porovná MD5 a vypíše soubory, které se liší. Ověřeno celým řetězem na Pi včetně stínové kopie.

  • config/ a OSM/ do datového adresáře s porovnáním MD5 6. 9. 2026
  • Modely a librknnrt.so, ověření na robotu 7. 9. 2026

deploy/README.md · DevLog 2026-09-06, 2026-09-07

Vypnutí desky ze stránky náhledu

hotovo záměr nalezeno 6. 9. 2026 vyřešeno 13. 9. 2026

Aby šlo robotovi bezpečně odpojit napájení bez notebooku, stránka náhledu nabízí Power off (POST /poweroff): zastaví runtime a vypne desku příkazem z poweroffcmd=. Na Windows je příkaz prázdný a tlačítko se záměrně neukazuje (rozhodnutí autora). Odpověď se posílá až po pokusu, aby se selhání dozvěděla obsluha. Poprvé použito na robotu 13. 9. („robot na noc vypnut").

  • POST /poweroff, poweroffcmd=, tlačítko na stránce 6. 9. 2026
  • Použito na skutečné desce 13. 9. 2026

headless.md · DevLog 2026-09-06, 2026-09-13

Půdorys náhledu ukazuje, co se robot chystá udělat, a zóny k dosažení

hotovo záměr nalezeno 12. 9. 2026 vyřešeno 30. 9. 2026

Na půdorysu stránky náhledu přibyla trasa globální navigace, dráha z lokálního plánovače (i s uzly, z jejichž rozestupu je vidět vyhlazování), legenda včetně dosud nepopsané ujeté dráhy a kružnice o dojezdovém poloměru kolem míst mise (aktivní plnou čarou), aby šlo v terénu dohlížet na závod. Kvůli tomu nese GlobalNavMsg dojezdový poloměr a TrackMsg celý seznam míst; od 13. 9. se zóny kreslí na přichycených místech, od 14. 9. jsou i vrstvou ve World pohledu (GoalZones). Zdroje se nesčítají — přednost má to, co zadal člověk. Ověřeno testy a jízdou v simulaci. Trasa a lokální plán byly na zařízení vidět 17. 9. (snímky stránky 16:26: trasa, plán, mrkev) a na Robotouru 19. 9. obsluha na stránce sledovala přeplánování trasy; že někdo viděl i zóny (kružnice o dojezdovém poloměru), zapsané nebylo — ✅ autor 30. 9. 2026: zóny na stránce na zařízení vidět jsou.

  • Trasa a lokální plán s prahem stáří, legenda 12. 9. 2026
  • Zóny o dojezdovém poloměru, GlobalNavMsg v2 a TrackMsg v2 12. 9. 2026
  • Zóny na přichycených místech (TrackMsg v3) 13. 9. 2026
  • Trasa a lokální plán na stránce za jízdy — 17. 9. snímky 16:26, 19. 9. přeplánování vidět na stránce 17. 9. 2026
  • Zóny na stránce na zařízení — autor potvrdil, že jsou vidět 30. 9. 2026

headless.md, world-view.md, track-mission.md · DevLog 2026-09-12, 2026-09-13, 2026-09-14, 2026-09-17, 2026-09-20, 2026-09-30

Zaseknuté kamery D435 si runtime zotaví sám za ~29 s

hotovo záměr nalezeno 12. 9. 2026 vyřešeno 13. 9. 2026

Zamrzlý stream D435 dřív znamenal mrtvou kameru na stovky sekund až do restartu služby. CameraRecoverySupervisor po 15 neúspěšných pokusech o připojení vezme držené zastavení, počká na stání, nechá kamery zaparkovat jejich vlastní smyčku (žádost a potvrzení — první verze bourala pipeline z cizího vlákna a zatuhla) a vymění sdílený RealSense kontext. Na robotu ověřeno 5× z 5 na skutečné poruše, obnova 28–29 s. Odstup po neúspěchu se zdvojnásobuje a po třech marných zotaveních za 15 min se to u dané kamery vzdá, aby jedna vadná kamera nestahovala dokola i zdravé. Je to obvaz, ne léčba příčiny: proč teardown vede k zaseknutí jen asi ve 4 % případů, se neví, a za jízdy by to znamenalo zastavení na ~28 s každých pár minut.

  • Příčina změřena na živé poruše: reset USB ani odpojení uvcvideo nepomohly, jiný proces kameru zabral — zaseknutý je stav librealsense v našem procesu, ne zařízení 12. 9. 2026
  • Supervizor + tlačítko „Zotavit kamery“ na stránce náhledu 13. 9. 2026
  • Přestavba na žádost a potvrzení (IRecoverableCamera) po zatuhnutí první verze na robotu 13. 9. 2026
  • Ověření na skutečné poruše (5× z 5, 28–29 s) 13. 9. 2026
  • Druhá podoba záseku (kamera zmlkne bez selhaných dotazů) — počítá se každý neúspěšný pokus 13. 9. 2026
  • Rostoucí odstup a vzdání po třech marných zotaveních (tři pokusy o správné kritérium) 13. 9. 2026

plan-drive-hold.md, hardware.md, headless.md · DevLog 2026-09-12, 2026-09-13, 2026-09-14

Runtime zatuhl při volbě mise; z toho hlídač zatuhnutí

hotovo vada nalezeno 14. 9. 2026 vyřešeno 14. 9. 2026

Při volbě mise ze stránky se runtime na zařízení zasekl uvnitř Start(Mode.Run) — v journalu doběhlo corridor=false, mission=track už nikdy (běžně 5 ms mezi nimi), proces žil dál, stránka umlkla a autor robota vypnul; tím zmizel i stav, ze kterého by to šlo přečíst. Léčba není oprava (mechanismus záseku je neprokázaný), ale důkaz, který si robot pořídí sám: HangWatchdog (hangwatch=, výchozí 20 s) obaluje start, po vypršení jde do Trace hlášení a vedle něj minidump se zásobníky všech vláken. Reprodukce od stolu (32 kol volba mise → stop → restart) zásek nevyvolala; rozdíl je, že tehdy robot jel. Kandidátem na příčinu je od 15. 9. Stop() zatuhlý na UARTu bez dat (nález V5 auditu). 17. 9. 2026 hlídač na zařízení POPRVÉ běžel — a v 16:21:42 **vystřelil a odvedl přesně to, kvůli čemu vznikl**: zásek při volbě mise track, minidump logs/hang-Start-Run-20260917-162142.dmp, a z jeho zásobníků je příčina určená na řádek — je to **ABBA deadlock mezi zámkem TrackMission a zámkem WebStatus**, viz prov-deadlock-mise-webstatus. Tím je tohle téma vyřešené: hlídač je hotový, nasazený a prokázaný v provozu, a vada, kterou chytil, se vede samostatně. ⚠️ **Nechytí ale zásek ZA během** — token se po dokončení Start(Run) zahodí, takže zásek z téhož dne v 16:12 (4 s po startu) žádný dump nemá; viz prov-zatuhnuti-za-behu-mise.

  • Rozbor journalu a záznamů (dva omyly opravené měřením) 14. 9. 2026
  • HangWatchdog s minidumpem, arm před zámkem, jen pro Run 14. 9. 2026
  • Reprodukce od stolu — negativní 14. 9. 2026
  • Nasadit hlídač na zařízení a nechat zásek chytit v provozu 17. 9. 2026

headless.md · DevLog 2026-09-14, 2026-09-15

Externí audit — bezpečnostní vrstva řízení měla čtyři díry

hotovo vada nalezeno 15. 9. 2026 vyřešeno 30. 9. 2026

Autor dodal externí read-only audit; tři kritické a jeden vysoký nález se potvrdily přímo ve zdroji. Výjimka v taktu řídicí smyčky se polykala a robot jel po posledním příkazu až do zásahu 500ms watchdogu motorů (K1); Stop() nikdy neposlal motorům nulu, ačkoli dokumentace tvrdila opak (V1); brána „mise jen při drženém nouzovém zastavení“ prošla s odpojeným motorovým UARTem, protože fail-rámec driveru se četl jako stisk tlačítka a obnovení linky jako pokyn „jeď“ (K2); jedno NaN měření otrávilo fúzi natrvalo, protože gating na NaN nezabere (K3). K tomu diagnostika poruch z Debug do Trace na cestách, které audit jmenoval, se škrtičem PoruchaHlasic proti zaplavení záznamu (V3). Opraveno TDD — u každého nálezu nejdřív test, který na starém kódu spadl. ✅ Autor 30. 9. 2026: na zařízení ověřeno.

  • K1 — výjimka v taktu = Drive(0,0) + zpráva s nulami + Trace 15. 9. 2026
  • V1 — nula motorům v ControlLoop.Stop() 15. 9. 2026
  • K2 — fail-rámec není měření tlačítka (HasMeasurement), automaty mise i brány stojí 15. 9. 2026
  • K3 — brána na konečnost před fúzí a pojistka na výsledek kroku EKF 15. 9. 2026
  • V3 — Debug → Trace se škrtičem, DiagnostikaPoruchTests 15. 9. 2026
  • Ověřit na zařízení — autor potvrdil 30. 9. 2026

path-following.md, ekf-fusion.md · DevLog 2026-09-15, 2026-09-30

Deadlock mezi zámkem mise a zámkem stránky při volbě mise

hotovo vada nalezeno 17. 9. 2026 vyřešeno 19. 9. 2026

17. 9. 2026 v 16:21:22 se po volbě mise track ze stránky runtime zasekl uvnitř Start(Run). HangWatchdog vystřelil a pořídil minidump (logs/hang-Start-Run-20260917-162142.dmp) — a z jeho zásobníků je příčina určená jednoznačně. Je to klasická inverze pořadí zámků (ABBA): vlákno volby mise drží zámek TrackMission (StartMission → lock (gate) → EnterPhase → EmitState → EmitDerived → RelaySource.Post → WebStatus.Post) a čeká na zámek WebStatus; vlákno webového serveru drží zámek WebStatus (Handle → ToJson → lock (gate) → AppendHead) a čeká na zámek TrackMission (get_PhaseText). Spouštěč je proto úplně běžný provoz: stránka se sama obnovuje, takže stačí, aby dotaz na stav přišel ve chvíli, kdy se mise zakládá — a v terénu se na stránku kouká právě v ten okamžik, protože se z ní mise vybírá. ✅ **Že je cyklus UZAVŘENÝ (tedy skutečný deadlock, ne jen dlouhé čekání), je ověřené v kódu:** WebStatus.ToJson bere lock (gate) a **uvnitř něj** volá AppendHead, tedy i TrackMission.PhaseText. Sám se nerozpustí — jediné, co ho ukončí, je konec procesu. Sedí to i s tím, co obsluha udělala: stránka zmlkla a robota vypnula a zapnula. Kořen je porušení pravidla, které si RelaySource sám píše: fan-out běží na vlákně producenta, takže se do něj nesmí vstupovat s drženým zámkem. Léčba je publikovat AŽ MIMO zámek — pod zámkem zprávu jen složit. Totéž platí pro každou další misi a stupeň, který volá EmitDerived zevnitř lock, a pro WebStatus.ToJson, který si má stav misí napřed ofotit a teprve pak skládat odpověď. **Opraveno 17. 9. 2026, z obou stran** (jedna by stačila, ale invariant má platit oběma směry): mise skládá zprávu pod zámkem a **publikuje až mimo něj** — drží to using rozsah (Publikace()), takže se na to nedá zapomenout ani při return uprostřed zámku, a vnořená volání (Abort zevnitř OnGlobalNav) mlčí podle Monitor.IsEntered, aby publikoval vždy jen nejvnějšnější rozsah. WebStatus.ToJson si stav mise **ofotí před** svým zámkem (NactiMisi), takže se drží vždy jen jeden zámek. ⚠️ **Prohlédnuty byly všechny mise a týká se to jen dvou:** TrackMission a RobotourMission. FreeRunMission i MagCalMission nemají zámek **žádný** (a MagCalCollector taky ne), takže tam ten tvar vzniknout nemůže — dřívější tvrzení, že mají tentýž tvar, bylo mylné. Cesta WebStatus → AppendMagCal → MagCalWriteBlockedReason čte jen uloženou zprávu, ne misi. Hlídají to tři testy (MisePublikujeMimoZamekTests, jeden i v rigu Robotouru), které **prokazatelně chytají vrácenou vadu** — po dočasném vrácení publikace pod zámek spadly. Na zařízení od 18. 9. (binárka nasazená spolu s profilem a44b4f4): 18. 9. dvě volby mise Track ze stránky, 19. 9. na Robotouru nejméně osm voleb mise Robotour z telefonu s otevřeným, samoobnovujícím se náhledem — bez jediného záseku, kdežto 17. 9. nastal při jedné ze tří voleb. Důkaz je statistický (závod), deterministicky to kryjí testy.

  • Příčina určená z minidumpu (oba zásobníky, uzavřený cyklus zámků) 17. 9. 2026
  • Publikovat mimo zámek (Publikace() + Vypust()) v TrackMission i RobotourMission 17. 9. 2026
  • WebStatus.ToJson si stav mise ofotí předem (NactiMisi), ne pod vlastním zámkem 17. 9. 2026
  • Testy pořadí zámků (ověřeno vrácením vady — spadnou) 17. 9. 2026
  • Ověřit na zařízení (volba mise ze stránky při otevřeném náhledu) — 18. 9. 2× Track, 19. 9. ≥ 8× Robotour bez záseku; důkaz statistický 19. 9. 2026

headless.md, TrackMission.cs, WebStatus.cs, RelaySource.cs · DevLog 2026-09-17, 2026-09-18, 2026-09-19

Oblast

Hardware a senzory

Kamera D435 se za provozu odmlčí

otevřeno vada nalezeno 31. 8. 2026

Při prvním běhu aplikace na Pi se pravá D435 po ~4600 s odmlčela; odpojená nebyla, v jádře se opakovalo USBDEVFS_CLEAR_HALT. Rešerše 11. 9. ukázala, že je to cizí, Intelem nevyřešený problém, a naše léčba je to, k čemu dojdou všichni: hlídka zamrzlého streamu, zbourání pipeline a nové připojení, od 13. 9. supervizor zotavení s drženým zastavením — ověřený na robotu na skutečné poruše (obě kamery zpět za 29 s, dřív mrtvá kamera desítky minut). Je to obvaz, ne léčba: porucha přijde asi jednou za 17 minut. Hypotéza „může za to T265" padla 14. 9. měřením a CLEAR_HALT se ukázal jako šum, ne podpis poruchy; podezřelá je fyzická větev USB 2-1.3 (samostatné téma). Druhá epizoda 18. 9.: zamrzla barva pravé D435 (15:47:17) a supervizor ji vrátil za 32 s, robot stál.

  • 'Rešerše: cizí nevyřešený problém, propustnost USB ani sousedé na hubu to nejsou' 11. 9. 2026
  • Supervizor zotavení kamer s drženým zastavením, ověřen na skutečné poruše 13. 9. 2026
  • Vyvrátit hypotézu T265 / CLEAR_HALT měřením na zařízení 14. 9. 2026
  • Odstranit příčinu (kabel nebo port větve 2-1.3)
  • Jízdy 1. 10. 2026 (52 min, bez T265; ARBot.Analyze perf blok 6, cameras --vypadky): jedno zamrznutí ≥ 5 s (levá 15:21:44, restart pipeline, snímky zpět za 13,5 s), ~1s zamrznutí barvy pod hlídkou ve FreeRunu 33 za 10 min (29. 9. ~2,5/min, tedy neubyla). NOVÉ: **souběžné výpadky OBOU kamer** (snímky nechodí vůbec, IMU běží) — Track 15:12:37,6 +3,0 s, 15:18:18,3 +2,7 s, 15:21:29,9 +2,5 s, 15:25:57,2 +1,0 s; FreeRun 15:31:05,6 +3,1 s, 15:35:03,5 +3,4 s; v logu nic, hlídka zamrzlého streamu je nevidí, plánování během nich stojí (při 1,7 m/s ~5 m) a po těch delších (2,5–3,4 s) se smazal grid (detektor skoku pózy přes mezeru). 29. 9. žádný 7. 10. 2026

čeká na Tvrdé záseky kamer na větvi USB 2-1.3 · hardware.md, plan-drive-hold.md, rozhodnutí 11. 9. 2026 · DevLog 2026-08-31, 2026-09-06, 2026-09-11, 2026-09-13, 2026-09-14, 2026-09-18, 2026-10-07

Akcelerometr VN100 měří o 7 % víc než g

otevřeno vada nalezeno 6. 9. 2026

Vedlejší nález z rozboru kurzu: medián |a| je 10,51 m/s² proti 9,81, tedy +7 %, a sklon pole vychází 61–63° proti tabulkovým ~66°. Později se dohledal bias +0,27 m/s² v ose Z, registr 25 (kompenzace akcelerometru) je jednotkový. Při kalibraci magnetometru to zvedá rozptyl sklonu (proto sklon vypadl z brány verdiktu) a svislici natočí o ~1° při náklonu. Kalibrace akcelerometru je otevřený samostatný úkol. 12. 9. to nezávisle potvrdil živý senzor (registr 27 dává +7,3 %, registr 25 je jednotkový); z náklonů do 40° se ale elipsoida akcelerometru neurčí. 18. 9. 2026 beze změny: |a| v klidu 10,48 m/s² (+6,9 %), sklon pole 62,8–63,0° proti 65,95° z registru 21 — kalibrace magnetometru na to nesáhla, jak se čekalo.

  • Změřit bias ze záznamu a přečíst registr 25 12. 9. 2026
  • Kalibrace akcelerometru (registr 25)

imu-and-frames.md, plan-vn100-kalibrace.md · DevLog 2026-09-06, 2026-09-10, 2026-09-12, 2026-09-18

Po kalibraci zbývá konstantní posun kurzu −3,7°, který nejde rozložit

otevřeno vada nalezeno 12. 9. 2026

Po ověření kalibrace zůstal kurz VN100 proti GPS o −3,7° vedle. Není to železo (půlrozdíl mezi opačnými směry jen ∓1° a mezi běhy mění znaménko) ani deklinace (ta by rozpor zvětšila na −10°), a tímhle měřením se nedá rozložit na pootočení senzoru, zbytek kalibrace a šikmé jetí — na to je potřeba průjezd téhož úseku s robotem otočeným o 180°. Z živého senzoru se přitom zjistilo, že vestavěný model pole je zastaralý o ~1,9° (epocha ~2015), takže zbytek je ještě o tolik větší, a že registr 83 je ve flash, ačkoli se zapisuje bez uložení. Od 14. 9. byl kurz rozbitý železem od kabelů, takže měření mělo smysl opakovat až po nové kalibraci — ta proběhla 17. 9. 18. 9. 2026 první jízda po nové kalibraci: rozpor IMU − GPS kurz je zase na obou protilehlých kurzech stejný (−3,6 / −2,9° a −1,65 / −1,22°), tedy konstanta — ale **mezi dvěma běhy 13 minut po sobě jiná** (−3,4 proti −1,1° středně). Sedí to s dotahováním VPE po každém startu procesu (registr 83, ~100–170 s); průjezd s robotem otočeným o 180° to pořád nerozloží, ale ukazuje to, že hledaná „konstanta" je spíš pomalá proměnná.

  • Zbytek změřen a rozložen podle směru a místa 12. 9. 2026
  • Registry přečteny na živém senzoru (deklinace se aplikuje, model zastaralý) 12. 9. 2026
  • Průjezd téhož úseku s robotem otočeným o 180°

imu-and-frames.md · DevLog 2026-09-12, 2026-09-18

Tvrdé záseky kamer na větvi USB 2-1.3

otevřeno vada nalezeno 13. 9. 2026

Dvanáct z dvanácti tvrdých záseků kamery RealSense přišlo na témž fyzickém USB portu, ať na něm visela kterákoli kamera (13. 9. se schválně prohodily; přiřazení portu ke kameře je změřené přes CLEAR_HALT během výpadku). Hypotéza „může za to T265“ padla měřením 14. 9.: bez ní se CLEAR_HALT (7,4 → 7,1–7,9/min) ani zamrzání streamu (3,4 → 3,6–4,2/h) nezměnily — a CLEAR_HALT teče 3–15/min i ve zdravém stavu, takže jako měřidlo je mrtvý. Další krok je kabel nebo port, ne software: autor 14. 9. večer přesadil kameru na volný port téhož hubu (testuje větev, ne hub ani řadič); vyhodnocení v DevLogu zatím není — a nula záseků za hodinu nic neznamená, za 3 h čistého běhu už ano. 18. 9. 15:47 přišel tvrdý zásek pravé D435 — té přesazené (supervizor zasahuje až po 15 selhaných dotazech, tedy táž třída jako 12 z 12 na 2-1.3): buď zásek putuje s kamerou nebo kabelem, ne s portem, nebo je nový port na téže větvi. Port pravé kamery od 14. 9. zapsaný není (13. a 17. 9. se navíc hýbalo kabely kvůli magnetometru).

  • Prohodit kamery mezi porty a sbírat epizody (8 z 8 na 2-1.3) 13. 9. 2026
  • Běh bez T265 — hypotéza CLEAR_HALT vyvrácena, port potvrzen (12 z 12) 14. 9. 2026
  • Přesadit kameru z 2-1.3 na volný port téhož hubu 14. 9. 2026
  • Vyhodnotit přesazení: zjistit port pravé kamery od 14. 9. (/sys/bus/usb/devices/2-1.*/serial), spočítat čistý běh služby 14.–19. 9. a přiřadit k němu zásek 18. 9. 15:47
  • Podle výsledku kabel / jiná větev hubu / řadič

hardware.md, rozhodnutí 13. 9. 2026 (odpojení T265) · DevLog 2026-09-13, 2026-09-14, 2026-09-18

VN100 29. 9. — pole o 7 % slabší a kurz proti GPS −5,5 / +10,8°, ačkoli se na robotu nic neměnilo; jediná známá změna je ohřátí sluncem na 54 °C

otevřeno vada nalezeno 29. 9. 2026

Rozbor jízd 29. 9. 2026 v Modřanech (records/test/20260929-150844.rec Track na sever, -151634.rec FreeRun na jih; ARBot.Analyze heading, vn100) proti 25. 9. (20260925-142428.rec, -144658.rec) a 27. 9. (20260927-172546.rec, -173033.rec). **Velikost pole |B|** p50 **0,461 / 0,467 G** proti 0,494–0,505 G 25. a 27. 9. (reference 0,4897, po kalibraci 18. 9. 0,484–0,490), tedy o ~7 % méně; sklon 65,6–65,7° se nezměnil. **Kurz:** IMU yaw − GPS kurz p50 **−5,5°** (Track) a **+10,8°** (FreeRun, ke konci až +25°) proti −1,5 / +0,7° 25. 9. a −3,2 / −0,8° 27. 9. Chybuje IMU, ne GPS (Doppler − směr posunu polohy 0,6 / 0,5°). Fúze kurz drží podle kompasu (odhad − GPS kurz −3,3 ± 6,5° / +4,3 ± 11,2°) a koridor ho nekorigoval (lok-assoc-sousedni-usek), takže póza ujela od GPS příčně o 10 a 16 m. **Teplota senzoru** 47–54 °C proti 28–36 °C 25. a 27. 9.; s ní i offset syrového gyra (lok-freerun-kurz-staci-na-zapad). Opačné znaménko rozporu tam a zpět by ukazovalo na železo vázané na tělo robota, jenže na jih se v Track (+1,3 / +3,8°) a ve FreeRun (+10,9°) liší a ve FreeRun se yaw za 7 min odtrhl od vlastního pole (+1,3 → −22°), takže to může být i drift VPE. Harmonický rozklad nerozhodne: kurz měl v jízdách rozptyl jen 44° a 27°. **Autor 29. 9.: na robotu se nic neměnilo.** LED pásek (40 cm od senzoru, nesvítí) byl na robotu už při kalibraci 17. 9., takže jeho železo je v ní; nedokončená mission=magcal 28. 9. vrátila registr 23 shodný (hw-magcal-uncompmag-kompenzovany). Rušení závislé na proudu motorů zanedbatelné (0,00035 G/A). **Teplotu autor vysvětluje dlouhým stáním na přímém slunci** — a ta je jediná známá změna. **Rozklad chyby kurzu** (IMU yaw − GPS kurz = (kurz z pole − GPS kurz) − (kurz z pole − yaw), obojí z heading): (a) **směr samotného pole** proti GPS kurzu je 25. a 27. 9. +2,5 až +4,6° (≈ deklinace), 29. 9. **−0,8°** na sever a **+5,7°** na jih — posun ~3–4° s opačným znaménkem tam a zpět, tedy malý offset pole v tělese; (b) **za polem se táhne VPE**: kurz z pole − yaw 25. a 27. 9. +3,2 až +4,7°, 29. 9. +5,1° v Track, ale ve FreeRun **−6,6 ± 8,5°** a v čase +1,3 → −22°, zesílení k poli v Track K = 0,014 1/s (τ 71 s proti 28–53 s 18. 9.). V Track je tedy většina chyby ve směru pole, ve FreeRun ve VPE. **|B| proti teplotě** přes šest záznamů leží na jedné přímce ~**−1,8 mG/°C** (~−0,37 %/°C): 28–31 °C → 0,490–0,508 G, 33–36 °C → 0,492–0,496 G, 47–54 °C → 0,445–0,471 G; to by celý pokles o 7 % vysvětlilo. **Uvnitř jízdy to potvrdit nejde:** za 2–4 °C by se |B| měnila o 4–8 mG, jenže jinými vlivy (kurz, zbytkové železo) kolísá o ±10 mG i při stálé teplotě (25. 9. -144658 0,490 → 0,508 G při 30,8–31,2 °C); regrese po košících kurzu dává −7 až +9 mG/°C. **Pracovní hypotéza (neprokázaná):** ohřátí na 54 °C změnilo citlivost a offset magnetometru → pole o 7 % pod referencí registru 21 (0,4896 G) a o 3–4° jinam → VPE, které |B| s referencí porovnává, magnetometru méně věří a kurz se táhne za gyrem. Stejnoměrná změna citlivosti sama kurz neotočí — otočení dělá až offset (a), a ten je malý. Příčina neurčena.

  • Změřeno: |B|, IMU yaw − GPS kurz a teplota proti 25. a 27. 9. (heading, vn100) 29. 9. 2026
  • Zjistit, co se na robotu mezi 27. a 29. 9. změnilo v okolí VN100 a odkud je senzor o 20 °C teplejší. Autor 29. 9.: na robotu se nic neměnilo (LED pásek byl i při kalibraci 17. 9., 40 cm od senzoru, nesvítí); teplota = dlouhé stání na přímém slunci 29. 9. 2026
  • Rozklad chyby kurzu na směr pole a VPE a |B| proti teplotě přes šest záznamů 25.–29. 9.: napříč dny ~−1,8 mG/°C (vysvětlí celých 7 %), uvnitř jízdy nerozhodne (rozsah 2–4 °C, jiné vlivy ±10 mG) 29. 9. 2026
  • Měřidlo: ARBot.Analyze vn100 blok 7 — |B| proti teplotě senzoru po minutách a regrese v koších kurzu po 30° (od IMUState verze 5). Ověřeno nad 20260929-151634.rec a 20260925-144658.rec (čísla shodná s ručním rozborem); starší záznam bez teploty blok odmítne 29. 9. 2026
  • Záznamy 1. 10. 2026 (20261001-144638.rec, -152906.rec): senzor nebyl studený (start 50,5 °C), během Tracku chladl na 41,7 °C. Ve STEJNÉM místě a směru (49 košů po 20 m projetých dvakrát, ΔT −9 °C) bylo |B| vyšší o 19,9 mG (p10–p90 17,8–20,9), tj. **−2,2 mG/°C** — teplotní závislost pole je tím potvrzená uvnitř jízdy (zmatená už jen s dobou od zapnutí). Kurz s teplotou nesouvisí: na sever IMU − GPS −3,6° při 51 °C a −6,0° při 42 °C, na jih +3,1 až +3,7°; ujetí VPE (+12 až +23°, K = 0,0047 1/s, τ 215 s) přišlo v chladnější části jízdy. Otočka na místě v záznamech není 7. 10. 2026
  • Jízda s chladným senzorem (bez dlouhého stání na slunci): vrátí-li se |B| k ~0,49–0,50 G a IMU yaw − GPS kurz k −3 … +1°, je příčinou ohřátí; pokud ne, hledat dál (poloha kabelů ke kamerám). Nejčistší je týž pokus za studena a po ohřátí na témž místě s otočkou na místě — teplota se pak neplete s kurzem ani s místem
  • Minutový záznam s jednou otočkou na místě (rozpětí |B| přes otočku; 18. 9. zbytkové vodorovné železo 11–18 mG) — rozliší železo od driftu VPE; při železe nová mission=magcal

imu-and-frames.md, Vn100Report.cs · DevLog 2026-09-29, 2026-10-07

Napětí baterie z Roboteqa je na 4S LiFePO4 podezřele nízké (nikdy nad 12,6 V)

otevřeno vada nalezeno 6. 10. 2026

Při výběru nových článků (6. 10. 2026) se ukázalo, že napětí baterie z motorové jednotky (GetValue(_V, 2), tedy napětí baterie, ne vnitřní) nebylo v dokumentovaných záznamech nikdy nad 12,6 V — „po nabití" 12,5 V (Robotour 19. 9.), 1. 9. 12,3–12,6 V, 2. 9. 11,7–12,3 V. Baterie jsou čtyři články WINA LiFePO4 3,2 V / 15 Ah a 4S LiFePO4 má v klidu mezi ~20 a 90 % nabití 13,0–13,3 V; 12,5 V (3,12 V/článek) je ~10 %. Úbytek zátěží to není (elektronika ~1,6 A, jízda 5–10 A). Vysvětlení: (a) odchylka měření nebo úbytek na vedení k jednotce, (b) nenabitá baterie, (c) slabý nebo nevyrovnaný článek (např. 3 × 3,33 V + 2,5 V = 12,5 V). Na tom závisí, jestli nové články pomůžou, i jestli batwarn= 11,6 V „v údajích jednotky" varuje včas. Rozbor a varianty náhrady článků: hardware.md, „Napájení — trakční baterie".

  • Multimetr: napětí balíku na svorkách proti řádku „baterie [V]“ na stránce náhledu, po plném nabití a po jízdě
  • Multimetr: napětí každého článku zvlášť v klidu (zdravé a vyrovnané do ±0,03 V). Autor 7. 10.: **3,29 V na článek** (balík ~13,16 V, v ploché části křivky) — slabý ani nevyrovnaný článek to není 7. 10. 2026
  • Zjistit, jestli balík má BMS s vyvažováním. Autor 7. 10.: má jednoduchou BMS — vyvažuje, chrání články a umí baterii odpojit, stav nabití ani nic jiného nehlásí 7. 10. 2026
  • Měření stavu nabití a proudu z baterie: buď chytrá BMS s UART místo dnešní (JBD/Daly/JK), nebo dnešní BMS ponechat a přidat bočník s převodníkem (INA226/INA228 na I2C Orange Pi, náboj počítá náš software)
  • Stav článků (autor 7. 10.): po ~10 letech znatelný pokles kapacity a články jsou značně nafouklé — vyměnit za 4× WINA 15 Ah 7. 10. 2026
  • Koupit 4× WINA 3,2 V / 15 Ah a chytrou BMS (doporučení JBD-SP04S020, varianta 60 A — deska 138 × 102 mm se do prostoru baterie nevejde, montovat vedle), sestavit s vyrovnáním článků nahoře. BMS JBD-SP04S020 60 A objednána 8. 10. 2026 (autor)
  • Podle výsledku: přeladit batwarn=, případně driver BMS do HAL a stav baterie do záznamu

hardware.md · DevLog 2026-10-06

Dávka rámců motorů přečtená z bufferu po záseku hlásí rychlost kol 0 (a jednou 7,4 m/s) jako platné měření

otevřeno vada nalezeno 7. 10. 2026

Po záseku procesu 1. 10. 2026 (prov-zasek-procesu-1s) přečetl SDC2160Ex 111 rámců z bufferu za 7 ms. Mají HasMeasurement = true, ale rychlost se počítá jako Δenkodér / Δrazítko příchodu, a razítka jsou od sebe < 1 ms — rychlost kol tedy vyjde 0,000 (a jednou 7,39 / 7,50 m/s). Fúze tak může dostat „stojím" přes PLATNÉ rámce, tedy obchvat opravy hw-motor-chybovy-ramec. V HEAD to řeší interval z času jednotky (řádek T=, 9afb50c) — ale jen se skriptem ≥ 2.1 v jednotce; se starým skriptem vada trvá.

  • Nalezeno nad 1. 10. (rámce #166124–#166234, interval a rychlost) 7. 10. 2026
  • Ověřit na záznamu s binárkou ≥ 9afb50c a skriptem 2.1/2.2, že dávka po záseku dá rychlost z času jednotky

SDC2160Ex.cs · DevLog 2026-10-07

Driver NeoPixel (WS2812) přes SPI na Armbianu

v kódu, na HW neověřeno záměr nalezeno 7. 7. 2026 vyřešeno 7. 7. 2026

ArmbianSpiNeoPixelDriver posílá sub-bity LED pásku jedním zápisem přes /dev/spidev0.0; SpiDevice vstupuje jako parametr, vlastníkem je volající. Buildy pro OrangePI zelené, ale na desce nikdy neběželo — časování PulseConfig proti SPI hodinám a reálný běh animační smyčky (NeoPixelProcessor: blinkry, KnightRider, Alert) zbývá ověřit. Driver navíc není v runtime nikde založený: blok NeoPixel v ARBotHW.Init je od 11. 7. 2026 zakomentovaný (jen FTDI varianta pro Windows), takže na Pi by nesvítilo nic ani s hotovým driverem. Od 28. 9. 2026 ho ARBotHW na Orange Pi zakládá (neopixel=, výchozí true) a NeoPixelBridge mu podle pravidel z ARBot2 posílá stav robota (couvání, brzda, blinkry, nouzové zastavení z DriveCommandMsg, přední Alert při čekání na stisk stopu). Na robotu nasazeno, runtime posílá 20 snímků/s bez chyb, ale **pásek nesvítí** — příčina je fyzická (úroveň 3,3 V proti 5 V WS2812, zapojení), musí se přeměřit.

  • Driver + balíček System.Device.Gpio 7. 7. 2026
  • Založit driver v ARBotHW (Armbian), NeoPixelBridge podle ARBot2, hlášení poruch a zhasnutí při zastavení, pravidlo udev pro /dev/spidev0.0; 10 testů 28. 9. 2026
  • Nasazeno na Orange Pi: journal „LED pasek bezi“, statistika spi0 20 přenosů/s × 864 B bez chyb, SPI skutečně 6,25 MHz (200 MHz / 32) — časování v tolerancích 28. 9. 2026
  • Pásek nesvítí — přeměřit multimetrem (deploy/spitest.sh): na kterém pinu je MOSI (DIN je na GPIO1_B2) a jaká je úroveň; pak opravit POSTUP.md (uvádí MOSI = GPIO1_B1). 28. 9. večer puštěn vzor high (SPI 6,25 MHz, linka vytížená ~71 %), autor: měření vyžaduje rozebrat robota — odloženo

OrangePi5Ultra/POSTUP.md, deploy/README.md · DevLog 2026-06-23, 2026-07-07, 2026-09-28

Chybový rámec motorového driveru se tvářil jako měření

v kódu, na HW neověřeno vada nalezeno 27. 8. 2026 vyřešeno 15. 9. 2026

Když se z řídicí jednotky motorů nepodaří přečíst telemetrii, driver vyrábí zástupný rámec s nulami a příznakem stopu. Fúze z něj brala „stojím", panel vypisoval 0 V (na Pi to vypadalo jako blikání napětí) a automat mise si obnovení linky s nestisknutým tlačítkem vyložil jako „jeď". Rozlišuje to příznak HasMeasurement (MotorStateBase verze 3): mapper z takového rámce měření nevyrobí, panel drží poslední naměřené hodnoty, a od 15. 9. na něj hledí i automaty misí a držené zastavení. Stop z rámce platí dál (fail-safe). Projeví se jen na skutečném železe, virtuální motory chybovou větev nemají.

  • HasMeasurement v driverech a mapperu 27. 8. 2026
  • Panel motoru nevypisuje nuly z chybového rámce, řádek „Snímek" přizná chybějící měření 31. 8. 2026
  • Automaty misí a StopHold berou fail-rámec jako „žádná zpráva" 15. 9. 2026
  • Ověřit na zařízení při skutečném výpadku telemetrie
  • Track 1. 10. 2026 (20261001-144638.rec): dva fail-rámce (15:15:41,819 a 43,413) vznikly zásekem celého procesu 1,19 s (prov-zasek-procesu-1s), ne výpadkem jednotky. Fúze z nich „stojím“ nevzala (V min 0,567 m/s odpovídá kolům 0,46–0,60 m/s); pokles 1,9 → 0,57 m/s je skutečné zpomalení kol (watchdog jednotky, pak příkaz 0,51 m/s po smazání gridu). Automat mise ani StopHold fail-rámec neviděly (poslední stav ≤ 1 ms), jejich brány tedy ověřené nejsou. ⚠️ Obchvat: dávka 111 PLATNÝCH rámců po záseku má rychlost kol 0,000 (hw-motor-davka-po-zaseku) 7. 10. 2026

rozhodnutí 27. 8. 2026, hardware.md · DevLog 2026-08-27, 2026-08-31, 2026-09-15, 2026-10-07

Levá D435 po restartu pipeline (zamrzlá barva) úplně ztichla — vlákno kamery zatuhlo v nativním volání

v kódu, na HW neověřeno vada nalezeno 24. 9. 2026 vyřešeno 26. 9. 2026

records/test/20260923-143515.rec: ve 14:40:53 levé D435 zamrzla barva, driver ohlásil restart pipeline a pak už o ní nepřišlo nic — žádný dotaz, připojení ani chyba, žádné snímky; pravá jela do konce. Supervizor zotavení nezasáhl, protože kamera o nic nežádala (na rozdíl od záseků 12.–18. 9., kdy vlákno žilo a hlásilo QueryDevices selhalo). Vlákno tedy zatuhlo v nativním volání RealSense. Podezřelé místo: hlídka zamrzlého streamu bourala pipeline UVNITŘ using (frames) (s neuvolněným framesetem), ostatní cesty až po uvolnění — podezření, ne dokázaná příčina (13. 9. stejná cesta doběhla). Opraveno bourání až po uvolnění a přidán NativeCallWatch (Stop/Dispose/Start/QueryDevices u D435 i T265, limit hangwatch=), který při zatuhnutí zapíše, ve kterém volání vlákno visí, a pořídí minidump. **Opakovalo se 25. 9. 2026 DVAKRÁT, vždy levá D435, a NativeCallWatch to na zařízení zachytil:** 20260925-143643.rec 14:40:12 (zamrzla barva) a 20260925-144658.rec 15:08:12 (zamrzla hloubka) → restart pipeline → **pipeline.Stop se vrátil, pipeline.Dispose ne** (hlášení po 20 s, „nakonec doběhlo" nepřišlo nikdy) → minidumpy logs/hang-kamera-Left-740112071040-pipeline.Dispose-20260925-144033.dmp a …-150833.dmp na Pi. Levá kamera pak do konce záznamu neposlala snímek (66 s, resp. 118 s), pravá jela dál. Probrala se až restartem procesu (/stop ze stránky → systemd). V 20260925-144200.rec zamrzly obě kamery a restart pipeline doběhl (obě zpět do 15 s). Oprava z 24. 9. (bourat až po uvolnění framesetu) tedy zatuhnutí **neodstranila** — visí přímo nativní Dispose. **Rozbor dumpů 26. 9. 2026** (gdb přímo na Pi, všechny tři dumpy z 25. 9. včetně ranního Right …-070157): visící vlákno je vždy rs2_delete_pipeline → ~pipeline → ~device_hub → context::stop → polling_device_watcher::stop → dispatcher::stop → std::mutex::lock, tedy rušení pipeline čeká, až doběhne kolo **hlídače zařízení** RealSense kontextu. To kolo je zaměstnané výčtem USB (query_uvc_devices → libusb_init_context → udev_enumerate_scan_devices, v okamžiku dumpu uvnitř libudev). V prvním dumpu k tomu jiné vlákno ze spravovaného kódu dělá rs2_create_device → rs435_device — to je **hon na odpojenou T265** (RealSenseShared.Query, ~1×/s): Context.QueryDevices() bere všechny řady (maska 0xfe) a čtení d.Info[…] každé zařízení plně vytvoří a otevře jeho UVC rozhraní, **i obě D435**. U streamujících to končí „failed to set power state" (odtud ta hláška v logu), ale uvolněnou levou D435 po pipeline.Stop to skutečně otevře a zavře: kernel log od 14:40:13 / 15:08:12 ukazuje Found UVC … 2-1.2 každých ~1–2 s bez konce (pravá 2-1.4 ne). Každé otevření vyvolá udev události, hlídač zařízení pořád vyčítá a Dispose se k jeho mutexu nedostane. **Navržená léčba:** hon na T265 omezit na její produktovou řadu (rs2_query_devices_ex s maskou RS2_PRODUCT_LINE_T200 = 0x10), aby se D435 při něm vůbec nevytvářely. ⚠️ Vedlejší hypotéza: hon sahal na streamující D435 ~1×/s i během měření 14. 9. „bez T265" (kamera byla odpojená, hon běžel dál), takže jeho vliv na samotné zamrzání streamů změřený **není**.

  • Bourat pipeline až po uvolnění framesetu + NativeCallWatch s minidumpem 24. 9. 2026
  • Na zařízení: sledovat, jestli se zatuhnutí opakuje — 25. 9. dvakrát (levá D435, visí pipeline.Dispose), minidumpy pořízené 25. 9. 2026
  • Přečteny minidumpy z Pi (gdb): Dispose čeká na mutex hlídače zařízení, ten je zaměstnaný výčtem USB, který živí hon na T265 přes všechny produktové řady 26. 9. 2026
  • Léčba (autor): T265 driver se nezakládá (ARBotHW, zakomentováno s odůvodněním) — T265 je od 14. 9. odpojená, hon tím zmizí 26. 9. 2026
  • Zpětně v záznamech z Robotouru (cameras --vypadky): táž vada už 19. 9. — Kolo3-navrat 14:36:55 levá D435, barva stála 5 s → restart pipeline → „pipeline pripojena“ nepřišlo, levá mlčela do konce záznamu (172 s, návrat do depa dojet na pravou kameru); v Kolo3a 14:06:30 tentýž restart doběhl (snímky zpět za 2,7 s). Kolo3b bez 5s zamrznutí, ale 147 krátkých (≤ 1,1 s, razítko barvy z driveru stojí) pod prahem hlídky 26. 9. 2026
  • Ověřit na zařízení: po zamrznutí a restartu pipeline se kamera vrátí (žádné NativeCallWatch hlášení), kernel po Stop bez opakovaného Found UVC; a jestli ubylo samotných zamrznutí
  • Záznamy 29. 9. (20260929-150844.rec, -151634.rec, 13,7 min, bez T265): jedno zamrznutí — pravá D435 15:18:10 barva stála 5 s → restart pipeline → 15× QueryDevices selhalo: failed to set power state → supervizor zotavení (držené zastavení 2 s, nový RealSense kontext) → obě D435 zpět 15:18:39, tedy **29 s**, bez NativeCallWatch. Restart pipeline sám kameru nevrátil, vrátil ji supervizor. Jinak jen krátká zamrznutí barvy ~1 s (10 + 5 a 13 + 6×). Kernel log z Pi neprověřen 29. 9. 2026
  • Průběžně z journalu Pi (28. 9., 14.–28. 9.): bez T265 zatím jen 1,2 h běhu a 5 restartů — všech 5 obnoveno, 4 do 5 s (80 %; s T265 20 % z 49, medián 33 s, 7× neobnoveno do konce služby, 6× NativeCallWatch), 1 přes supervizor za 29 s, žádné NativeCallWatch. Četnost zamrznutí beze změny (4,1 proti 3,2 za h, n = 5). Slibné, ale jedno ráno — přeměřit po delším provozu 28. 9. 2026
  • Rozhodnout léčbu zatuhlého vlákna — autor: nic neléčit, jen zapsat důkaz (restart služby by přerušil misi; decisions.md 24. 9.) 24. 9. 2026
  • Záznamy 1. 10. 2026 (20261001-144638.rec + -152906.rec, 52 min, bez T265): jedno zamrznutí ≥ 5 s — levá D435 15:21:44 barva stála 5 s → restart pipeline → 15:21:57 „pipeline připojena“, bez snímků 13,5 s, bez NativeCallWatch (limit 20 s, takže to znamená jen „žádné volání nad 20 s“) a bez supervizoru. Krátká zamrznutí barvy (~1 s) ve FreeRunu 33 za 10 min (29. 9. ~2,5/min) — neubyla. Kernel log neprověřen (n = 1, ověřovací krok zůstává) 7. 10. 2026

hardware.md, NativeCallWatch.cs, rozhodnutí 24. 9. 2026 · DevLog 2026-09-24, 2026-09-26, 2026-09-28, 2026-09-29, 2026-10-07

Rampa motorové jednotky je 2,6× strmější, než říká Profile.MaxAcceleration

v kódu, na HW neověřeno vada nalezeno 5. 10. 2026 vyřešeno 5. 10. 2026

Nalezeno při rozboru rozjezdu po uvolnění holdu a nouzového zastavení (ARBot.Analyze hold --estop). Kola zrychlují ~1,0–1,3 m/s², ačkoli runtime nastavuje jednotce Profile.MaxAcceleration (0,40 m/s², do 27. 9. 2026 0,50). Příčina je v převodu jednotek: MotorAcceleration.ToUnits počítá 600·a/obvod, tedy jednotky Roboteq příkazu !AC (0,1 ot/min za sekundu), ale SDC2160Ex.SetAcceleration to číslo posílá do proměnné MicroBasic skriptu (!VAR 1/2), který ho přičítá jako time[ms]·acceleration k rychlosti v miliontinách plného rozsahu (MaxTheoreticalSpeed = 2,16 m/s). Skutečná rampa je tedy jednotky · 2,16 / 1000 = **1,04 m/s²** pro 0,40 (482 jednotek) a **1,30 m/s²** pro 0,50 — činitel 0,6 · MaxTheoreticalSpeed / obvod = 2,6. Naměřeno: 29. 9. kola 0,04 → 0,57 m/s za 0,5 s (≈ 1,06 m/s²), 25. 9. ≈ 1,2 m/s². Táž hodnota jde do zpomalení (skript ji bere pro obě strany rampy), takže i nouzové dobrzdění jednotky je 2,6× strmější. Plánovač a profil pohybu přitom počítají s 0,40 m/s² — u brzdění je to konzervativní, u modelu rozjezdu ne. ⚠️ Oprava převodu by zpomalila rozjezd robota 2,6× proti dnešku — je to změna chování, ne jen kosmetika; rozhoduje autor. ✅ **Převod opraven 5. 10. 2026 (autor: „určitě je potřeba opravit převod"):** MotorAcceleration.ToScriptUnits = 1000·a / MaxTheoreticalSpeed (0,40 m/s² → 185 jednotek místo 482), SDC2160Ex ho používá; ToUnits zůstává pro nativní !AC u SDC2160. Skript v jednotce se nemění (oprava je v hodnotě, kterou posílá hostitel). Profile.MaxAcceleration zůstal 0,40 m/s² — ⚠️ **pod nouzovým zastavením tím jednotka brzdí 0,40 místo 1,04 m/s²**, takže z maxspeed=1.7 je brzdná dráha **~3,6 m místo ~1,4 m**; hodnotu rozhoduje autor. ✅ **Týž den rozděleno (autor: oddělit akceleraci při běžném provozu od nouzového zastavení):** skript jednotky 2.2 má rampy zvlášť — běžná jízda (VAR 1/2, jedna rampa pro rozjezd i brzdění; samostatné běžné brzdění VAR 8 i Profile.MaxDecceleration autor 6. 10. zrušil kvůli symetrii) a nouzové zastavení i watchdog (VAR 9, Profile.EmergencyDeceleration 1,0 m/s², tedy to, s čím robot fakticky brzdil celé září). Nouzová rampa je ve **skriptu**, protože nouzové zastavení obsluhuje jednotka i bez hostitele; nula v proměnné ji nezmrazí (výchozí hodnoty ve skriptu) a skript ji hlásí řádkem ED=. ⚠️ **Do jednotky se skript musí nahrát ručně** a do té doby by nová binárka brzdila pod stopem jen 0,40 m/s² — driver to hlásí do Trace. Detail: doc/hardware.md.

  • Změřeno ze záznamů a dopočteno z převodu jednotek: rampa 1,04 m/s² místo 0,40 5. 10. 2026
  • Rozhodnout (autor): opravit převod pro SDC2160Ex (jednotky = 1000·a / MaxTheoreticalSpeed) a případně zvednout MaxAcceleration na skutečně chtěnou hodnotu, nebo dnešní 1,04 m/s² zapsat jako skutečnost do Profile. Autor: opravit převod; v kódu (MotorAcceleration.ToScriptUnits, 3 nové testy) 5. 10. 2026
  • Rozhodnout (autor) hodnotu Profile.MaxAcceleration po opravě: 0,40 m/s² znamená pod nouzovým zastavením brzdnou dráhu ~3,6 m z 1,7 m/s (dřív ~1,4 m); táž hodnota jde do plánovače (LatencyMotionProfile, MaxDecceleration zvlášť). Autor: oddělit běžnou akceleraci od nouzového zastavení — skript 2.2 (VAR 9 nouzové + watchdog, výchozí hodnoty ve skriptu, řádek ED=), MotorRamps/IMotorControl.SetRamps, Profile.EmergencyDeceleration 1,0 m/s², driver hlásí starý skript do Trace, simulace brzdí pod stopem nouzovou rampou; testy HAL +5, Common +3. 6. 10. (autor): běžná jízda jen MaxAcceleration — VAR 8, MotorRamps.Deceleration i Profile.MaxDecceleration zrušeny, pole obálky plánovače přejmenováno na LocalPlannerConfig.MaxAcceleration 5. 10. 2026
  • Nahrát skript 2.2 do motorové jednotky (Roborun+) a v Trace ověřit hlášení ED= (1,00 m/s², shodné s nastavením)
  • Ověřit na zařízení: zrychlení kol při rozjezdu ~0,40 m/s², brzdění pod nouzovým zastavením ~1,0 m/s² (z 1,7 m/s ~1,4 m) a při watchdogu (ARBot.Analyze hold --estop); případně změřit, jestli jde nouzová rampa strměji bez prokluzu a s nákladem

SDC2160Ex.cs, MotorAcceleration.cs, plan-drive-hold.md · DevLog 2026-10-05

Driver chytré BMS JBD — stav nabití, proud a články do záznamu a na stránku

v kódu, na HW neověřeno záměr nalezeno 8. 10. 2026 vyřešeno 8. 10. 2026

Nová BMS JBD-SP04S020 (60 A, objednána 8. 10. 2026) hlásí stav nabití z počítání náboje, proud z baterie, napětí článků, teplotu a příznaky ochran; dnešní jednoduchá BMS nehlásí nic a napětí z motorové jednotky je u LiFePO4 špatné měřidlo. Rozsah (autor): jen vidět a zaznamenat — nic se podle toho neřídí, varování přejde z napětí na procenta (batwarnsoc=). Jen čtení, připojení přes USB–RS485. Dvě vrstvy: JbdProtocol (bajty, testovatelné bez HW) a tenký driver JbdBms. Návrh: plan-bms-jbd.md, kroky: plan-bms-jbd-kroky.md. **V kódu 8. 10. 2026:** fáze 1–3 (testy Common 1 801, HAL 172, Runtime 161; po finální kontrole opraveny dvě vady), ověřeno headless se simulovanou BMS (batwarnsoc=90 → „baterie 80 % (práh 90 %) — NABÍT" a hláška do Trace). Výchozí UartBms= je prázdný, takže bez profilu se BMS nezakládá. ⚠️ Na zařízení neběželo — BMS ještě nedorazila; rozložení bajtů je z veřejné dokumentace.

  • Fáze 1 — JbdProtocol, zpráva BmsState, BmsProtection, registrace v katalogu záznamu; testy na pevných bajtech 8. 10. 2026
  • Fáze 2 — driver JbdBms, IBms, parametr UartBms, ARBotHW (real i virtual), zdroj zpráv, stáří měření na stránce, VirtualBms v panelu 8. 10. 2026
  • Fáze 3 — BatteryMonitor podle stavu nabití (batwarnsoc=), řádky na stránce náhledu, hlášky do Trace 8. 10. 2026
  • Fáze 4 — na zařízení: zachytit skutečné rámce do testů, porovnat s aplikací v mobilu, cesta by-id do profilu
  • Fáze 5 (volitelně) — ARBot.Analyze battery: spotřeba ze záznamu (průměrný a špičkový proud, Wh/km)

plan-bms-jbd.md, plan-bms-jbd-kroky.md, hardware.md · DevLog 2026-10-08

Zprovoznění cílové desky Orange Pi 5 Ultra (Armbian, RealSense, USB, SPI, GPU, WiFi)

hotovo záměr nalezeno 23. 6. 2026 vyřešeno 23. 6. 2026

Bring-up hardwarové platformy robota mimo aplikaci: librealsense 2.53.1 zkompilovaná ze zdrojů (poslední verze s D435 i T265, flagy pro GCC 15 / CMake 4), „mrtvý" USB3 port oživený overlayem dwc3-host (OTG řadič byl v peripheral režimu), SPI pro NeoPixel, GPU overlay panthor-gpu (softwarový rendering 198 % → 11 % CPU), WiFi přes iwd kvůli selhávajícímu WPA2 handshake s Rockchip driverem, Samba a RustDesk. Celé je to zachycené jako idempotentní skript setup-orangepi.sh pro případ reinstalace. Práce běžela ~17.–23. 6., v gitu je jen kotva 23. 6.

  • RealSense 2.53.1 ze zdrojů, D435 i T265 ověřené rs-enumerate-devices 23. 6. 2026
  • USB3 OTG port do host režimu, SPI overlay, GPU overlay, WiFi na iwd 23. 6. 2026
  • Idempotentní setup-orangepi.sh + POSTUP.md 23. 6. 2026

OrangePi5Ultra/POSTUP.md, setup-orangepi.sh, hardware.md · DevLog 2026-06-23

HAL vrstva a platforma OrangePI — jedna aplikace pro Windows i ARM64

hotovo záměr nalezeno 30. 6. 2026 vyřešeno 24. 7. 2026

Hardwarový kód se oddělil do ARBot.HAL (sdílené) + HALWindows / HALArmbian, kamery a IMU se přepsaly z WPF Media3D na System.Numerics, takže aplikace ani HAL netáhnou WPF a zůstávají net10.0. Přibyla platforma OrangePI (Armbian/ARM64) s vlastním HAL a druhou verzí RealSense wrapperu (2.53 na ARM proti 2.47 na Windows — managed wrapper musí verzí sedět na nativní knihovnu, minor rozdíl není ABI-kompatibilní). D435 běžela v aplikaci na skutečném Orange Pi 5. 7.; VN100 (VectorNav.dll je MSIL, jde i na ARM) a T265 se doplnily 13. 7., sjednocené zapojení senzorů v ARBotHW s větví pro OrangePI 24. 7.

  • Projekty HAL v buildu, Uart na System.IO.Ports, WPF → System.Numerics, HALWindows bez -windows 30. 6. 2026
  • Platforma OrangePI, HALArmbian s RealSense 2.53, D435 ověřena v aplikaci na Orange Pi 5. 7. 2026
  • Reorganizace HAL do Devices/* a sjednocení namespace 7. 7. 2026
  • VN100 a T265 v ARM buildu 13. 7. 2026
  • Sjednocené zapojení senzorů v ARBotHW (port parametrem) s větví pro OrangePI 24. 7. 2026

build-and-platforms.md, architecture.md · DevLog 2026-06-30, 2026-07-02, 2026-07-05, 2026-07-07, 2026-07-13, 2026-07-24

GPS četla UBX zprávy po částech a ztrácela synchronizaci

hotovo vada nalezeno 13. 7. 2026 vyřešeno 13. 7. 2026

UBXMessage.Parse četl payload jedním Read(buf, 0, len), který na sériovém portu vrátí i méně bajtů, takže se parser rozjížděl a data chodila nerovnoměrně. Nahrazeno blokujícím čtením celé délky; fixy chodí plynule ~10 Hz. Rozhraní IGPS a IMotorControl při tom dostala událost MeasurementArived.

hardware.md · DevLog 2026-07-13

Kamery RealSense odolné proti odpojení a znovupřipojení za běhu

hotovo záměr nalezeno 13. 7. 2026 vyřešeno 6. 9. 2026

T265 i D435 se připojují líně ve vlastní smyčce, odpojení poznají přes QueryDevices a timeout TryWaitForFrames (T265 se odpojení projeví jen timeoutem, ne výjimkou), pipeline zboří a znovu postaví bez busy-loopu; IsError říká „nepřipojeno". Na obou platformách. Na zařízení mechanismus reconnectu prokazatelně běží (journal 6. 9. počítá reconnecty). Výpadky D435 za provozu se ale ukázaly jako širší, Intelem nevyřešený problém — zamrzlý stream, supervizor zotavení kamer a vadná USB větev jsou navazující samostatná témata.

  • T265 lazy reconnect 13. 7. 2026
  • D435 lazy reconnect na obou platformách 21. 7. 2026
  • Ověřeno na zařízení (reconnecty v journalu) 6. 9. 2026

hardware.md · DevLog 2026-07-13, 2026-07-21, 2026-09-06, 2026-09-11

Obava, že librealsense 2.53 už T265 nepodporuje

hotovo vada nalezeno 13. 7. 2026 vyřešeno 11. 9. 2026

Při portu T265 na Armbian se zapsalo riziko „T265 byl v librealsense 2.50+ odebrán, podporu v 2.53 nutno ověřit na HW", a build-and-platforms.md to vedl jako otevřenou otázku. Rešerše 11. 9. ukázala, že to byl omyl: v2.53.1 má src/tm2 a T265 vypadl až ve 2.54.1; 2.50 je jen poslední validovaná verze. Na zařízení T265 3. 9. skutečně nabootovala. Sedíme tedy na stropu verzí, nahoru ani dolů nemá smysl. (Že se T265 13. 9. odpojila natrvalo, je jiné rozhodnutí.)

  • T265 běží na zařízení 3. 9. 2026
  • Rešerše a oprava tvrzení v dokumentaci 11. 9. 2026

build-and-platforms.md, hardware.md · DevLog 2026-07-13, 2026-07-30, 2026-09-11

Nulové nebo záporné zrychlení motorů prošlo do řadiče

hotovo vada nalezeno 18. 8. 2026 vyřešeno 26. 9. 2026

Drivery posílaly hodnotu zrychlení bez kontroly — záporná prošla (rampa diverguje až na plnou rychlost opačným směrem), malá se zaokrouhlila na nulu a nula za jízdy znamená, že nouzové zastavení nemá čím zabrat. Pojistka ve skriptu jednotky by robota stejně nezastavila. Nově společný převod MotorAcceleration.ToUnits (velikost, minimum 1); skript RizeniDiffPodvozku.mbs byl dosynchronizován a 30. 8. nahrán do jednotky. Na robotu funguje dobře (potvrdil autor 26. 9. 2026).

  • MotorAcceleration.ToUnits v obou driverech, 5 testů 18. 8. 2026
  • Skript nahrán do motorové jednotky 30. 8. 2026
  • Ověřit nouzové zastavení a rampu na robotu 26. 9. 2026

MotorAcceleration.cs, hardware.md · DevLog 2026-08-18, 2026-08-30, 2026-09-26

Kamery RealSense nešly za řetězem dvou USB hubů

hotovo vada nalezeno 30. 8. 2026 vyřešeno 30. 8. 2026

T265 se nezobrazila vůbec a D435 hlásily „no frames received" — vypadalo to na softwarovou vadu, ale hardware byl v pořádku. Obě D435 visely za řetězem dvou USB3 hubů a při současné inicializaci se praly o zdroj (pokaždé selhala jiná). Změřeno skriptem rs-bench: za dvěma huby 0 z 5, přímo na desce 10 z 10, za jedním napájeným hubem 10 z 10. Vadí tedy až dva huby za sebou, ne hub sám; robot jede na jednom napájeném hubu. Dvě zamítnuté hypotézy (napájení, uvcvideo) jsou v postupu zapsané.

  • Změřit varianty zapojení rs-bench (5 běhů na variantu) 30. 8. 2026
  • Přepojit na jeden napájený hub, obraz potvrzen autorem 30. 8. 2026

OrangePi5Ultra/POSTUP.md (krok 9), hardware.md · DevLog 2026-08-30

Sériové porty periferií na Orange Pi byly jen odhad — a špatný

hotovo vada nalezeno 31. 8. 2026 vyřešeno 31. 8. 2026

V kódu pro ARM64 byl jen odhad /dev/ttyS0 pro IMU a motor s GPS neměly port vůbec, takže by se na Pi nezaložily. Skript find-serial-ports.sh porty najde pasivně (bez zápisu do nich) a vypíše hotové parametry: všechny tři periferie visí na USB (VN100 přes CP2102, Roboteq a u-blox jako USB CDC), /dev/ttyS0 na RK3588 neexistuje. Do kódu šla jména z /dev/serial/by-id, protože čísla ttyACM* závisejí na pořadí enumerace a prohození GPS s motorem by bylo tiché. Ověřeno na zařízení dekódováním streamu VN100 a týž den během aplikace s reálnými drivery (GPS 9,99 Hz, IMU 8 kB/s, motor 386 řádků/s).

  • Skript find-serial-ports.sh, porty by-id v ARBotHW.Init 31. 8. 2026
  • Aplikace na Pi s reálnými drivery všech tří UART senzorů 31. 8. 2026

hardware.md, find-serial-ports.sh · DevLog 2026-08-31

GPS ztrácela 92 % měření, protože se port četl po jednom bajtu

hotovo vada nalezeno 31. 8. 2026 vyřešeno 31. 8. 2026

Autor viděl GPS na 0,8 Hz s občasným skokem na 3,2 Hz; první vysvětlení „u-blox má výchozích 1 Hz" bylo hádání. Přijímač ve skutečnosti jede 10 Hz a k tomu posílá ~200 NMEA vět za sekundu, ale Uart.Read(int) bral z portu jeden bajt a při prázdném portu spal 10 ms. Změřeno vedle sebe na zařízení: 0,88 proti 10,09 měření/s. Čtení si teď bere všechno, co v portu je, do vnitřního bufferu; ostatní způsoby čtení buffer nejdřív vyprázdní, aby se styly nemíchaly. Ověřeno na zařízení reálnými drivery (GPS 9,99 Hz, IMU i motor beze změny). Vypnutí NMEA v přijímači (87 % dat) se vědomě neudělalo — vada byla v našem čtení.

  • Změřit přijímač proti driveru na volném portu 31. 8. 2026
  • Vnitřní buffer v Uart.Read(int), ověřeno na zařízení 31. 8. 2026

rozhodnutí 31. 8. 2026, hardware.md · DevLog 2026-08-31

Zaseknutá kamera D435 se tvářila zdravě navždy

hotovo vada nalezeno 1. 9. 2026 vyřešeno 1. 9. 2026

Při dořešení odmlčené pravé kamery z 31. 8. se našly dvě vady v driveru: kamera, které přestaly chodit snímky, z USB nezmizela, takže se pipeline nikdy nezbourala a panel hlásil OK; a selhání dotazu na USB (failed to set power state) se hlásilo jako „kamera odpojena", což by poslalo člověka hledat kabel. Nově se počítají timeouty po sobě a po třech se pipeline restartuje (StallRestarts), dotaz na přítomnost umí říct „nevím". Hlavní příčina 31. 8. byla ale fyzická (port 4 hubu), kód je záchranná síť — a ta 13. 9. skutečnou poruchu opravdu zachytila.

  • Zásek podle počtu timeoutů, restart pipeline, DevicePresent jako bool? 1. 9. 2026
  • Ověřeno na zařízení s uměle zkráceným timeoutem 1. 9. 2026
  • Zachytilo skutečný zásek za provozu (obnova kamer za 29 s) 13. 9. 2026

hardware.md, rozhodnutí 1. 9. 2026 · DevLog 2026-09-01, 2026-09-13

Kamery se po bootu vyčetly jen na USB 2.0 a robot byl bez vidění

hotovo vada nalezeno 2. 9. 2026 vyřešeno 30. 9. 2026

Obě D435 se po bootu hlásily jen rychlostí USB 2.0, na které se hloubka a barva nevejdou ani pro jednu kameru — robot tedy neviděl nic a kernel si nestěžoval. Odpojení a zapojení linku vrátilo na 5 Gbps. Domněnka o nedovřeném konektoru padla (autor s kabely nehýbal); jde o SuperSpeed linku, která se při bootu nenatrénuje. Série restartů na nabíječce dala 6× dobře, jediná stopa je napájení (selhání přišlo na dosluhující baterii). Od 11. 9. driver typ linky hlásí a na USB 2.0 varuje i s léčbou; měření na baterii se neudělalo. ✅ **Uzavřeno 30. 9. 2026 (autor): od 2. 9. se to neopakovalo** — a série startů na baterii v principu proběhla při testech v terénu. Doloženo i záznamy: všech 27 jízd 12.–29. 9. nese snímky z OBOU kamer s hloubkou i barvou (vzorek ~200 snímků na záznam, 100 %; na USB 2.0 by D435 neposlala obojí), kde je připojení kamery v záznamu, driver hlásí USB 3.2 (29×) a hláška o USB 2 není v žádném. Příčina neurčena; kdyby se vrátilo, ohlásí to UsbLinkCheck.

  • Fyzické přepojení kamer, ověřeno 30/30 fps 2. 9. 2026
  • Studený start a pět teplých restartů na nabíječce (6× dobře) 2. 9. 2026
  • Driver hlásí typ USB linky (UsbLinkCheck), varování na USB 2.0 11. 9. 2026
  • Zopakovat sérii startů na baterii bez nabíječky — v principu proběhla při testech v terénu (autor 30. 9.: starty na baterii 12.–29. 9.), vada se od 2. 9. neopakovala, záznamy všechny na USB 3.2 30. 9. 2026

hardware.md, OrangePi5Ultra/POSTUP.md · DevLog 2026-09-02, 2026-09-11, 2026-09-30

Tři drivery se třemi kontexty RealSense bootovaly T265 naráz a shodily proces

hotovo vada nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

První pád rozebraný z minidumpu: SIGSEGV v librealsense při bootu firmwaru T265, když zařízení mezi enumerací a otevřením změnilo USB identitu. U nás k tomu docházelo proto, že každý ze tří driverů kamer měl vlastní Context a každý dotaz na zařízení spouštěl boot T265 — tři konkurenční bootery nad běžícími streamy. Léčba RealSenseShared: jeden kontext, všechny dotazy pod jedním zámkem, T265 se nabootuje synchronně před D435, k tomu hardware reset při zaseknutém stavu. Nasazeno na Pi týž den; hardware reset se 13. 9. na robotu zkusil (T265 v rozbitém stavu nespravil, to umí jen fyzické přepojení).

  • RealSenseShared — jeden kontext, zámek, boot T265 před D435 3. 9. 2026
  • Hardware reset T265 v driveru 3. 9. 2026
  • Nasazeno a běží na Pi 3. 9. 2026

hardware.md · DevLog 2026-09-03, 2026-09-13

Když se kamera nedá znovu vyčíst, proces roste v paměti

hotovo vada nalezeno 6. 9. 2026 vyřešeno 30. 9. 2026

Po nasazení levá kamera nenaběhla a QueryDevices hlásil „failed to set power state" ~0,7× za sekundu; běh s 93 selháními vyšplhal na 1,8 GB proti 130–140 MB, tedy ~25 MB na jeden neúspěšný dotaz. Managed strana je v pořádku (vše v using), roste to na nativní straně, takže léčba není dozavírat, ale přestat se ptát každou sekundu. Restart služby kameru vrátil. 14. 9. runtime hledal odpojenou T265 ~1× za sekundu (7 829 řádků za 168 minut) — dotaz přes sdílený zámek jde dál, a 17. 9. se ukázalo, že hlášky marného dotazu tečou i do záznamu (140 s po zatuhnutí). Rozpor k přeměření: 14. 9. běh se 7 829 selháními T265 paměťově nevadil, takže růst ~25 MB na dotaz je buď vázaný na zapojenou, ale zaseknutou D435 („failed to set power state"), nebo měl 6. 9. jinou příčinu. ✅ **Uzavřeno 30. 9. 2026 (autor): od 6. 9. se neopakovalo a driver dnes vypadá jinak.** Supervizor zotavení (od 13. 9.) vymění RealSense kontext po 15 marných dotazech, takže série selhání končí po ~15 s místo 93 dotazů (všechny pozorované epizody se vrátily, naposledy 29. 9. za 29 s), a od 26. 9. se nehledá odpojená T265. ⚠️ **Zbytkové riziko vědomě ponecháno:** když zotavení u kamery vzdá (3× marně za 15 min), D435Camera se ptá dál každou sekundu bez konce (ReconnectPeriodMs) — kdyby růst ~25 MB na dotaz platil, je to scénář z 6. 9. Backoff ani paměť procesu v PerfMsg autor nechce (30. 9.); růst paměti ze záznamu změřit nejde.

  • Backoff dotazů QueryDevices po selhání — nahrazeno supervizorem zotavení kamer (13. 9.), backoff po vzdání zotavení autor 30. 9. nechce 30. 9. 2026
  • Změřit růst paměti při trvale selhávajícím dotazu (T265 chybí / D435 zaseknutá) a jestli končí pádem — nedělá se (autor 30. 9.): od 6. 9. se neopakovalo, T265 se od 26. 9. nehledá 30. 9. 2026

hardware.md · DevLog 2026-09-06, 2026-09-14, 2026-09-17, 2026-09-30

Pravá D435 posílala pořád tentýž barevný snímek a nikdo to nepoznal

hotovo vada nalezeno 6. 9. 2026 vyřešeno 6. 9. 2026

V 11minutovém záznamu měla pravá kamera jeden různý barevný obraz ze sta, hloubka jela; snímky chodily 10 Hz, stránka svítila zeleně a occupancy grid i mise běžely nad nehybnou fotkou. Vada je v librealsense/USB (stojí i razítko), naše kopie je v pořádku. Léčba: StreamFreezeWatch hlídá razítka a při stání přes 5 s zboří pipeline; přibyl rozbor ARBot.Analyze cameras. Regrese z téhož dne (hlídka četla razítko z už uvolněného framu a shodila každý grab) se našla náhodou v journalu a opravila; s opravou na robotu 0 chyb. Že se kamera restartem probere, ukázalo až zotavení kamer z 13. 9.

  • ARBot.Analyze cameras a nález nad záznamem 6. 9. 2026
  • StreamFreezeWatch na obou platformách 6. 9. 2026
  • Regrese (frame uvolněný před čtením razítka) opravena a ověřena na robotu 6. 9. 2026

hardware.md, record-replay.md · DevLog 2026-09-06, 2026-09-12, 2026-09-13

Kurz z VN100 byl o −59° vedle, protože senzor přišel o konfiguraci

hotovo vada nalezeno 6. 9. 2026 vyřešeno 6. 9. 2026

Čtyři dny předtím kurz seděl na −0,25°. Ze záznamu se dokázalo, že chyba není v GPS, v kódu ani v gyru, ale v atitudovém řešení senzoru — a ten si přitom hlásil nejistotu 0,23°, kterou fúze brala doslova. Read-only deploy/vnprobe.sh na živém senzoru našel dva změněné registry: heading mode Relative místo Absolute (yaw k místu náběhu, ne k severu) a vymazanou kalibraci magnetometru. vnrestore.sh obojí obnovil do flash; heading mode zabral prokazatelně (kurz se za ~100 s přetočil na pole). Obnovená kalibrace z ARBot2 se ale ukázala horší než žádná (bias větší než zemské pole, kompas přestal reagovat na otáčení) a týž den se vymazala.

  • ARBot.Analyze heading bez ground truth a ARBot.Analyze vn100 ze záznamu 6. 9. 2026
  • deploy/vnprobe.sh — registry 35 a 23 nalezeny jako příčina 6. 9. 2026
  • deploy/vnrestore.sh — Absolute + zápis do flash 6. 9. 2026
  • Stará kalibrace změřena jako horší než žádná a vymazána (--clearmag) 6. 9. 2026

imu-and-frames.md, vnprobe.sh, vnrestore.sh · DevLog 2026-09-06

Kurz ze senzoru se táhne za vlastním magnetometrem minuty

hotovo vada nalezeno 7. 9. 2026 vyřešeno 18. 9. 2026

Zesílení zpětné vazby od magnetometru vyšlo K = 0,0049 1/s, tedy časová konstanta 206 s: po zatáčce je yaw desítky stupňů vedle i proti svému vlastnímu poli. Původní závěr „to kalibrace neopraví" byl 10. 9. podle manuálu VN označen za nepodložený a 12. 9. se po kalibraci konstanta zkrátila na 53 s — z většiny to tedy bylo nezkalibrované železo. Ze 14. 9. je ale zpátky a horší (345 s), protože na robotu přibylo nové železo. Je to v senzoru; nastavení nejistot ve fúzi na to nesahá. ✅ **Uzavřeno 18. 9. 2026:** po nové kalibraci τ 28–53 s ve dvou jízdách (12. 9. 53 s, 14. 9. s rozbitým železem 345 s, původně 206 s). Dlouhá konstanta byla důsledek nezkalibrovaného železa; zbylých ~30–50 s je vlastnost VPE (registr 35 má zapnuté adaptivní filtrování) a fúzi nevadí — mezi odečty kompasu nese kurz gyro.

  • Změřit K ze záznamu (blok 2 ARBot.Analyze vn100) 7. 9. 2026
  • Přeměřit po kalibraci (206 → 53 s) 12. 9. 2026
  • Přeměřit po nové kalibraci — 18. 9.: K 0,036 / 0,019 1/s (τ 28 / 53 s) ve dvou jízdách, tedy jako 12. 9.; se špatným železem 14. 9. bylo 345 s 18. 9. 2026

čeká na Kalibrace magnetometru přestala účinkovat — přibylo železo od kabelů ke kamerám · imu-and-frames.md · DevLog 2026-09-07, 2026-09-10, 2026-09-12, 2026-09-15, 2026-09-18

Železo na těle robota kazí kurz o desítky stupňů

hotovo vada nalezeno 7. 9. 2026 vyřešeno 12. 9. 2026

Po opravě registrů projetá smyčka venku: IMU yaw − GPS kurz p50 −24°, sd 18,6°, přičemž chybuje IMU (třetí nezávislá cesta Doppler − posun polohy sedí na 0,3°). Podpis je železo vázané na tělo: tvrdé 27,2°, měkké 25,2°, |B| i sklon kolísají, ačkoli mají být konstanty. Motory to skoro nejsou (−0,0026 G/A, desetina rozpětí), takže to kalibrace odečte. Změřila se misí magcal 10. 9., zapsala do senzoru 11. 9. a 12. 9. venku sedí: zbytkové tvrdé železo 0,0023 G, rozpětí |B| 0,148 → 0,019 G, kurz −24° → −3,6°. Zbylá konstanta −3,7° není železo a tímhle měřením ji rozložit nejde.

  • Smyčka venku a blok 4 ARBot.Analyze vn100 (párování pole s proudem motorů) 7. 9. 2026
  • Kalibrace změřena v terénu misí magcal 10. 9. 2026
  • Zapsána do senzoru a do flash (vnrestore.sh --magcal) 11. 9. 2026
  • Ověřena venku třemi záznamy 12. 9. 2026

imu-and-frames.md, Vn100Report.cs · DevLog 2026-09-07, 2026-09-10, 2026-09-11, 2026-09-12, 2026-09-15

První výjezd s kalibrací magnetometru skončil bez výsledku a našel tři vady

hotovo vada nalezeno 10. 9. 2026 vyřešeno 17. 9. 2026

Obsluha mission=magcal nedovedla do konce, protože verdikt byl diagnóza bez pokynu (při kompletním pokrytí radil „otáčej dál"), skupiny náklonu se klíčovaly velikostí odklonu, kterou ruka neudrží, a obsluha neviděla, kam robota natočit. Léčba: vedle elipsoidy se prokládá i samotná koule, která rozliší „chybí náklon" od „měnilo se pole"; jde zapsat aspoň tvrdé železo; místo půdorysu je mapa pokrytí 24 × 5 poloh robota. Z dokumentace VN100 přibyly dvě opravy práce s registrem 44 (reset před během, vypnutí i po nedokončené misi). Rovinná rotace přitom projde všemi branami a vrátí nesmyslný bias, proto přibyla třetí brána na měřítko. Od 15. 9. jde celá kalibrace projít v simulaci. ✅ **Na skutečném senzoru to doběhlo 17. 9. 2026** (records/test/20260917-161759.rec) a v záznamu je vidět, že zabraly všechny tři opravy: pokrytí vyšlo **úplné** (24/24 azimutů, 5 náklonových skupin, z toho 4 odkloněné, na obě strany), skupiny jsou klíčované **polohou robota**, ne velikostí odklonu („na rovině, zvednutý předek, zvednutá levá, zvednutá zadní, zvednutá pravá"), a verdikt byl po celou dobu **pokyn, ne diagnóza** — od „chybí azimuty 30–345°; podlož robota aspoň o 15 stupňů" přes „máš jen jednu stranu (zvednutá zadní) — podlož robota na DRUHOU stranu" až po **HOTOVO ve 48. s** (podmíněnost 330, sd|B| 0,0026 G). Kalibrace se v 16:20:20 zapsala do registru 23 i do flash. Tím je téma uzavřené. ⚠️ Co z toho neplyne: že je ta kalibrace v pořádku dlouhodobě (drží se hw-zelezo-od-kabelu-kamer) a že stránka po zápisu říká pravdu — kolektor sbírá dál a verdikt se rozpadne, viz mise-magcal-sber-po-zapisu.

  • Proložení koule (TryFitSphere) a verdikt s pokynem 10. 9. 2026
  • Zápis samotného tvrdého železa ze stránky 10. 9. 2026
  • Mapa pokrytí 24 × 5 a klíčování směrem místo velikostí náklonu 10. 9. 2026
  • Registr 44 se před během resetuje a po misi vypíná 10. 9. 2026
  • Kalibrace projitá od začátku do konce v simulaci s vnuceným železem 15. 9. 2026
  • Spustit mission=magcal na senzoru s novým kódem 17. 9. 2026

plan-vn100-kalibrace.md, rozhodnutí 10. 9. 2026, imu-and-frames.md · DevLog 2026-09-10, 2026-09-15, 2026-09-17

Verdikt kalibrace shodil rozptyl sklonu, který měří akcelerometr, ne magnetometr

hotovo vada nalezeno 10. 9. 2026 vyřešeno 12. 9. 2026

Druhý výjezd 10. 9. doběhl s úplným pokrytím a elipsoida se proložila, ale verdikt zamítl výsledek kvůli rozptylu sklonu 2,09° proti prahu 0,5° — a ten roste s dynamikou otáčení rukou a s biasem akcelerometru, o poli nic neříká. Stránka tak nabídla horší výsledek, než který odmítla. Autor rozhodl sklon z brány vyřadit (jen diagnostika); kalibrace z toho záznamu se 11. 9. zapsala do senzoru a do flash (deploy/vnrestore.sh --magcal) a 12. 9. venku sedí: rozpětí velikosti pole přes otočku 0,148 → 0,019 G, kurz proti GPS z −24° na −3,6°, setrvačnost atitudy 206 → 53 s. Od 14. 9. ji ale přebilo železo od kabelů ke kamerám (samostatné téma).

  • Rozbor sklonu po řádcích a azimutech, akcelerometr jako koule 10. 9. 2026
  • Rozptyl sklonu vyřazen z brány, jen diagnostika 10. 9. 2026
  • Kalibrace ze záznamu zapsána do senzoru a flash 11. 9. 2026
  • Ověřena venku třemi záznamy včetně statické otočky 12. 9. 2026

rozhodnutí 10. 9. 2026, plan-vn100-kalibrace.md, imu-and-frames.md, deploy/README.md · DevLog 2026-09-10, 2026-09-11, 2026-09-12

Kalibrace se do senzoru zapisovala ve špatném rámci, offset se přičítal

hotovo vada nalezeno 11. 9. 2026 vyřešeno 11. 9. 2026

Při nasazení kalibrace se na živém senzoru změřilo, jak VN100 registr 23 aplikuje: C·(m − b), tedy stejný vzorec jako náš Apply, potvrzeno i z ICD. Měřit se musí přes víc os a s nejednotkovou maticí — z osy X samotné vyjde opak, protože mezi kompenzací a výstupem leží registr 26, a jednotková matice nerozliší C·m − b od C·(m − b). Hlavní nález: registr 23 se aplikuje před registrem 26, fit běží až za převodem do rámce robota, takže bias v X a Y měl obrácené znaménko a offset 0,22 G se přičítal; v tom stavu byla kalibrace pár hodin na robotu. ToVnwrg23() teď rámec převádí, hlídají to testy a 12. 9. venku kalibrace sedí.

  • Konvence registru 23 změřena na senzoru a doložena ICD 11. 9. 2026
  • Rámec změřen čistým biasem po osách, ToVnwrg23() převádí 11. 9. 2026

rozhodnutí 11. 9. 2026, plan-vn100-kalibrace.md, deploy/vnrestore.sh · DevLog 2026-09-11, 2026-09-12

„Surové" pole magnetometru je kompenzované, druhá kalibrace by tu první přepsala

hotovo vada nalezeno 11. 9. 2026 vyřešeno 28. 9. 2026

Registr 54, který ICD uvádí jako nekompenzovaná měření, se na našem senzoru mění podle registru 23 stejně jako kompenzovaný výstup; 12. 9. se ze záznamu potvrdilo, že binární UncompMag je bit po bitu shodný s kompenzovaným polem. Kalibrační mise ale sbírá právě tohle pole a výsledek zapisuje do registru 23 přímo, takže druhé spuštění by dobrou kalibraci přepsalo maticí blízkou jednotkové. Mise si teď registr 23 před sběrem vymaže (jen do RAM, výpadek napájení vrátí flash) a při ukončení bez zápisu ho vrátí; když ho nejde přečíst ani vymazat, nezačne. Skládání kalibrací se zamítlo, protože potřebuje rámcovou transformaci, která už jednou kousla. Vymazání na senzoru proběhlo 17. 9. 2026: mise magcal došla do fáze Written (bez přečtení a vymazání registru 23 se do sběru nedostane) a zapsaná kalibrace 18. 9. drží (zbytkové železo 11–18 mG), což by při sběru přes starou kompenzaci nevyšlo. Vrácení registru po nedokončené misi ověřeno na senzoru 28. 9. 2026 (mise ukončená tlačítkem na stránce: registr 23 i 44 přečtené vnprobe.sh před a po jsou shodné). Pád procesu během mise registr nevrátí — známé chování, neřešeno (hw-magcal-reg23-po-padu).

  • Změřit Magnetometer proti MagnetometerRaw ze záznamu 12. 9. 2026
  • Mise registr 23 vymaže a po nedokončení vrátí 12. 9. 2026
  • Ověřit na senzoru, že se registr před sběrem vymaže — 17. 9., mise došla do Written, kalibrace 18. 9. drží 17. 9. 2026
  • Ověřit na senzoru vrácení registru 23 po nedokončené misi — 28. 9. (binárka 8587ff65): magcal 7:51:21 vymazala, Stop na stránce 7:51:45 vrátila; vnprobe.sh před a po: registr 23 i 44 (0,1,5) shodné 28. 9. 2026

rozhodnutí 12. 9. 2026, imu-and-frames.md, plan-vn100-kalibrace.md · DevLog 2026-09-11, 2026-09-12, 2026-09-17, 2026-09-28

Odpojená T265: runtime ji dál hledá a zahlcuje journal

hotovo vada nalezeno 13. 9. 2026 vyřešeno 30. 9. 2026

T265 se 13. 9. rozbila tak, že se připojí, ale nedává pózu; softwarový reset selže a nepomůže ani restart služby, jen fyzické přepojení — a po něm se za 1,5 h zasekla znovu. Každé její marné zotavení přitom stahovalo kontextem i obě zdravé D435 a zastavovalo robota. Autor rozhodl kameru odpojit natrvalo (od 13. 9. večer na sběrnici není). Runtime ji ale dál hledá ~1×/s přes sdílený zámek RealSense a na každý pokus píše chybu do journalu (7 829 řádků za 168 min) — neškodí, ale zahlcuje; nezakládat ji, když není na sběrnici, zbývá. Profil ji vypnout neumí (žádný parametr, ARBotHW ji zakládá bezpodmínečně) a 17. 9. se ukázalo, že hledání teče i do záznamu, ne jen do journalu (po zatuhnutí runtime bylo vlákno T265 jediné živé, 140 s hlášek v .rec). ✅ **Vyřešeno 26. 9. 2026, uzavřeno 30. 9. (autor):** T265 se v ARBotHW nezakládá vůbec (zakomentováno s odůvodněním, hw-d435-vlakno-zatuhlo-po-restartu). Ověřeno záznamy: hlášek o T265 bylo v jízdách 14.–25. 9. 128–1 198 na záznam, od binárky 8587ff65 (jízdy 27. a 29. 9.) **nula**.

  • T265 zapojena do zotavení kamer, per-kamera vzdání po třech marných pokusech 13. 9. 2026
  • Nezakládat T265 v runtime, když není na sběrnici (hledání 1×/s přes sdílený zámek) — T265 se od 26. 9. nezakládá vůbec; v záznamech 27. a 29. 9. žádná hláška o T265 26. 9. 2026

rozhodnutí 13. 9. 2026, hardware.md · DevLog 2026-09-13, 2026-09-14, 2026-09-17, 2026-09-26, 2026-09-30

Kalibrace magnetometru přestala účinkovat — přibylo železo od kabelů ke kamerám

hotovo vada nalezeno 15. 9. 2026 vyřešeno 18. 9. 2026

Kalibrace z 11. 9., ověřená 12. 9., v záznamech ze 14. 9. už neúčinkuje: velikost pole při stání 0,614 G proti 0,4897, rozpětí přes záznam 0,177 G (12. 9. 0,019 G), IMU yaw − GPS kurz p50 −15,6° a atitudové řešení senzoru se táhne za polem 345 s. Fúze kurz přebírá, takže to jde 1:1 do mapy i do mrkve — a platí to zpětně pro všechna měření nad těmi záznamy. Zdroj zúžen měřením na kabely ke kamerám (13. 9. se prohodily): je to jejich železo, ne proud — rozsvícení obou kamer posune pole jen o 6,4 mG, 4 % offsetu. 16. 9. železo přetrvává. Pro test kabelů vzniklo živé měřidlo v UI (panel magnetometru v dokumentu IMU s řádkem „Klid“, protože 1° otočení dělá víc než celý hledaný efekt) — na skutečném VN100 neběželo. Nevysvětlený zůstává klidový bias gyra −161 a −453 °/h proti +13 °/h 12. 9. 17. 9. 2026 to bylo ještě horší než 14. 9.: |B| p50 0,693 G proti referenčním 0,4897 (14. 9. 0,614), rozpětí 0,584–0,737 G, a kurz z kompasu byl fakticky náhodný — IMU yaw − GPS kurz sd 121°, 2. harmonická 114°, a ze tří modelů vyhrál „zamrzlý kompas" (zbytkový rozptyl 76,5° proti 96 a 115). Že chybuje IMU a ne GPS, potvrdila třetí cesta: Doppler − směr posunu polohy −1,8° ± 12,9°. Fúze kurz přebírá (odhad − IMU yaw 18,1° ± 17,4°), takže to šlo 1:1 do mapy i do mrkve. Nová kalibrace se týž den změřila (mission=magcal) a v 16:20:20 zapsala do registru 23 i do flash; tvrdé železo z proložení koule vyšlo 0,2518 G. Obsluha hlásí, že směr při následující jízdě vypadal velmi dobře — záznam z ní ale není, takže ověřené to není. ✅ **Uzavřeno 18. 9. 2026:** nová kalibrace ze 17. 9. při první jízdě drží — zbytkové vodorovné železo **11–18 mG** (14./17. 9.: 158–169 mG; 12. 9. při otáčení na místě 1,3 mG), |B| na referenci, VPE τ 28–53 s, kurz proti GPS −2,5 / −1,6°. Kabely jsou statické (přechody kamer 1–6 mG). Platnost kalibrace je dál vázaná na polohu kabelů — při jejich pohybu znovu mission=magcal. Tabulka: imu-and-frames.md, „Po NOVÉ kalibraci".

  • Rozbor záznamů ze 14. 9., dva omyly opravené měřením 15. 9. 2026
  • Měřidla ARBot.Analyze vn100 blok 5 (kamery) a heading --bin (vývoj rozporu v čase) 15. 9. 2026
  • Panel magnetometru v UI (MagTrace, 11 testů, ověřeno v simulaci) 15. 9. 2026
  • Kabely v poloze, ve které se 17. 9. kalibrovalo; 18. 9. jízda: skok pole při zapnutí kamer 1–6 mG (statické, v kalibraci) 17. 9. 2026
  • mission=magcal s náklony na obě strany a nová kalibrace do senzoru 17. 9. 2026
  • Ověřit novou kalibraci záznamem — 18. 9. (20260918-154028.rec, -155329.rec): zbytkové vodorovné železo 11–18 mG proti 158–169 mG, |B| 0,484–0,490 G, IMU − GPS kurz −2,5 / −1,6° (sd ~4°), VPE τ 28–53 s 18. 9. 2026

imu-and-frames.md, panel magnetometru (snímek) · DevLog 2026-09-15, 2026-09-16, 2026-09-17, 2026-09-18

GPSState.FixTime je nesmysl — ovladač u-bloxu skládá ITOW špatně

hotovo vada nalezeno 17. 9. 2026 vyřešeno 7. 10. 2026

uBloxGps.Read rozkládá ITOW (čas v GPS týdnu [ms]) na dny/hodiny/minuty/sekundy a **sekundy dělí špatně**: s = ITOW/1000 - ((d*24+h)*60 + m*60), kde místo *60 má u hodin být *3600. Výsledek je pak mimo — v záznamech ze 17. 9. 2026 vychází FixTime „**9 dní** 02:16:12", ačkoli v GPS týdnu jsou dny jen 0–6. Do UI to jde rovnou (GpsDocument.FixTimeText), takže panel GPS ukazuje nesmyslný čas fixu. Chyba je naštěstí **deterministická a invertovatelná**: platí TotalMs = ITOW + 84 960 000·D + 3 540 000·H, takže se z uložené hodnoty dá ITOW spočítat zpátky — a ARBot.Analyze gps (blok A0) to dělá, protože starší záznamy se přepsat nedají a jsou jediným absolutním časem, který nepochází z hodin Pi. 26. 9. se ukázalo, že na to doplácí i **export GPX**: posun proti UTC vycházel −07:45 místo +02:00 a vyexportovaný Kolo3b.gpx má čas 21:40Z u odpoledního kola. **Opraveno 27. 9.:** FixTime je u u-bloxu **UTC čas dne z UTC polí NAV-PVT** (bez bitu validTime nula = neznámý), tedy totéž co u NMEA, a GPSState je **verze 3**. Starší záznamy přepočítává jediná funkce GPSState.UtcTimeOfDay() (inverze rozbitého rozkladu a odečet 18 s GPS−UTC); používá ji export GPX, panel GPS i ARBot.Analyze gps (A0), jehož vlastní kopie inverze zmizela. Nad 20260925-142428.rec dává UTC 12:24:22 z uložených „10 dní 22:12:40" a posun hodin Pi 6,9 s. Mimochodem opraven PVTMessage.Year (četl offset 2 místo 4; nikde se nepoužíval).

  • Nález a invertovatelnost ověřená na záznamech (den v týdnu vyšel 4 = čtvrtek) 17. 9. 2026
  • uBloxGps.FixTimeFrom z UTC polí NAV-PVT, GPSState verze 3, UtcTimeOfDay() pro starší záznamy (GPX, panel, Analyze A0) 27. 9. 2026
  • Testy: inverze pro všech 7 × 24 hodin, UTC pole a offsety PVT, posun GPX nad záznamem verze 2 (12 testů) 27. 9. 2026
  • Ověřeno na zařízení 1. 10. 2026 (binárka f848fdf obsahuje 8ebd41f): 20261001-144638.rec a -152906.rec mají GPSState verze 3 u všech 25 156 / 6 021 fixů, FixTime je přímo UTC čas dne (12:46:30,10–13:28:25,70), žádný nulový ani nad 1 den, krok 100 ms; gps A0 ho ukazuje bez přepočtu. Posun hodin Pi proti UTC 8,50 s, stálý celých 42 min a navazující na 3,9 s (17. 9.) a 6,9 s (25. 9.) — jde tedy o UTC, ne o GPS čas (ten by vyskočil o 18 s). Panel GPS na zařízení není (headless), ve View čte tutéž UtcTimeOfDay() 7. 10. 2026

uBloxGps.cs, GpsReport.cs · DevLog 2026-09-17, 2026-09-27, 2026-10-07

VN100 startuje s běžící palubní HSI (registr 44 = Run uložený do flash misí magcal)

hotovo vada nalezeno 25. 9. 2026 vyřešeno 30. 9. 2026

deploy/vnprobe.sh 25. 9. 2026 přečetl $VNRRG,44,1,1,5 (export ARBot2: 0,1,5). MagCalMission.Zapis volala SaveToFlash() (VNWNV, ukládá celou RAM) DŘÍV než VypniHsi(), takže se do flash uložil i registr 44 v režimu Run a senzor od kalibrace 17. 9. startoval s běžící palubní HSI (výsledek do registru 47, neaplikovaný). Opraveno pořadí + test (PriZapisu_JeHsiVypnutaDRIV_NezSeUkladaDoFlash); vnrestore.sh nově píše i 44,0,1,5. Příčinou driftu kurzu 23. 9. to být nemusí — stejný stav byl ve flash i při dobrých jízdách 18. 9.; TN002 kap. 5.2 ale běžící HSI vede mezi příčinami ujíždějícího kurzu.

  • Pořadí v MagCalMission.Zapis (HSI off před VNWNV) + test, vnrestore.sh píše registr 44 25. 9. 2026
  • Srovnat senzor: vnrestore.sh (bez přepínače = registr 23 beze změny), pak vypnout/zapnout a vnprobe.sh → 44 má být 0,1,5. Autor 30. 9.: srovnáno; vnprobe.sh 28. 9. před misí magcal i po ní četl registr 44 0,1,5. Opravené pořadí zápisu v MagCalMission na senzoru neběželo (od té doby se kalibrace nezapisovala), drží ho test 30. 9. 2026

imu-and-frames.md, MagCalMission.cs · DevLog 2026-09-25, 2026-09-28, 2026-09-30

T265 nedává pózu — firmware hlásí chybu vidění

zamítnuto vada nalezeno 3. 9. 2026 vyřešeno 13. 9. 2026

Ani po opravě driverů z T265 nechodila póza. Sonda přímo nad librealsense ukázala, že gyro a akcelerometr chodí, ale on-device VIO půl sekundy po startu hlásí SLAM_ERROR Vision — v místnosti byla tma. Zároveň se ukázalo, že „OK" v panelu senzorů znamenalo jen otevřenou pipeline, ne snímky. Dál se zjistilo (6. 9.), že T265 nebyla do fúze vůbec napojená, a 13. 9. se po replugu pózu dávat naučila, ale za 1,5 h se zasekla znovu a zotavení jí nepomáhá. Autor 13. 9. rozhodl kameru odpojit natrvalo — dělá víc potíží než užitku.

  • Sonda nad librealsense: SLAM_ERROR Vision, příčina tma 3. 9. 2026
  • Po replugu dává pózu, za 1,5 h se zasekne znovu 13. 9. 2026
  • Rozhodnutí odpojit T265 natrvalo 13. 9. 2026

hardware.md, rozhodnutí 13. 9. 2026 · DevLog 2026-09-03, 2026-09-06, 2026-09-13

Za výpadky kamer může souběh s T265 (hypotéza CLEAR_HALT)

zamítnuto vada nalezeno 11. 9. 2026 vyřešeno 14. 9. 2026

Rešerše ukázala, že odmlčení D435 za provozu je cizí, Intelem nevyřešený problém a naše léčba (detekce, zbourání pipeline, reconnect) je to, k čemu dojdou všichni. Nejsilnější stopa byla vlastní: po přidání T265 vyskočil CLEAR_HALT z 1 na ~72. Propustnost USB i VN100 s GPS na témž hubu se vyloučily výpočtem, opravily se dva omyly o verzi SDK a backendu, a rozhodlo se na backend ani verzi nesahat, dokud se to nezměří. Měření 14. 9. bez T265 hypotézu vyvrátilo: CLEAR_HALT i zamrzání streamu zůstaly stejné a CLEAR_HALT teče i ve zdravém stavu, jako měřidlo je mrtvý. Podezřelá je od té doby fyzická větev USB 2-1.3. Vedlejší výsledek: driver hlásí typ USB linky.

  • Rešerše a rozhodnutí nejdřív měřit 11. 9. 2026
  • Driver hlásí typ USB linky (UsbLinkCheck), na HW neběželo 11. 9. 2026
  • Běh bez T265 změřen na robotu, hypotéza padla 14. 9. 2026

hardware.md, rozhodnutí 11. 9. 2026, build-and-platforms.md · DevLog 2026-09-11, 2026-09-14

Pád procesu během mise magcal nechá senzor bez kalibrace magnetometru

zamítnuto vada nalezeno 28. 9. 2026 vyřešeno 28. 9. 2026

Mise magcal si registr 23 (kompenzace magnetometru) na dobu sběru vymaže v RAM senzoru a zapne palubní HSI; vrací obojí v Stop(). Ten se zavolá při ukončení ze stránky, SIGTERM (restart služby, nasazení) i Power off — ověřeno 28. 9. Při **pádu procesu** (výjimka, SIGSEGV, kill -9, zatuhnutí zabité systemd) se ale nezavolá a senzor zůstane bez kalibrace a s běžící HSI, dokud neztratí napájení. Služba se přitom sama restartuje, takže robot jezdí dál s kurzem, který 6. 9. dělal chybu ±25°. Vypnutí vypínačem je v pořádku (flash se během mise nemění). Léčba navržená, nedělaná: při startu runtime varovat, když je registr 23 jednotkový, nebo při startu ovladače resetovat senzor ($VNRST načte flash). **Autor 28. 9. 2026: známé chování, neřešit** — náprava je vypnout a zapnout robota.

  • Nález z kódu (MagCalMission.Stop, ARBotRuntime.Stop); normální ukončení ověřeno na senzoru 28. 9. 2026
  • Rozhodnutí autora: známé chování, neřešit (zapsáno v plan-vn100-kalibrace.md a decisions.md) 28. 9. 2026

rozhodnutí 28. 9. 2026, plan-vn100-kalibrace.md, imu-and-frames.md · DevLog 2026-09-28

Oblast

Nástroje, záznam a analýza

Headless testy UI v Avalonii — ověřeno spikem, nezavedeno

otevřeno záměr nalezeno 1. 9. 2026

Na otázku autora, jestli by šlo omezit jeho účast při klikání v UI, se spikem mimo repozitář ověřilo, že Avalonia.Headless.NUnit vykreslí skutečný vizuální strom včetně DataGridu a recyklace řádků — tedy přesně mechanismus vady z 31. 8. v panelu Konfigurace. Cena je NUnit 4.5.1 (projekt pinuje 4.3.2) a nový testovací projekt; hlavní riziko jsou UI testy, které projdou naprázdno. Dvakrát se to použilo jednorázově k ověření změn; do repa zavedeno není.

  • Spike: panel Výkon a DataGrid Konfigurace headless 1. 9. 2026
  • Zavést testovací projekt a pravidlo „asertovat i předpoklad"

Views/README.md · DevLog 2026-09-01, 2026-09-02

Pohled v aplikaci s rozborem limitů jízdy pro aktuální nastavení

otevřeno záměr nalezeno 25. 9. 2026

Nápad autora (25. 9. 2026): parametry jízdy (strop rychlosti, zrychlení, rychlost otáčení, lookahead, tolerance rohu) se mění podle schopností robotu i podmínek soutěže, takže tabulky v path-following.md jsou spočtené pro jednu pevnou sadu a na aktuální hodnoty se nepřepisují. Místo toho by aplikace mohla mít pohled, který tentýž rozbor spočítá z právě účinné konfigurace: rychlost a poloměr podle úhlu zatáčky, náběh rotace, chybu oblouku proti klotoidě, seříznutí zatáčky lookaheadem, nejhorší úhel a porovnání součtu s rezervou PathEpsilonMargin. Rozbor by počítal tentýž kód jako plánovač (IMotionProfile, geometrie rohu), ne opis vzorců. Užitečné hlavně při změně maxspeed= před soutěží: při 1,7 m/s už součet (~11,7 mm) přesahuje rezervu 10 mm.

  • Návrh pohledu (tabulka a/nebo graf podle úhlu zatáčky, zdroj parametrů z ParamRegistry)
  • Implementace (Tools → Limity jízdy), výpočet sdílený s plánovačem

path-following.md, configuration.md · DevLog 2026-09-25

Údaje z BMS nejsou v telemetrickém pohledu

otevřeno záměr nalezeno 8. 10. 2026

Zpráva BmsState (hw-bms-jbd-driver) jde do záznamu, ale telemetrický pohled má sloupce vyjmenované ručně (Src/ARBot/Telemetry/TelemetryColumns.cs), takže stav nabití, proud ani napětí článků v něm vidět nejsou. Plán driveru pohled vědomě neměnil.

  • Sloupce BmsState do TelemetryColumns (stav nabití, proud, napětí baterie, min/max článku, teplota, ochrany)

plan-bms-jbd.md · DevLog 2026-10-08

Profil scény před robotem — surové body hloubky a vysvětlení klasifikace buněk gridu

v kódu, na HW neověřeno záměr nalezeno 23. 9. 2026 vyřešeno 24. 9. 2026

Nástroj na ladění detekce terénu (Tools → Profil scény, open=profile). Ukazuje graf z(r) v jednom azimutu polárního gridu: surové body z 16 sloupců hloubky, ze kterých buňky vznikly, a přes ně buňky se třídou, referenční rovinou ± tolerancí a MeanZ/StdZ/MaxZ. Pod myší řekne, které kritérium klasifikace buňka překročila. Vysvětlení počítá tentýž kód jako CameraFrameProcessor, nesoulad s gridem hlásí. Běží v Run i ve View (hloubka i projekce jsou v záznamu). Vznikl kvůli otevřenému rozporu v lp-drsnost-povrchu-rychlostni-strop (náklon ukazuje hrbol, grid ne). Nad záznamem simulace: třída sedí ve všech 332 970 buňkách, počty bodů v 16 buňkách ±1 mezi sousedními prstenci (zaokrouhlení nativní SIMD cesty). Nad terénním záznamem zatím neběžel.

  • Fáze 1: graf z(r) v azimutu gridu, surové body + buňky + vysvětlení klasifikace, Run i View, profileshot= 24. 9. 2026
  • Projít terénní záznam z Robotouru (místo zakopnutí v Kolo3b) — je hrbol v bodech vidět a pohltí ho agregace buňky?
  • Fáze 2: 3D pohled na mračno (rotace/posun/zoom) — samostatný návrh, softwarová projekce vs. OpenGL

plan-profil-sceny.md, traversability-grid.md · DevLog 2026-09-24

Export otevřeného záznamu do GPX (stopa GPS a stopa fúze)

v kódu, na HW neověřeno záměr nalezeno 24. 9. 2026 vyřešeno 24. 9. 2026

File → Export GPX… ve View uloží celý záznam do GPX 1.1: stopa surových platných GPS fixů (ele, sat, hdop) a stopa fúze (RobotStateMsg) převedená přes počátek mapy ze záznamu (MapMsg.BuildOrigin, tatáž definice jako runtime; bez mapy se stopa vynechá). Nový segment při mezeře nad 2 s, póza proředěná na 10 Hz. Čas je UTC s posunem odvozeným z GPS (FixTime), protože razítka jsou místní čas nahrávajícího stroje bez zóny; bez GPS času se použije zóna PC. Fúzní stopa sedí na GlobalNavMsg runtime na 0,000 m (5 záznamů ze simulace); odvození UTC z GPS kryjí jen testy — na záznamu ze zařízení neověřeno. ⚠️ 26. 9. nad záznamy ze zařízení vyšel posun −07:45 místo +02:00: u-blox do 27. 9. skládal FixTime špatně (hw-gps-fixtime-rozbity, opraveno, čte se přes GPSState.UtcTimeOfDay()). GPX vyexportované dřív (Kolo3b.gpx) mají čas o hodiny vedle.

  • Jádro GpxExport + testy, MapMsg.BuildOrigin sdílený s World pohledem, příkaz File → Export GPX… 24. 9. 2026
  • Ověřit na záznamu ze zařízení: výpadky fixu jako segmenty (1. 10. 2026 žádný výpadek nad 2 s, jediná mezera 1,2 s v záseku procesu)
  • UTC na záznamu ze zařízení — GpxExport.Build nad 20261001-144638.rec: 25 156 bodů GPS i fúze v jednom úseku, posun UTC+02:00 z GPS času správně (první bod 12:46:38,610Z). Čas v GPX jsou hodiny Pi minus zóna, nese tedy jejich posun +8,5 s proti GPS. V UI neproklikáno 7. 10. 2026
  • Podnabídka Export GPX: GPS i fúze v jednom souboru / do dvou souborů (-gps, -fuze) / jen GPS / jen fúze (autor 24. 9.; GpxExportOptions.Tracks, 4 testy). V běžící aplikaci neproklikáno 24. 9. 2026

record-replay.md · DevLog 2026-09-24, 2026-09-27, 2026-10-07

Režim Simulate — věrný přepočet běhu nad záznamem

odloženo záměr nalezeno 27. 7. 2026

Třetí režim vedle Run a View: přehrát záznam do skutečné fúze, vize a řízení a porovnat výstup s tím, co robot udělal. Odloženo, protože je to rozsáhlé — replay řízený časem příchodu (T_out), reprodukce lokální mapy a vize, virtuální hodiny nad souborem — a i tak zůstane reziduální nejistota. Háček v datech se zavedl hned: záznam nese T_in i T_out, takže se Simulate postaví bez přepisu formátu. Část potřeby od té doby kryje offline ARBot.Analyze (přepočet koridoru, gridu, obálky ze zaznamenaných dat).

  • Záznam nese T_in i T_out 27. 7. 2026
  • T_out-řízený replay, virtuální hodiny, porovnání s tím, co robot udělal

record-replay.md (Odložený Simulate) · DevLog 2026-07-27

Vrstva hranic občas shodí Mapsui při přehrávání

odloženo vada nalezeno 23. 8. 2026

Při přehrávání se zapnutou vrstvou hranic občas vyskočí NullReferenceException uvnitř Mapsui (GetExtent). Diagnostika v okamžiku pádu vyloučila obsah featur (395 featur, žádná null ani bez extentu) i data (tytéž featury offline ve skutečném Mapsui: 322 cyklů, nula pádů); chování není deterministické. Vypadá to na souběh nad toutéž instancí vrstvy na straně knihovny. Po dohodě s autorem odloženo; platí pojistka try/catch — vrstva se vypne a důvod je v rámečku.

  • Pojistka: pád vrstvu vypne a důvod ukáže v rámečku 23. 8. 2026

world-view.md · DevLog 2026-08-23

Port z ARBot2 — vlastní třída Matrix nahrazena MathNet a testy převedeny na NUnit

hotovo záměr nalezeno 23. 6. 2026 vyřešeno 24. 6. 2026

Založení repozitáře ARBot3 a první krok portu z ARBot2: domácí třída Matrix (~2000 řádků netestovaného kódu) se smazala a všichni živí uživatelé (ECEF, Transformation, ICP, Intrinsics, EKFStepMsg) přešli na MathNet.Numerics, pro fixní 3D geometrii na System.Numerics. MathNet vyhrál mikro-benchmarkem (~2,5× rychlejší i na malých maticích EKF) a prověřenými dekompozicemi. Staré MSTest testy se převedly na NUnit a jako síť před migrací se přenesly charakterizační testy; mrtvý generický EKF framework vypadl z buildu.

  • Založení repozitáře (.gitattributes, .gitignore, README, LICENSE) 23. 6. 2026
  • Odstranění ARBot.Common.Common.Matrix, přepis uživatelů na MathNet / System.Numerics 24. 6. 2026
  • Migrace testů na NUnit + charakterizační testy Transformation / ECEF 24. 6. 2026

architecture.md · DevLog 2026-06-23, 2026-06-24

Uživatelské rozhraní — dokování, dokumenty senzorů a diagnostické panely

hotovo záměr nalezeno 30. 6. 2026 vyřešeno 30. 7. 2026

Aplikace dostala Avalonia okno s dokovacím enginem Dock 12, první živý dokument (RGB stream D435), panel Debug output napojený na Trace (s filtrem neškodných binding-warningů Avalonie), panel Sensors se stavem senzorů a spolehlivé znovuotevírání panelů včetně plovoucích oken. Základ DocumentBase / ToolBase s ViewLocator nahradil inline šablony samostatnými pohledy s design-time náhledem. Senzory mají vlastní dokumenty — IMU s kompasem a umělým horizontem z kvaternionu, GPS, motory, kamera s přepínačem RGB/hloubka — otevírané dvojklikem, aktualizované událostmi z driveru, ne pollováním.

  • MainWindow + Dock 12 (DockFactory, DockControl) 30. 6. 2026
  • Dokument D435 Test s živým RGB streamem 2. 7. 2026
  • Panel Debug output, panel Sensors, Dock UX bez duplikátů a plovoucí okna 7. 7. 2026
  • DocumentBase / ToolBase + ViewLocator, IMUDocument s kompasem a horizontem 10. 7. 2026
  • Dokumenty GPS, motory, kamera (RGB/hloubka) na událostech MeasurementArived 25. 7. 2026
  • Zapojení dokumentů do panelu Sensors (CreateSensorDocument) 30. 7. 2026

Views/README.md, rozhodnutí 25. 7. 2026 (backpressure UI, ReopenTool, DebugOutputTool) · DevLog 2026-06-30, 2026-07-02, 2026-07-07, 2026-07-10, 2026-07-25, 2026-07-30

Systém zpráv, řídicí smyčka a záznam / přehrávání běhu (Run / View)

hotovo záměr nalezeno 24. 7. 2026 vyřešeno 28. 7. 2026

Páteř aplikace — pipeline MessageSource / MessageTarget s rolemi a odbočkami, řízení jako periodický uzel nad schedulerem (jede i při výpadku měření), jeden Stream v ARBotRuntime s režimy Run a View. Každá zpráva má verzi, obraz se zaznamenává jako ImageMsg bez komprese (~1,8 GB/min ze dvou D435, na NVMe hodiny), záznam je best-effort s indexem, přehrávání umí seek a navigaci po záznamech, UI dokumenty se aktualizují vzorem „latest-wins". Režim Simulate (přepočet nad záznamem) se vědomě odložil s háčkem T_in / T_out v záznamu. Při tom se našlo, že .gitignore tiše ignoroval zdrojovou složku Logs/ s celým modelem zpráv. Záznamy z robota jsou od té doby hlavní pracovní nástroj projektu.

  • Zárodek systému zpráv a řídicí smyčka 24. 7. 2026
  • Serializace ImageMsg / CameraFrame, verzování zpráv, backpressure UI, příkazy Run/View 27. 7. 2026
  • ARBotRuntime Run/View, ControlLoop nad schedulerem, SeekTo, ReplayNavTool 28. 7. 2026
  • Oprava .gitignore (zdrojový Logs/ nebyl v gitu) 28. 7. 2026

record-replay.md, architecture.md, rozhodnutí 25. 7. 2026 · DevLog 2026-07-24, 2026-07-27, 2026-07-28

Bezobslužný self-test pro reprodukovatelné měření výkonu

hotovo záměr nalezeno 1. 8. 2026 vyřešeno 1. 8. 2026

Při honbě za GC pauzami se každé měření dělalo ručně a výsledky mezi běhy nešly srovnat. Parametr selftest=true nechá aplikaci samu otevřít zadaná okna, pustit Run, po st_seconds zastavit, zapsat souhrn z CSV do logs/selftest-result.txt a skončit; varianty (st_record, st_images, no_uart) dávají A/B měření bez obsluhy. Týž den se jím změřilo pět variant po 20 s a doložilo, že periodické záseky zmizely. Umí i snímek obrazovky a krátké video pro ilustrace do DevLogu.

  • Harness selftest=true + varianty a souhrn z CSV 1. 8. 2026
  • Diag počítadla UI v souhrnu (bitmapy, rendery) 1. 8. 2026
  • Screenshot a video (st_shot, st_video, GIF/mp4 přes ffmpeg s fallbackem) 1. 8. 2026

selftest.md · DevLog 2026-08-01

World (geo) pohled nad mapovým podkladem

hotovo záměr nalezeno 6. 8. 2026 vyřešeno 14. 8. 2026

Vedle robot-centrického pohledu vznikl geografický pohled nad podkladem (Mapsui, OSM online nebo offline MBTiles, na ARM výchozí bez podkladu) s vrstvami z proudu zpráv: poloha a kurz, stopa, trasa a graf, síť z mapy jako pásy proměnné šířky (MapMsg, šířka v uzlu), lokální mapa a plán. Při zprovoznění se našly tři vady: vrstva lokální mapy se nekreslila (špatný styl vrstvy), robot byl otočený o 180° a značka robota se stopou se kreslily ze surového GPS, kdežto plán z fúzované pózy - rozestup byl přesně chyba fixu. Od 14. 8. jde všechno z jednoho rámce a surové fixy jsou samostatná vypínatelná vrstva.

  • Dokument s Mapsui, podklady, vrstvy, export výřezu do MBTiles 6. 8. 2026
  • Síť z OsmNav jako MapMsg a šířka cesty v uzlu 7. 8. 2026
  • Mapa se publikuje z runtime, robot kreslený správně otočený 13. 8. 2026
  • Jeden rámec pro všechna lokální data, vrstva Surové GPS, oprava stylu vrstvy Lokální mapa 14. 8. 2026

world-view.md, rozhodnutí 4. 8. 2026 (Mapsui) · DevLog 2026-08-06, 2026-08-07, 2026-08-13, 2026-08-14

Repo nešlo postavit na čistém počítači a skript o tom lhal

hotovo vada nalezeno 12. 8. 2026 vyřešeno 13. 8. 2026

Na novém stroji chyběla nativní knihovna i složka RealSense 2.0/ (nebyla v gitu, protože ji chytala ignorovací pravidla pro x64/), a build_all.bat skončil hláškou „HOTOVO", ačkoli nepostavil nic - CMake nebyl v cestě a záporný návratový kód WSL propadl jako úspěch. RealSense DLL jsou od 12. 8. v gitu (bez 200 MB symbolů), skript si VS najde přes vswhere, ARM část s vysvětlením přeskočí a souhrn říká pravdu.

  • RealSense DLL do gitu, negace v .gitignore 12. 8. 2026
  • Oprava build_all.bat (vswhere, pravdivý souhrn, porovnání s nulou) 13. 8. 2026

build-and-platforms.md · DevLog 2026-08-12, 2026-08-13

Virtuální hardware - simulace kamer, motorů, GPS a IMU

hotovo záměr nalezeno 12. 8. 2026 vyřešeno 19. 8. 2026

Vývoj vizuální cesty bez kamer: VirtualCamera renderuje RGB i hloubku z načtené OSM mapy a pózy robota, tutéž projekci použije k renderu i vrátí navigaci, takže neshoda v hloubkové cestě je skutečná chyba, ne artefakt. Den nato přibyly virtuální motory (přesná inverze odometrie), GPS a IMU nad modelem SimulatedRobot - uzavřená smyčka přes skutečnou fúzi dává chybu polohy ~0,2 m. Šev ARBotHW byl zprvu jednosměrný (po simulaci se skutečné kamery už nevrátily); od 14. 8. je režim HwMode volitelný v menu a po startu neběží žádný HW. Od té doby na simulaci stojí většina měření v projektu.

  • VirtualCamera, RoadScene, renderer, round-trip test 12. 8. 2026
  • Virtuální motory, GPS, IMU, start= 13. 8. 2026
  • HwMode (None/Real/Virtual) a čistý šev v obou směrech 14. 8. 2026
  • Běh aplikace se simulací ověřen (korelace s mapou) 19. 8. 2026

virtual-hw.md · DevLog 2026-08-12, 2026-08-13, 2026-08-14, 2026-08-19

Ladicí výstup teče do záznamu jako zpráva Info

hotovo záměr nalezeno 14. 8. 2026 vyřešeno 5. 9. 2026

Aby šlo pustit skutečnou aplikaci na robotu a hlášky si přečíst z nahrávky místo opisování z okna, napojily se Trace.Listeners na zprávu Info (verze 2 s časem, oblastí a úrovní); filtruje se až při čtení. Test hned odhalil smyčku log → zpráva → odběratel → log, kterou drží jen tvrdý strop MaxPerSecond, a to, že .gitignore tiše ignoroval složku testů. Na tomhle mostu dnes stojí čtení poruch ze záznamů ze zařízení (ARBot.Analyze log); strop 200/s se později ukázal jako past pro horkou cestu a řeší ho PoruchaHlasic.

  • Info verze 2, TraceInfoBridge, TraceLogContext 14. 8. 2026
  • Razítka z TimeBase místo systémových hodin 4. 9. 2026
  • Čtení hlášek ze záznamu ze zařízení (ARBot.Analyze log) 5. 9. 2026

record-replay.md · DevLog 2026-08-14, 2026-09-04, 2026-09-05

Ladění nad záznamem — krok po témž proudu, hodnota pixelu, správné panely kamer

hotovo záměr nalezeno 16. 8. 2026 vyřešeno 17. 8. 2026

Replay panel se zhustil do jednoho řádku a umí skok na předchozí či následující zprávu téhož proudu, takže krokování drží jednu kameru. Obrazový dokument ukazuje hodnotu pixelu pod kurzorem v podkladu i overlayi naráz. Opravila se vada, kdy overlay nad pravou kamerou ukazoval sjízdnost levé a panely se přiřazovaly podle pořadí příchodu; replay panel se nově dokuje k Debug outputu, aby nepřekrýval obrázky.

  • Kompaktní Replay a skok po témž proudu 16. 8. 2026
  • Hodnota pixelu pod kurzorem 16. 8. 2026
  • Overlay a panel se párují podle jména kamery 16. 8. 2026
  • Replay panel dokovaný k Debug outputu 17. 8. 2026

record-replay.md, Views/README.md · DevLog 2026-08-16, 2026-08-17

Snímek obrazovky a videozáznam okna z toolbaru

hotovo záměr nalezeno 16. 8. 2026 vyřešeno 16. 8. 2026

Snímky a videa do dokumentace šly dosud pořídit jen self-testem z příkazové řádky, tedy s ukončením aplikace. Pod menu přibyl pruh Snímek / MP4 / GIF s průběžným kódováním do běžícího ffmpegu (konstantní paměť, snímky se při nestíhání zahazují) a limity s auto-stopem. Ověřeno na Windows; na Armbianu by bylo nutné nastavit ARBOT_FFMPEG.

screen-capture.md · DevLog 2026-08-16

Syntetická testovací mapa s koridorem a zúžením

hotovo záměr nalezeno 16. 8. 2026 vyřešeno 16. 8. 2026

Mapa OSM/SyntetickyKoridor.osm s pravoúhlými rohy, zúžením na 1 m, nálevkou zpět na 3 m a T křižovatkou pro zkoušky průjezdu a odbočení v simulaci. Šířka je v OsmNav vlastností uzlu, ne úseku, takže se musela zadat tagem na každém uzlu a rohům přidat pomocné uzly — jinak by zúžení vůbec nevzniklo. Souřadnice jsou vyrobené přesnou inverzí převodu, který používá aplikace; při ověřování se našla chyba délek hran (viz WGS84).

OSM/SyntetickyKoridor.osm, virtual-hw.md · DevLog 2026-08-16

Telemetrický pohled — údaje ze zpráv srovnané v čase a graf

hotovo záměr nalezeno 17. 8. 2026 vyřešeno 18. 8. 2026

Tabulka nad indexem záznamu, kde řádek je zpráva a sloupec údaj (póza, řídicí zásah, navigace, senzory), obousměrně svázaná s přehráváním, s výběrem sloupců, filtrem řádků a grafem vybraných řad kresleným vlastním controlem. Cesta příkaz → skutečnost se tak dá poprvé číst v jedné tabulce. Cestou se srovnaly směrové údaje (uloženo matematicky, azimut až při zobrazení) a doplnil chybějící HDOP ve virtuální GPS. Autor UI proklikal 18. 8.; režim Run zůstává nedělaný.

  • Fáze 1 — jádro v ARBot.Common/Telemetry, tabulka, synchronizace s přehráváním 17. 8. 2026
  • Fáze 2 — graf řad, lupa, odečítátko, přehazování sloupců 17. 8. 2026
  • Senzorové zprávy (motory, IMU, GPS) a odometrická rychlost v registru 18. 8. 2026
  • Sjednocené směrové údaje a přepínač Azimut 18. 8. 2026
  • Ruční proklikání UI autorem 18. 8. 2026

telemetry-view.md, plan-telemetry-view.md, rozhodnutí 17. 8. 2026 (vlastní graf místo OxyPlotu) · DevLog 2026-08-17, 2026-08-18, 2026-08-19

Tooltipy všech tří úrovní navigace ve World pohledu

hotovo záměr nalezeno 17. 8. 2026 vyřešeno 17. 8. 2026

Lokální plán byl v mapě jen modrá čára a parametry, které ji určily, nešly zjistit. Najetím na úsek plánu, hranu trasy nebo pás cesty v síti se teď ukáže popis (rychlosti, tolerance, druh hrany, šířka, stav globální navigace). Zároveň se opravilo pořadí a šířky vrstev — plán se kreslil pod trasou a mizel. Známá mezera: uzavřené a penalizované hrany se dál kreslí šedě jako zbytek grafu, rozlišuje je jen tooltip.

world-view.md, record-replay.md (zprávy s víc producenty) · DevLog 2026-08-17

Virtuální robot zmrazil zatáčení při saturaci kol

hotovo vada nalezeno 18. 8. 2026 vyřešeno 18. 8. 2026

Při požadavku ±30 °/s nebyly směrnice kurzu symetrické; fúze, odometrie i sklon spolu souhlasily, takže chyba byla v tom, že kola příkaz nevykonala. Simulace omezovala zrychlení každého kola zvlášť, a když byla saturovaná obě, rozdíl rychlostí (a tím rotace) zamrzl. Nově rampuje dopřednou rychlost a rozdíl zvlášť a při saturaci ustupuje dopředná — jako skutečný řadič; přibyl i strop rychlosti kola, který simulace neměla.

virtual-hw.md · DevLog 2026-08-18

Simulace konečně umí změřit lokalizaci a nechat odhad driftovat

hotovo záměr nalezeno 19. 8. 2026 vyřešeno 22. 8. 2026

Virtuální kamera renderovala z odhadu fúze, takže chyba odhadu posunula i obraz a nebyla vidět; model pohybu byl ideální a IMU hlásilo absolutní kurz s bílým šumem, takže odhad nikam nedriftoval a případ, který má hranová lokalizace léčit, v simulaci nevznikal. Bezobslužné běhy navíc měřily stojící robot, protože cíl šel zadat jen klikem v mapě. Kamery od 22. 8. renderují ze skutečné pózy (camerapose=truth), simulace umí prokluz kol (wheelslip=) a bias kurzu a gyra (imubias=), skutečná póza jde do záznamu jako GroundTruthMsg se stejným razítkem jako odhad, cíl jde zadat z příkazové řádky (goal=lat,lon) a panel Virtuální senzory ukazuje živou chybu lokalizace. Prokluz je ověřený za jízdy (enkodéry 17,89 m proti skutečným 17,71 m). Začalo to 19. 8. vnucenou chybou pózy v renderu (poseerror=) a 21. 8. druhou mapou pro kamery (visionmap=): chyba je v datech, ne v pozorovateli. Tuze posunutá dvojnice mapy (24. 8.) patří k rovné testovací mapě.

  • poseerror= — umělá chyba pózy v renderu virtuální kamery 19. 8. 2026
  • camerapose=fusion|truth a dva testy (konvergence korekce, robot na cestě při špatné mapě) 22. 8. 2026
  • Prokluz kol, bias IMU, GroundTruthMsg v záznamu, camerapose=truth jako výchozí 22. 8. 2026
  • goal=lat,lon — první měření za jízdy, prokluz ověřen za běhu 22. 8. 2026
  • Šum z příkazové řádky imunoise= / gpsnoise= pro bezobslužné A/B 22. 8. 2026
  • visionmap= — druhá mapa pro kamery, vrstva Mapa (vize) ve World pohledu 21. 8. 2026

virtual-hw.md, rozhodnutí 22. 8. 2026, SimulatedRobot.cs, GroundTruthMsg.cs · DevLog 2026-08-19, 2026-08-20, 2026-08-21, 2026-08-22, 2026-08-24, 2026-08-31

Hlášky ze startu runtime se do záznamu nedostanou

hotovo vada nalezeno 20. 8. 2026 vyřešeno 30. 9. 2026

Most Trace → záznam se připojuje až na konci drátování, takže hlášky o načtení mapy, počáteční póze nebo o tom, proč se nějaký stupeň nezaložil, jdou jen do debug outputu. U záznamu z terénu se tak nedá přečíst, proč něco nevzniklo. Účinná konfigurace se od 5. 9. po připojení mostu zopakuje a přibyl příkaz ARBot.Analyze log, ale trasovací hlášky z drátování zůstávají mimo (znovu nalezeno 15. 9.). Nejnověji chyběl řádek „corridor=false: hranová lokalizace se nezakládá“ — v journalu byl, v .rec ne. Ještě 29. 9. chyběly v .rec třeba „mission=track: … nastartovana“ nebo načtení mapy. ✅ **Opraveno 30. 9. 2026:** most se založí a zapojí do Trace na začátku WireRun (hned za WaitReady), verze a konfigurace jdou jako první a řádky z drátování čekají ve frontě mostu, dokud se se stupni nespustí. Ověřeno v headless simulaci: záznam nese všech 13 hlášek, které dřív šly jen na konzoli. Mimo záznam zůstává jen to, co je před Start (výpis RuntimeBootstrap, hlavička headless, čekání na HW).

  • Konfigurace a verze se po připojení mostu zopakují do záznamu 5. 9. 2026
  • ARBot.Analyze log — textový log ze záznamu 5. 9. 2026
  • Připojit most dřív nebo hlášky z drátování pufrovat — most se zapojí na začátku WireRun, řádky čekají v jeho frontě; test RadkyPredStartem_OdejdouPoStartu, ověřeno v headless simulaci 30. 9. 2026

record-replay.md, headless.md · DevLog 2026-08-20, 2026-09-05, 2026-09-15, 2026-09-30

Cesty k mapám byly absolutní a vázané na jeden stroj

hotovo vada nalezeno 21. 8. 2026 vyřešeno 21. 8. 2026

Profily spouštění nesly absolutní cesty z jiného stroje a relativní map= se řešila proti pracovnímu adresáři, takže virtuální HW na jiné kopii repa tiše nevznikl. Relativní cesta k mapě se teď řeší proti kořenu repozitáře jako u logs/ a records/, a hláška říká, která mapa přesně chybí. Hledání kořene repa zůstalo ve čtyřech kopiích jako dluh.

virtual-hw.md · DevLog 2026-08-21

Zastavení a spuštění jednotlivého senzoru z panelu

hotovo záměr nalezeno 21. 8. 2026 vyřešeno 21. 8. 2026

Senzor nešlo zastavit vůbec — vyzvednutí měření ho skrytě spouštělo, takže ho UI nebo runtime do jednoho tiku zapnuly zpátky. To skryté spuštění bylo redundantní (každý senzor startuje v konstruktoru) a zrušilo se; řádek panelu senzorů má tlačítko Stop/Start a motory před zastavením dostanou nulovou rychlost. Vypnutí nepřežije start runtime. Logika ověřena headless; tlačítko za běhu podle autora funguje (17. 9. 2026).

Views/README.md · DevLog 2026-08-21

Hranice cesty a proložené přímky vidět v Obrázcích a v mapě

hotovo záměr nalezeno 22. 8. 2026 vyřešeno 23. 8. 2026

Autor tomu koridoru „pořádně nerozuměl, nedokázal si to představit". Detekované hranice se proto kreslí jako overlay nad barevným snímkem (jen když je vrstva vybraná) a jako vrstva „Hranice cesty" ve World pohledu; od 23. 8. nese RoadCorridorMsg v4 i obě proložené přímky jako úsečky, plněné ještě před jakoukoli kontrolou, takže u zamítnutých cyklů je vidět proč (příčná hrana křižovatky místo okraje). Cestou se opravily tři vady zobrazení: overlay napoprvé nic nekreslil, ve World byla vidět jen jedna kamera (Clear() mazal druhou) a prázdná vrstva neměla vysvětlení — teď rámeček říká, kolik bodů z kolika kamer a jestli proložení vůbec běží (corridor=false). Výpadky metrických bodů (18–36 % sloupců) jsou vidět jako čára a počet v popisce.

  • Overlay v Obrázcích a vrstva ve World pohledu 22. 8. 2026
  • Proložené přímky ve zprávě (RoadCorridorMsg v4) a v mapě, rámeček s vysvětlením 23. 8. 2026
  • Výpadky bodů viditelné a počítané, oprava zobrazení druhé kamery 23. 8. 2026

Views/README.md, world-view.md, map-correlation-localization.md · DevLog 2026-08-22, 2026-08-23

Analyzátory záznamů do repozitáře (ARBot.Analyze)

hotovo záměr nalezeno 23. 8. 2026 vyřešeno 24. 8. 2026

Předchozí sezení psalo měřicí nástroje ve scratchpadu a do DevLogu zapsalo „recept", jak je postavit znovu — přiznání, že pravidlo „vše v repozitáři" platí i na měřidla. Vznikl projekt ARBot.Analyze (corridor, dump, types) a RecordFile, který drží pasti čtení záznamu (čte se přes index, katalog musí CameraFrame doregistrovat). Hned další den přibyly corridorfit (koridor přepočítaný ze zaznamenaných bodů, --synth proti pravdě), edgebias (odchylky hranových bodů proti známému okraji) a grid (polární grid tak, jak ho vidělo UI). Od té doby je to hlavní měřidlo projektu a příkazů je přes dvacet.

  • Projekt v řešení, corridor / dump / types, RecordFile 23. 8. 2026
  • corridorfit, edgebias, grid 24. 8. 2026

record-replay.md, ARBot.Analyze · DevLog 2026-08-23, 2026-08-24

Hranice se kreslily jednou pózou pro obě kamery — chyba až 2 m

hotovo vada nalezeno 23. 8. 2026 vyřešeno 23. 8. 2026

Vrstva promítala všechny body „poslední známou" pózou, ačkoli snímky obou kamer jsou až 400 ms od sebe; rozdíl kurzu p90 3,2° dělal na dosahu 8 m chybu kreslení p50 0,15 m, max 2 m. Navíc promítala ground truth, kdežto occupancy grid se plní odhadem — vrstvy se nemohly krýt ani principiálně. Po seeku se zprávy podle razítka spárovat nedají (rekonstrukce stavu dodá jednu zprávu na klíč), takže póza musí cestovat ve zprávě: CameraFrame v6 a RoadCorridorMsg v5 nesou pózu v okamžiku pořízení, kamery ji stampují lambdou EstimatedPoseAt (vždy odhad z fúze, jiná než renderovací camerapose=). Ověřeno testy; pozdější záznamy verzi 6 běžně nesou.

  • Póza v metadatech snímku a koridoru (CameraFrame v6, RoadCorridorMsg v5) 23. 8. 2026
  • World vrstva promítá per snímek, přepínač „Hranice ze skutečné pózy" 23. 8. 2026

record-replay.md, virtual-hw.md, world-view.md · DevLog 2026-08-23

Virtuální kamery jely 6,8 Hz místo 30, protože 71 % času generovaly šum

hotovo vada nalezeno 23. 8. 2026 vyřešeno 23. 8. 2026

Jeden snímek stál 93 ms, z toho 66 ms šum: DeterministicNoise.Gaussian počítal Box–Mullera ze dvou hashů (38 ns na vzorek) a barevný šum se volal třikrát na pixel. Nahrazeno kvantilovou tabulkou (jeden hash + čtení z pole, 4096 položek kvůli L1): 7 ns na vzorek, snímek 51 ms, kamery 10 Hz; na hranové lokalizaci NoPair 20 → 1 a chyba polohy 0,046 → 0,036 m. Starší záznamy mají jinou realizaci téhož šumu. Ani 10 Hz ale není 30 — render bez šumu stojí 27 ms a paralelizace po řádcích by na Orange Pi brala výkon řídicí smyčce; vědomě neřešeno.

  • Kvantilová tabulka místo Box–Mullera (Gaussian 38 → 7 ns) 23. 8. 2026

virtual-hw.md · DevLog 2026-08-23

Delší rovná testovací mapa se známou pravdou

hotovo záměr nalezeno 23. 8. 2026 vyřešeno 24. 8. 2026

SyntetickyKoridor.osm je ze ~40 % křižovatka a slepý konec, a navíc má nálevku, takže se statistika koridoru počítala i tam, kde koridor existovat nemá — záznam 20260822-100403 je tím vychýlený benchmark. OSM/SyntetickyRovny.osm je jeden rovný úsek 160 m konstantní šířky 2,0 m: 921 přijatých z 962 cyklů, prvních 60 s bez jediného zamítnutí, nerovnoběžnost p50 0,086°. Dvojnice SyntetickyRovnyPosunuty.osm je tuhá translace (+0,60 m východ, −0,40 m sever), takže korelace s mapou má poprvé jednu správnou odpověď (uzavírá otevřený bod z 20. 8.). Mapy hlídá test (rovnost, šířka i mezi uzly, délka, posun stejným vektorem). Past: robot startuje ve středu obálky uzlů, takže z mapy dlouhé L je ve směru jízdy jen L/2.

  • SyntetickyRovny.osm 160 m × 2 m a profily v launchSettings.json 24. 8. 2026
  • SyntetickyRovnyPosunuty.osm jako tuhá translace pro visionmap= 24. 8. 2026
  • Testy SyntetickeMapyTests hlídají vlastnosti map 24. 8. 2026
  • Gate rovnoběžnosti prošetřen a ponechán, násypka zapsána jako vlastnost staré mapy 24. 8. 2026

map-correlation-localization.md, SyntetickyRovny.osm, SyntetickeMapyTests.cs · DevLog 2026-08-23, 2026-08-24, 2026-08-25, 2026-09-03

Tráva v simulaci se renderovala špatně — šev na hranici, mrtvé parametry scény, tráva bez výšky

hotovo vada nalezeno 23. 8. 2026 vyřešeno 24. 8. 2026

Tři vady renderu virtuálních kamer, které zkreslovaly měření koridoru. Drsnost trávy rozdvojila roviny vozovky a trávy, takže paprsky mířící na hranici netrefily ani jednu a podél celého okraje běžela čára bez hloubky (23 % sloupců bez bodu); správná fyzika je svislá stěna trávy na okraji — po opravě 96,7 % sloupců s bodem a chyba polohy p50 0,151 → 0,055 m. Pak se ukázalo, že grassheight= / grassrough= / depthnoise= z UI i z příkazové řádky neměly žádný účinek: VirtualHWOptions.Scene měla vlastní výchozí instanci, takže se renderovalo z jiné scény, než do které se hodnoty zapisovaly — tři hypotézy z úvahy padly, rozhodlo až měření výstupu běžící aplikace (ARBot.Analyze grid). A barevný render protínal jen rovinu vozovky, takže vyvýšená tráva nezakrývala cestu za sebou; teď jde stejnou cestou jako hloubka (rychlá cesta při nulové trávě zůstává).

  • Svislá stěna trávy na rozhraní cesty a trávy 23. 8. 2026
  • Parametry scény se skutečně uplatňují (VirtualHWOptions.Scene), výpis s čím se renderuje 24. 8. 2026
  • RenderColor přes obě roviny, tráva zakrývá cestu; opravená hláška „dokonalá rovina“ 24. 8. 2026
  • Doměřen vliv šumu scény (drsnost trávy dominuje, šum hloubky téměř nic) 24. 8. 2026

virtual-hw.md, grass-traversability.png · DevLog 2026-08-23, 2026-08-24

Konfigurace aplikace — registr parametrů, profily ze souboru a panel

hotovo záměr nalezeno 31. 8. 2026 vyřešeno 1. 9. 2026

Aplikace se dosud nastavovala výhradně z příkazové řádky a klíč parametru nikde neexistoval jako věc: nešlo vypsat, co lze nastavit, a překlep tiše propadl na výchozí hodnotu. Vznikl registr parametrů s typem a popisem, profily klíč=hodnota (config=cesta) s precedencí default → profil → příkazová řádka, evidence původu hodnoty a panel *Tools → Konfigurace* s validací, rozbalovacími seznamy u výčtů a uložením profilu. Neznámý klíč nebo neplatná hodnota v profilu je chyba při startu. Panel autor proklikal (našel při tom vadu ztrácející hodnoty při scrollu tabulky). Na zařízení profily zprvu nefungovaly (chyběly soubory v build výstupu, 1. 9.); od 4. 9. se parametry čtou typovanými odkazy a od 5. 9. jde účinná konfigurace do záznamu.

  • Registr, profil, precedence, panel, validace hodnot, chyby v polích jako standard 31. 8. 2026
  • Vada ztrácející hodnoty při recyklaci řádků DataGrid (dva typy řádků) 31. 8. 2026
  • Tlačítko *Uložit a restartovat* ověřeno autorem; profily fungují na zařízení 1. 9. 2026
  • Typované odkazy ParamRegistry.X.Value místo Program.GetParam* 4. 9. 2026
  • Účinná konfigurace a verze binárky do záznamu 5. 9. 2026

configuration.md, plan-configuration.md, Views/README.md · DevLog 2026-08-31, 2026-09-01, 2026-09-04, 2026-09-05

Údaje v panelech senzorů poskakovaly a špatně se četly

hotovo vada nalezeno 31. 8. 2026 vyřešeno 31. 8. 2026

Víc hodnot v jednom textovém bloku: když se změnil počet znaků (číslo snímku přeteče o řád, frekvence z 0,8 na 30,0), posunulo se všechno za tím údajem. Každá hodnota má teď vlastní buňku pevné šířky a řádek „Snímek" (číslo, Hz, čas) kreslí sdílený control na pevné souřadnice pro všechny čtyři senzory; motoru ten řádek chyběl úplně. Po zpětné vazbě z běhu se opravily dvě další pasti layoutu (control uvnitř tabulky, Auto sloupce s proměnlivým textem). Podle autora ověřeno za běhu (17. 9. 2026) — panely i čísla v overlayi kamery sedí.

  • Vlastní buňky pevné šířky, sdílený SensorFrameInfoControl, řádek „Snímek" u motoru 31. 8. 2026
  • Ověřeno za běhu (sdělení autora) 17. 9. 2026

Views/README.md · DevLog 2026-08-31

Mapa načtená z panelu World měla jinou šířku cest než síť, po které robot jede

hotovo vada nalezeno 1. 9. 2026 vyřešeno 1. 9. 2026

Mapa se do aplikace dostávala dvěma cestami — runtime přes map= a tlačítko v panelu World, které si soubor parsovalo samo s šířkou cest natvrdo 2 m proti výchozím 3 m runtime. Týž soubor tak vypadal v panelu jinak než síť, podle které robot jede. Autor upřesnil smysl tlačítka („vidět, co robot dostane, dřív než to dostane"), proto je načtená mapa samostatnou náhledovou vrstvou vedle navigační sítě, čte roadwidth= a použitou šířku píše do stavového řádku. Panel autor proklikal.

  • Náhledová vrstva, šířka z registru, přeuspořádaný panel 1. 9. 2026

world-view.md · DevLog 2026-09-01

Analyzátor záznamů nikdy nepřečetl motorová data — katalog zpráv se rozešel

hotovo vada nalezeno 2. 9. 2026 vyřešeno 2. 9. 2026

Při hledání napětí baterie hlásil ARBot.Analyze nula motorových rámců, přestože index jich ukazoval přes osm tisíc; málem z toho vznikl závěr, že motor v tom běhu nejel. Nástroj si katalog zpráv skládal sám a chyběl mu MotorStateBase — chybějící typ se projeví jako zprávy, které „neexistují", ne jako chyba. Táž past kousla už 25. 8. u GPS. Léčba je společný MessageCatalog.RecordDefaults() pro oba konzumenty a test, který reflexí kontroluje každou zprávu z ARBot.Common.

  • Společný katalog RecordDefaults() a test RecordCatalogTests 2. 9. 2026

record-replay.md · DevLog 2026-09-02

Záznam useknutý vybitou baterií nešel otevřít — index se opraví z dat

hotovo vada nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

Dva záznamy z večera 2. 9. skončily uprostřed, když došla baterie; data přežila až na poslední snímek, ale sidecar index u jednoho ukazoval za konec dat a u druhého o 1 409 zpráv zaostal, takže View spadl na konci streamu. Index se teď načítá tolerantně, ověří proti datům a zbytek se dopočítá skenem hlaviček; opravený se zapíše na disk a původní zůstane jako .idx.bad. Napojeno do View i do analyzátoru, oba záznamy se otevřou.

  • Tolerantní načtení indexu a oprava skenem dat 3. 9. 2026

record-replay.md · DevLog 2026-09-03

Plán v pohledu World obarvený rychlostí a graf rychlost vs. vzdálenost

hotovo záměr nalezeno 3. 9. 2026 vyřešeno 3. 9. 2026

Tooltip nad pohybujícími se úseky plánu byl k ničemu, proto se úseky kreslí barvou podle stropu rychlosti a vpravo dole je graf rychlostního profilu podél dráhy, se společnou škálou. Model je v Common s testy, ověřeno snímkem ze self-testu. Graf hned ukázal, že robot jede trojnásobkem stropu prvního uzlu — z toho vzešel nález o neúčinné rychlostní obálce.

  • Model PlanSpeedProfile, kreslení a škála SpeedPalette 3. 9. 2026

world-view.md · DevLog 2026-09-03

Čtyři místa míchala dvě časové základny

hotovo vada nalezeno 4. 9. 2026 vyřešeno 4. 9. 2026

Na pokyn autora „ať celá aplikace měří stejně" se prošlo, kde se čte čas: latence snímku v CameraFrameProcessor, hodiny PerfMsg, hodiny zpráv Info v záznamu a start mise Robotour braly DateTime.Now proti razítkům z TimeBase, který záměrně nesleduje skoky NTP a je bez offsetu zóny. Všechno šlo do záznamu nebo diagnostiky, takže posun o dvě hodiny nevypadal jako chyba, jen jako nesmyslné číslo. Pravidlo je v CLAUDE.md; audit 15. 9. dohledal ještě razítka T265 a D435 z hodin kamery a přidal strážný test.

  • Čtyři místa na TimeBase.Now, pravidlo v CLAUDE.md 4. 9. 2026
  • Audit: razítka kamer ukotvená na TimeBase, CasZTimeBaseTests 15. 9. 2026

rozhodnutí 4. 9. 2026, CLAUDE.md · DevLog 2026-09-04, 2026-09-15

V notebooku ležel natvrdo API klíč s platností do roku 2042

hotovo vada nalezeno 7. 9. 2026 vyřešeno 7. 9. 2026

Pravidlo „vše v repozitáři" přihlašovací údaje nevyjímalo, a v trénovacím notebooku byl LabelBox klíč s platností do roku 2042. Zachránilo to jen to, že soubor ještě nebyl commitnutý. Klíč autor zneplatnil a vydal nový s krátkou platností a menším oprávněním; notebook ho čte z Colab Secrets / proměnné prostředí a při chybějícím klíči padá hláškou, ne tichým None. Do CLAUDE.md přibyla výslovná výjimka z pravidla.

  • Klíč zneplatnit, vydat nový (4 týdny, Project lead) 7. 9. 2026
  • Čtení z prostředí bez tichého fallbacku, výjimka v CLAUDE.md 7. 9. 2026

CLAUDE.md · DevLog 2026-09-07

Virtuální magnetometr s vnuceným železem

hotovo záměr nalezeno 8. 9. 2026 vyřešeno 8. 9. 2026

Do té doby VirtualImu neposílalo ani magnetické pole, ani zrychlení, takže kalibrační mise v simulaci nedělala vůbec nic. Teď simulace umí tvrdé i plné měkké železo, šum, náklon a „otáčení robotem rukou" (motory to vyvolat nejde — mise zahodí regulátor). Nejcennější je test od začátku do konce: do simulace se vloží známé železo a mise musí vrátit právě ta čísla — jediná kontrola, která chytí záměnu rámců nebo obrácenou inverzi. Neověřuje to železo skutečného robota, jen náš řetěz.

  • Pole a gravitace z pózy, vnucené železo, VirtualMagCalControl, ovládání v panelu 8. 9. 2026
  • Test „vložené železo = vrácené železo" a běh mission=magcal v simulaci 8. 9. 2026

virtual-hw.md · DevLog 2026-09-08, 2026-09-11

Překlep cfg= místo config= shodil celý běh a vypadal jako vada motorů

hotovo vada nalezeno 12. 9. 2026 vyřešeno 12. 9. 2026

Neznámý klíč se jen s varováním ignoroval (mezi argumenty jsou i cizí přepínače), nenačetl se profil, bez mapy se nezaložil virtuální HW, nebyly motory a stránka hlásila, že nouzové zastavení nejde stisknout. Klíč podobný známému parametru (překlep nebo zkratka) je teď chyba při startu s návrhem správného jména; stisk virtuálního stopu bez virtuálního HW vrací 409 místo úspěchu. Ověřeno skutečným během headless v simulaci. Zapsala se i past v pořadí kroků: nová mise si hlídá stisk až od svého startu, takže stop se má držet, dokud stránka nenapíše „připravena k odjezdu".

  • Podobný neznámý klíč je chyba s návrhem 12. 9. 2026
  • POST /virtualestop bez virtuálního HW vrací 409 12. 9. 2026

configuration.md, headless.md · DevLog 2026-09-12

Panel Konfigurace tiše mazal z profilu klíče shodné s defaultem

hotovo vada nalezeno 12. 9. 2026 vyřešeno 30. 9. 2026

Uložení profilu z panelu zapisovalo jen hodnoty odlišné od defaultu, takže z pi-provoz.cfg zmizel schválně připnutý npumodel= — po příští změně defaultu by robot tiše počítal jiným modelem. Teď se zapisují i klíče, které v profilu výslovně byly. Z téhož uložení vyšel druhý nález: panel uložil cestu s windowsovým zpětným lomítkem, které na Linuxu je obyčejný znak, takže by mapa na Pi nebyla nalezena; hlídá to nový test nad profily v repu. Ručně psané komentáře v profilu se při uložení ztrácejí dál (skládají se znovu z registru) — známá mez. ✅ Autor 30. 9. 2026: uložení z panelu je v pořádku.

  • Zapisují se i výslovně nastavené klíče 12. 9. 2026
  • Test na linuxový tvar cest v profilech 12. 9. 2026
  • Proklikat uložení v panelu — autor potvrdil, že je to v pořádku 30. 9. 2026

configuration.md · DevLog 2026-09-12, 2026-09-30

Ve View se ztrácela mapa ze záznamu a lokální vrstvy plavaly

hotovo vada nalezeno 14. 9. 2026 vyřešeno 14. 9. 2026

Při přehrávání záznamu se nezobrazila mapa, trasa se pohybovala a značka cíle neseděla na zónu — tři příznaky jedné příčiny: MapMsg je v záznamu jen jednou (při startu) a kdo si World pohled otevřel až za ní, mapu neviděl; bez mapy spadne geografický počátek na nouzový dopočet z GPS fixu, který se s každým fixem posouvá. Nová vrstva zón vadu zviditelnila, protože jako jediná kreslí ze zeměpisných souřadnic. Mapa se teď odchytává z přehrávaného streamu i ve View a pohled říká nahlas, když jede na nouzovém počátku. Testem to pokrýt nešlo (zakládal by singleton runtime); scénář proklikal autor a je v pořádku (17. 9. 2026).

  • Odchyt MapMsg ve View, varování „BEZ MAPY“ v pohledu 14. 9. 2026
  • Scénář proklikán autorem (otevřít záznam, pak World pohled) 17. 9. 2026

world-view.md, record-replay.md · DevLog 2026-09-14

Dojezdové zóny vidět i ve World pohledu aplikace

hotovo záměr nalezeno 14. 9. 2026 vyřešeno 14. 9. 2026

Půdorys stránky náhledu kreslil zóny od 12. 9., v Avalonii vidět nebyly, protože ta logika seděla uvnitř webového náhledu. Výběr zón je teď ve sdíleném GoalZones (výstup v LLA, převod si dělá každý pohled sám) a World pohled má vrstvu „Zóny“. Dvě věci našlo až spuštění: Mapsui vrstvu nepřekresloval bez DataHasChanged(), a kružnice o poloměru 3 m má při běžném zoomu 3 pixely, takže vypadalo, že se zóny nekreslí vůbec — ke kružnici patří značka ve středu. Ověřeno v běžící aplikaci v simulaci.

  • GoalZones sdílený mezi webem a World pohledem, vrstva Zóny, značka ve středu 14. 9. 2026

world-view.md, snímek z aplikace · DevLog 2026-09-14

Aplikace natrvalo zatuhla při zavření menu (deadlock kompozitoru Avalonia 12.0.3)

hotovo vada nalezeno 24. 9. 2026 vyřešeno 27. 9. 2026

Při File → Export GPX během replay aplikace zatuhla (okno nešlo posunout, menu neotevřít, CPU 0). Zásobníky (dotnet-stack) ukázaly, že export se vůbec nespustil: UI vlákno viselo už při zavírání rozbaleného menu v WinUiCompositedWindow.Dispose na zámku SyncRoot, který drželo vlákno kompozitoru, a to čekalo v OnCommitCompleted na _wakeEvent (render smyčka uspaná, když se nic nekreslí) — probuzení by poslalo právě UI vlákno. Chyba Avalonie, opravená v PR #21591 (vyšla ve 12.0.5 a 12.1.x). Týká se zavření JAKÉHOKOLI popupu, závisí na načasování. Léčba: Avalonia 12.0.3 → 12.0.5 (Avalonia, Desktop, Themes.Fluent, Fonts.Inter). Build x64 i OrangePI, kouřový běh aplikace ve View OK; samotný deadlock nejde spolehlivě vyvolat, takže jeho zmizení je doložené zdrojem opravy, ne opakovaným pokusem. Autor 27. 9. potvrdil, že se po upgradu při běžném používání už nestalo. Krok „UI na Armbianu“ odpadl: na robotu běží ARBot.Headless, Avalonia UI se na Pi nenasazuje.

  • Aktualizace Avalonia 12.0.3 → 12.0.5, build x64 + OrangePI, kouřový běh ve View 24. 9. 2026
  • Ověřeno používáním aplikace na PC (autor): po upgradu se zatuhnutí neopakovalo 27. 9. 2026

build-and-platforms.md · DevLog 2026-09-24, 2026-09-27

ARBot.Analyze: rozbor uváznutí (zasek), výkon řízení (perf), baterie a ujetá dráha ze záznamu

hotovo záměr nalezeno 7. 10. 2026 vyřešeno 7. 10. 2026

Při rozboru jízd 1. 10. 2026 vznikly v repu čtyři měřidla. zasek: buňka pod robotem (kanál, log-odds, odstup), hledání úniku pravidly PlanEscape bez horizontu (jak daleko je východ a jestli ho zatarasila geometrie), replay plánovače, stáří hodnot buněk, s --frames přehrání snímků kódem robota (kdy kamera buňku naposledy viděla), s --png půdorys a snímky kamer. perf: PerfMsg po sekundách a minutách, nejhorší intervaly, stupně, mezery v proudech a souběžné výpadky kamer (fáze 4 prov-perf-monitoring). battery a odometer přehrají BatteryMonitor a Odometer z dnešního kódu nad starším záznamem. Opraveny vady měřidel: wedge četl všechny snímky (čekal na 3. kameru) a počítal s rychlostí 1,2 místo 1,7 m/s ze záznamu, nav popisoval detektor C ve verzi před 29. 9., corridor psal práh inlierů „25" místo hodnoty ze záznamu. Ověřeno během nad záznamy (shoda replaye plánovače se záznamem 376/376 stavů), ARBot.Analyze testy nemá.

  • zasek, perf, battery, odometer, LogConfig (konfigurace ze záznamu), opravy wedge, nav, corridor 7. 10. 2026

record-replay.md, ZasekReport.cs, PerfReport.cs · DevLog 2026-10-07

Oblast

Web a dokumentace

Dokumentace v repozitáři — rozcestník CLAUDE.md, doménové doc/*.md a DevLog

hotovo záměr nalezeno 10. 7. 2026 vyřešeno 30. 7. 2026

Poznatky se od začátku vedou výhradně v repozitáři: CLAUDE.md jako rozcestník s pravidly, doménové dokumenty v doc/ (fúze, rámce, platformy, UI) a od 30. 7. denní DevLog, jehož začátek se zpětně zrekonstruoval z gitu a z časů změn souborů (proto jsou záznamy do 9. 8. hrubší). Rozhodnutí se vedou v decisions.md. Vzor pro všechno další dokumentování projektu včetně tohoto registru.

  • CLAUDE.md rozcestník + doménové doc/*.md + Views/README.md 10. 7. 2026
  • Zavedení DevLogu a zpětná rekonstrukce od 23. 6. 30. 7. 2026

devlog.md, decisions.md · DevLog 2026-07-10, 2026-07-30

Web arbot.cz převeden z Google Sites na GitHub Pages

hotovo záměr nalezeno 13. 9. 2026 vyřešeno 21. 9. 2026

Autor zvolil GitHub Pages: statické HTML bez frameworku s relativními odkazy, sdílená sazba, web natrvalo tmavý. Přeneseno je vše ze Sites — sedm stránek, vzorce (doplněné z autorova LaTeXu, sázené MathJaxem), čtyři karusely fotek (30 snímků schovaných jako pozadí skrytých divů), tři schémata podvozku překreslená jako inline SVG (přebarvování rastrů byla slepá ulička), 22 odkazů v tabulce umístění, 11 článků z let 2009–2017 s obrázky a videi, ročníky 2024–2025 a nová úvodní stránka s fotkou a čtyřmi čísly. Web měl 18 stránek s ručně opsanou hlavičkou; od 18. 9. hlavičku a menu generuje tools/menu.cs (web-menu-generator) a stránek je 21 plus index. 17. 9. se složka přejmenovala z docs/ na web/ (vedle doc/ to byla past) a publikace přešla na workflow GitHub Actions, protože režim „z větve“ jiné jméno než /docs neumí — v nastavení repozitáře se to musí přepnout ve stejnou chvíli jako push, jinak web spadne. Stav 21. 9. 2026 (audit, gh api repos/AlesRuda/ARBot3/pages): Source je „workflow", doména arbot.cz je na Pages přepnutá (CNAME, certifikát pro arbot.cz i www, HTTPS vynucené), https://arbot.cz/ odpovídá 200 a alesruda.github.io/ARBot3/ přesměrovává. Publikaci Google Sites autor zrušil 18. 9. 2026 (doména tedy běžela na Pages nejpozději tehdy). web/README.md „Jak to zapnout" popisuje kroky, které už jsou provedené. Článek „Tuhnutí MD23" (2012) a dva mrtvé odkazy se dohledávat nebudou — rozhodnutí autora 21. 9. 2026 („už je to velká historie"), stránka z roku 2013 to říká na místě odkazu. Tím je převod hotový.

  • Převod sedmi stránek + prezentace do repa 13. 9. 2026
  • Vzorce z LaTeXu, karusely, tmavý web, SVG schémata podvozku, vztah (14) 14. 9. 2026
  • Ročníky 2024 a 2025 v tabulce umístění 15. 9. 2026
  • Odkazy v tabulce umístění, 11 článků přenesených ze Sites, chronologický seznam, nová úvodní stránka 16. 9. 2026
  • Zapnout GitHub Pages (autor; web běží na github.io) 17. 9. 2026
  • Doména arbot.cz na Pages (DNS, CNAME, certifikát) — živá nejpozději 18. 9. (kdy se rušily Sites), ověřeno 21. 9. přes gh api 18. 9. 2026
  • Zrušit publikaci Google Sites (autor, 18. 9.) 18. 9. 2026
  • Dohledat starý blogový článek „Tuhnutí MD23“ (2012) a dva mrtvé odkazy — nebude se hledat, rozhodnutí autora („velká historie") 21. 9. 2026
  • Generátor hlavičky a menu — tools/menu.cs, vlastní téma web-menu-generator 18. 9. 2026
  • Přejmenování docs/ → web/, oprava odkazů, workflow pages.yml 17. 9. 2026
  • Přepnout Settings → Pages → Source na GitHub Actions (autor, ve chvíli pushe) 18. 9. 2026
  • Stránka „Čím si projekt prošel“ generovaná z registru úkolů (doc/ukoly.yaml) 17. 9. 2026

web/README.md, index.html, plan-ukoly.md · DevLog 2026-09-13, 2026-09-14, 2026-09-15, 2026-09-16, 2026-09-17, 2026-09-18, 2026-09-21

Popularizační stránka o softwaru robota

hotovo záměr nalezeno 13. 9. 2026 vyřešeno 13. 9. 2026

Stránka pro laika a středoškoláka: řídicí řetězec jako čtyři otázky, které si robot 10×/s odpovídá (co je kolem mě → kde jsem → kudy → jak jet), mise, ovládání z telefonu, simulace a záznam. Čtyři ručně kreslené SVG schémata, čísla výhradně z měření vedených v repu (88,2 % proti 78,0 % u rozpoznání cesty, 2,7 ms na NPU, kurz 24° → 3° po kalibraci) a sekce, která přiznává, co je ověřené jen v simulaci. K tomu podklad pro Google Sites (text blok po bloku, schémata do PNG přes headless Chrome); stránka se pak přestěhovala do webu.

  • Stránka + podklad pro Google Sites 13. 9. 2026

prezentace.html, prezentace-google-sites.md · DevLog 2026-09-13

Kód, komentáře a dokumentace si odporovaly — hlídač odkazů a opravy

hotovo vada nalezeno 15. 9. 2026 vyřešeno 15. 9. 2026

Na podnět autora („uhlídat, aby si to odpovídalo, není jednoduché“) se strojově ověřilo, co šlo: přesun runtime do vlastního projektu nechal mrtvé odkazy v šesti doménových dokumentech a jedenáct dní si jich nikdo nevšiml; CLAUDE.md si odporovala sama se sebou o třicet řádků (systemd jednotka „neexistuje“ a o pár odrážek níž je popsaná); konfigurace tvrdila 62 parametrů, registr jich má 85. Opraveno a přibyl test, že každý odkaz v živé dokumentaci vede na existující soubor (DevLog a plány se schválně nehlídají — jsou to záznamy historie). Že komentář popisuje to, co kód dělá, strojově neověří nic; na tom stály dva omyly téhož dne.

  • DokumentaceOdkazyTests, opravy rozporů v CLAUDE.md a doc/*.md 15. 9. 2026

configuration.md · DevLog 2026-09-15

Článek o regulátoru sledování dráhy a skupina „Technické články“ na webu

hotovo záměr nalezeno 18. 9. 2026 vyřešeno 18. 9. 2026

Třetí technický článek ve stylu *Modelu podvozku* a *Detekce kraje vozovky*: odvození poloměru oblouku vepsaného do rohu z tolerance uzlu, strop rychlosti z limitu otáčení, brzdná obálka ze zpětného průchodu, exekuce každých 100 ms — a jako pointa západka, kdy omezovač v ≤ d/(k·T_rot) dostával d = max(d_min, τ·v), tedy veličinu odvozenou z vlastního výstupu; ukázáno, že větev τ·v > d_min je nesplnitelná a soustava se sesune na podlahu 0,048 m/s, což je přesně to, co se 14. 8. 2026 naměřilo na robotu. Tři ručně psaná inline SVG, souřadnice dopočítané skriptem z týchž vzorců, které stránka odvozuje. Čísla jsou přepočítaná z Profile.cs (v_max 1,2 m/s, a 0,5 m/s²), ne opsaná z path-following.md, kde zůstaly starší hodnoty 0,8 a 0,2 — proto vychází zlom mezi limitem otáčení a v_max na 32° a náběh rotace na 3,2°, ne na 40° a 8°. Zároveň se na přání autora přestalo menu prodlužovat s každým článkem: *Model podvozku* a *Detekce kraje vozovky* z lišty zmizely a nahradil je rozcestník *Technické články*. Rozbalovací podmenu se zamítlo — lišta by rostla donekonečna, dropdown chce vlastní CSS a na dotykovém displeji se hover chová hůř. Druhý tehdejší důvod („menu je natvrdo ve 22 místech, takže dropdown = 22 editací u každého článku“) padl ještě týž den, viz web-menu-generator; rozhodnutí na něm ale nestálo a platí dál.

  • Stránka regulator-sledovani-drahy.html (3 SVG, vzorce 1–11) 18. 9. 2026
  • Rozcestník technicke-clanky.html, menu přepsané ve 21 HTML + generátoru 18. 9. 2026

regulator-sledovani-drahy.html, technicke-clanky.html, path-following.md · DevLog 2026-09-18

Menu webu opsané ve 22 místech — generátor tools/menu.cs

hotovo záměr nalezeno 18. 9. 2026 vyřešeno 18. 9. 2026

Z dotazu autora „přišlo mi komplikované dávat menu na 22 míst a bude jich více“. Hlavička <header class="sitehead"> byla opsaná v každé stránce zvlášť — 21 HTML plus kopie v tools/ukoly.cs — a rostlo to s každou novou stránkou; web/README.md to vedlo jako vědomý dluh od 16. 9. Nový nástroj drží menu na jednom místě a přepisuje ten blok ve všech web/**/*.html; CI job generovane-soubory pustí ukoly.cs, pak menu.cs a porovná výsledek s commitem, takže ručně upravená hlavička i zapomenuté spuštění spadnou. Pořadí je povinné — ukoly.cs vypíše prázdnou hlavičku a naplní ji až menu.cs. Zamítnuty Jekyll (_layouts) i skládání stránek až ve workflow: obojí by porušilo to hlavní, co o složce web/ platí — že je přesně tím, co se publikuje, takže se web dá prohlédnout lokálně a rozbitý výstup se pozná před pushem, ne až na živém webu. Ověření, že převod nic nezměnil, je silné: **první běh generátoru nepřepsal ani jeden z 21 souborů**, tedy vyrobil bajt po bajtu totéž, co tam bylo ručně. Navíc zmizel ruční class="on" — stránka bez vlastní položky v menu je zapsaná ve skupině (články o soutěžích, technické články) a zvýraznění vyrábí generátor. Stránka, kterou nástroj nezná, je chyba (kód 1, nepřepíše nic): jinak by na ní nebylo zvýrazněné nic.

  • tools/menu.cs, menu vyňaté z tools/ukoly.cs, CI job generovane-soubory 18. 9. 2026
  • Ověřeno — první běh beze změny, změna položky propadne do 21 stránek, neznámá stránka spadne 18. 9. 2026

web/README.md, menu.cs · DevLog 2026-09-18

Článek o Robotouru 2026 na webu — čtyři kola s čísly ze záznamů

hotovo záměr nalezeno 19. 9. 2026 vyřešeno 20. 9. 2026

Stránka web/pages/robotour-2026.html ve stylu starších článků o soutěžích: předkolo (skener nedostal snímek kvůli jménu kamery), 1. kolo (práh HDOP a ostrov v mapě), 2. kolo (poprvé vyjel, po 27 s jízdy došla baterie — medián napětí z MotorStateBase v Kolo2.rec 10,6 V a konec 10,0 V proti 12,1 V dopoledne a 12,5 V po nabití), 3. kolo (první celé doručení na HW, 830 m, cestou do depa 16 penalizací správné hrany) a 4. kolo (9 penalizací, uváznutí v pěšince) s vysvětlením z rozboru 20. 9. (nav-phi-obracena-hrana, lok-koridor-skoky-pozy). Čísla jsou z ARBot.Analyze mission / route / nav, snímek s QR kódem z pravé kamery je z mission --png (web/assets/img/clanky/robotour-2026-qr.jpg). Odkaz v seznamu článků na *Umístění v soutěžích*, stránka je ve skupině té položky v tools/menu.cs. Výsledek (7. místo, 13 bodů) je v tabulce výsledků i v článku (doplněno 20. 9. 2026).

  • Stránka článku, obrázek, odkaz v seznamu článků, skupina v generátoru menu 20. 9. 2026

robotour-2026.html, robotour-mission.md, global-navigation-runtime.md · DevLog 2026-09-19, 2026-09-20