Rocker
terénní robot
Robota s nezávislým pohonem a řízením všech kol jsem si chtěl postavit již dávno.
Konečně jsem objevil vhodné pohony - robotická serva (WaveShare ST3215),
která splnila téměř všechny požadavky (a za rozumnou cenu).
A tak vznikl robot se čtyřkolovým podvozkem typu rocker-bogie.
Aktualizace: 24.7.2024 Jízda po trase
Základní údaje
- Autor
- Martin Locker
- Řídicí počítače
- low level - STM32F103
- high level - Raspberry Pi 3B
- Senzory
- IMU
- GPS
- Lidar LDrobot LD-06
- hloubková kamera RealSense D455
- Pohon
- 8x digitální robotické servo WaveShare ST3215
- Napájení
- pohony LiPol 3s 5Ah
- elektronika power banka 20Ah
- Koncepce
- čtyřkolový podvozek typu Rocker-bogie (výkyvné uložení kol)
- každé kolo má nezávislý pohon a nezávislé natočení směru
Charakteristika robota
Podvozek
Podvozek robota je postaven z hliníkových profilů, plexi a dílů vyrobených 3D tiskem z PLA.
Snahou bylo udělat konstrukci co nejčistší (aby nikde nic nepřekáželo, nekoukaly dráty, ...).
Takže některé části jsou nakonec celkem komplikované - převodovka s pohonem uvnitř kola,
vidlice kol, jejímž vnitřkem vedou vodiče k servům (viz. fotky).
Kolo |
Vidlice kola |
Pohon kola |
Kompletní pohon |
Součásti kyvných ramen |
Tělo robota |
Podvozek 2 |
Podvozek 3 |
Podvozek 4 |
Řízení pohybu
Podvozek je navržen tak, že osy zatáčení kol jsou ve vrcholech čtverce (robot má stejný rozchod
i rozvor kol).
Díky nezávislému natáčení každého kola lze realizovat dva základní způsoby řízené:
Vlastní řízení (výpočty natočení kol a jejich rychlosti) řídí mikrokontroler na základě povelů z nadřízeného systému
(1. dopředná rychlost + úhlová rychlost, 2. rychlost + směr).
- "automobilové" řízení s (ackermannovým) řízením všech čtyř kol a samostatným řízením rychlosti každého kola
- synchrodrive (všesměrové řízení) - všechna kola natáčena do stejného směru a otáčejí se stejnou rychlostí
+ otáčení na místě (kola se natočí ve směru kružnice procházející osami natáčení kol)
Vlastní řízení (výpočty natočení kol a jejich rychlosti) řídí mikrokontroler na základě povelů z nadřízeného systému
(1. dopředná rychlost + úhlová rychlost, 2. rychlost + směr).
Video
První jízda - dálkově řízeno
28. ledna 2024 - Odladěn driver pro komunikaci se servy
Po postrčení Martinem D. jsem (po delší době) vytáhl robota a pustil se konečně do
napsání rozumného rozhraní pro komunikaci s digitálními servy.
Snažil jsem se to napsat tak, aby to bylo použitelné na různých platformách
(zatím tedy AVR, STM32 a ESP32). Nejnižší vrstvu implementující jednodrátovou
sériovou komunikaci jsem oddělil od vyšších vrstev a pro STM32 vyzkoušel
tři varianty realizace - standardní využití knihovní obsluhy uartu
(s možností využití hw řešení single wire half duplex na STM32), vlastní obsluha
uartu přes přerušení (zatím nevyzkoušeno) a využití dma přenosu (to by měla být
cílová varianta). Bohužel zatím DMA přenos nepůjde použít, protože na použité desce
zrovna UART3 sdílí stejné kanály s rozhraním SPI1, které bude sloužit pro komunikaci
s RPi a tam je dma nutností.
Low level mikrokontroler by měl být v budoucnu schopen obsloužit všechny
periferie (kromě kamery), tj. pohony, imu, gps a lidar. Z hlediska pohonů
bude zajišťovat výpočet natočení jednotlivých kol a jejich rychlosti dle
povelů z nadřízeného systému a zpětné čtení enkodérů. U dalších periferií bude
zajišťovat periodické vyčítání dat. Proto se snažím napsat obsluhu tak, aby co
nejméně zatěžovala mikrokontroler. Použití dma pro uart jsem už zvládl (po
větším úsilí) při vyčítání lidaru. Proto to u komunikace se servy už celkem
šlo (jen se museli použít dva kanály - pro vysílání a příjem).
Závěr
- hotovo: vyčítání dat z lidaru, komunikace se servy
- k řešení: doladit řízení pohonů (výpočty natočení a rychlostí), komunikace s imu (třetí uart po fyzické vrstvě can), komunikace s RPi (spi)
5. května 2024 - Uživatelské rozhraní pro robota
Po posouzení možností jak realizovat na robotovi uživatelské rozhraní (GUI),
tj. lehkého prozkoumání jak to naprogramovat v Qt, wxWidgets, ... a
zhodnocení času potřebného k jejich zvládnutí s dostupným výkonem na Raspberry Pi 3B,
jsem došel k závěru, že tudy cesta nevede. Při povídání s Martinem D.
jsem nadhodil možnost realizovat GUI jako webovou stránku, což bylo
ohodnoceno, že to není tak špatný nápad.
Trošku problém je, že je potřeba obousměrná komunikace - zobrazování, ovládání.
Což se na webu realizuje obvykle různými oklikami. Před nedávnem jsem však
toto zkoušel na ESP32, kde je dostupná knihovna pro komunikaci pomocí websocketů.
Celkem to fungovalo, takže jsem očekával, že něco podobného najdu i pro
Raspberry Pi, resp. linux. Určitě nechci na RPi provozovat webserver
(toho výkonu není na rozdávání).
Bohužel jsem nic vhodného nenašel. Tak jsem začal z různých zdrojů zkoumat
komunikaci pomocí socketů, není to až taková věda. Takže z nějakých
příkladů upravit socket server nebyl problém. Horší je, že jsem nenašel
žádný příklad, kde by to bylo řešeno neblokujícím způsobem. Všude používali
blokující volání, tj. nebylo možné posílat a přijímat data současně (předpokládali
pouze komunikaci - dotaz/odpověď). Nakonec jsem to tedy snad nějak zvládl
přepsat.
Poslední krok bylo upravit to na websockety, aby to fungovalo s webovým prohlížečem.
O tom jsem neměl vůbec povědomost. Takže jsem opět začal hledat nějakou
knihovnu, výběr byl velmi omezený. Nakonec jsem vybral
libwebsocket. Než jsem začal zkoumat zdrojáky, tak jsem raději nejprve nastudoval
příslušné RFC (a bylo to dobrá volba, celkem jsem pochopil jak to celé funguje).
S drobnými úpravami se mi podařilo ukázkový příklad přeložit, spustit a kupodivu
se to tvářilo, že to funguje. Opět to ale bylo napsáno s využitím blokujicího
volání funkcí socketu. Takže s přechozí zkušeností jsem to přepsal a vypadalo to,
že je hotovo (pátek po 8. večer).
V sobotu chci poslat na webovou stránku nejen text, ale i obrázek. Ale ouha,
nějak to nejde poslat, resp. zjišťuji, že přijde jen kus dat a následně
socket spadne. Z těch dat přijde jen malý kousek, řádově desítky bytů (u přenosu
textu to stačilo). Tak zkoumám, kde se to "rozbije" a nakonec zjišťuju, že
to je v přípravě rámce. V té knihovně je obrovská bota, parametr udávající délku
dat se ukládá do proměnné o velikosti "7 bitů". Výsledkem je, že nejde poslat
více než 125 B. Ono to kódování packetů je trochu složitější (do 125 B je základní,
pro delší se to kóduje jinak). Takže po úpravě velikosti proměnné na int se to rozbíhá
a přenáším celý obrázek o velikosti cca 20 KB.
Chvíli bojuji s překódováním dat do base64 v javascriptu, aby se to dalo zobrazit
jako obrázek. A opět to vypadá, že to funguje. Ale nejásejme předčasně.
Zkouším trošku větší obrázek, a to pro změnu shodí socket ihned.
Už jdu téměř na jistotu a kontroluju vygenerovanou hlavičku packetu. Druhý
limit pro odlišné kódování je 64 KB a opravdu tentokrát to uloží do hlavičky
jen první byte délky zprávy (ostatní zahodí) = druhá zásadní chyba. Ještě, že jsem si prozíravě
nastudoval to RFC (jinak bych to těžko hledal). Po opravě přenáším i ten 100 KB
obrázek. Že nikdo u doporučované knihovny, která je téměř 10 let na githubu,
nezkusí přenášet více než 125 B dat, jsem opravdu nečekal. Proč si já vždycky
vyberu špatně.
Dalším testováním odhaluji, že to ještě není ono. Sice socket otevřený při
připojení clienta beží jako neblokující, ale socket serveru je stále blokující.
V principu by to nevadilo, ale pokud to pustím ve zvláštním vláknu, tak to nejde
shodit (visí to na funkci čekající na připojení klienta). Upravuju i serverovou
stranu na neblokující. Zase to vypadá dobře, ale jen než zkusím opět ten velký obrázek.
Bohužel je teď neblokující i zápis do streamu, a když se to nevejde do bufferu (64 KB),
resp. ještě není vyprázdněný, tak to spadne. Takže ještě upravit volání write, aby zkontrolovalo
kolik dat se předalo k odeslání a postupně to odeslat po částech.
Už dlouho jsem se do programování takhle nezakousl. Ale po třech "dnech" to snad
funguje.
Závěr
- hotovo (snad, je třeba to řádně otestovat): odesílání dat na webovou stránku (text, obrázek) a příjem dat z webu (pouze text)
15. května 2024 - Jízda na kužel
Myslel jsem si, že když mám funkční jednotlivé komponenty - komunikace s řídicím mikrokontrolerem, websocket,
webkameru, detekci kužele, tak to jen dám dohromady a mám funčního robota. Bohužel to opět tak
přímočaré nebylo.
Snažil jsem se veškeré komponenty psát jako samostatná vlákna, aby se vzájemně
nezdržovaly (hlavně detekce kužele). Jakmile jsem to všechno dal do jednoho programu, tak během startu websocket serveru to padalo do GP fault.
Nakonec jsem to vyřešit tím, že vlákno nevytvářím hned v konstruktoru objektu, ale až po startu vlastního programu.
To ještě musím dostudovat, co tam je za problém.
Ale první test jízdy na kužel fungoval na první dobrou, tak jak jsem to od stolu napsal. Jedinou úpravu jsem udělal, snížil jsem
zesílení regulátoru řízení (mělo to snahu kmitat). Teď to jezdí dle mých představ.
Jízda na kužel - první testy
Horší bude až to pustím venku, jsem zvědav jak se s tím ta webkamerka popere.
24. července 2024 - Jízda po naprogramované dráze
Konečně jsem se dostal k tomu, že jsem vzal robota ven, abych otestoval jízdu
přes waypointy. Pro navigaci se používá odometrie (tedy jen měření ujeté vzdálenosti)
a směr z kompasu (AHRS).
První test byl trojúhelník, k prvnímu waypointu to dojelo bez problémů, ale pak
se robot měl otočit o více než 90° a ztuhnul (doma jsem testoval jen čtvetec a tam
byly všechny úhly max. 90°). Tušil jsem, co je za chybu, ale nemohl jsem najít, proč
není úhel zatáčení omezen na 45° (max. co dovoluje kinematika). Nakonec nalezena
blbá chyba (hodnota se sice omezí, ale přesto se počítá s původní).
Zhodnocení po složitější trase (5 bodů). Vzdálenost ujetá podle odometrie je nad očekávání dobrá
(chyba v jednotkách procent odpovídá jízdě po nerovnostech).
S kompasem je to trošku horší, po první jízdě jsem tam přidal korekci na odchylku magnetického severu (a chyby
montáže IMU), nakonec kompromisní hodnota 7°. Ještě výhledově zkusím překalibrovat
kompas, vzal jsem ho tak, jak je z minulého robota.
Výsledná ochylka po ujetí celé cca 100 m trasy rychlostí 0,5 m je méně než 2 m, viz. video.
Jízda po trase - 5 waypointů, cca 100 m
Korekci z gps jsem nakonec nevyzkoušel (někde tam mám chybu v přepočtu z gps na xy)
a na sluníčku je na to blbě vidět (pozn. už je to opravené).
Ale vzhledem k přesnosti jízdy z odometrie a kompasu by tomu ta obyčená gps (kde to lítá +- 10 m)
asi moc nepomohla.
A teď to horší, použitá webkamera je venku na sluníčku úplně slepá (přepálený obraz).
Po návratu domů a hledání chyby v přepočtu gps se mi dvakrát opakovaně
stalo, že přestalo komunikovat STM32 s Raspberry. Pomohlo až kompletní vypnutí.
Doufám, že zjistím, co se to děje, do teď s tím nebyl žádný problém.