czech english

Pozyx

radiová lokalizace

GPS je velice užitečný systém pro velké množství aplikací vyžadující pozici … ale co dělat, pokud jste uvnitř budovy a nemáte signál? Pozyx je možná odpověď, kterou se pokusíme blíže prozkoumat. Konkrétně s „Creator Kit” máme více plánů, ale postupně. Blog update: 1/3/2023 — pypozyx.SingleRegister(size=2)

Creator Kit

Firma Pozyx nabízí několik sestav pro lokalizaci uvnitř budov. (*) V tomto článku se budeme zabývat sadou Creator Kit, který jsme na experimenty pořídili. Není to úplně levná hračka (cca 1000EUR), ale pokud systém umožní lokalizaci s přesností na 10cm do vzdálenosti 100m od majáčků (anchors), tak se to možná vyplatí. Uvidíme.
A pokud to úplně fungovat nebude, tak tento blog je ideální místo, kde se ventilovat.
(*) Pozyx by měl fungovat i venku, ale v některých zemích platí různá omezení.

Obsah



Blog

17. prosinec 2021 — První test

Včera dorazil balíček z Belgie. Po odtranění DHL expres obalovací krabice z něj vypadlo toto:
A co je uvnitř? K tomu použiji foto přímo od výrobce:
Je tam 5 kotev (anchor) majáčků, které jsou typicky umístěny na známých pozicích po budově. Dále najdete 4 vývojové tagy pro mobilní zařízení, které chceme lokalizovat. Zbývají ještě 3 power banky, 5 USB zdrojů (je dobré správně zvolit zemi, pro kterou budou zástrčky), nějaké uchyty na suchý zip a spousta USB kabelů.
A jak dopadl první test? Podle očekávání — selhal. Zapojil jsem anchor přes USB kabel do počítače, ale nic. Žádná zpráva v dmesg, nic nového v lsusb? Nějaké nápady? Ano, asi mne to mělo hned napadnout, že „napájecí kabely” z power banky komunikaci podporovat nebudou. No byl tam ještě jeden super-kabel, který ma na sobě dokonce display. Podle čísel tipuji že je to napájení a proud, který kabelem protéká, ale hlavně to komunikuje:
[1063478.914191] usb 1-6: new full-speed USB device number 8 using xhci_hcd
[1063479.064155] usb 1-6: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[1063479.064161] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1063479.064164] usb 1-6: Product: Pozyx Virtual ComPort in FS Mode
[1063479.064167] usb 1-6: Manufacturer: Pozyx Labs
[1063479.064170] usb 1-6: SerialNumber: 203E359F484E
[1063479.113745] cdc_acm 1-6:1.0: ttyACM0: USB ACM device
[1063479.114345] usbcore: registered new interface driver cdc_acm
[1063479.114349] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
Hodí se balíčk pypozyx a fajn je Pozyx-Python-library na GitHubu. Asi nejrychlejší je si repository stáhnout, editovat tutorials/ready_to_range.py (je tam třeba vyplnit vůči kterému ID chcete měřit vzdálenost) a pak už jenom vidíte výpis jako:
1966732 ms, 1034 mm, -79 dBm
1966777 ms, 959 mm, -79 dBm
1966823 ms, 1006 mm, -79 dBm
1966868 ms, 1011 mm, -79 dBm
1966912 ms, 1002 mm, -79 dBm
1966957 ms, 1020 mm, -79 dBm
1967001 ms, 992 mm, -79 dBm
1967045 ms, 978 mm, -79 dBm
1967090 ms, 983 mm, -79 dBm
1967137 ms, 974 mm, -79 dBm
1967183 ms, 988 mm, -79 dBm
1967228 ms, 974 mm, -79 dBm
Asi očekávané chování, že když mezi majáčky cca 1m od sebe dám ruku, tak se detekovaná vzdálenost nepatrně změní. Příště by to chtělo autodetekci, jaké majáčky jsem vůbec zapnul.

19. prosinec 2021 — pozyx.doRanging()

Pypozyx knihovna má „trošku” zvrhlou notaci volání jednotlivých funkcí. Asi je to inspirováno Arduinem, ale … prostě místo aby funkce vrátila daný výsledek, tak je třeba jí předat třídu (resp. strukturu?), kam se výsledky uloží a funkce pouze vrací kód pro úspěch nebo selhání.
Jako další plán jsem chtěl zkusit remote ranging, tj. mám-li zařízení A, B a C, kde v počítači mám zapojený přes USB (jo, tentokrát již spravným kabelem) zařízení A, tak se chci dozvědět vzdálenost mezi B a C. A opravdu to je přímočaré, prostě zavoláte pozyx.doRanging(B, C) a je to. Ono totiž všechna zařízení spolu komunikují a tak si to nasdílí. Celkový kód vypadá takto:
import pypozyx

serial_port = '/dev/ttyACM0'
pozyx = pypozyx.PozyxSerial(serial_port)

remote_id = 0x0D53
destination_id = 0x0D67

device_range = pypozyx.DeviceRange()
status = pozyx.doRanging(destination_id, device_range, remote_id)
print(device_range)
A výsledek je jednoduše:
63812 ms, 1081 mm, -80 dBm
p.s. tak už mi funguje i ta autodetekce — funkce getDeviceListSize() mi stále vracela 0, i když jsem měl zapnuto hned několik zařízení. Trik je v tom, že je třeba nejprve zavolat doDiscoveryAll(). Pak už číslo sedí a pokračování kódu vypadá takto:
pozyx.doDiscoveryAll()
list_size = pypozyx.SingleRegister()
pozyx.getDeviceListSize(list_size)
device_list = pypozyx.DeviceList(list_size=list_size[0])
pozyx.getDeviceIds(device_list)
print([hex(i) for i in device_list])
a výsledek jsou ta dvě vzdálená zařízení:
['0xd53', '0xd67']

21. prosinec 2021 — Lillyino robotické kvarteto

Jedna z motivací, proč jsem si Pozyx pořídil, bylo demo Lilly Clark se čtyřmi autonomními mobilními roboty. Všichni mají na sobě anchor majáček a v daném čase se vždy pohybuje pouze jeden a jeho pozici odměřují zbývající tři stojící roboti. A tak se postupně střídají a jako skupina udržují celkem kvalitní globální pozici.
K dispozici je TEAM (Trilateration for Exploration and Mapping with Robotic Networks) článek a video. Je to nějaká studentská prezentace a některé „detaily” jsou tam možná až moc zjednodušené, ale jako motivační video snad OK. Konkrétně popis GPS je v realitě 3D a neznámá je i absolutní čas. Demo s robotama je ale ve školních prostorách v jednom patře, tj. 2D, a navíc Pozyx přimo vrací vzdálenost mezi zařízeními.

22. prosinec 2021 — Hodinový test a mrtvé kotvy

Je čas vrátit se do reality. Chtěl jsem udělat první test, kdy budu měřit vzdálenost mezi dvěma majáčky po dobu jedné hodiny. První divnost byla, že zařízení, které je přímo zapojené přes USB do počítače své ID zamlčuje, resp. lze zjistit, ale přes pozyx.doRanging() místo ID potrebuje remote_id=None.
Po 50 minutách už jsem to nevydržel, vypnul test a přidal další majáček. A po chvíli koukám, že dva majáčky/kotvy jsou mrtvé (nebliká ani LEDka na majáčku ani LEDka na powerbance). Co to?
Ono asi stačí jenom trošku počítat. Ten vychytralý USB kabel, co ukazuje proud a napětí, říká 5V a 0.2A. Pronásobením je tedy spotřeba cca 1W (potvrzeno i supportem, kdy ale záleží na konfiguraci, množství majáčků v dosahu a režimu měření). A teď powerbanky. Jsou překvapivě malé = tak malé jsem ještě neviděl. ;-( … 1200mAh. Zkrátím to, napájet majáček ta powerbanka (nebo powerbančička) vydži max tu hodinu.
Ještě je možné, že po prvním nabití nemají plnou kapacitu, protože se dvěma plně nabitými a jednou napůl jsem dostal tento graf:
Dobrá zpráva je, že ty dva majáčky vydržely celou hodinu. Ale ten částečně nabitý jen cca 20s. Je vidět i rozptyl, jak to poskakuje cca těch +/- 10cm.
Možná ještě podivné pozorování ze včerejška, kdy jsem měřil pouze vzdálenost dvou vzdálených majáčků a je tam vidět díra, kdy žádná měření nejsou k dispozici — dnes bych podezříval tu baterku, tj. možná se jeden resetoval a po nějakém čase se vzpamatoval??
včerejší 50min běh s výpadky
včerejší 50min běh s výpadky
p.s. pro to hraní jsem si udělal pracovní feature/pozyx větev a je tam i experimentální OSGAR Pozyx driver.
p.s.2 nabití všech třech powerbank trvalo 2 hodiny, tak jsem ready na další hodinový test …
MartinL píše: S největší pravděpodobností je v té powerbance LiON baterka, která má nominální napětí 3,6V a tebou uváděnou kapacitu 1200 mAh. Obsahuje měnič na 5V, který nebude mít 100% učinnost, ale takových 80% to snad bude. Tudíž proud odebíraný z baterky bude cca dvojnásobný oproti tomu, co teče na těch 5V. Tj. pro 5V a 0,2A to bude asi 0,4A. Takže teoretická výdrž baterky by měla být 1200 / 400 = 3 hodiny. Pokud to vydrží jen tu hodinu, tak je ta baterka hodně špatná nebo je ten odběr podstatně vyšší.

23. prosinec 2021 — Decaware, DWM1000 a další

Na včerejším Robotika post SubT pravidelném callu došlo i na Pozyx a jestli to není nějaká mrtvá větev v oblasti indoor radiové lokalizace. Jirka říkal, že existuje FIRA Consortium, do kterého jsou zapojeni velcí hráči (Apple, Google, Samsung, …) a jestli spíše to není cesta? A že také existují i jiné hračky za $40 ve srovnání s 1050EUR za Pozyx Creator kit?!
Dobrá zpráva je, že obě cesty mají společný základ a to jsou UWB (Ultra Wide Band) čipy od firmy Decawave, kterou loni koupila firma Quorvo (viz. Qorvo Completes Acquisition of Decawave). Když jsem o Pozyxu slyšel poprvé a psal o tom svému bývalému šefovi z Haptica/Irsko (podle mailu to bylo před šesti lety), tak to komentoval: I don’t know the guys but their kit is based on the UWB sensors of another Irish company http://www.decawave.com/. Malý svět.
Jirka také zmiňoval firmu Locatify, kde lokalizaci použivají pro audio doprovod v galerii. A až to bude standard v telefonech, tak nebudete potřebovat ani žádné další zařizeni.
Franta posílal odkaz na článek ESP32 UWB board features DW1000 module for accurate indoor positioning (aha, to jsem si ani nevšiml, že je ze včerejška), tak se nám to pěkně schází.
Teď je asi na čase si přečíst to společné jádro — DWM1000 datasheet.
Ještě přidám dvě poznámky ke včerejšímu blogu. Když jsem zkoušel měřit jenom vůči jednomu majáčku, tak to vydrželo skoro dvě hodiny a to jsem před tím ještě cca 20min jen tak měřil sensory s pohybem. Tj. výdrž powerbanky není jen 1 hodina, ale ani ty 3 hodiny co počítal MartinL. 2 hodiny je ale na test už OK, tak se posunu k dalším pokusům.
Ještě bylo zvláštní, že když jsem zase zkoušel měřit vzdálenosti mezi čtyřmi majáčky, tak se to po nějaké době „kousne” (dříve jsem myslel, že to došla ta baterka). Možná to má něco společného s tím, co píše Lilly, kdy jednotlivé anchor moduly měla zapojené přes USB do robotů, ale dávala si velký pozor, aby nemluvili současně:
One thing I've wondered about is that it seems you can't call .doRanging(device B) on pozyx device A and .doRanging(device A) on pozyx device B at the same time -- in my experience it would cause them to stop outputting anything usable until reboot. Have you observed the same thing? … zatím ještě nevím, ale možná to je to, co vidím na grafu níže:
Na co se to koukáme? Jenotlivé barvy odpovídají páru majáčků/kotev, pro které v daném čase volám doRanging(). None odpovídá zařízení zapojenému přímo do PC. Na začátku jsem to nechal vše staticky v pokoji, ale po cca 10 minutách (čas 600s) mne to přestalo bavit a každý jednotlivý majáček jsem vzal a prošel se s ním a pak ho vrátil na své místo. Ještě bych měl říci, že ta funkce vrací 3 hodnoty: POZYX_SUCCESS, POZYX_FAILURE, POZYX_TIMEOUT. V grafu vidíte pouze ty POZYX_SUCCESS.
Jedna z divností je třeba zelená (3431, 3455), která je po chvíli konstantní. Mimochodem ta funkce vrací ve struktuře i čas měření, ale bohužel netuším jakého zařízení, protože je to čas od spuštění. Tato čára má stále stejný čas. Skoro to vypadá, že modro-žlutá 3431 umře, ale fialovo-hnědá 3455 žije dál a reportuje základně poslední měření z 3431??
Ještě mám jednu obavu, jestli mi prostě neusínají? Ona cena Pozyxu je i v nástrojích na konfiguraci, které jsem ještě ani nezkoušel instalovat … a auto-sleep tam je …
p.s. přemýšlím, jestli vedle dotazu pozyx.doRanging(A, B) bych neměl také zkoušet pozyx.doRanging(B, A), aneb jak to vidí ze svého pohledu to druhé zařízení?

24. prosinec 2021 — Creator Anchor vs. Developer Tag

Vánoce, vánoce, přicházejí …
Včera jsem to nevydržel a rozšrouboval anchor/kotvu, abych se podíval dovnitř. Zkoumal jsem totiž nově i na Developer Tag (Arduino shield) a přišlo mi, že rozměrově jsou si hodně podobné. Zkoušel jsem ale také Pozyx Device Configurator a ten nějak poznal, že to jsou různá zařízení:
„Trošku” zklamání bylo „množství” věcí co lze nastavit — vlastně je všechny vidíte výše: Channel, Datarate, Preamble, PRF a Power.
Jak vidíte, tak desky jsou jiné — na kotvách chybí akcelerometry, gyra, kompas, tlakoměr … prostě se očekává, že budou statické.
acc = pypozyx.Acceleration()
pozyx.getLinearAcceleration_mg(acc)
print(acc)
s výsledkem:
X: -4.0, Y: -7.0, Z: -33.0
Ještě drobná mezihra byla, že po připojení developer tagu jsem zkoušel zase anchor a vůbec nic nefungovalo! Trošku jsem se vyděsil, že jsem v konfiguraci něco zmenil. Panika. Zkusím další kotvu a stejné chování! A důvod? No změnilo se číslo portu.
[1146360.588322] usb 1-6: new full-speed USB device number 20 using xhci_hcd
[1146360.738850] usb 1-6: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[1146360.738855] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1146360.738859] usb 1-6: Product: Pozyx Virtual ComPort in FS Mode
[1146360.738861] usb 1-6: Manufacturer: Pozyx Labs
[1146360.738863] usb 1-6: SerialNumber: 359E385B3438
[1146360.741406] cdc_acm 1-6:1.0: ttyACM1: USB ACM device
No jo no … asi žádné překvapení ttyACM1 místo nuly na konci.
Pěkné je, že se můžete ptát na stavy senzorů i vzdálených zařízení: pozyx.getLinearAcceleration_mg(acc, 0x680a). Pro kotvu je pak odpověď poměrně nudná: 'X: 0.0, Y: 0.0, Z: 0.0'
Ještě existuje raw varianta, která najednou vrací měření ze všech senzorů:
>>> raw = pypozyx.RawSensorData()
>>> pozyx.getAllSensorData(raw)
1
>>> str(raw)
'97840500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0'

>>> pozyx.getAllSensorData(raw, 0x680a)
1
>>> str(raw)
'97824750, -101, 224, 949, -28, -224, -520, -2, -1, 2, 202, -87, -217, 16152, 2007, 567, -1788,
    -8, -4, 0, -93, 229, 948, 32'
Včera jsem také koukal na ten datasheet DWM-1000 a on je to vlastně pouze modul co obaluje čip DW1000:
A jak vidíte, tak SPI komunikace jde přimo do čipu, žádný extra konvertor tam není. Ale to si necháme až na příště …

25. prosinec 2021 — DW1000 první přiblížení

Nevím, kolik toho k tématu dnes sepíšu, tak alespoň dva odkazy, ze kterých budu vycházet:
První PDFko jsem před pár dny jenom narychlo prolílt, abych se ujistil, že to moc číst nemůžu. A to druhé (application note) mi naopak přišlo čtivé a zajímavé. Teď mám pocit, že bych se měl zase vrátit k tomu prvnímu, protože z toho by mělo být jasné co všechno řeší čip DW1000 a o co se musí postarat řídící počítač, ale uvidíme …
The DW1000 is a physical layer ultra-wideband (UWB) radio and brings the features of location awareness, robust communications and resilience to multipath fading to a wireless sensor network (WSN).
A more formal definition of a WSN is that it could be considered as a physically distributed computing system that interacts with the surrounding environment and provides a means to efficiently transfer this interaction over a span of physical area larger than the transmission range of the individual radio links between nodes.
The radio communications over a link between nodes is relatively expensive in terms of power. The communications of 1-bit of information over a radio link is equivalent to the execution of 1000 to 3000 instructions on a microprocessor.
... this means a sensor node needs a quarter of the transmit power to communicate over half the distance. This means that multi-hop networking is more efficient in terms of transmit power and the expense of more nodes.
A node in any WSN could use a routing table with range to neighbouring nodes as a metric to control the transmit power to the minimum it requires to reliably communicate with that neighbouring node.
For the DW1000 UWB PHY, the receive power is a constant for any link distance, therefore the policy or protocol that controls when the receiver is active is very important for energy conservation.
The DW1000 physical layer (PHY) has the capability to provide communication and precision ranging functions, even where a line of sight (LOS) radio path may not exist.
Ve zkratce — vyplatí se posílat signál na kratší vzdálenost, protože je to méně energeticky náročné. DW1000 umožňuje jak komunikaci tak měření vzdálenosti a je to tedy základní kámen pro mesh-sítě.
Ve článku následuje vysvětlení generování signálu a přeposílání +1 a -1 pulzu.
The DW1000 derives ranging capability from calculations using its ability to precisely timestamp message transmission and reception events. The DW1000 acquires these precision timestamps by building an accurate estimate of the channel impulse response (CIR) and processing this data.
The DW1000 builds estimates of the CIR by correlating a known preamble sequence against the received signal and accumulating the result over a period of time. These preamble sequences are based on preamble codes from the large family of codes called perfect ternary sequences.
The estimated CIR provides information about the first received radio path from another node. This radio path is known as the first path or leading edge of the CIR. The DW1000 contains signal processing technology that finds this leading edge in the CIR and produces timestamps to a resolution of 15 picoseconds. By using the DW1000 generated timestamps a ranging application can produce ranges to a precision of 10 cm.
The method used by DW1000 for ranging is known as threshold based time of arrival (TOA).
The DW1000 payload consists of a number of symbols. A single symbol carries two information bits.
  • The payload bit is encoded as a burst in the symbol position
  • The convolutional parity bit is encoded as the polarity of the burst.
A coherent receiver such as the DW1000 has the ability to see the polarity of a transmitted burst and so may utilise it in a convolutional decoding algorithm. This is known as systematic forward error correction (FEC) as the encoding preserves the original data bits.
In two-way ranging, a node exchanges timestamps with another node to calculate a time of flight (TOF) between the nodes. This allows the calculation of a range between the two nodes.
In one-way ranging, a node can transmit blinks to a number of other receiving nodes. The timestamps from these other receiving nodes are used as time difference of arrival (TDOA) values. A multilateration algorithm can then calculate the position of the transmitting node from the TDOA values.
If the receiving nodes are in fixed location then the scheme is known as anchor based location. If the receiving nodes are mobile then the scheme is known as anchor-less location, however the receiving nodes may need to locate themselves before the TDOA multilateration is performed.
DecaWave is a pioneering fabless semiconductor company whose flagship product, the DW1000, is a complete, single chip CMOS Ultra-Wideband IC based on the IEEE 802.15.4- 2011 UWB standard. This device is the first in a family of parts that will operate at data rates of 110 kbps, 850 kbps and 6.8 Mbps.
To by asi na copy and paste stačilo. Za mne to UWB vypadá zajímavě. Možná ještě než se pokusím znova prokousat tím uživatelským manuálem k DW1000, tak motivační český článek ze Smartmanie:
Co mne tam zaujalo, že nové (resp. už skoro rok staré) Samsung Galaxy S21+ a další telefony již UWB technologii podporují! Bylo by zajímavé to zkusit zkombinovat s Pozyxem, ale mám obavy, že si „moc rozumnět nebudou”. Leda by existovala nějaká zadní vrátka a přes seriák se dalo bavit přímo s SPI čipu … ale je to spíše nepravděpodobné. :-(
Což mne ještě přivádí k otázce, co měl Jirka: kdo tedy tu pozici počítá? No je to na 90% ten extra čip, kterému po seriáku čtete nebo zapisujete registry a případně i pouštíte extra funkce. Seznam dostupných registrů/příkazů je na pypozyx/definitions/registers.py. Je to cílené jako aplikace pro Arduino a Python wrapper je jen malý extra bonus.
p.s. tak ještě doplním řádově levnější alternativu k Pozyx Creator Kit: MDEK1001 přímo od Decawave/Qorvo:

27. prosinec 2021 — DWM1001 API a Jirkovy dotazy

Dnes bych se vrátil k modulu DMW1001, který prodávají za cca 5x nižší cenu než Pozyx. Ono tam ještě může být nějaké „ale” … no to se asi časem vyjasní. Jirka mi poslal několik odkazů a pár dotazů, na které asi zatím nemám odpověď, ale třeba někdo z vás ano.
První dokument je DWM1001-API-Guide.pdf, kde o modulu píší: The DWM1001 module is a radio transceiver module integrating the Nordic Semiconductor nRF52 MCU and Decawave’s DW1000 IC. The nRF52 MCU, which has Bluetooth v4.2 protocol stack implemented, is acting as the main processor of the DWM1001 module. … a možná nám pomůže rozlousknout otázky, co řeší čip DW1000 a o co se musí starat main processor (tady ten Nordic Semiconductor nRF52).
Uhh, chtěl jsem připsat, že na rozdíl od Pozyxu budou k DMW1001 i zdrojové kódy … a jsou: DWM1001, DW10001-DEV AND MDEK1001 DOCUMENTS, SOURCE CODE, ANDROID APPLICATION & R2.0 FIRMWARE IMAGE … jen je to 1.8GB!
No nic, zpět k API dokumentu. Každé jednotlivé zařízení si můžete nakonfigurovat jako anchor nebo tag, kde anchor je očekáván, že je statický se známou pozicí a tag je pohyblivý a pozici určuje vůči pozorovaným anchors/kotvám. Většina příkazu je typu set/get. Příkladem může být dwm_pos_set, který nastaví pozici, pokud je zařízení konfigurované jako kotva (v tag módu je pozice uložena, ale jinak je ignorována). Odpovídající funkce je dwm_pos_get, která vrátí aktuální pozici a pokud není k dispozici, tak tu jenž je uložena.
Funkce, která mne asi nejvíce zaujala je dwm_loc_getGet last distances to the anchors (tag is currently ranging to) and the associated position. The interrupt is triggered when all TWR measurements have completed and the LE has finished. Vrací to pole jak vzdáleností ke kotvám, tak jejich pozice. Pole má maximálně 15 prvků. A také to posílá pozici samotného zařízení … prostě kompletní info na jakém základě je pozice počítaná.
Je tam ještě spousta funkcí pro konfiguraci, správu verzi firmware (všechny zařízení se umí automaticky updateovat) a Bluetooth. Zatím jsem moc nepochopil co jsou user data (max 34 bajtů) a co je label (max 16 bajtů). A ještě jsem zapomněl na GPIO, tj. vzdálené digitální vstupy a výstupy.
Modul poskytuje i jednoduchý terminál přes UART. Zajímavě vypadají např. příkazy: la, ln a lr, tedy list anchors, list nodes a list routes. Předpokládám, že je to popis aktuální sítě, ale třeba větě: List nodes heard by BN through backhaul, only works for BN. moc nerozumím. :( Aha, tak BN = Bridge Node, to zatím ještě neznám.
Další link od Jirky: https://www.decawave.com/sites/default/files/aps010_dw1000_wsn.pdf The DW1000 provides the physical layer of the protocol stack and has some MAC protocol assist features. The remaining layers of the protocol stack are realized as software executing on an external microprocessor. [kapitola 5]
A Jirkův dotaz: Tj. zajímalo by me, jestli se Pozyx umí domluvit "za roh." Z robotika.cz vím, ze se můžeš nodu A zeptat na vzdálenost mezi B a C. Ale je nutné, aby A aspoň na jeden z těch dvou měl přímé spojeni? Nebo se můžu zeptat i na Y a Z, které jsou dostupné jen s meziskoky přes další uzly? Pokud umi Pozyx i meziskoky, je tam nezanedbatelný value-add nad DW1000, asi i ospravedlňující cenový rozdíl.
Hmm, ale jak to vyzkoušet? Byt máme malý a tak si myslím, že když je všude WiFi, tak všude bude i signal pro kotvy/tagy. Napadl mne jeden pokus s tagem ve výtahu a monitorovat z domova, ve kterém je patře … ale zas tak moc jich nemám a na hru follow me teď úplně náladu nemám.
p.s. jinak s tím Androidem to úplně růžově nevypadá. Viz článek Google has added an Ultra-wideband (UWB) API in Android, kde ale pak píšou update, že to API pro Android 12 zatím nebude dostupné aplikacím třetích stran … ale2 už je to skoro rok a třeba se něco brzy změní
p.s.2 procházka se psem …
… no na sledování polohy výtahu to rozhodně není. Jediné co z toho vidím je, že procházka byla cca 15 minut a že ten signal se ztratil už na chodbě, tak ten Jirkův pokus by asi šel udělat i tady …
p.s.3 tak se ta vzájemné měření propagují … bez spojky nevidím vzdálenosti … ale vlastně vzájemné vzdálenosti těch přimo nedosažitelných nodů nedostanu :(
vzdálené měření
vzdálené měření
(je tam také úlet na začátku — těch cca 70 metrů, ale pak se to srovná)

4. leden 2022 — Informační střípky

Minulý týden jsem toho moc na počítači neudělal — to jsem si raději užival tajících hor, kde se turistické stezky změnily v divoké horské potoky. Ale Jirka se činil a mám plnou schránku nejrůznějších odkazů, článků a doporučení. Také jsem dostal nějaké odpovědi od podpory Pozyxu a od Lilly.
Začal bych od opovědi Pozyxu. Poslali jednak datasheet k Development tagu a pak odpověď na téma kompatibility a otevřenosti SW: Regarding your other question, there is no compatibility with other devices due to the software which is indeed closed source. We also don't provide a way to directly communicate with the DW1000 chip. Ještě přidali přání do nového roku, ale tyto špatné zprávy (asi očekávané) to přebily. Obávám se, že svým dalším dotazem, jak je to ve srovnání s DMK1001 za 199USD jsem asi podporu ukončil …
… tak ne, před chvíli ještě Robb odpověděl: I understand your remarks, the creator kit was our first product when the company just started and is thus already quite a few years old by now. Regarding the advantage compared to the MDEK1001 Kit. Our product has different features that I don't find for the other kit such as:
  • Arduino compatibility
  • Python programming using the python library
  • Extensive documentation with code examples
  • Visualization on a floor plan
  • on board IMU with access to IMU data
  • Access data via the MQTT stream (locally or via the cloud)
  • Implementation of certain filters
  • Implementation of localization algorithms
  • Auto calibration for more than 4 anchors
  • Easy configuration using the creator controller
  • Cleaner looking application with more options
If you want program on the MDEK1001 Kit you will need a good technical knowledge and invest a significant time in reading the documentation whereas our system is much more user-friendly for people who don't have such a technical background.
Tak jo, tolik info přímo od Pozyxu. Zatím srovnání nemám, ale Jirka vypadal, že si možná ten alternativní kit pořídí.
A teď co nového od Jirky, který se rozhodně mezi svátkama neflákal.
Asi první skupina se týká komunikace. Ona mesh komunikace je primární účel této technologie a lokalizace je takový vedlejší prodkut, i když je nutná k vytvoření rozumné komunikační sítě. DWM1001 kit podporuje pouze 34 bajtů pro uživatelská data což je na jeden packet hrozně málo.
Decawave does not provide the library source code, or support any use of the PANS library except through the PANS API which is described in the API Document. … hmm, tak také samá voda. A po pravdě žádné info o 1023 bajtových zprávách jsem tam neviděl (ale prošel jsem to hodně rychle).
Dále tu mám dotaz k minulému experimentu — doplňuji obrázek bytu a umístění kotev ke grafu:
Pozice kotev k experimetu z 27/12
Pozice kotev k experimetu z 27/12
Sedím u počítače, kde základna je None, bez 3455 další kotvy vůbec nevidím, a když přidám 3455 tak můžu zjistit pouze vzdálenosti k 3455, ale nikoliv vzdálenosti sousedních kotev 3411 a 3431.
Jirka píše: Při činnosti skrz zdi a za roh doporučuje Decawave přenastavit parametry: APS006_Part-2-NLOS-Operation-and-Optimizations_v1.5.pdf. Pak si věří na zhruba 10m skrz dvě slabé zdi. Tj. na byt by to mohlo při troše štestí a dobrém umístění kotev stačit. V dalším dokumentu pak přidávají "nižši frekvence, vyšší dosah" (což je vidět i na 2.4 GHz wifi vs 5 GHz wifi): aps017_max_range_in_dw1000_systems.pdf

6. leden 2022 — Follow me

Dnes bych přidal druhou dávku „kompilovaných mailů od Jirky”. Včera jsme se na callu bavili, že není špatné najít všechny odkazy na jednom místě, tak je to lepší hledat na webu než v mailech.
Začal bych mailem z 30/12: A trochu pro pobavení UWB Follow Me - čtyři kotvy na robotovi, jeden tag na clověkovi:
… něco podobného bych rád zkusil s Edurem, pak John Deere a případně i se Spiderem (ten má rozhodně širší základnu).
Další maily se točili kolem toho, jak moc je UWB s DW1000 čipem certifikované a použitelné v různých zemích.
JI: Odkazy táham z téhle přednašky (půl hodiny, asi za ten čas asi stojí): https://www.youtube.com/watch?v=TR-rahy3Y2k (Po třinácté minutě jsou tyhle regulace.)

Evropská regulace

As per the ECC/DEC/(06)04 [i.2] and Decision 2007/131/EC [i.4] and its amendments [i.5], [i.6], the UWB transmitter equipment conforming to the present document is not to be installed at a fixed outdoor location, for use in flying models, aircraft and other forms of aviation. The present document applies to UWB equipment with an output connection used with a dedicated antenna or UWB equipment with an integral antenna. ETSI.ORG en_30206501v020101p.pdf (strana 7) Mobilní nelétající užití venku je asi OK.
Nicméně, navazující pravidla přidávají: (LT = Location Tracking) LT2 systems: These systems, operating in the 3,1 GHz to 4,8 GHz region (see ECC/REC(11)09 [i.8]), are intended for person and object tracking and industrial applications at well-defined locations. The transmitting terminals in these systems may be located indoors or outdoors, and may be fixed or mobile. They operate at fixed sites and may be subject to registration and authorization, provided local coordination with possible interference victims has been performed, ECC Report 167 [i.10] and ECC Report 170 [i.11]. ETSI.ORG en_30206502v020100a.pdf (strana 8) Tj. pro určité frekvence je asi lokalizace (ne přenos dat) možná i outdoor fixed. Auta a vlaky v pohybu (!) budou asi jestě další speciální kategorie: Furthermore, it does not cover LT1 UWB transmitters that are operated on board a road or rail vehicle running on a public network or highway.
Jestli ty frekvence čtu dobře, jsou to kanály 1 až 4. Z nějakého Decawave dokumentu si vybavuju default: 5.

Martine, v tom 1.8 GB zipu od Decawave je sice hromada zdrojaků, ale to nejdůležitější, co běží na tom Nordic cosi Armu řídícím DW1000, je tam jenom v binarní formě:
Otázka: ... But I can’t fing the PANS’s source code
Odpověď: PANS is shipped as a library/binary only. There is no source code for this library available for download. https://decaforum.decawave.com/t/dwm1001-pans-release-2/4347/17
Je tam dost knihoven a zdrojáků, aby si člověk napsal vlastní, ale je nutné začít od nuly.
Koukám na to, protože hledám původ omezení uživatelských zpráv na 34 B. Jeden strop je TLV format, který používá 1B pro délku zprávy. Nicméně jsou tam 3B headeru a 252 B zbývá (anebo víc? počítá se ten header do délky?). Takže nevím. Jenže „prostě to zkompiluju s vyšší hodnotou” kvůli nepřítomnosti zdrojáků nepůjde.

U mě se podobně ochladilo po zjištení, že ten Decawave firmware pro dev board je closed source. Je tam pár drobností, které bych dělal jinak. Jednak těch 34 B pro usr_data packet, jednak celé chovaní kolem bluetooth - kupříkladu tam neni mesh , takže při nastavování musí být všechna zařízení v dosahu BLE. Vždyť je to komunikační modul s dlouhym dosahem, proboha!
Tj. koukám, kolik může dát práce to celé přeprogramovat.
Což je zajímavá výzva pro matfyzáky:
Vstup:
  • N komunikačních zařízení, která umí Send, Receive, GetTime a GetUniqueId.
  • Všechna komunikují na jednom komunikačním kanálu a když mluví dvě blízká zařízení najednou, ruší se.
  • Ne všechna zařízeni jsou v komunikačním dosahu, ale každé je v dosahu aspoň tří dalších, která nejsou v jedné přímce.
Výstup:
  • Všech N zařízení zná své 3D souřadnice.
Volitelný výstup:
  • Schopnost routovat zprávy z A do B, i když nejsou v přímém komunikačním dosahu.
S pomocí Send, Receive, GetTime a GetUniqueId se snadno udelá GetDistanceTo (two-way ranging), takže předpokladejme, že ta existuje taky. Akorát spotřebuje 2xSend, ideálně těsně po sobě.
Rozšířená varianta úlohy:
  • Některá z těch N zařízení jsou mobilní a průběžně mění jak pozici, tak topologii sítě.

Alternativni vyrobce podobné technologie: www.nxp.com Plus: FIRA stack installed (ať už to znamená co přesně) Mínus: Nevidím volně dostupné velké množství datasheetu, jako ma Decawave.
p.s. Oprava matfyzácké úlohy: „Vždycky jsou v dosahu alespoň čtyři další zařízení a nejsou v jedne rovině.” Nebo tak nějak. Proste „cokoli je geometricky potřeba, je splněno.”
MD: nebylo by použitelné některé to jejich repo? https://github.com/Decawave/uwb-apps
JI: Jo, jo, z těch příkladů se dá vyjít. Jsou to, mimochodem, ty zdrojáky v tom 1.8 GB balíku.
Jsou nejspíš dobré na ověření toho, že dokážeme zkompilovat, nahrát a pustit funkční kód. Mezi těmi příklady a celou tou jejich closed source PANS funkcionalitou je ale dlouhá cesta.
MD: oni tam těch repo mají 8 … není toto blíže? https://github.com/Decawave/uwb-core
JI: Jo, to vypada sloziteji. Já jsem se napoprvé lekl někde u NewtOS („Co prosim?”), ale asi jsem měl pokračovat.
Mimochodem, proklikal jsem se odtamtud na https://lohmega.com/faq/, kde dole zmiňují důležitost výšky antény nad zemí. A když si tak vybavuju snímky některých průmyslových instalací z přednášek, co jsem videl, asi by se to mělo aplikovat i na výšku pod stropem a vlastně vůbec vzdálenost od odrazive plochy (https:/wikipedia.org/wiki/Fresnel_zone).
p.s. Autoři článku Error-Corrections-for-Ultrawideband-Ranging.pdf (obr. 5), který je teda hlavně o něčem jiném, pozoruji nekolikaminutový (až ~18 min) warmpup DW1000, než začne hlásit stabilní čísla.

10. leden 2022 — pozyx.doPositioning()

Asi je na čase udělat pár pokusů ve scénáři, pro který je Pozyx primárně určený — lokalizace. Přiznám se, že voláním jednotlivých funkcí jsem neuspěl a od automatické kalibrace sítě autoři odrazují. Používám tedy manuální nastavení a vzor tutoriál Ready to localize.
Přepsaný kód vypadá následovně:
from pypozyx import PozyxSerial, DeviceCoordinates, Coordinates

serial_port = '/dev/ttyACM0'
pozyx = PozyxSerial(serial_port)

anchors = [DeviceCoordinates(0x0D53, 1, Coordinates(2980, 2240, 1250)),
           DeviceCoordinates(0x0D67, 1, Coordinates(2980, 3140, 1250)),
           DeviceCoordinates(0x0D7F, 1, Coordinates(710, 160, 930)),
           DeviceCoordinates(0x6826, 1, Coordinates(130, 4350, 2230))]

remote_id = None
status = pozyx.clearDevices(remote_id)
for anchor in anchors:
    status &= pozyx.addDevice(anchor, remote_id=remote_id)

position = Coordinates()
status = pozyx.doPositioning(position, 3, remote_id=remote_id)
print(status, position)
A výsledek:
1 X: 2841.0, Y: 1249.0, Z: 776.0
To je OK. Stejně tak potěšila vzdálená lokalizace, kdy místo remote_id=None vyplníte konkretní ID zařízení. Jen poznámka, že informace o všech kotvách je třeba nejprve do zařízení nahrát (lze případně uložit dlohodobě pomocí pozyx.saveAnchorIds() a pozyx.saveRegisters()).
Aby to zas nebylo tak moc růžové, tak ta pozice 2x extra stabilní není, ale to může být mým rozložením kotev:
POS ID 0x0000, x(mm): 2780.0 y(mm): 1240.0 z(mm): 834.0
POS ID 0x0000, x(mm): 2882.0 y(mm): 1177.0 z(mm): 856.0
POS ID 0x0000, x(mm): 3541.0 y(mm): 1390.0 z(mm): 1539.0
POS ID 0x0000, x(mm): 2618.0 y(mm): 1414.0 z(mm): 754.0
POS ID 0x0000, x(mm): 2710.0 y(mm): 1233.0 z(mm): 1133.0
POS ID 0x0000, x(mm): 2860.0 y(mm): 1212.0 z(mm): 845.0
POS ID 0x0000, x(mm): 2881.0 y(mm): 1228.0 z(mm): 858.0
POS ID 0x0000, x(mm): 2864.0 y(mm): 1225.0 z(mm): 842.0
POS ID 0x0000, x(mm): 2890.0 y(mm): 1122.0 z(mm): 933.0
POS ID 0x0000, x(mm): 2882.0 y(mm): 1227.0 z(mm): 844.0
POS ID 0x0000, x(mm): 2871.0 y(mm): 1158.0 z(mm): 940.0
POS ID 0x0000, x(mm): 2896.0 y(mm): 1218.0 z(mm): 847.0
POS ID 0x0000, x(mm): 2898.0 y(mm): 1206.0 z(mm): 863.0
POS ID 0x0000, x(mm): 2675.0 y(mm): 1356.0 z(mm): 888.0

14. leden 2022 — (Ne)dostupnost a časové známky

Dlužím vám pár informací ohledně vývojového kitu MDEK1001 za $199 (teoreticky). První co mne při objednání trošku zklamalo byla cena dopravy:
Cena dopravy pro MDEK1001 z Smmetry Electronics
Cena dopravy pro MDEK1001 z Smmetry Electronics
Plus to nebylo na skladě, tak jsem se 2x rozhoupával, zda do toho jít. Naskladněné to mělo být 12. ledna 2022 (ano, to již bylo — ja to objednával 5. ledna). Jirka přiznal, že si to již objednal a to mne poštouchlo, ale chyba lávky. Nejprve přišel formulář, na co že se to chystáme používat. Byl jsem varován Jirkou, takže OK. Druhý den ale přišel mail: Unfortunately, we are now out of stock and it will take until April for item to arrive. Please confirm if you would like to wait and keep your order opened. Hmm, no Jirka objednával dříve a tak snad se vešel do té várky k 12/1 … jo jo, to by bylo moc jednoduché. 11/1 přeposílal mail: Unfortunately, the supplier had a delay and the new date is May 2022. Jirka objednávku zrušil a hledá alternativy. Já bych asi také měl … aneb Pozyx je předražený, ale na druhou stranu jsem ho dostal ještě ten týden před vánoci.
Tak a teď ty časové známky. V úterý jsem dělal nějaké experimenty v hale ČZU a to také úplně růžové nebylo. Vedle informace kolik je naměřená vzdálenost mezi A a B? je třeba se i ptát jak stará je tato informace?. Krabičky totiž s radostí odpoví to vím, to vím, ale může to být několik minut staré! Měřil jsem totiž nejprve krátké (cca 5m) vzdálenosti a pak přes celou halu (cca 20m) a chodily mi dál ty krátké … ale se starou časovou známkou, což zase oceňuji.
A ještě se mi často děje jedna nepěknost — zapomínám některé kotvy zapnout (případně jim může dojít baterka). Pokud se ptáte jen na pozici, tak je schopné si to něco vymyslet, tedy nejčastěji (0, 0, 0), což možná člověka trkne. Ale pokud to jsou jiná čísla a vezme to v úvahu měření z minulého století, tak špatný, špatný, špatný, abych citoval jednu sci-fi co jsem dostal pod stromečkem.
A jak moc velká skleróza může být naznačuje tento obrázek (pozn. že ty časové známky jsou interní, od času 0 od okamžiku napájení kotvy) … hmm, takže jsem si ten obrázek interpretoval „naruby”??
zapomenuté (nenapájené) kotvy
zapomenuté (nenapájené) kotvy
No jsou vidět dvě hlavní „časové” skupinky, ale ta červená mne mate … to bude chtít ještě nějakou revizi.

15. leden 2022 — Dosah 100 metrů? Ha, ha, ha

Jo, jo, jak titulek z Blesku. Jirka by to jistě rozporoval, že pro jiný kanál a preambuli bych mohl dostat více, takže první dálkové měření venku na zahradě bylo s defaultním nastavením: kanál 5, datarate 110, preambule 1024, PRF 64, power 11.5 (vycházím z toho obrázku pro 0x6867, kterou jsem měl zapojenou do počítače). Bylo to na výšku na monitoru na notebooku (jinak položeném na zemi) a s druhou krabičkou (0x0D67) připojenou na powerbance jsem šel přes zahradu tam a pak zpět. Přidal jsem tam cca 5s pauzy u „visuálně význačných bodů”, ale nutně jsem trasu nezopakoval. A výsledek vypadá takto:
No 100m to není. Je zvláštní, že v druhém pokusu je to ještě horší než v tom prvním — že by se ta powerbanka tak rychle vybila? Skoro to vypadá jistější do 30m a někdy do 50m. Možná znova zkusím projít nastavení, jestli nemůžu zvětšit citlivost a ty powerbanky nabiju na max, ale s tímto nastavením by pořádně nefungovalo ani sekání zahrady, resp. by to chtělo hustější síť kotev.
p.s. koukám znova na to nastavení a kanál můžu nastavit na 1, 2, 3, 4, 5, 7 (ano, 6 tam chybí). Datarate můžu zvýšit z 110 na 850 nebo 6810. Preambule je od 64 do 4096 (mám 1024). PRF je 16 nebo 64 a power je od 0.0 do 33.0 (používám 11.5). Závěr — je tam prostor pro zlepšení/experimenty.

16. leden 2022 — UWB channels

Dnes bych začal opisem tabulek z dw1000_user_manual_2.11.pdf. Jirka včerejší post komentoval: Co nejnižší kanál, co nejnižší datarate, co nejdelší preamble, PRF netuším, "power" zní jako "moarrrrre", anténu aspoň půl metru nad zemí ve volném prostoru, ještě lépe metr nad zemí, a v cestě by neměla být žádná překážka nebo odrazová plocha, jako třeba země, takže nejlépe testovat přes údolí nebo mezi mrakodrapy.
První tabulka naznačuje, že defaultní kombinace co používám (110kbs a 1024 preambule) není výrobcem doporučovaná:
Tabulka doporučených délek preambule
Tabulka doporučených délek preambule
The preamble sequence used at all data rates is the same, i.e. it does not depend on the chosen data rate. The preamble sequence length, (i.e. the number of symbol intervals for which it is repeated), has a significant effect on the operational range and the accuracy of timestamps. Table 57 gives some recommended preamble sequence lengths to use depending on the data rate. In general, a longer preamble gives improved range performance and better first path time of arrival information while a shorter preamble gives a shorter air time and saves power. When operating a low data rate for long range, then a long preamble is needed to achieve that range. At a high data rate the operating range is naturally short so there is no point in sending a very long preamble as it wastes time and power for no added range advantage.
There are two choices of mean pulse repetition frequency (PRF) within the DW1000. These are 16 MHz PRF or 64 MHz PRF. The higher PRF gives more accuracy on the first path timestamp and perhaps slightly improved operating range, however this comes at the price of additional power consumption.
Tabulka frekvencí a šířka pásma pro jednotlivé kanály
Tabulka frekvencí a šířka pásma pro jednotlivé kanály
Strana 209, sekce 9.1 Operating Range: The operating range also varies depending on the channel centre frequency and channel bandwidth selected – a lower centre frequency gets more range than a higher one, while the wider bandwidth channels channel 4 and channel 6 have more range than the standard 500 MHz bandwidth channels as the wider channel allows more energy to be sent at a given dBm / MHz regulatory limit. (předpokládám, že 6 má být 7?)
Zatím si to interpretuji tak, že nejlepší výsledek bych měl dostat pro kanál 1 (možná 4?), datarate nechat na 110kbps, preamble zvýšit na 4096, PRF nechat na 64 a power „co to dá”???
No nic, dnes to nebude. :( Ten úžasný nastavovač device-configurator-1.3.6.appimage sice dovolí vyplnit co jsem napsal výše, ale neuloží to do zařízení a po zapnutí se to vrátí do defaultu. Divné. Je tam možnost si vytvořit vlastní profil pro danou kombinaci (našel jsem tam např. High range a High update rate), ale do zařízení se to uloží jen krátkodobě. Co je nastavené lze zjistit i z Pythonu:
>>> serial_port = '/dev/ttyACM0'
>>> pozyx = pypozyx.PozyxSerial(serial_port)
>>> data = pypozyx.SingleRegister()
>>> pozyx.getUWBChannel(data)
1
>>> print(data)
0x5
Je tam i odpovídající setUWBChannel(), s popisem If using this remotely, remember to change the local UWB channel as well to make sure you are still able to communicate with the remote device. Trošku mi to připomíná „Kdyby tisíc klarinetů” — až vyhodíte pojistky bude tma … no nic, je čas sekat třisky a vrátit se do civilizace.

23. leden 2022 — Channel 1, preambule 4096, gain 33 = více jak 80 metrů

Dnešní měření mi zase dodala naději. Udělal jsem drobný hack, který všem vypsaným zařízením nastaví:
settings = pypozyx.UWBSettings()
settings.bitrate = 0  # {0: '110 kbit/s', 1: '850 kbit/s', 2: '6.81 Mbit/s'}
settings.channel = 1
settings.prf = 2  # {1: '16 MHz', 2: '64 MHz'}
settings.gain_db = 33.0
# {0x0C: '4096 symbols', 0x28: '2048 symbols', 0x18: '1536 symbols', 0x08: '1024 symbols',
#  0x34: '512 symbols', 0x24: '256 symbols', 0x14: '128 symbols', 0x04: '64 symbols'}
settings.plen = 0x0C
self.pozyx.setUWBSettings(settings, remote_id=remote_id)
A když jsem nechal jednu kotvu uvnitř a druhou obešel chatu, tak nebyl žádný výpadek. Podobně pak dole na zahradě stejný test jako před týdnem. Základnu jsem dal tentorkát na převráceny plastový sud (tj. mělo by to být alespoň ten metr nad zemí) a druhou kotvu jsem napájel z 5000mA powerbanky dříve používané na lodičce. Primárně jsem zkoušel nové nastavení výše (kanál 1, preambule 4096, max gain 33 čert ví čeho). A výsledky (opakované 2x) mne tak potěšili, že jsem se prošel ještě vedle na „pole” a na 80 metrech to stále něco měřilo. Je tam mezera, protože čast zakrýva skoro padlý strom. No a nakonec jsem použil defaultní nastavení jako referenci.
Ještě bych zmínil, že při testování změny nastavení mi vzdálenost mezi dvěma kotvama skočila v průměru z 3.93m na 4.01m, ale to je vlastně v toleranci — možná by s různým nastavením šlo zjistit, zda je mezi zařízeními nějaká překážka?? No nic, příště, možná, …

1. únor 2022 — DW1000 + BU01 (Jirka)

Už mi zase ten seznam co jsem všechno za poslední dobu neudělal nějak nezdravě narostl. Navíc dnes není 1. února, ale už 5. To datum se ale váže k Jirkovu mailu (začal psát s diakritikou, abych při přepisování nedělal tolik chyb ), kde popisuje své první úspěchy s alternativní deskou používající DW1000 čip.
Za sebe bych si udělal alespoň „záložku” na českou IoT stránku, kde jednak je celá technologie UWB popsána, a dále jsem tam poprvé viděl grafy energetické náročnosti v závislosti na typu vysílané/přijímané části zpráv:
Tak teď ten slibovaný mail od Jirky:
Pracuju s NodeMCU-BU01, což je poměrně minimalistická deska s STM32F103C8 mikrokontrolérem kolem BU01 modulu s DW1000 čipem od Decawave pro komunikaci a následně pro měření vzdálenosti. Koupil jsem těch desek deset a vypadá to, že některé přišly flashnuté jako "anchor" a jiné jako "tag". To je ale zatím vcelku jedno, protože s defaultním firmware jsem je zatím nedonutil k vzájemné komunikaci. Ani se moc nesnažím, protože chci firmware vlastní.
Slušnou nadvládu nad tou deskou získávám, když vyjdu z "opencm" příkladu na https://github.com/satoshinm/pill_blink. OpenCM3 je knihovna dostatečne nízkoúrovňová, abych mohl řešit potíže, a dostatečně vysokoúrovňová na to, abych se nezbláznil z registrů a prescalerů a všeho možného. V důsledku dokážu blikat všemi třemi LED na palubě, komunikovat s PC přes UART a reagovat na přerušení vyvolané stiskem tlačítka. Dokumentaci OpenCM3 bych ale hodnotil jako nedostatečnou.
Mikrokontrolér programuji a debuguji pomocí stlink-tools přes ST-LINK/V2 Mini. Občas sáhnu po OpenOCD, které se zdá mocnější, ale konkrétní výhody jsem zatím nenašel. Resp. tu jednu, o které vím, zatím nevyužívám. Snad až se budu snažit flashovat firmware větší než 64kB. Ono totiž tenhle procesor má podle datasheetu 64kB flash a to samé o sobě i tvrdí, ale ve skutečnosti má často 128kB. Jak je to konkrétně s mými kousky zatím nevím. S OpenOCD jde při flashování ignorovat, co o sobě ten procesor hlásí.
Co zatím taky nevím, je, jestli funguje USB pro přenos dat a ne jen pro napájení. Defaultní firmware přes USB nekomunikuje. USB bootloadery, které jsem nahrával - HID Bootloader a STM32duino-bootloader - nefungují. PC ani nedetekuje připojené zařízení. Včera jsem asi konečně vykopal psa, který to způsobuje. Externí oscilátor na NodeMCU-BU01 tiká na 16MHz, zatímco většina desek se stejným procesorem používá oscilátor na 8Mhz. Pokud bootloadery předpokládají 8MHz, je pak časování na USB úplně mimo.
Nejspíš z podobného důvodu, kvůli oscilátoru, jsem zatím nerozchodil ani Arduino pro STM32. Zephyr OS jednak naráží na to samé, jednak i po pokusu o přenastavení padá program v nějakém ošetření přerušení, o které jsem ani neprosil. Zephyr i Arduino prozatím odkládám.
Jako další krok bude nutné rozchodit SPI, abych se měl jak domluvit s DW1000. Jako bonus by se mi líbilo rozchodit to USB, abych nemusel pořád pracně připojovat USB-UART převodník. Pak by možná i znovu nastal čas na bootloader, aby nebyl potřeba ani ten STLINK.

10. únor 2022 — Decawave driver (Jirka)

OK, dnes to budou zase novinky od Jirky, jeden starší a jeden nový …

[Update 5/2/2022]

0xdeca0130! Tj. dokážu přes SPI přečíst device id z DW1000. Zádrhel byl opět v mizerné dokumentaci knihovny OpenCM3. Pro zápis a čtení přes SPI neslouží funkce spi_write() a spi_read(), a to dokonce navzdory tomu, že jsou tyhle dvě funkce použité ve vzorovém příkladu pro SPI. Je potřeba použít spi_xfer(). Teď ještě k tomu vlastnímu readfromspi() přidat writetospi() a měl by začít fungovat celý driver od Decawave. Kus jsem ho už použil pro to čtení device id.

[Update 10/2/2022]

Mám portovaný Decawave driver. Funguje mi posílání a příjem zpráv. Mačkáním tlačítka na jedné desce blikám ledkou na druhé. Na obou deskách je stejný firmware, takže se přepínají navzájem.
Zajímavý zádrhel je vnitřní stavový automat DW1000. Kupříkladu ze stavu "přijímám" neumí přejít přímo do stavu "vysílám". Nejdříve je potřeba příjem přerušit a přejít do stavu "nic nedělám". Zároveň se taky ve stavu "přijímám" sám od sebe neudrží. Když přijde částečná, či jinak porušená zpráva, přejde DW1000 do stavu "chyba, nic nedělám". Takže je nutné pořád kontrolovat, zda pořád ještě přijímá, a případně ho znovu nahodit. Nebo si nastavit přerušení, aby pokrylo nejen příjem nové platné zprávy, ale i různé chyby, a v rámci obsluhy přerušení pak řešit, jestli přišla zpráva, nebo nastala chyba. A když tak znovu zapnout příjem.
Když už mluvím o přerušení … Na desce je bohužel tlačítko na portu A, pinu 0, zatímco DW1000 IRQ pin je připojený na port B, pin 0. Ztěžuje to život. U procesoru stm32f103 jsou oba připojitelné pouze na ten stejný interrupt, EXTI0. Řešit v jedné obslužné rutině dva možné zdroje přerušení není nic pěkného. Vlastně jsem to ani nezkoušel, takže nevím, jestli to zkombinovat vůbec jde. Alternativou je jeden z těch zdrojů pollovat. Protože v budoucnu asi tlačítko nebude potřeba, polluju to. Později tuhle ošklivou část kódu smažu.
Blíží se čas na nižší aplikační vrstvu: Komunikační protokol z PC přes sériák, komunikace se vzdálenými moduly přes proxy modul a UWB, časem snad včetně výroby mesh sítě. Pro vyšší aplikační vrstvu budou potřeba pokusy s časováním a měřením vzdálenosti.

13. únor 2022 — Pozyx + GPS

Dnes jsem udělal pár rychlých testů na zahradě. Zasloužilo by si to pořádně rozměřit a udělat už pořádné kotvy, ale … raději něco málo než vůbec nic. Graf (z druhého pokusu) mne zaujal:
Je na něm pěkně vidět, že ty tři kotvy se nepohybovaly, zatímco None „základna” (notebook s GPS a Pozyxem) vzdálenost je proměnná. Špatná zpáva je, že tam byla ještě čtvrtá kotva a ta při druhém pokusu vůbec vidět není.
set OK 3431
set OK 3455
set OK 3411
ERROR 26662
set OK None
Tak jo, už to vidím … ono již při prvním pokusu vypadlo spojení v čase 150s a pak už se tedy spojení neobnovilo. :-( … moc spolehnutí na to tedy není.
Teď bych měl přidat obázek z JOSM a spočítat pozici pomocí trilaterace, ale asi na to úplně při nedělním večeru nemám sil. Možná zítra. Pro referenci si sem schovám logy gps-pozyx-220213_142833.log a gps-pozyx-220213_143221.log.

16. únor 2022 — No GPS vs. BU01 Single Sided

Ještě o víkendu jsem si říkal, že by mohla být zábava jet s Jirkou „paralelní slalom” a porovnávat, kdo se kam za jakou dobu dostal, ale teď už vím s jistotou, že by to divácky byla hrozná nuda: Jirka by byl v cíli dříve než já se vůbec rozhoupu vyjet.
Tak jsem si konečně rozchodil JOSM (ano, nakonec zbaběle pod Windows) a dupnul data z GPS seriáku:
python -m osgar.logger gps-pozyx-220213_142833.log --stream gps_serial.raw --raw
$GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPRMC,142833.775,V,,,,,,,130222,,*25 $GPGGA,142834.775,,,,,0,00,,,M,0.0,M,,0000*5B $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPRMC,142834.775,V,,,,,,,130222,,*22 $GPGGA,142835.775,,,,,0,00,,,M,0.0,M,,0000*5A $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPRMC,142835.775,V,,,,,,,130222,,*23 $GPGGA,142836.775,,,,,0,00,,,M,0.0,M,,0000*59 $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPGSV,2,1,07,29,54,218,31,02,43,079,27,31,23,084,26,27,28,165,*76 $GPGSV,2,2,07,04,22,045,,24,13,156,,20,01,100,*4F
(zdá se, že ani naformátovat text s dolarama a dvěma mínus mi moc nejde) … no nic, o co jde? Není tam žádná pozíce!
Nechal jsem se naivně ukolébat "statistikou":
python -m osgar.logger gps-pozyx-220213_142833.log
 k           name bytes | count | freq Hz
---------
 0            sys   715 |    6 |   0.0Hz
 1   gps.position   540 |  180 |   1.0Hz
 2 gps_serial.raw 36730 | 5731 |  31.8Hz
 3    pozyx.range 56498 | 3104 |  17.2Hz
 4 pozyx.settings   796 |   10 |   0.1Hz

Total time 0:03:00.231309
ale ona ta `gps.position` je
python -m osgar.logger gps-pozyx-220213_142833.log --stream gps.position
0:00:01.093414 1 [None, None]
0:00:02.105047 1 [None, None]
0:00:03.097231 1 [None, None]
0:00:04.101952 1 [None, None]
… tak teorie, že Pozyx (na plný výkon) nejspíše trošku ovliňuje i příjem GPS. Zároveň se přiznám, že jsem se nijak nesnažil je od sebe extra odstínit.
A teď příspěvky Jirky:

Update 14-02-2022 (Jirka)

  • Posílám strukturované zprávy, včetně hlavičky podle IEEE 802.15.4. Díky tomu může DW1000 filtrovat příchozí zprávy podle adresáta a nezatěžovat mikroprocesor cizími zprávami.
  • Prvním uživatelem strukturovaných zpráv je Single-sided Two-way Ranging, aneb cesta tam a zase zpátky. To je nejjednodušší způsob měření vzdálenosti a Decawave ho v uživatelské dokumentaci srdečně nedoporučuje kvůli velké citlivosti na různé nepřesnosti. Dobrá zpráva je, že mi naměřená doba letu signálu roste se vzdáleností mezi moduly. Ne tak dobrá zpráva je, že při malých vzdálenostech, pod 1.5 metru, ten vztah není lineární.
V dalším kroku nejspíš přejdu na Double-Sided Two-way ranging, které je sice složitější, vyžaduje více poslaných zpráv, ale mělo by být o řád až dva přesnější. Pak bude potřeba přijít na to, jak je to s těmi zpožděními signálu při cestě k anténě a z ní, což do naměřené doby letu signálu zanáší konstantní chybu.
Takhle nějak, viz příloha, vypadá odhad vzdálenosti vůči skutečné vzdálenosti. Tohle je hodně optimistický případ, protože to jsou stejná data, na kterých jsem ten převod kalibroval. Přijde mi to dost citlivé na umístění předmětů, včetně mě, kolem antén(y). Něco takového asi způsobovalo i tu nelinearitu včera, kterou dneska nevidím. Po 1.9 m se změní typ povrchu podlahy a celé to skočí.

Update 16-02-2022 (Jirka)

Doporučované Double-sided Two-way Ranging na krátké vzdálenosti vypadá skoro nerozlišitelně od Single-sided Two-way Ranging. Viz příloha. Střední kvadratická chyba je téměř stejná. Rozdíly v rychlosti hodin obou zařízení, a tedy výhody Double-sided, se ale asi více projeví až při větší vzdálenosti. Budu muset vymyslet, jak testovat na větší vzdálenost a nezmoknout při tom

17. únor 2022 — Pozyx path vs. BU01 default range

Tak jo, nejlepší je mít nějakou urgentní nezajímavou práci a pak hraní jde úplně samo. A ano, zase jsem to „lehce” ošidil, protože místo pořádné trilaterace je to pouze průběžný update pozice vůči měření k právě přijaté vzdálenosti ke kotvě. Ty chodí v různé časy … a vlastně by to i Kalmanem skončilo, jen tam teď není žádný model pohybu a K=1.
Co mne ale zase znervónilo byl assert na měření vzdálenosti mezi kotvami:
AssertionError: ((0, 0, 0), (12.721, 29.308, 0), 31.94969021759053, 12.417)
Prostě dvě kotvy co mají být cca 32 metrů od sebe „naměříme” 12.4m! No je to na 95% přetečení měření k mezi jinými uzly …

Update 17-02-2022 12:44am (Jirka)

Maximální hlášená vzdálenost v garáži je těsně nad 30 metrů. Až překvapivě se to shoduje s délkou té garáže, resp. toho parkoviště, odhadnuté podle Google maps. Kolem 29 metrů to měření začalo vypadávat. Těžko říct, jestli kvůli vzdálenosti, nebo kvůli rušivým odrazům.
V bytě přes zdi končím po pěti metrech.
Nastavené je to podle příkladu od Decawave. Zkusím si s tím pohrát.

Update 17-02-2022 8:50pm (Jirka)

Na čerstvém povětří: channel=5, prf=64M, prefix_len=128,preamble_code=10: 77 m hlášených, ale podle Google maps to dost možná bylo ke 100 m. Že by se našla ta chybějící třetina rychlosti světla při převodu? Pak bych měl ale při malých vzdálenostech docela velkou chybu. channel=4, prf=64M, prefix_len=128,preamble_code=20: 60 m hlášených, ale nad 50 m už to bylo mizerné, s mnoha výpadky. Podle map 80 m.
Zajímavostí terénního profilu je, že jsem šel přes mělký ďolík. Na protějším svahu byl příjem spolehlivější, než uprostřed dole. Navzdory tomu, že to bylo pořád v přímé viditelnosti. Tj. pro lokalizaci sekačky bude nejvhodnější, bude-li sekačka létat.

Update 17-02-2022 9:54pm (Jirka)

(to bylo po mém dotazu, zda to nechce vyzkoušet na více zařízeních)
Dost vysoko na mém seznamu priorit je kalibrace a ta chybějící třetina rychlosti světla. Dokud neměřím vzdálenost, nechce se mi to komplikovat více zařízeními. Decawave driver obsahuje korekční tabulku a magický offset, které používá pro opravu odhadu. To ale můj problém neřeší. Takže tady ještě nějaká práce zbývá.

Update 17-02-2022 9:54pm (Jirka)

Application Note 11 popisuje, kde se bere ta korekční tabulka. Silnější signál dřív překročí threshold pro detekci jeho přítomnosti. Různí uživatelé interpolují různě nelineárně [ 1, 2 ]. V [ 1 ] taky pozorovali citlivost na náklon antény a na přítomnost vodivých předmětů v jejím okolí.
Zajímavá je taky Application Note 17, která tvrdí, že kvůli odrazům od země může nastat situace, kdy je signál detekovaný do nějaké vzdálenosti, pak kus není a pak zase je.
p.s. k tomu mé pozorování, že ta pozice je taková klikatice je očekávaně, protože se nutně nepohybuji v rovině kotev a tak jsou vzdálenosti větší a budou moji pozici odstrkovat ... mi přijde v kontextu tech šílených kalibrací jen takové drobné placnutí do vody

21. únor 2022 — BU01 korekce korekce

Doplňuji víkendové reporty od Jirky …

Update 19-02-2022 9:01am (Jirka)

Kalibrace na větších vdálenostech s anténou výš nad zemí, i když jen 80 cm místo doporučených 140 cm, vypadá lépe. Viz příloha. Na obrázku je méně bodů, než minule, protože různá měření v jedné vzdálenosti tentokrát nejdříve průměruji a pak až interpoluji.
Strmost převodu z tiků DW1000 na vzdálenost tentokrát odpovídá 97.4 % očekávané rychlosti světla. To je o řád lepší, než minule. A stále o řád horší, než abych byl spokojený. Pořád je to čtvrt metru rozdílu v desetimetrové vzdálenosti.
Jedním možným vysvětlením je ta dříve vysvětlená korekce pro klesající sílu signálu. Jestli čtu kód dobře, je zhruba na úrovni 3 % vzdálenosti. Podle odpovědi na fóru na poměrně detailní dotaz je korekci potřeba odečítat, což po zamyšlení dává smysl, ne přičítat, jak jsem myslel podle názvu funkce. To už by pak sedělo o kus lépe.
Druhým zajímavým prvkem je výrok ve stejné odpovědi: "As was mentioned in the code comment, uus indicates UWB microsecond, not microsecond. In calculation, 1 uus is around 1.025 us." To je jako co, tyhle dvoje různé mikrosekundy, které se liší o 2.5 %, resp. 2.4 % v opačném směru porovnání? Na to se budu muset ještě podívat.
Double sided two-way ranging ver2
Double sided two-way ranging ver2

Update 19-02-2022 9:58am (Jirka)

Tak ten 1.025 faktor to není. To je něco specifického pro jejich kód a mého se to netýká. Převádí tam zadanou dobu odezvy kotvy z mikrosekund na tiky pomocí *512, jenže 512 tiků je ve skutečnosti trochu více, než jedna mikrosekunda, což pak musí zohlednit. Já všechno zadávám a měřím v ticích a takový převod tam nikde nemám.
V tuhle chvíli mi asi jako možná příčina zbývající chyby zůstávají odrazy signálu od zdí a podlahy a ten pokles síly signálu se vzdáleností, který pak ovlivňuje čas detekce.
Martine, přijde mi to, že ty tomu Pozyxu prostě věříš a že jsi přesnost s metrem v ruce neměřil. Je to tak? Pravda, je, že s metrem v ruce beztak nepoznáš, jestli pro převod nepoužívají nějakou podezřelou rychlost světla, nebo nějakou magickou konstantu či tabulku :-/
Tady bych asi měl připsat nějakou odpověď. Nahrubo jsem to měřil na začátku, ale teď tomu opravdu "slepě věřím", resp. nevěřím a ptám se na vzdálenosti mezi kotvami, které už by měly být konstantní. Měl jsem sem dát grafy od Lilly, které jsem úplně nepochopil, ale třeba někdo jo. A vlastně graf rozdílů k Ground Truth mi přijde čitelnější. Tak tedy skok v čase ..."

Update 19-01-2022 (Lilly, před měsícem)

I didn't experiment with the settings (so as to not have to reconfigure them every reboot). Looking through your blog, I see you got ranges 30-50m, which is pretty good!
I did all my experimenting indoors (much smaller ranges) but one thing I noticed was that there appeared to be different and non-zero biases for different pairs of pozyx anchors:
Another thing I was trying to figure out was whether estimates would be equally good in every direction. Here "UWB inside" was when I had installed the pozyx anchors next to the RPis on the robot (so the body of the robot itself was causing obstructions), and "UWB on top" was after moving the pozyx anchor externally, above the lidar. It looks like there might be some directionality, but hard to say from this one test.

Update 27-01-2022 (Lilly, cca před měsícem)

80m is really promising!
My old notes are somewhat unorderly, but I have these plots of error and true distance. The pozyx devices were around 20cm off the ground, and the hallway width changed from about 2m to about 5m, which probably had a significant impact. I only realized that after these tests, so it's not carefully noted in my measurements.

Update 19-02-2022 8:11pm (Jirka)

Když si tu korekční tabulku od Decawave překreslím do grafu "korekce relativní vůči vzdálenosti" (příloha), je vidět, že ve vzdálenostech 4 až 12 metrů dochází k opravě o 1.8 % až 3.5 %. Zuby v grafu jsou artefakty toho, že je ta korekce po částech konstantní. O 2.6 % nižší rychlost světla v mé lineární interpolaci dělá v tomto rozsahu vzdáleností něco podobného. Z poklesu křivky korekčního grafu se dá tušit, že pro vyšší vzdálenosti vyjde moje lineární interpolace špatně.
Asi ještě zkusím, jestli tu korekční tabulku nejde aplikovat na měření z mého modulu. Nebo najít nějakou pěknou výpočetně nenáročnou nelineární aproximaci. Pokud ne, nechám to být, protože vevnitř nad 10 m stejně nenaměřím a ven se s tím zatím nechystám.

Update 19-02-2022 8:11pm (Jirka)

Při započtení korekcí od Decawave pro jejich vývojové moduly se mi interpolační převodní konstanta z času na vzdálenost přiblíží k rychlosti světla na 0.6 %. Dovedl bych si představit, že to při pečlivější kalibraci dokážu ještě srazit tak na polovinu, či třetinu. O řád už to nesrazím, tam někde už narazím na závislost rychlosti světla ve vzduchu na teplotě/tlaku.

Update 21-02-2022 7:53pm (Jirka)

Tohle není konečná verze, ale spíš proof-of-concept na uchycení modulu, který nemá díry na šrouby. Zatím to použiju jako stojan pro kalibraci ve volném prostoru.

3. březen 2022 — BU01 měření rychlosti světla

Dnes bych začal zase s víkendovými novinkami od Jirky. Vlastně mi celkem přijde vtipné, že s těma UWB krabičkami si člověk na koleně může měřit rychlost světla … (no teď koukám, že chybí i nějaké dovětky k poslednímu reportu, takže toho bude více).

Update 21-02-2022 9:20pm (Jirka)

Ano, za ideálních podmínek to vypadá dobře. Ale znáš mě … jak to nemám na mikrometry, jsem nesvůj
Je potřeba brát v potaz, že jsem pro tu interpolaci vždycky průměroval dvanáct měření. Jednotlivá měření mi pořád ještě dost skákala. Nicméně včera jsem výrazně zkrátil pevnou dobu odezvy v two-way ranging a vypadá to, ťuk ťuk na dřevo, že poskakování ubylo. Tak uvidíme při příští kalibraci, na špejli, ve volnějším prostoru.
Dost se bojím těch různých efektů, které popisuje Lilly a na které narážím já: Směrovost, citlivost na náklon, citlivost na předměty okolo a především v cestě signálu, snížený výkon u podlahy. Většinu času to bude fungovat v podmínkách hodně neideálních. Proto to chci zpřesnit co nejvíc, aby to i při zvýšené chybě pořád stačilo. Na tu závislost na konkrétní dvojici zařízení, kterou zmiňuje Lilly, jsem teda taky hodně zvědavý.

Update 24-02-2022 12:47pm (Jirka)

Kalibrace i na větší vzdálenosti venku ve volném prostoru, průměrování přes ještě víc měření plus opravená optimalizace interpolačních parametrů rovná se naměřená rychlost světla 0.013 % od udávané (ve vzduchu). Takže nakonec až někde u té hranice závislosti na tlaku, teplotě, vlhkosti a spol. To jsem nečekal. Pro srovnání, ve vzduchu je světlo o 0.03 % pomalejší než ve vakuu (wikipedia).
V dalším kroku zkusím naměřit rozptyl jednotlivých měření, bez průměrování. A pak asi přijde na řadu zkusit, nakolik je to se stejnými parametry přenositelné na jinou dvojici modulů.

Update 27-02-2022 10:34pm (Jirka)

Různé dvojice modulů dávají, asi podle očekávání, trochu jiná měření. Viz příloha. Jedna dvojice odhaduje stejnou vzdálenost na 174 cm, druhá na 179.5 cm. Obě dvojice se směrodatnou odchylkou "šumu" pod tři centimetry.
Když matematicky ne úplně korektně smíchám chybu, kterou vidím v kalibraci převodu z tiků na vzdálenost, směrodatnou odchylku šumu, a těch pět centimetrů rozdílu mezi moduly, čekal bych dvě třetiny měření tak do osmi centimetrů od správné hodnoty a téměř všechna do šestnácti cm. V tomhle odhadu ještě nejsou zahrnuty chyby vzniklé náklonem antény a blízkostí k různým překážkám. To přidá k odhadu dalších pár centimetrů. Tohle platí pro jednotlivá měření. Při prohnání série měření Kalmanem a při kalibraci každé antény zvlášť, jak doporučuje Decawave, zase pár centimetrů zmizí.
Malý robot bez dalších senzorů takhle přesně na nabíječku nejspíš nenajede, ale dveřmi v bytě by naslepo projet mohl. Větší robot by mohl zvládnout mostek v Martinově japonské zahradě, aniž by polekal pádem kapry koi.
Měření pro dva různé páry
Měření pro dva různé páry
p.s. Odvolávám. Příště se musím nejdřív víc zamyslet. Šum jednotlivých měření není 3 cm. To je šum průměrovaných (!) měření. Ten 5cm rozdíl mezi dvěma dvojicemi modulů platí.

Update 03-03-2022 1:17pm (Jirka)

Jenom rychlá poznámka …
Zatímco u dev kitů z Decawave by měla být zpoždění antén změřená v továrně a zapsaná v One Time Programmable paměti, u mých modulů na dané OTP adrese není nic.
Toto se váže k úternímu mailu, že Mouser psal, že už má MDEK1001 na skladě: mouser.com:MDEK1001v úterý tam bylo něco přes 300, teď je 216 a než dám push na web, tak už možná nebudou. No nic.
Vidím to tak, že své "novinky" s "dual tagem" si nechám na příště ... (md)

4. březen 2022 — Auta a UWB stereo tag

Téma „k čemu je to vlastně vůbec dobré?” je takové „oblíbené”, resp. se stále vracející. Zhruba před 14 dny jsme se s Jirkou bavili, že BMW používá UWB zámky a jestli by z toho nešlo vymačkat trošku více? Jirka navrhoval, že by bylo fajn se dozvědět, že auto před autem, za kterým jedete, prudce brzdí. Mohlo by tuto informaci poslat a člověk (resp. jeho stroj) by se to dozvěděl dříve než by to uviděl. To by jako aplikace šlo, co říkate? U těch zámků asi nebude extra velký radiový výkon, ale třeba jich tam bude více?
Já cvičně experimentoval s párem — přidělal jsem ho na prkno 115cm dlouhé a to má přijít na zahrádku auta. No a pro první pokusy vlastně auto vůbec není potřeba. Po pravdě ani nevím, jestli ta motivace byl Jirkův nápad nebo jsem chtěl zjistit, jak dobře by šla zjišťovat vedle absolutní pozice i absolutní orientace pouze z UWB tagů, ale to je teď asi už jedno. V praxi je rozhodně užitečné vědět, že to zuřivě brzdící auto je před vámi nebo v sousedním pruhu, což se z jednoho majáku úplně snadno nedozvíte. Jo a ultra rychle zipování by se mi také líbilo. (trávíce včera půl hodiny v koloně způsobené jenom zipem)
Hrál jsem si zase pouze s pěti Pozyx kotvama — dvě na prkně a tři statické. Jako vedlejší efekt je pozorování, že autodetekce statických kotev by asi selhala, protože to jsou dva „pod-grafy”, resp. dvě soustavy, které se vůči sobě pohybují. Začnu s dalším kryptickým obrázkem, který jsem posílal Pozyx supportu:
Co na obrázku vidíme? Minimálně v čase 40s končí fialovo-modré koleje. Prostě v grafu už nejsou žádná měření vůči krabičce s ID 26727. Dále mne tam rozčiluje žlutá tečka na šedivé stopě take okolo 40s … skoro jako by to souviselo?! (za mne je to záměna IDs — prostě ta naměřená vzdálenost patří jinému páru)
Co ještě můžu řící, že počítač aneb „sběrné místo” jsem měl připojen k jedné statické kotvě a ta ID na prkně byla 0x0D7F a 0x0D53. hex(3411), hex(3455) = ('0xd53', '0xd7f') … takže opravdu ta šedivá stopa jsou "tagy" na prkně.
Co je snad dobrá zpráva je, že ostatní kotvy si povídaly celou dobu i když jsem rozhodně nebyl v přímé viditelnosti. Byl jsem zvědav co Z-ová souřadnice mimo rovinu těch třech kotev … příště.
Ještě jeden obrázek, resp. 2D mapka dvou okruhů s prknem/stereo-tagy. Trošku to skáče, což může být Z-ová souřadnice, případně zastínění "operátorem". Ale nahrubo je myslím vidět, že ty dva okruhy jsou cca 1m od sebe:

6. březen 2022 — 2+D vs. 2.5D

Dnes nemám nic nového, jen takové „bloumání” nad tím co dále. Přemýšlel jsem nad scénářema, které bych rád realizoval. Vlastně je to klasické dostaň se z místa A na místo B a vyplň ohraničený prostor (sekání, uklízení, sázení stromků, …).
U té cesty si přestavuji, že jako uživatel „vytýčím koridor” pomocí majáčků/kotev, možná bych to jednou projel ručně a zbytek „kyvadlové dopravy” už by jezdil sám. Na robotovi bych nechal dva tagy, to se mi zatím líbí, ale pro trilateraci bych typicky viděl pouze maják před a za sebou. Že by to byla spíše bilaterace? Před naší za naší cesta má ať nepráší … jestli to teď nebude na blacklistu, vlastně na blocklistu. No nic, co jsem to chtěl říci? Že situace, kdy uvidím právě dvě kotvy bude nejběžnější a měl bych se s tím tedy vypořádat.
U posekání zahrady nebo osázení mýtiny bych si představoval typicky 4 kotvy po obvodu a zase pár na robotovi/robotech. Vlastně mi přijde UWB technologie v lese daleko rozumnější než DGPS … schválně jestli na podobný projekt ještě znova dojde.
A teď ten název 2+D vs. 2.5D … určitě existuje nějaký termín pro povrchovou lokalizaci vs. 3D lokalizaci v prostoru. Nechť mám pozemního robota a jezdím v terénu, tj. pro každé XY mám pravě jediné Z, na které robot skonči, když ho „pustím”. Ale to není 2.5D, co používá Pozyx. Tam je jedním ze vstupů Z-ová souřadnice (konstantní) a 3D pozice kotev vůči této hladině pozici kompenzují. Pokud ale pojedu přímo od kotvy K(i) na K(i+1) se stereo-tagem, tak bych asi měl být schopen dopočítat i ten Z-ový profil.
To mi připomíná stále ty Jirkovy kapry koi co jsem ještě nekomentoval. … no je to spíše polorozpadlá, cca 1m široká, lávka, po které bych chtěl být schopen spolehlivě navigovat robůtky, třeba s cihlou, taškou nebo barelem na zádech …

8. březen 2022 — Eduro a dosažené BU01 milníky

Dnes jsem jezdil s Edurem na ČZU a bylo to celkem užitečné cvičení. Nejprve „klasika” aneb staré bolesti, na které jsem už s radostí zapomněl:
  • nepoužívat STOP tlačítko (občas se resetuje APU3 počítač)
  • odometrie občas „skočí”
Zásilka s MDEK1001 dnes nedorazila a v rozčílení jsem si nakonec na testy vzal jen dvě kotvy na hraní. Na Eduru jsem doinstaloval pypozyx balíček a hned to fungovalo. Drobný problém byl, když jsem kotvu vypnul a zapomněl, že ta stále napájena na robotovi se s tou nově nabootovanou nedomluví (jiný kanál, preambule, atd.).
K věci — zajímavé mi přišlo toto měření:
Eduro jízda 5m
Eduro jízda 5m
Trošku jsem hacknul "go.py", aby robot jel 2x tam a zpět a výstup byl následující:
Asi je jasné o co mi jde — v oblasti mezi 3. a 4. metrem je nějaká divnost. Obě kotvy byly po celou dobu jízdy vzájemně viditelné, volný koridor byl minimálně 1m (odhad). Skoro to vypadá, že došlo k nějakému odrazu od zaparkovaného Spidera nebo nějaká interference s WiFi??
Další pokusy na chobě bez překážek bohužel byly k ničemu, protože jsem si nevšiml, že umřela powerbanka u kotvy a následně jsem zapomněl vypnout kotvu na Eduru, takže každá komunikovala na jiném kanálu.
A teď ještě novinky od Jirky …

Update 07-03-2022 11:30pm (Jirka)

Dosáhl jsem několika milníků najednou:
  • Přidal jsem jednoduché textové rozhraní přes sériák, včetně automatického doplňování příkazů a vyhledávání v historii na straně PC.
  • K použitému printf() přibylo sscanf(), takže se nevejdu do 64 kB flash a žiju i z těch druhých 64 kB, které oficiálně neexistují. Šlo by to udělat úsporněji, ale chtěl jsem to zkusit i takhle.
  • Moduly teď "blikají", takže si můžu vypsat seznam viditelných sousedů. Soused, který se nějakou dobu neozval, je ze seznamu odebrán.
  • Dohromady tak místo broadcastové adresy můžu při měření vzdálenosti měřit vůči konkrétnímu viditelnému sousedovi. Zatím nepodporuji měření, kdy iniciátorem není modul připojený k PC.
"Blikání" je zárodek mesh protokolu - záblesk posílá routovací informace - ale mám toho ještě hodně k rozmyšlení. Statická spolehlivá síť je jednoduchá, ale mizení a roaming modulů to zesložiťují.

20. březen 2022 — BU01 mesh a Babel

Update 11-03-2022 1:49pm (Jirka)

Mesh síť funguje, včetně roamingu, mizení a restartování uzlů. Můžu provádět traceroute na uzel mimo přímý dosah. Klíčové slovo je Babel, i když jsem ten algoritmus pro své účely hodně zjednodušil.
Teď je otázka, jestli budu nějak zobecňovat přeposílání traceroute packetů, nebo to řešit "case by case". Pokud začnu zobecňovat, skoro abych si nastudoval OSI vrstvy.

Update 20-03-2022 9:50am (Jirka)

Upravil jsem mesh protokol, aby fungovalo nejen restartování jednotlivých uzlů, ale i celých podsítí. To se například hodí, když jsou moduly v jedné místnosti napájené z jednoho zdroje. Teď se během pár sekund přisynchronizuje všechno a ne jen krajní uzel připojený do vnějšího světa.
A hlavně, přidal jsem schopnost uzlu A zeptat se uzlu B na jeho vzdálenost k uzlu C. V kombinaci s tou mesh sítí mohou být B a C kdekoli v síti. Jestli jsem to dobře pochopil, u Pozyxu musí být B v přímém rádiovém dosahu A.
Když už teď můžu z modulu připojeného k PC měřit vzdálenost mezi jinými moduly, je asi čas vrátit se ke kalibraci antén a provést ji nejen pro jednu konkrétní dvojici zařízení. Při té příležitosti asi vznikne na straně PC nějaká knihovna ke komunikaci moduly, abych nemusel všechno pořád zadávat a kopírovat ručně. A pak už snad dojde na lokalizaci …

30. březen 2022 — BU01 kalibrační čtverec

Update 29-03-2022 8:30pm (Jirka)

Když umístím moduly do čtverce a změřím vzdálenost mezi všemi dvojicemi, dokážu z toho vypočítat zpoždění na jednotlivých anténách. Podle očekávání vyjde pro každý modul jiné.
Respektive, protože je double-sided two-way ranging lehce asymetrické, dokážu spočítat zvlášť zpoždění na anténě při vysílání a při příjmu. Nicméně pro všech pět modulů, které jsem zatím zkoušel, vychází obě hodnoty, až na drobné odchylky, stejně.
Teď musím přijít na to, jak vyrobit, nejspíš na flash, konfiguraci, abych mohl každý modul nastavit jinak, aniž bych překompilovával kód. Na "write once" paměť v DW1000 se mi moc sahat nechce. Jednak je to "once" a to nemám rád, jednak je to podle dokumentace podivné cvičení, ve kterém dokonce vystupuje vyšší napětí.
Abych mohl stavět velký kalibrační čtverec, začal jsem taky řešit napájení z baterie a plastové krabičky, abych nebyl omezený délkou USB kabelů. Dobrá zpráva je, že když zapojím Li-Ion článek s napětím 3.6 V na napájecí piny pro 5 V, modul funguje. Takže tam možná nemusím přidělávat vlastní step down z 3.6 V na 3.3 V. Připojovat těch 3.6 V, resp. až 4.2 V (?), rovnou na 3.3 V se mi nechce. Ještě musím vyzkoušet chování při téměř vybitém článku, kolem 3 V. Ten step down, který mám, je totiž zároveň step up, takže tady by mohl pomoct. Ale zase bude mít nějaké vlastní ztráty, takže se to celé vybije dřív. No nevím. Asi "keep it simple". Vlastně už při vyšších napětích to bude "zajímavé", protože palubní regulátor z 5 V na 3.3 V na výstupu klesne pod 3.3 V. Ještě je co zkoušet

13. duben 2022 — BU01 zapouzdřeno jest

Update 4/4/22, 10:20 AM (Jirka)

Zapouzdřeno jest. Viz příloha. Teď se můžu pustit do prostorově rozsáhlejších instalací a můžu zkoušet životnost na baterie.
Dobrá zpráva: Modul přestane fungovat až někde mezi 3.25 - 3.3 V na 5V napájení, po téměř čtyřech hodinách běhu s 32 měřeními vzdálenosti za sekundu plus režie pro mesh síťování. V tu chvíli je baterie téměř vybitá. Nabíječka do ní pak dostane 670 mAh, při kapacitě baterie 700 mAh. Takže připojovat step down/up converter je zbytečné, déle to stejně nepoběží.
Špatná zpráva: Moduly, které vybijí baterii až do dna, po jejím nabití a opětovném spuštění "blbnou". Opraví to přeflashování kódu. Což mě vede k podezření, že při nízkém napětí se poruší data na flash. Takže se modul až do tak hlubokého stavu vybití dostat nesmí.
Dobrá zpráva: Palubní mikrokontrolér umí monitorovat vlastní napájecí napětí a umí se uspat. Jestli si dobře pamatuju, DW1000 je také možné uspat. Takže příští krok je naprogramovat pud sebezáchovy.

Update 4/6/22, 3:49 PM (Jirka)

Uspání při vybité baterii už funguje. Sledování napětí na mikrokontroléru jsem sice nerozchodil, ale to nevadí, protože DW1000 ho umí také, ve větším rozsahu a s jemnějším rozlišením. Za cenu další SPI komunikace.
Víte, co se stane, když si chcete ověřit sleep kontroléru tím, že ho dáte hned na začátek main()? Šípková Růženka! Takový sebeuspávající se modul se blbě flashuje novým kódem. No nic. Ponaučení pro příště.
Zajímavé debugování bylo na téma "jednou za čas se to zasekne." Když jsem zvýšil četnost komunikace po sériáku, pravděpodobnost záseku vzrostla. Když jsem povypínal okolní moduly, klesla. Abych tu detektivku zkrátil: Pokud seriák na mikrokontroléru nestíhá, nastane "overrun error", nastaví se error flag, zavolá se interrupt, ten zjistí, že nejsou k dispozici žádná data, ukončí se, mikrokontrolér najde nastavený error flag, zavolá interrupt, ehm. A zatímco se ten interrupt handler takhle krásně cyklí, všechno ostatní musí počkat. Na věky věků. Ámen. Mazání toho flagu jeho přečtením následovaným voláním recv() mi taky nepřijde zrovna intuitivní.
Kdyby ode mně někdo tohle chtěl koupit, tak by mi cena nastavená Pozyxem snad ani nepřišla nesmyslná. Pro jednohubku na ochutnávku. Takových "pitomostí", které je potřeba vyřešit, je docela hodně. A to to ještě vlastně ani nedělá nic užitečného. reklama-begin Potřebujete sledovat objekty ve vymezeném prostoru? Můžeme vám pomoct s řešením na míru! Ptejte se Martina, co a jak.reklama-end A tak

20. duben 2022 — BU01 Follow Me

Dal jsem tři moduly na Deedee, malého domácího robota, a zkouším jízdu za čtvrtým modulem, neseným v ruce. Takové malé "follow me". Jenže. Jak je ten robot úzký, pod 30 cm, tak 2d trilaterace protíná téměř soustředné kruhy. Takový výpočet je, jak by řekla dcera, hodně hodňácky citlivý na chybu měření vzdálenosti. Ať už systematickou, nebo nesystematickou. Empiricky vzato, odhad polohy majáčku neseného dva metry rovně před robotem poskakuje o půl metru na každou stranu a dost často trilaterace ani nenajde platné řešení. Ze zjednodušené simulace mi vychází šum s odchylkou do strany (1 sigma) 0.4 m, tj. většina odhadů Y, které je ve skutečnosti 0, někde mezi -1 m a +1m. To je na dvoumetrové vzdálenosti hodně. Robot se podle toho chová: zmateně.
Částečným řešením pro nesystematickou chybu bude co nejvíc zvýšit frekvenci měření a průměrovat polohu majáčku v čase. Dobrý den, pane Kálmáne. Pro vyřešení systematické chyby je užitečný všechen ten předchozí čas investovaný do kalibrace modulů.
Jiným řešením by byl větší robot. Podle simulace alespoň půl metru široký. Metr by byl ještě lepší, ale to už by se robot ani nevešel do dveří. Každopádně nový robot na doma, natož větší, není na pořadu dne.
Další zajímavý zdroj potíží je umístění modulů na robotovi i majáčku nízko nad zemí. V závislosti na výšce majáčku nad zemí vzniká při trilateraci systematická (!) chyba do strany zhruba taky někde mezi 0.3 a 0.5 m. S tou asi nepůjde dělat nic. Jedině už opravdu pevná instalace "kotev" v prostředí, místo na robotovi, a víc krmit dítě, aby rychleji rostlo a mohlo držet majáček výš. Do dvou metrů nad zemí doporučených v dokumentaci dceři ještě "něco málo" zbývá.

26. duben 2022 — BU01 Follow Me obrázky

Update 4/21/22, 7:58 PM (Jirka)

Chtěl jsi obrázek, máš ho mít. Červeně polohy robota, zeleně odhadnuté polohy majáčku. Je to dost smutný pohled.
p.s. No, nejel rovně. Navigoval na poskakující maják a vyhýbal se při tom překážkám. Ta červená trajektorie podle tracking kamery je asi dobře.

Update 4/24/22, 7:41 PM (Jirka)

Ale jo. Když lépe nastavím parametry antén a proženu odhad pozice majáčku Kalmanovým filtrem, něco to dělá.
Lépe to funguje na krátkou vzdálenost tak do tří metrů. A i tak to občas mívá několikasekundové výpadky. Budu se muset podívat, jestli nefunguje měření vzdálenosti, nebo chodí odhady, ze kterých je zmatená trilaterace.

4. květen 2022 —BU01 stavový automat

Update 4/30/22, 10:23 PM (Jirka)

Ach, ten stavový automat. Výpadky při jízdách za majáčkem byly způsobené tím, že chodily nesmyslné vzdálenosti, řádově v kilometrech, a kód na PC je zahazoval. Nesmyslné vzdálenosti chodily, protože mikrokontrolér při měření vzdálenosti často používal časovou známku následující příchozí zprávy. Následující zpráva ale neměla ani přijít, protože DW1000 neměl ani být na příjmu. Jenže byl. Jak to? Protože ze stavu RX (příjem) po přijetí zprávy nejdříve (!) přejde do IDLE (nicnedělání) a až potom (!) ohlásí mikrokontroléru, že přišla zpráva. Na základě předchozí zkušenosti, že DW1000 přechází z RX do IDLE i při chybách při příjmu, mikrokontrolér monitoroval stav DW1000 a při IDLE okamžitě znovu aktivoval příjem. Když se to špatně sešlo, aktivoval příjem před zpracováním příchozí zprávy.
Řešením je aktivovat příjem až po zpracování příchozí zprávy, po ukončení vlastního vysílání a když nastane chyba při příjmu. Jenže ne všechny chyby při příjmu, ukazuje se, přepnou DW1000 z RX do IDLE. Když RX znovu aktivuji při všech chybách příjmu, nastane předchozí problém. Jenom v tom řetězci musí ještě těsně před přijetím zprávy nastat chyba příjmu, čímž se to stává vzácnějším. Takže jsem musel zjistit, co které chyby způsobují. Které přepnou do IDLE a které ne. Dokumentace je bohužel neúplná a, řekl bych, v tomhle bodě dokonce špatně. Takže jsem jsem strávil několik dní čekáním na každý jednotlivý typ chyby příjmu. Moc pěkné cvičení.
Teď už to vypadá, že race condition nenastává (přidal jsem její detekci) a že neplatné vzdálenosti jsou řádově v metrech, což může klidně být nějaký odražený signál. Tak snad to teď, ťuk ťuk na dřevo, bude lepší.
MD: o jaké dvě skupiny zpráv se tedy jedná?

Update 5/1/22, 1:33 PM (Jirka)

Z RX do IDLE přepíná Frame Wait Timeout (RFTO). V RX to zůstane po PHY Header Error (RPHE), CRC Error (RFCE), Sync Loss Error (RFSL), Preamble Timeout (RXPTO), SFD Timeout (SFDT) a Frame rejected due to filtering configuration (ARFE).
Podle dokumentace by to mělo přinejmenším při RXPTO, SFDT a RFTO přejít do IDLE. Ostatní nejsou dokumentované.
Až na ten Frame Wait Timeout se to chová, jako by bylo zapnuté RX-auto-reenable (RXAUTR), což ale nedělám. Asi bych se měl aspoň podívat, jestli tohle je zapnuté, nebo není. Podle dokumentace by default měl být "vypnuto", i když fráze typu "děje se X, pokud není zapnuté RXAUTR, pak Y", vlastně o defaultu, v matematickém smyslu, nic neříkají. Tak odvolávám: "The default value is 0." To zní jednoznačně.

8. leden 2023 — Pozyx digital I/O

Přes vánoční prázdniny jsem měl domácí úkol, který jsem samozřejmě neudělal. :( V rámci příprav na ELROB 2024 Jirka navrhl, že bychom mohli využít další z vlastnosti UWB modulů a to jejich digitálních vstupů a výstupů. Konkrétně po úvodní fázi „follow me” (následuj mne) je třeba robotu „říci”, že má přepnout do módu „vrať se na start” a proč k tomu rovnou nepoužít UWB tag?
Ano, Jirkova motivace je „oprášit všechny technologie co tu tak leží” a tak už samotný follow me by používal jak prastarý lidar (viz Eduro follow me na Floriade 2012, tj. před deseti lety), RGBD kamery a UWB tagy a kotvy. Jirka plánuje (resp. on na rozdíl ode mne úkol přes vánoce samozřejmě udělal, takže bych měl použít už minulý čas) použít své čínské moduly s vlastním kódem, já pak Pozyx.
Pozyx digitální I/O moc popsané nejsou. Našel jsem zmínku v developer tag_v1.5 datasheet.pdf, ale tento dokument není veřejně dostupný, resp. jsem ho nenašel. Tam píšou: A general purpose input/output pin. By default this pin is not configured and it can be used for other purposes. When configured as an output pin, the maximum output voltage is 3.3V (the operating voltage of the board). The pin is 5V tolerant. + tabulka:
GPIO1 Pin 9
GPIO2 Pin 10
GPIO3 Pin 11
GPIO4 Pin 12
Další indicie jsou popisy Pozyx konstant:
# The GPIO modes
    GPIO_DIGITAL_INPUT = 0
    GPIO_PUSH_PULL = 1
    GPIO_OPEN_DRAIN = 1

    ALL_GPIO_MODES = [GPIO_DIGITAL_INPUT, GPIO_PUSH_PULL, GPIO_OPEN_DRAIN]

    # The GPIO pull resistor configuration
    GPIO_NO_PULL = 0
    GPIO_PULL_UP = 1
    GPIO_PULL_DOWN = 2

    ALL_GPIO_PULLS = [GPIO_NO_PULL, GPIO_PULL_UP, GPIO_PULL_DOWN]
a konečně např. funkce setConfigGPIO().
Kód asi nikoho neohromí, ale stejně
>>> import pypozyx
>>> pozyx = pypozyx.PozyxSerial('/dev/ttyACM0')
>>> reg = pypozyx.SingleRegister()
>>> pozyx.getConfigModeGPIO(1, reg)
1

>>> pypozyx.POZYX_SUCCESS
1
>>> pypozyx.POZYX_FAILURE
0
>>> pypozyx.POZYX_TIMEOUT
8

>>> mode = pypozyx.SingleRegister()
>>> pull = pypozyx.SingleRegister()
>>> mode.value = pypozyx.PozyxConstants.GPIO_DIGITAL_INPUT
>>> pull.value = pypozyx.PozyxConstants.GPIO_PULL_UP
>>> pozyx.setConfigGPIO(1, mode, pull, 0x6827)
/home/md/.virtualenvs/osgar/lib/python3.8/site-packages/pypozyx/lib.py:194: UserWarning: setConfigGPIO: 0 wrong GPIO mode
  warn("setConfigGPIO: {} wrong GPIO mode".format(mode[0]))
/home/md/.virtualenvs/osgar/lib/python3.8/site-packages/pypozyx/lib.py:196: UserWarning: setConfigGPIO: 1 wrong GPIO pull
  warn("setConfigGPIO: {} wrong GPIO pull".format(pull[0]))
1
>>> pozyx.setConfigGPIO(1, mode, pull, 0x6827)
1

>>> pozyx.getGPIO(2, reg, 0x6827)
1
>>> reg.value
0
>>> pozyx.getGPIO(1, reg, 0x6827)
1
>>> reg.value
1
>>> 
>>> pozyx.getGPIO(1, reg, 0x6827)
1
>>> reg.value
0
>>> pozyx.getGPIO(1, reg, 0x6827)
1
>>> reg.value
1
trošku omáčky — už jsem dost zapomněl, jak se Pozyx používá, takže na vše je třeba nějaký pomocný "register" (pypozyx.SingleRegister()), co obsahuje vstupně-výstupní hodnoty. Funkce vrací úspěch, selhaní nebo timeout … co je co ale není zřejmé, tak proto ten výpis konstant (1 je úspěch). Pak mne zmátlo, že konfigurace GPIO 1 jako vstup s pull upem generovalo varování?! Ale jak vidíte, tak pouze jednou. Neodolal jsem a vytvořil pull request #78 do jinak dost mrtvého projektu. No a co není úplně vidět, tak po zapnutí pull-upu je vstup 1 (u GPIO 2 jsem to neudělal a tam zůstala 0) a když jsem spojil drátkem pin 9 a GND, tak jsem ze vzdáleného zařízení vyčetl 0. Hurá!
A teď už to jenom celé udělat pořádně …

10. leden 2023 — Look-at-me ver0

Dnešní pokusy s robotem Eduro, třema Pozyx kotvama a jedním tagem bych úplně za úspěšné neprohlásil. Na druhou stranu je to po několika měsících (na Eduru byl posledni git log z Fri Mar 4 19:40:45 2022 +0100), bylo fajn, že balíčky s Pozyxem už tam byly nainstalované a tato část hned fungovala. Co tedy nefungovalo?
Rozhodl jsem se kopirovat Jirkův setup se třema kotvama na robotovi a pouze jedním tagem, který má být sledován. Plán byl rovnostranný trojúhelník s tím, že jsem nejprve zvažoval jeden vrchol dopředu, ale pak mi přišlo snažší jen porovnávat měření z levé a pravé kotvy a zadní si nechat jen jako „zálohu”, pokud by robot byl otočený o 180 stupňů, tak aby měl šanci to vůbec zjistit.
Skript se jmenuje follome_uwb.py, ale fakticky jsem skončil u nějakého Look-at-me, kdy dopřednou rychlost jsem dal 0 a manipuloval pouze s úhlovou rychlostí (a robot se tedy pouze otáčel na místě). „Mrtvou zónu” jsem nechal pro rozdíl levého a pravého měření +/- 5cm a jinak se robot točil rychlostí math.degrees(10) ve směru korekce. A ano, toto byla první chyba — stále se mi vracející. Toto převádí 10 radiánů na stupně, které pak interpretuji jako radiány! Škoda mluvit i když po opravě ten assert naznačuje, jak moc jsem byl mimo.
AssertionError: ([0, 1000], [0, 3282806], datetime.timedelta(microseconds=907468))
Je to hodně citlivé a ten mechanický setup si holt zaslouži revizi. Konstrukci je třeba dát výše, dál od všech železných divnosti, wifi anténa 15cm od UWB krabičky také není ideální. Robot „tančil” i když tag byl položený na židli. Také mi přišlo, že 0 není uprostřed a bude třeba tam doplnit nějaký umělý offset, ale to se pomalu dostáváme k ultra přesné kalibraci co dělal Jirka loni.
to be continued (teď už timeout, než nás vyhodí ze školy) …

24. leden 2023 — Dva na jednoho

Dnes to celkem šlo. Zapojil jsem dvě Pozyx kotvy přímo do počítače a oba moduly současně měřily vzdálenost na společný tag. Co mne trošku překvapilo byly průběžné výsledky. Nejprve statistika měření s dotazem na vstupy a výstupy:
k           name bytes | count | freq Hz
---------
 0            sys   458 |   5 |   0.3Hz
 1    pozyx.range 10251 | 603 |  40.0Hz
 2 pozyx.settings   158 |   2 |   0.1Hz
 3     pozyx.gpio  3618 | 603 |  40.0Hz
OK, tj. cca 40Hz (i když jak jsem později zjistil, z těchto měření může být netriviální zlomek nevalidních).
k           name bytes | count | freq Hz
---------
 0            sys   497 |   5 |   0.5Hz
 1    pozyx.range 10897 | 641 |  62.4Hz
 2 pozyx.settings   158 |   2 |   0.2Hz
 3     pozyx.gpio     0 |   0 |   0.0Hz
Pak jsem GPIO vyhodil z konfigurace a frekvence se zvýšila. Prima, ale to bylo očekávané. A pak přišla to nečekané měření:
k                 name bytes | count | freq Hz
---------–
 0                  sys   996 |   8 |   0.8Hz
 1     pozyx_left.range 15279 | 900 |  85.4Hz
 2  pozyx_left.settings    78 |   1 |   0.1Hz
 3      pozyx_left.gpio     0 |   0 |   0.0Hz
 4    pozyx_right.range 15131 | 893 |  84.7Hz
 5 pozyx_right.settings   158 |   2 |   0.2Hz
 6     pozyx_right.gpio     0 |   0 |   0.0Hz
Zapojil jsem dvě kotvy na dva různé seriové (resp. USB) porty a frekvence ještě více narostla?!
No zakopaný pes, velmi pravděpodobně, je v tom, že vždy i druhá kotva „slyší” komunikaci té první a reportuje to do PC. Tj. jednotlivá měření nejsou pouze vlastní, ale i přeslechy. Tam jsem i viděl neplatné (status pro doRanging() je 0) záznamy.
Asi nejlepší je tabulka se zapojeným followme, kde příkaz s rychlosti (followme.desired_speed) se odešle pouze pro validní měření:
k                   name bytes | count | freq Hz
---------—-
 0                    sys  1504 |   9 |   0.9Hz
 1       pozyx_left.range 15475 | 914 |  86.7Hz
 2    pozyx_left.settings   158 |   2 |   0.2Hz
 3        pozyx_left.gpio     0 |   0 |   0.0Hz
 4      pozyx_right.range 15041 | 893 |  84.7Hz
 5   pozyx_right.settings   158 |   2 |   0.2Hz
 6       pozyx_right.gpio     0 |   0 |   0.0Hz
 7 followme.desired_speed  2090 | 418 |  39.6Hz
… zhruba tedy cca na 20Hz pro každou kotvu.
Zkoušel jsem to pak na Eduru a tam mne zase iritovalo, že záleží jakou kotvu připojím dříve, aby získala port 0. Přimé dotazy jsou s remote_id=None, ale tím se ztrácí ID té přípojené kotvy. Řešení je identifikace na začátku:
>>> pozyx = pypozyx.PozyxSerial('/dev/ttyACM0')
>>> pozyx.getNetworkId(network_id)
1
>>> hex(network_id.id)
'0xd67'

>>> pozyx = pypozyx.PozyxSerial('/dev/ttyACM1')
>>> network_id = pypozyx.NetworkID()
>>> pozyx.getNetworkId(network_id)
1
>>> hex(network_id.id)
'0xd53'
Moc pokusů jsem pak už neudělal, tak alespoň jeden vzorek. Ono většina videí je obráceně, což bych možná z pohledu ELROBu24 zvážil? Prostě na kameře nebude překážet osoba, které robota vede.
p.s. zapomněl jsem napsat, že k řízení jsem používal statistics.median pro okénko posledních deseti měření

31. leden 2023 — followme_uwb ver0

OK, první pokus Eduro sleduje UWB maják … a stejně tak i první (ano, samozřejmá) pozorování:
  • prohodím-li pravou a levou kotvu, tak je třeba i prohodit směr jízdy dopředu (za směr dozadu)
  • jezdí-li robot jenom dopředu a člověk je dál za robotem, tak vyrazí úplně špatným směrem
  • detekci nárazu moc neodkádat
Možná jsem měl neprve zmínit ten primitivní algoritmus co robota řídí:
diff = self.left_range - self.right_range
dist = (self.left_range + self.right_range)/2

speed = 0.0
if dist > 1.2:
    speed = 0.1

angular_speed = math.radians(10)
if abs(diff) < 0.05:
    self.send_speed_cmd(speed, 0.0)
elif diff > 0:
    self.send_speed_cmd(speed, -angular_speed)
else:
    self.send_speed_cmd(speed, angular_speed)
Ano, tak primitivní, žádné počítání průsečíků kružnic … a ano, také teď používám jen dvě kotvy, takže ani nepoznám co je vpředu a co je vzadu.
Chtělo by to nějaké srovnání, tj. asi lidar data (když už je stejně mám). Na druhou stranu lidar vidí nohy a jak je vidět na videu, tak dost zuřivě mávam rukama, abych robota nasměroval. Pak by se měl rychleji pohybovat a rychleji otáčet … ale tím spíše potřebuje collision avoidance.
Úplně „růžově” ty data nevypadají, ale ještě je tam skrytý ten median na 10 prvků, který to snad trošku srovná…
No nesrovnal. Pokud jsou kotvy od sebe 25cm, tak rozdíl 80cm je fakt marnost. No nevím, zda mám z toho obrázku úplně radost, ale je asi očekávaný. Další pokus bude s dřevěnou lištou od Standy a tedy se širší základnou.
A také o trošku zábavnější video. Ještě tam byla meziverze, ale ta byla pomalá/nudná, tak jsem zvedl rychlost:
speed = 0.0
if dist > 1.2:
    speed = min(0.5, 0.1 + (dist - 1.2) * 0.4)
tj. max 0.5m/s, ale s těma širokýma ramenama a pomalou úhlovou rychlostí už to trošku adrenalin je. Jasný další krok je ověření bezpečnosti a jak to teď je, tak si i myslím, že možná ta vysunutá ramena i vidí 270deg lidar … takže možná i uvidí ten okamžik, kdy si je urazí.
Další vylepšení bude třeba u rychlosti korekce směru, resp. omezení rychlosti když je směr pravděpodobně hodně špatně (např. kolmo vlevo).

7. únor 2023 — Bezpečnost především, časem …

Dnešek byl celkem poučný. Opakoval jsem pokus na chodbě, jen jsem vyrazil na druhou stranu a šel poměrně daleko od robota (4 až 5 metrů). A najednou se robot „zbláznil” a málem to napral plnou rychlostí do zdi:
No doběhl jsem ho a zastavil těsně před nárazem, ale … proč mi to dělá?!
Prostě najednou bylo měření skoro o metr vedle. A ano, myslím si že už jsem minule sliboval, že tam bude třeba dodělat „collision avoidance” a místo toho jsem přidal sběr senzorických dat z tagu (jak to dělat jsem našel tady). To jsem zvědav, jestli tam bude alespoň vidět, že jsem popoběhl?
V každém případě se ptám na stav senzorů jen na jedné straně robota a tak se tam snížil update na cca 10Hz, zatím co na druhé zůstal cca na 30Hz. Nemyslím si, že tím to bylo, ale vyloučit to nemůžu.
Senzorická data tagu vypadají, že odpovídají tabulce registrů:
registers:
    PRESSURE = 0x50  # Pressure data in mPa
    ACCELERATION_X = 0x54  # Accelerometer data (in mg)
    ACCELERATION_Y = 0x56
    ACCELERATION_Z = 0x58
    MAGNETIC_X = 0x5A  # Magnemtometer data
    MAGNETIC_Y = 0x5C
    MAGNETIC_Z = 0x5E
    GYRO_X = 0x60  # Gyroscope data
    GYRO_Y = 0x62
    GYRO_Z = 0x64
    # Euler angles heading (or yaw)  (1 degree = 16 LSB )
    EULER_ANGLE_HEADING = 0x66
    EULER_ANGLE_YAW = 0x66
    EULER_ANGLE_ROLL = 0x68  # Euler angles roll ( 1 degree = 16 LSB )
    EULER_ANGLE_PITCH = 0x6A  # Euler angles pitch ( 1 degree = 16 LSB )
    QUATERNION_W = 0x6C  # Weight of quaternion.
    QUATERNION_X = 0x6E  # x of quaternion
    QUATERNION_Y = 0x70  # y of quaternion
    QUATERNION_Z = 0x72  # z of quaternion
    LINEAR_ACCELERATION_X = 0x74  # Linear acceleration in x-direction
    LINEAR_ACCELERATION_Y = 0x76  # Linear acceleration in y-direction
    LINEAR_ACCELERATION_Z = 0x78  # Linear acceleration in z-direction
    GRAVITY_VECTOR_X = 0x7A  # x-component of gravity vector
    GRAVITY_VECTOR_Y = 0x7C  # y-component of gravity vector
    GRAVITY_VECTOR_Z = 0x7E  # z-component of gravity vector
    TEMPERATURE = 0x80  # Temperature
je to 24 čísel s tím, že první asi opravdu je tlak, poslední teplota (ta odpovídá i startu ve studené hale a pak po třetí minutě návrat) a aktivita před 90s je trošku vidět na „linear acceleration”:

14. únor 2023 — Follow me UWB on/off

Na posledním callu Jirka říkal, že ještě před vyhybáním se překážkam nejprve zapojí ten digitální vypínač. A to bych nebyl já, abych se hned neopičil. Tímto tedy děkuji TomášoviP za připájení konektoru a tlačítka — mini demo můžete vidět na mini-videu. Po minulých zkušenostech jsem tam také rovnou přidal test na volný prostor — pokud je překážka blíž jak 1m, tak dovol pouze otáčení. To se ukázalo až moc opatrné, tak půlením intervalu a přeměřováním robota, kdy 50cm je málo, jsme skončili na 70cm.
Další kousek je rychlost otáčení odpovídající chybě natočení robota. Zatím jsem to ignoroval a byl „pyšný” na kód, kdy detekuje tag vlevo/uprostřed/vpravo a neřeší jak moc … tak teď by mne to celkem zajímalo a jestli jsem neudělal chybu ve výpočtu, tak by to mělo být relativně jednoduché. Nechť je robot v pozici (0, 0) a kouká ve směru osy X. Kotvy nechť jsou od sebe daleko B, jako base, a tak jejich pozice je (0, B/2) a (0, -B/2). Pak změřím dvě vzdálenosti L a R. Pro pozici tagu na (x, y) platí, že
L = sqrt(x^2 + (y-B/2)^2)
R = sqrt(x^2 + (y+B/2)^2)

L^2 - R^2 = x^2 + (y-B/2)^2 - x^2 - (y+B/2)^2
L^2 - R^2 = -2*y*B*/2 - 2*y*B*/2 = -2*y*B
y = (R^2 - L^2)/(2*B)
Jak se znám, tak tam bude určitě nějaká „drobná numerická chybička” … hlavně by to nemělo fungovat, když R bude větší než L + B, není-liž pravda?! Nevidím to, tak opravu nechám zkušenému čtenáři.
p.s. jestě jedna drobnost z dnešního testování — ty USB konektory nejsou nějak super spolehlivé a při „ťuknutí” o zeď nejspíše částečně vypadly. Po opětném zapojení se ale detekovaly jako nová zařízení /dev/ttyACM2 a /dev/ttyACM3 … no asi by to chtělo ta USB pravidla.

21. únor 2023 — Pull request #953

Dneska jsem to do limitu (22h) nedal. A ani není žádný velký posun, kterým bych se mohl pochlubit. Jirka už minulou středu říkal, že řeší návrat po trase a problém s průjezdem úzkými dveřmi … no holt se mi pomalu ztrácí za horizontem, sigh.
Tak co je nového? Říkal jsem si, že bych si měl odložit skoro-použitelné UWB follow me demo a tak jsem vytvořil pull request do OSGARa. Tedy nejprve jsem asi 10 minut hledal, jak se sakra pull requesty vytváří, než mi došlo, že nejsem přihlášený a tak tam tlačítko create pull request chybí. V druhém kroku všechny testy na linuxu (Ubuntu 18.04) byly ve stavu canceled s odkazem na github issue, že nebude tato vykopávka dále v CI podporovaná. Po domluvě s Jakubem jsem tedy zvedl na poslední stabilní Ubuntu 22.04, ale tam jsem zase narazil na nepodporovaný Python 3.6. Ten jsem tedy nahradil za Python 3.9 (OSGAR byl testovaný pro linux a windows s Python 3.6, 3.7 a 3.8), ale to zase kolidovalo s prastarými balíčky a … vzdal jsem to a teď je tam pouze Python 3.7 a Python 3.8. TODO. … nějak pomalu tuším, kde jsem propálil trošku toho času …
Vznikla nová větev feature/follow-uwb-path a pokusil jsem se o první „návrat na základnu”. Původní název dnešního zápisu měl být „červená a modrá” (tlačítka na Eduru) nebo „Freudovo nabájení” (když chcete zároveň říci napájení a nabíjení, to byla zase řeč o Spiderovi) … ale to by asi bylo kryptické i pro mne. Jo, tak ty tlačítka červené mi evokuje nahrávání, tj. follow me mode a zbylé modré je tedy follow recorded path. Nejjednodušší varianta, co mne napadla, bylo si průběžně ukládat pose2d, tj. (x, y, heading) do pole a když se měl po trase vrátit domu, tak pokud o 180 stupňů otočený heading robota z první pozice od startu bližší než 20cm byl menší než jeden stupeň, tak jeď jinak se pomalu otáčej, aby rozdíl nahraného a současného (převráceného) headingu byl menší. Možná kód bude srozumitelnější:
elif self.navigation_mode == MODE_FOLLOW_PATH:
            for i, p in enumerate(self.path):
                d = math.hypot(data[0] - p[0], data[1] - p[1]) / 1000.0
                if d < DIST_STEP:
                    break
            if i == 0 or not self.follow_enabled:
                self.send_speed_cmd(0, 0)
            else:
                speed = 0.0
                diff = (data[2] - p[2]) % 36000 - 18000
                if abs(diff) < 100:
                    angular_speed = 0
                    speed = 0.1
                elif diff < 0:
                    angular_speed = math.radians(10)
                else:
                    angular_speed = -math.radians(10)
                self.send_speed_cmd(speed, angular_speed)
V prvním pokusu jsem špatně odhadl singularitu na 360deg, ve druhém zapomněl robota zastavovat, když UWB tlačítko je ve stavu off … a pak to vlastně zhruba dělalo co mělo. … no resp. ne úplně, viz např. poslední video. Vybral jsem ho, že je tam vidět Spider, což byl ještě další bod na seznamu a ten skončil s
File "/home/md/git/osgar/osgar/drivers/spider.py", line 186, in update
    assert False, channel  # unsupported channel
AssertionError: move
takže je jasné, kde budeme navazovat příště. Jinak i u Spidera jsem uvažoval o aplikaci follow me (možná se čtyřma kotvami, každá v jednom rohu … ve spider módu totiž může jet libovolným směrem), ale po dnešních pokusech s oživením bych udělal opak, že ten tag by uživatele chránil a pokud bude blíže jak 3 metry, tak se Spider automaticky zastaví až už jede jakýmkoliv směrem!
Ještě jsem chtěl napsat doplnění k minulému záznamu … teď vím, že mám alespoň dva čtenáře . Ano, ten problém s počítáním pozice tagu nastane, když se pokusím vedle y ještě zjistit x a tam mohu mít odmocninu ze záporného čísla … díky ML za potvrzeni.
p.s. koukám, že ani do 00:00 limitu jsem to nedal :(
p.s.2 ono vlastně není překvapivé, že Eduro do Spidera narazilo, protože algoritmus výše řeže zatáčky o 20cm …

1. březen 2023 — pypozyx.SingleRegister(size=2)

Včera se toho na poli Pozyxu moc nedělo. TomášP mi vytvořil druhé tlačítko na UWB tag, takže teď můžu (stejně jako Jirka) přepínat vzdáleně mód sledování a návratu po trase. Motivace byla přechod z robota Eduro na Kloubáka K2, který žádný přepínač přímo na robotovi nemá.
Koukal jsem do kódu pypozyx knihovny, protože jsem odmítal kvúli vyčítání druhého bitu posílat extra dotaz. Implementace je taková, že každý GPIO má vlastní registr:
GPIO_1 = 0x85  # Value of the GPIO pin 1
GPIO_2 = 0x86  # Value of the GPIO pin 2
GPIO_3 = 0x87  # Value of the GPIO pin 3
GPIO_4 = 0x88  # Value of the GPIO pin 4
a pro dotaz se pak používá funkce getGPIO(), která je implementovaná následovně:
def getGPIO(self, gpio_num, value, remote_id=None):
    gpio_register = PozyxRegisters.GPIO_1 + gpio_num - 1
    return self.getRead(gpio_register, value, remote_id)
getRead už je pak obecné čtení spojené s komunikací s dalším zařízením pokud remote_id není None. Co s tím? No trik je v tom, že volání toho čtení neobsahuje (tedy na první pohled) informaci, kolik se toho má přečíst?! Toto je dané typem vstupně/výstupní struktury předávané ve value. Zde je použitý SingleRegister, tedy jeden bajt. Ale … registry můžou být i 2 a 4 bajtové, takže pokud změníte defaultní size=1 na 2, tak vyčtete stavy obou pinů najednou. Ano, mají pak třeba hodnotu 257 = 0x101 … ale to už se dá.
Na K2 jsme popozyx doinstalovali, ale vlastně jsem ho už nestihl vyzkoušet. USB by měla být k dispozici, ale vše je „pod kapotou”.
Ještě jsem udělal pár pokusů s Edurem s testem návratu po trase (stejný kód jako minule) a moc slavné to nebylo, tj. dnes bez videa.