RoboOrienteering 2013
fandorama reportáž a II. létající blog
Čtvrtý ročník soutěže „RoboOrienteering” se konal sobotu 15. června 2013 zpět na domácí půdě v Zámeckém parku v Rychnově nad Kněžnou. Jela se tři kola s tím, že pravidla byla téměř stejná jako minulý rok. Létající roboti byli tolerováni. Bylo nás pět (týmů) a bylo to fajn. Spíše takové malé robotické soustředění. Blog update: 22/7 — THE END
Toto je verze 0 fandorama článku. Do konce června bych
ho rád ještě nechal „živý” a přidával postupně příspěvky od jednotlivých
týmů, jestli dorazí. Stejně tak bych nechal ještě otevřený blog a vymyslel, co
dál …
- 2013-06-21 — doplněné info od Short Circuits Prague
- 2013-06-24 — doplněné info od Plecharts
Projet parkem přes kontrolní body (oranžové kužele) a dostat se do cíle není
vůbec triviální. Zatímco pro kolové roboty jsou celkem výzva kořeny dosahající
i několik metrů od kmene, pro létající roboty jsou to obrovské koruny stromů a
větve i 10m velké (a až k zemi). Kolem kuželů je křídou označený kruh o
poloměru 2.5m, kde musí robot nějakým způsobem naznačit, že kontrolní bod/cíl
dosáhl. Extra body jsou za dotek kužele, který se ale letos už nesměl
shazovat. Tým dostane GPS souřadnice bodů 10 minut před startem a na jejich
průjezd má 30 minut. Pro rok 2014 budou pravidla trošku jiná, ale to bych si
nechal na závěr.
Robotický klub Mariánské lázně
Výkonem dominoval Robotický klub Mariánské Lázně, pod vedením Karla Čermáka.
Loni ve Svinařích bych býval měl „drobné” výtky, až se mi z toho ani nechtělo
sepisovat článek na robotika.cz, ale letos to byl
neodiskutovatelně nejlépe připravený tým, který si plně právem zasloužil
vítězství.
Povídání se pravděpodobně dočkáme později (zatím si můžete přečíst o
integraci gyroskopu z tanku T72, ve frontě už čeká
pokračování experimentů s leteckým gyroskopem, pak bude RoboOrienteering 2012
ve Svinařích … ve zkratce, buďte trpěliví a budete odměněni rozsáhlejšími
články).
Co jsem já mohl na robotu snadno pozorovat a z povídání zachytit bylo: pěkné
odpružení během jízdy, laserový dálkoměr (pouze jeden paprsek, nikoliv skener)
a zvláštní integrace pneumatiky, kdy robot si u kužele pro skenování prostoru
natvrdo „sednul”, aby to pružení nerušilo. Z kamery se pak ověřovala barva
detekovaného objektu a pokud byla oranžová, tak robot vyrazil vpřed dokud ho
nezastavily infra nárazníky kombinované s mechanickým nárazníkem.
Co jsem stihl robota vidět v akci, tak fungoval bezchybně jen v posledním kole
se zasekl ve svahu cca 1m od cíle.
Short Circuits Prague
„Šorti” podcenili přípravu, resp. z toho co povídal Pavel na to nezbyl
de-facto žádný čas. Jelo se s loňským kódem s částečně integrovaným laserem.
Na RoboOrienteeringu je tento tým často smolařem — nezapomenutelé bylo
poslední kolo loni ve Svinařích, kdy robot dojel do cíle, ale nezastavil a
vyrazil na Prahu. Po několika minutách jízdy tak ztratil všechny body. Pokud
by ho tenkrát ručně zastavili, tak by byl robot diskvalifikován.
Letos to bylo podobné a zrada číhala na zemi, v kořenech. Minimálně ve dvou,
ale možná dokonce ve všech třech, kolech robot najel na nízký kořen a břichem
se o něj zasekl. Do příště Dan zkusí zaříznout mírně vyčnívající šroubky a
vyleštit podvozek, aby se snáz smýkal. Ale on si Murphy zase něco najde …
Doplňující info od Pavla Jiroutka:
Letošního Roboorienteeringu jsme se poprvé zúčastnili v naší nejnovější
konfiguraci, tedy s lidarem, novým notebookem a karosérií. Kvůli nedostatku
času (většímu než standardně) jsme se dostali jen k nejnutnějším úpravám. V
první řadě to bylo zprovoznění hlavního programu a debugovacích nástrojů na
novém notebooku s i7 procesorem a Windows 8. Ačkoliv už jsme na tomto systému
odjeli soutěž v Písku, ještě pořád se občas objeví nečekaný problém s
kompatibilitou ovladačů hardwaru a knihoven, nebo problém způsobený jiným
operačním systémem a procesorem. V kódu, který fungoval roky stabilně, se nám
začaly dít divné věci. Nutno říct, že za vším byly doposud identifikovány chyby
v kódu - zejména použití vláken na non-thread-safe modulech, které na
pomalejším HW překvapivě problémy nezpůsobovalo. Další úpravy od loňska se
týkaly použití lidaru pro detekci překážek místo sonarů. Lidar jsme pro tento
účel nasměrovali přímo dopředu, aby jeho rovina nekolidovala pokud možno s
trávou. Ještě večer před soutěží jsme měli zapojenou novou inerciální jednotku,
kterou chceme používat jako kompas s kompenzací náklonu. Po testech se ale
ukázalo, že jednotku ještě nemáme plně pod kontrolou a výsledná data vykazují
menší stabilitu, než data z našeho tradičního kompasu. Do soutěže jsme šli tedy
bez IMU.
Soutěž samotná nebyla žádné drama. Tedy snad kromě homologace, při které jsme
mezi řečí zjistili, že se od minulého ročníku změnila pravidla. Návody,
pravidla a podobné typy dokumentů samozřejmě nečteme. Během asi hodiny před
závodem jsme upravili robota tak, aby neporážel kužely, ale snažil se jen
dotknout, a aby hlasitě oznamoval dosažení waypointu. Dotek kuželu jsme
vyřešili úpravou náklonu kamery, kterou jsme umístili tak, aby ztratila kužel
ze zorného pole právě v okamžiku, kdy je potřeba zabrzdit, aby se kužel
nezvrhnul. Jednoduchá metoda zafungovala při testech i v závodu překvapivě
dobře. První kolo závodu bylo pro nás poněkud divoké, protože robot jel o
poznání jinam, než kam měl. Chvíli jsme si dokonce mysleli, že jsme mu
zapomněli změnit trasu z testovacích waypointů. Nakonec se ukázalo, že problém
byl v hodně rozhozené GPS na začátku závodu a v hodně posunutém kompasu. Před
sezónou jsme přesunuli kompas ze stožáru pod kapotu robota a nevšimli jsme si,
že se začal chovat hodně jinak než na stožáru. V Písku se problém díky rovné
cestě a relativnímu požití kompasu neprojevil. Při Roboorienteering ale
používáme kompas absolutně a to se ukázalo jako problém. Pro druhé kolo jsme
tedy kompas přesunuli zpět na stožár a nově ho nakalibrovali. I přes tyto
problémy robot dojel v prvním kole poměrně daleko. Bohužel skončil - stejně
jako ve všech dalších kolech - uvíznutý na kořenech stromu, které nevnímal jako
překážku. Do druhého kola jsme zavedli drobnou změnu pro stabilizaci GPS -
robota jsme nechali jet prvních několik desítek sekund rovně, až pak jsme
přešli na standardní RO plánování. Ve druhém a třetím kole jel robot celkem
stabilně, bohužel se v obou případech zaseknul podvozkem o nízké překážky na
zemi. Tento problém budeme kompenzovat pravděpodobně pouze hardwarově -
vyztužením odpružení podvozku a odstraněním všech šroubů, které vyčnívají pod
robotem.
V soutěži jsme skončili na druhém místě z celkem čtyř soutěžících robotů.
Děkujeme organizátorům za příjemnou soutěž s dobrým zázemím. Pořád máme
potenciál na zlepšování, proto se rádi zúčastníme i v dalších ročnících.
Heidi (čtyřtulka)
Heidi už znáte a detailnější info z příprav si můžete přečíst níže v blogu, tak
alespoň jak to na soutěži vypadalo.
Navigační program pro RO2013 v kostce:
- převeď GPS souřadnice do roviny a spočítej úhly a vzdálenosti
- pro každý směr a vzdálenost leť v 1m širokém koridoru ve výšce 1.5m (korekce v Y, Z a A)
- pulzně udržuj rychlost 1m/s (pokud je vyšší nastav úhel 0 jinak „20% výkon”)
- pokud je překážka blíže jak 1m, couvej 1.5m, udělej 360 stupňový sken na místě a natoč se směrem největší mezery
- jinak pokud je překážka blíže jak 2m, posuň osu koridoru na další 4m letu o 1m vlevo
- během přechodu 0.5s ignoruj další překážky (aby nenasbíral nesmyslný offset ještě z původní překážky)
- po uletění požadované vzdálenosti zastav a indikuj dosažení kontrolního bodu změnou letové hladiny na místě na 0.5m, 2.5m a zpět na 1.5
První kolo: H-video D-video
Heidi odstartovala, vyrazila správným směrem na kužel a přeletěla ho. V cestě
měla strom a tak udělala 360 stupňový sken. A nic. Zůstala viset ve vzduchu. Na
konzoli jsem viděl:
Hover… Traceback (most recent call last): File "M:\hg\md\heidi\ardrone.py", line 1440, in <module> roboorienteering( replayLog=replayLog, metaLog=metaLog, dirDist=dirDist ) File "M:\hg\md\heidi\ardrone.py", line 1360, in roboorienteering ROVer2( drone, dirDist ) File "M:\hg\md\heidi\ardrone.py", line 1344, in ROVer2 ROStep( self, desiredSpeed=desiredSpeed, desiredHeading=desiredHeading, dist =desiredDist ) File "M:\hg\md\heidi\ardrone.py", line 1174, in ROStep turnToAngle( gapDir ) TypeError: turnToAngle() takes at least 2 arguments (1 given)
… sigh, hrubka. Kus kódu, který jsem nevyzkoušel. Ani v simulátoru. Mám padáka.
Za zmínku ještě stojí 4x „Navdata TIMEOUT!”, kde v první nastal cca 3m od
startu. Následuje skok v pozici cca 0.5m zpět. Je dost možné, že takto se
chyba v pozici snadno zhoršila.
Druhé kolo: H-video D-video
Druhý start byl na nakloněné cestičce v blízkosti hned několika stromů. Nejprve
„oblíbené” couvání cca 3m a pak téměř ukázkové vyhýbání překážce. Na videu to
vypadá jako náraz, ale byl to spíše jemný dotek, rychlé couvání, sken a vyrazil
do volného prostoru . Nevím, jak ostatním, ale mne se ten začátek líbil.
Pak už zase video-dokumentace chybí. Podle odometrie se dostala až na (12.1,
-48.0), tj. cca 50m od startu. Kontrolní bod ale zase minula a tak bodově pouze
přímá vzdálenost k cíli … a v realitě zase byla dál.
Algoritmus jsem načrtnul v úvodu, tak teď realita. Sonarových měření moc není
(měřil jsem s frekvencí 10Hz), takže každé měření jsem bral vážně (to obecně
nedoporučuji, ale nějak začít musíte). Ze sonarového logu vidím: …, 2.58,
1.02, 1.09, 1.05, 2.61, 0.86, 0.73, 0.63, 0.53, 0.39, 0.26, 0.19, 2.65, 1.65,
2.12, 0.23, 0.32, 0.43, 0.57, 0.74, 5.09 … těch 10cm za 0.1s zhruba odpovídá
požadované rychlosti 1m/s. Horší je to v „integračním logu”:
(105, 261) 43 (107, 73) 43 (109, 53) 66 (112, 19) 43 (113, 265) 22
První měření pod 1m tedy nezachytil, pak mu jedno vypadlo, pak dvě … ale
stejně už na tu naměřenou vzdálenost 0.73m reagoval. Zajímavé by teď bylo
zjistit, jaký podíl na tom nárazu má setrvačnost (přechod z dopředného letu
1m/s na couvání) a jaké opožděná informace (tj. že už byl 19cm od stromu, když
zaregistroval těch 73cm). Zkusil bych to později porovnat s časovými známkami u
videa.
Třetí kolo: H-video D-video
Poslední kolo bylo rozhodující. Před Heidi startoval ostravský Aegis, který z
neznámého důvodu vyrazil přesně opačným směrem, než byl cíl. Když Heidi krátce
po startu nabourala do první lampy a získala by tak jen 1 bod, tak byl
všeobecný souhlas pokus opakovat. Třetí kola byla tedy dvě.
V prvním pokusu 2x detekoval překážku do dvou metrů a posunul tedy koridor o 2m
vlevo. Následuje detekce ve 14cm a celkem tvrdý náraz. Ze sonaru žádné včasné
varování nepřišlo: 3.33, 2.07, 0.14, 0.12. Sloup byl nejspíš moc vlevo.
Následovalo couvání, sken, lokalizace Davida a hrr na něj . Mezeru si sice
vybrala pěknou, ale v kódu „trošku” chybí myšlenka co dál. Drona se tedy
„vrátí do starých kolejí” a má stejný problém s lampou jako krátce po startu.
Znova couvání, znova sken, ale třetí „vyjednávání” s lampou už nepřežije a
silný boční náraz končí automatickým vypnutím motorů.
Třetí kolo, druhý pokus: H-video D-video
Druhý pokus se neměl počítat — ono na pořadí by to nic nezměnilo, jenom ten
rozdíl mezi 3. a 4. místem by byl bodově méně výrazný. Ale jsem za něj rád.
Vlastně to byl nejlepší let. Ono to soutěžení je i psychologická záležitost.
Kdybych si se čtyřtulkou hrál na zahradě, tak metr od větví stromu už v panice
mačkám emergency stop. Tady to byl poslední pokus, který ukázal, že když je
to nutné, tak si drona dokáže cestu i prosekat. Většina video záznamu bohužel
chybí, tak si to užilo jenom pár svědků naživo. Ano, skončilo to zase zamotáním
do větví jiného stromu, ale až po několika desítkách metrů …
Závěry
RO2013 se mi líbil a zase jsem se něčemu přiučil. I Heidi se posunula dál.
Shrnul bych, co se změnilo ve srovnání se
soutěží v Písku, která byla před měsícem:
- integrace nového HW (sonar)
- částečné vyřešení ztráty komunikace (bohužel jen navdata, třeba opravit i video kanály)
- regulace rychlosti (i když teď už to není tak zajímavé/dramatické)
- skenování prostředí a první pokusy s vyhýbáním se překážkám
Mezi nevyřešené úlohy patří např. občasné couvání na startu. Dosavadní pokusy
sice vedly k tomu, že drona byla „papírově” na místě (podle odometrie) ale v
realitě to bylo ještě horší a asi si i pokazila vnitřní kalibraci během jinak
automatizovaného startu. Parrot a fórum na
můj dotaz zatím mlčí
…
Aegis
Aegis byl pro mne zcela nový tým. Z Ostravy. Z Prahy do Ostravy je to daleko a
stejně tak v opačném směru, ale Rychnov nad Kněžnou je kompromis. Vtipné
bylo, že když jsem se zeptal, zda neznají Petra Nováka, co napsal knížku
Mobilní roboty, tak se ukázalo,
že je to vedoucí jejich katedry, školitel i spolupracovník . Tak po letech
střípky pomalu zapadají.
Jejich robotu se ale letos příliš nedařilo. Hlavní programátor nedorazil a
obsluha robota byla o to náročnější. V prvním kole vyhořel na parsování
vstupního textového souboru - očekával mezery, ale v souboru byly tabulátory.
Druhé kolo už bylo lepší a získal 77 bodů. V posledním kole asi zlobila GPS a
robot se rozhodl jet zcela opačným směrem, než byly kontrolní body a cíl.
Mimochodem je to snad jeden z nových týmů, který uvidíme na
Robotour 2013 v Polsku.
Plecharts
Plecharts už známe jak z loňského RoboOrienteeringu, tak i z
Robotour. Robota byste ale nepoznali. Je
několikanásobně větší a ještě vícenásobně těžší. Je to trošku cesta na které si
vylámal zuby Kamil ze Sirael s robotem Hana a z prvních let Robotour i Short
Circuits s Kryplíkem. Prostě velký robot zní lákavě, ale typicky to znamená i
velké problémy :-( … a i letošní příspěvek Plecharts to dokazuje. Pokud
máte podobné myšlenky a ještě příliš zkušeností s robotama nemáte, tak vám to
nedoporučuji. Vedle toho, že vám může robot snadno ublížit, na jeho testování
(a to by jste měli dělat skoro non-stop) budete potřebovat vždy minimálně dva
lidi a řádově více sil a energie. Robot měl hned několik problémů a skončil na
mechanických, které byly v danou chvíli fatální. Snad příště.
Doplňující info od Jardy Peška:
Každý rok jsem se potýkal s tím, že robot byl příliš malý nebo měl málo místa
na všechny prototypy modulů, tak jsem na letošní rok postavil opravdu monstrum.
Rozměry robota jsou okolo 100x70x40 cm a váží s baterií okolo 70kg, takže se mu
dá říkat tank. Zde byl asi první problém, protože takto velký robot vyžaduje
velký výkon, který sice motory dodávaly, ale nakonec se zničila jedna z
řemenic které přenášely výkon od motoru k převodovce a tak se robot nakonec ani
nemohl pokusit ujet rovně několik metrů abychom měli alespoň pár bodů.
Dalším letošním problémem byla celková nepřipravenost, protože stavba nového
podvozku vyžadovala více času než jsem předpokládal. Jako by to nestačilo, při
vývoji softwaru se ukázalo, že jsem několikrát zvolil cestu, která nikam
nevedla, což jen přidalo ke zpoždění. Musel jsem tedy na poslední chvíli
upravit již otestovaný software z loňského Roboorienteeringu ve Svinařích, kde
robot fungoval výborně. Po přepsání jednoho modulu aby robot místo vlastního
regulátoru ovládal dva modelářské regulátory přišlo na řadu testování, již v
Rychnově. Zde ovšem nastal problém, loňský software si příliš nerozuměl s
notebookem nebo novým modulem řízení a místo toho aby jel když nemá před sebou
překážku tak dělal opak, nebo se dokonce jenom „cukal“ na místě.
Snad se mi povede vyladit všechny tyto problémy do Robotour 2013, kde již bude
moci nový podvozek a software plně zazářit.
Závěr
Nejprve bych rád poděkoval fandorama přispěvovatelům
Pavlu Skotákovi a Janu M, kteří mne vyhecovali
se soutěže s Heidi zúčastnit. Dále bych rád poděkoval Tomášovi z Eduro Teamu,
kolegům Zonkovi a Šimimu z práce za pomoc s integrací sonaru (USB konektor,
linux prostředí a možnost zkompilování driveru, kabeláž). Díky patří i Davidu
Obdržálkovi (viz D-video), že celou
soutěž natáčel a mám tak vůbec nějakou dokumentaci, když většina H-video-logů
chybí. A konečně velké díky organizátorovi Martinu Lockerovi, bez kterého by
soutěž nebyla. Dík patří samozřejmě i údržbě Zámeckého parku a
dalším sponzorům.
p.s. zmiňoval jsem změnu pravidel do roku 2014 — budou se rozvážet golfové
míčky a různé kontrolní body budou různě hodnocené. První náčrt najdete
zde.
Odkazy:
- Stránky organizátorů: http://www.vosrk.cz/roboorienteering/
- Výsledková tabulka: http://www.vosrk.cz/roboorienteering/2013/vysledky.htm
- Videa od Davida Obdržálka: https://www.youtube.com/user/RobonikaCZ.
Fandorama
- Detaily tohoto projektu: https://fandorama.cz/projekty/921778164/roboorienteering-2013/
Blog
Toto je druhý „létající blog” o autonomní navigaci Heidi,
tentokrát ve venkovním prostředí. Úkol je doletět na první kontrolní bod
(kužel), dotknout se ho a přitom nenabourat cestou do stromu. Nic víc a nic
míň. Pro rozjezd plánuji využít soutěže
Robotem rovně — tento blog bude zase
mix z příprav na obě akce.
Předešlý díl s prvními pokusy případně naleznete
zde. Stejně jako u IARC se i tady předem se
omlouvám za texty bez korekcí.
19. dubna 2013 — cross-compiled Hello World
AR Drone 2.0 má USB port, ale jak jsem psal na konci prvního blogu, nové
senzory (USB <-> I2C převodník a GPS modul) nebyly rozpoznané a nešlo z nich
tedy číst data. Je potřeba si tedy drivery sám zkompilovat, což je krok,
kterému jsem se původně chtěl vyhnout.
Princip cross-compilace je mi snad jasný: jiný procesor, jiná instrukční sada a
je tedy třeba donutit kompilátor generovat výstup pro jiný procesor než na
kterém sám běží. Stejným způsobem jsme programovali i ATmega8 čipy, když jsme
před osmi lety blikali s LEDkou. Máte-li Ubuntu Linux na vašem
PC, tak můžete zkusit postupovat podle vzoru na
http://paparazzi.enac.fr/wiki/AR_Drone_2/getting_started. Já jsem použil
pracovní Debian, kde mi kolega „přikouzlil” ještě
cpp-4.4-arm-linux-gnueabi, g++-4.4-arm-linux-gnueabi,
gcc-4.4-arm-linux-gnueabi, libstdc++6-4.4-dev-armel-cross, s tím že problémy
byly s knihovnou libgmp3c2, která zrovna zaniká (?). Nevím. Koukal jsem jen
přes rameno a neměl z toho moc dobrý pocit.
Je mi jasné, že správně vybraný procesor ještě není všechno (na AR Drone 2.0 je
1 GHz 32 bit ARM Cortex A8
processor s 800MHz video DSP TMS320DMC64x). Program se bude odkazovat na
existující knihovny a pod. Ale asi mi nezbývá než to zkusit. Pro test jsem
použil jednoduchý příklad z
Raspberry Pi
fóra.
23. dubna 2013 — logování videa
Ukládat obrázky nebo videa z autonomní jízdy či letu je obecně užitečná věc.
Pokud nejste důkladní a důslední (že by slovo „dad” vzniklo od toho?), což ja
bohužel nejsem (i když k většině testů si alespoň jednořádkovou poznámku
napíšu), tak „video vám napoví”, co že se to vlastně stalo. I po několika
letech. Možná mne to donutí vyhledat obrázky z jízdy v Rychnově na prvním
RoboOrienteeringu (rok 2010), abych si připomněl ty obrovské stromy, občas s
větvemi až k zemi, vystouplé kořeny i 2m od kmenu … no možná později,
nebudu se přece v této fázi sám zastrašovat …
Pokus o nahrání videa jsem dělal už v samém počátku experimentování s
Heidi, ale moc jsem si s tím nevěděl rady a byly urgentnější
záležitosti. Stačilo rovnou ukládat data z TCP spojení na portu 5555:
HOST = '192.168.1.1' # The remote host VIDEO_PORT = 5555 … drone = ARDrone2() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP s.connect((HOST, VIDEO_PORT)) f = open( datetime.datetime.now().strftime("video_%y%m%d_%H%M%S.bin"), "wb" ) for i in xrange(1000): drone.update() data = s.recv(10240) f.write(data) f.flush() f.close() s.close()
Je jasné, že dokud nedokážu soubor parsovat, tak to celé trošku pozbývá smyslu.
Rozhodl jsem se přeskočit „kovaříčky” a šel rovnou za „kovářem”, tedy na
stránky http://www.ffmpeg.org/, kde najdete jak knihovny tak nástroje,
které používá většina programů spolupracující s AR Drone 2 (CV Drone, SDK 2.0,
…). Proklikal jsem se na instalaci pro
windows, stáhl si Shared Version, rozbalil 7-Zipem, objevil vedle
ffmpeg rovnou i ffplay, přidal název uloženého souboru z Heidi a … ono to
rovnou fungovalo!
A teď má skrytá motivace. Chtěl bych získat jak video z dopředné kamery, tak z
kamery, co je namířená dolu. AR Drone 2 už nenabízí „obraz v obraze”, ale
video je možné nahrávat. Při nahrávání by drona měla vysílat na
VIDEO_RECORDER_PORT=5553. Když jsem zkoušel kdysi dronu s tabletem a nahrál
si svůj první pokus venku, tak přestože jsem přepnul na dolní kameru, tak
aplikace vždy nahrávala z té hlavní, dopředné kamery. Tenkrát mne to mrzelo,
ale … už vidíte, kam mířím? Když přepnu pohled na dolní kameru a pustím
nahrávání, tak bych měl dostat stream z obou kamer současně . Zní to až
moc jednoduše, že ano? Taky to hned nefungovalo (snad už platí minulý čas).
Multiconfiguration
Pro nahrávání videa jsem použil příkaz:
drone.confirmedConfig( "AT*CONFIG=%i,\"video:video_codec\",\"136\"\r" )
kde 136=0x88=MP4_360P_H264_360P_CODEC, tedy zobrazování a nahrávání v rozlišení
640x360. Změnil jsem číslo portu na 5553 a nic. Žádná data. Na rozdíl od
autonomní navigace na
značku toto zajímá daleko více lidí a tak jsem odpověď snadno
našel na fóru. Ten „podraz”
je multi-konfigurace a je dost možné, že to bude i rozuzlení k té navigaci na
značku, co mi ve Vídni chyběla …
Co to ta multiconfiguration je? Z důvodu kolize některých příkazů se starou
generací AR Drone je povinnost před některými AT*CONFIG příkazy posílat ještě
AT*CONFIG_IDS s hash kódem pro aplikaci, uživatele a session. Pokud to
neuděláte, tak sice dostanete ACK, ale nic se neprovede. V dalším
příspěvku na fóru je
i návod jak si nechat vypisovat chybová hlášení drony, což může být příště
užitečné:
When the AR.Drone refuses a configuration, it writes an error on its stdout
stream. To see the output of program.elf on the AR.Drone, you may just connect
to it using telnet, kill the currently running program ("killall program.elf"),
then run it again ("/bin/program.elf"). The stdout will the be redirected to
your telnet console, and you'll be able to see why the AR.Drone is refusing
your configurations.
Po přidání AT*CONFIG_IDS to sice už nahrává, ale výsledek ffplay přehrát nelze
:-(. Tady by asi stálo za to rozumnět
H.264/MPEG-4 formátu.
Detailům nerozumím, ale problém je podobný jako u spojovaní MPEG-2 video …
prostě né všechny snímky jsou si rovny (první je celý a následuje X
rozdílových) a pokud začnete špatným snímkem, tak to ani ffplay nezvládne.
Který snímek je vhodný začátek lze vyčíst z extra PaVE (Parrot Video Embeded)
sekce, konkrétně vás zajímá frame_type. Střídá se číslo 1 následované 29x 3 …
alespoň u statického pohledu, v akční scéně to možná bude jinak. Při šanci 1:29
se ani moc nedivím, že mi to nefungovalo. Řešení je najít první typ 1 a před
ním to smazat.
Případ vyřešen? Zatím ne. Vypadá to, že teď je zase problém s dekódováním
druhého videa. Drona má jenom jeden video čip, takže jeden video stream je
zpracovávaný softwareově … ale nechci předbíhat, nejprve nasbírám více
„stereo” vzorků.
24. dubna 2013 — PaVE 64 vs. 68
Nevím. Nefunguje to. Je mi jasné, že jsem to včera zakřikl. Když otevřu obě
spojení (pro nahrávání port 5553 a normální video 5555), tak nějaká data
nasbírám. Ale nejdou přehrát, ani když je odříznu na první I-frame (princip
komprese videa a co je I/P/B frame je celkem pěkně popsaný na
wikipédii).
Kde teď vidím možný zadrhel je už samotná PaVE (Parrot Video Encapsulation)
hlavička. Začíná značkou "PaVE" a následující informace o použitém codecu,
velikosti hlavičky a dat, rozměr obrázku … speciální zarovnání je na 64bajtů.
Když si ale přečtete velikost z uint16_t header_size; /* Size of the
parrot_video_encapsulation_t */ tak dostanete 68! Počítal jsem to snad 5x, ta
struktura má opravdu 64batjů a různé programy s tím počítají, ale v popisce je
něco jiného.
Předpokládám, že ffplay.exe žádny PaVE nezná a přeskakuje na sekce začínající
nějakou signaturou pro H.264 kódování, ale nevím. To by vysvětlovalo proč by
přehrávání mohlo fungovat ať už PaVE sekci smažete nebo jí tam necháte.
Přišlo mi, že CV Drone to vůbec neřeší,
Tomáš Krajník dohledává
ztracené začátky (a čte jen 64bajtů hlavičky). Zkusím header_size ubrat 4 a
payload_size zase 4 přidat … žádná pozorovatelná změna.
Co mne ale ještě více trápí je, že ze třech pokusů jsem dostal dost podobný
úvodní obrázek (asi bych měl před čtyřtulku dát digitální hodiny nebo místo na
lednici budu koukat na elektrickou troubu s displayem) … extra cache u
ffplay.exe nepředpokládám (jako, že by pokračoval na přehrávání staršího
souboru stejného jména), tak mi spíše drona posílá staré video. Dokud ale
spolehlivě nerozlousknu jeho přehrávání, tak to asi ještě nemá smysl řešit.
Asi to chce klid, více Nutelly, a začít možná s jednoduchým C prográmkem
inspirovaným z různých zdrojů …
26. dubna 2013 — video timestamps
Dnes jen telegraficky:
- velikost PaVE struktury u AR Drone 2 bývala 64 bajtů (např. stroje vyrobené loni v létě) a teď je 68 bajtů, i když ani poslední SDK 2.0.1 tuto novou strukturu neobsahuje. Podle Firmwares 1.11.5 (AR.Drone 1) and 2.2.9 (AR.Drone 2.0) are included a toho, že sám mám 2.3.3, soudím, že ke změně došlo „někde mezi”. Správně je tedy respektovat velikost headeru, jak přichází v datech.
- při čtení PaVE bloku a dekódování každého snímku zvlášť vše funguje jak má. Sice při míchání dvou Céčkových zdrojáků se mi chvíli pletly alokace a natvrdo to padalo, ale … konec dobrý, všechno dobré. Jeden video stream má CODEC_ID_H264 a druhý CODEC_ID_MPEG4.
- pro debugování jsem si nemohl vynachválit jednoduchý OpenCV kód :
cvShowImage( "camera", img ); cvWaitKey(100);
s čekáním 100ms nebo s 0 a procházení po snímcích (čeká to na stisk klávesy)
- potvrdilo se mé podezření, že nahrávané video na portu 5553 je z jiného času než video z 5555. Důvodů mne napadá hned několik: nahrávání explicitně nevypínám, TCP buffer na začátku nevyprazdňuji, sychnroně čtu (navdata, video1, video2), jeden video stream může být úsporněji zabalený, … je to pěkně vidět na časových známkách (timestamp):
navdata: TIME 73.279479 0x92443b7 TIME 78.425933 0x9c67fcd video3311: TIMESTAMP 74686 TIMESTAMP 78631 video3311_rec: TIMESTAMP 73643 TIMESTAMP 76479----navdata: TIME 347.396301 0x2b660c0d TIME 353.056152 0x2c20db58 video3745: TIMESTAMP 348770 TIMESTAMP 353269 video3745_rec: TIMESTAMP 76675 TIMESTAMP 79316
- domnívám se, že timestamp v NavData struktuře je něco jiného než v PaVE bloku u videa … tj. že na fóru se pletou … navdata jsou v podivně zabalených mikrosekundách a videa v milisekundách.
29. dubna 2013 — registrace
Nejprve díky příznivcům fandorama za podporu (částka na
RoboOrienteering reportáž je teď už nasbíraná). Přihlašuji Heidi jako
dalšího účastníka, viz.
http://www.vosrk.cz/roboorienteering/index.php?year=2013&page=tymy. Zatím
jsem tam jenom s Pavlem ze Short Circuits a je
těžké uvěřit, že jsme před deseti lety spolu poprvé tvořili tým na
Eurobota 2003. Tehdy Daisy
byla sedmá na světě, … jo to bývaly časy … .
Pavel psal: „Situace se změnila. Ta druhá akce mi nakonec odpadla, takže jsem
se dodatečně přihlásil na RO. Navíc jsem chtěl vidět, jak lítáš mezi stromy.”
Tak nás v tom nenechte samotné! Těším se na další přihlášené týmy …
30. dubna 2013 — všechno vylejt!
Pamatujete ještě scénku Kaisera s
Lábusem, Staníka, gumičky a nálev? Tak si teď připadám. Když jsem vše udělal
pořádně, jak by to mělo být, tak výsledek je, že současné nahrávání videa z
jednoho kanálu a sledování druhého nejde :-(. Ale popořádku …
Po minulé zkušenosti, kdy jsem si nebyl jistý, zda právě natočené video je
aktuální, jsem udělal to co jsem slíbil a dronu otočil, aby sledovala sporák
místo lednici … a vyplatilo se. Přiložené jsou referenční snímky první a
poslední záběr.
Ráno začalo hrozně, jak jinak. Zkusil jsem připravený prográmek s použitím
modulu multiprocessing, aby nahrávání videa probíhalo v jiném procesu a
nezdržovalo hlavní řídící smyčku. Skript proběhl, ale video bylo jen černé
nic (cvičně jsem nahrával jenom jeden kanál). Opakoval jsem to 3x a stále
stejný výsledek. Začal jsem to vidět dost černě a raději přepnul na minulou
implementaci … a zase nic!
Problém byl, že jsem video dekódoval špatným codecem. To je ale situace, kterou
snadno a rychle poznáte z pohledu do konzole, kde vyskakuji chybové hlášky, ale
nic tam nebylo. Došlo mi to až když jsem v Céčkovém kódu viděl fprintf
TIMESTAMP … já jsem si ten chybový výstup minule přesměroval do souboru,
abych ty časové známky mohl lépe studovat! Prima. Dobré ponaučení a vhodný
moment pro alokaci obou codeců a doplnění následujícího kousku kódu:
if( pave.video_codec == 4 ) cSelected = cH264; else cSelected = cMPEG4;
Jinými slovy, v PaVE struktuře je informace, o který codec se jedná, jen to
zapojit. Supr, tak už vidím všechna videa co jsem dnes nahrál.
Dopsal jsem funkce startVideo() a stopVideo() do ARDrone2 třídy pro oba kanály
a ten co chodí z portu 5553 byl stále z doby úplného začátku. Upravil jsem kód
aby se video přestalo nahrávat, ale stále stejné. Heidi jsem vypnul a znova
zapnul a pak to začalo být rozumné. Důvodem je pravděpodobně
„video:video_storage_space = 15360” konfigurace (nezdokumentované jednotky
předpokládám MB), která umožňuje v případě výpadku wifi spojení použít takto
velký vyrovnávací buffer.
Na informaci o bufferu jsem narazil, když jsem hledal, jak se přepíná dopředná
a spodní kamera — mimochodem nepoužívejte příklad z dokumentace. Není to
úplně zřejmé, ale ta nabízená varianta 2 není na AR Drone 2.0 podporovaná …
enumy jsou od 0, tj. pro pohled dolů potřebujete nastavit 1.
Dobrá zpráva - přepnul jsem pohled dolů a chodí mi data z pohledu na stůl.
Špatná zpráva - data chodí z obou kanálů stejná. Závěr? Nevím jak dostat video
současně z obou kanálů a prapraprapůvodní zmatení, kdy jsem nahrával a přepínal
pohled dolů, ale dostával nahraný pouze pohled dopředu, byl nejspíše stejný
problem s bufferem i u aplikace
AR.FreeFlight
2.0. Jako fatální důkaz mi posloužil následující kód:
drone = ARDrone2() drone.startVideo() drone.wait(2.0) drone.confirmedConfig( "AT*CONFIG=%i,\"video:video_channel\",\"0\"\r" ) # HORI view drone.wait(2.0) drone.confirmedConfig( "AT*CONFIG=%i,\"video:video_channel\",\"1\"\r" ) # VERT view drone.wait(2.0) drone.stopVideo()
A na obou video záznamech jsem viděl chvíli stůl (spodní kamera), chvíli sporák
(přední kamera) a pak zase stůl. To nezachrání už ani čulibrk.
3. května 2013 — test first
Test first je
oblíbená praktika z
eXtrémního
programování. Nebudu se teď pouštět do vysvětlování, proč je to dobré při
psaní kódu, spíše vysvětlím, jak si to interpretujeme v robotice. V kostce,
pokud lze nějakou vaši teorii ověřit/vyzkoušet, tak to udělejte jako první.
Vlastně je to takové „ověření předpokladů”, které když neplatí, tak je celá
další teorie zbytečná …
Co to má společného se životem čtyřtulky Heidi? Pamatujete, jak jsem se
holedbal, jak do Písku pojedu s kódem: „drone.moveForward(380)”? Tak jsem si
to o svátcích na zahradě konečně zkusil. A když už umím nahrávat a parsovat
to video, tak jsem vám průběh z pohledu Heidi dal i na
YouTube:
Test Zero
No měl to být test1, ale zapomněl jsem odkomentovat volání testovací funkce,
takže Heidi pouze vzlétla a hned zase přistála. To by běžně byl i doporučený
první pokus, ale … nejsušší místo na zahradě byla střecha auta, takže když
šla čtyřtulka na přistání, místo aby letěla 10 metrů vpřed, tak jsem se dost
lekl. Konec videa není useknutý nějakým nárazem, ale prostě jako to
přistálo, tak se vše vypnulo. Do dalších testů jsem tam ještě přidal 1s pauzu
na konec.
Test One
Ten byl téměř ukázkový. Zase start z auta, ale pak se drona stočila mírně vlevo
(větřík?) a proletěla těsně vedle konstrukce skleníku. Přistání do vysokých
pampelišek nic moc, ale člověk si musí definovat priority …
Test Two
Druhý test jsem udělal se startem ze země a výsledek skončil pěkným kotrmelcem.
Nenapadlo by mne, že ta naše loučka má nějaký sklon, ale na 10 metrů to těch
50cm asi dá + vyšší tráva … no, viz video. Takže lze možná dronu používat i k
nivelaci.
Ještě možná krátkou historku ke konci tohoto testu. Naše Sindy (kokršpaněl) má
lovení a donášení zastřelených ptáků v genech, a tak místo aby se Heidi bála,
tak po tom jejím kotrmelci se na ní vrhla a chtěla mi ji v zubech přinést!
Test Three
Po pravdě mezi 2 a 3 byly ještě dva pokusy odstartovat, ale drona nechtěla
přejít z emergency stavu, takže jsem ji nakonec musel vypnout a znova zapnout
(logy jsem ještě neprošel, abych se dozvěděl více). U posledního testu jsem
nejprve vystoupal do 2m a pak teprve pokračoval v letu vpřed:
drone.flyToAltitude( 2.0, timeout=10.0 ) drone.moveForward(10.0, timeout=20.)
Tentokrát ji vánek zanesl cca 3m stranou, ale jinak asi OK.
Závěry
- testování doma není jako testování venku
- drona si snaží udržet absolutní výšku nezávisle na překážkách
- „emergency stop = přistání” je nedostatečné (poryvy větru, vyšší letová hladina)
- malé rozlišení kamery (640x360) je nepoužitelné — zkuste ve videu najít kužel (potřeba přepnout do 720i)
- hodila by se funkce „návrat na základnu”
Video konverze
Ještě bych zmínil konverzi videa z PaVE streamu z AR Drone 2.0 do AVI. Nakonec
jsem to udělal v CV Drone „quick and dirty” pomocí
příkladu
z OpenCV. Je v něm jednak vysvětleno, co je to „video containter” a pak
celý převod je těchto pár příkazů:
#include <opencv2/highgui/highgui.hpp> // Video write VideoWriter outputVideo; outputVideo.open( "output.avi" , -1, 30, Size( 640, 360 ), true); … outputVideo.write( img ); …
kde „img” je „IplImage *”, který při parsování a zobrazování průběžně máte
k dispozici.
Abych nelhal, tak úplně bezproblémové to nebylo, resp. stále není. Je to možná
mix DLLek, který vytvoří nesmyslně pojmenovaný soubor a destruktor se také
nezavolal správně, takže u AVI asi chybí index. Mým cílem bylo rychle (během
1h) dostat video na web a to šlo. Ideální to není a ani touto cestou dále
nechci chodit — ono totiž ta kvalita … je to 3x přebalované (drona,
CVDrone, Windows Movie Maker). Líbilo by se mi jen ty datové pakety poskládat,
ale zatím to není priorita.
p.s.
Ještě jsem si hrál na Járu Cimrmana a ověřoval, že
vyfukováním tabákového kouře do
vody zlato nevznikne … konkrétně jsem zkoušel různé „AT*CONFIG
video:video_channel”, jestli tam není nějaká nezdokumentovaná hodnota, která
by přepnula na nahrávání jiný kanál než se zobrazuje … a minimálně do hodnoty 10
tam nic použitelného není.
7. května 2013 — NAVDATA_ALTITUDE_TAG
Dnes jsem konečně trošku koukal na logy z prvních outdoor testů. Co mne
zajímalo mezi prvními je jak je to přesně s tou výškou, aby se znova neopakoval
kotrmelec na mírném svahu. K prozkoumání tedy stojí NAVDATA_ALTITUDE_TAG a s
ním spojená struktura:
typedef struct _navdata_altitude_t { uint16_t tag; uint16_t size; int32_t altitude_vision; float32_t altitude_vz; int32_t altitude_ref; int32_t altitude_raw; float32_t obs_accZ; float32_t obs_alt; vector31_t obs_x; uint32_t obs_state; vector21_t est_vb; uint32_t est_state ; }_ATTRIBUTE_PACKED_ navdata_altitude_t;
Komentářů k tomu moc není, ale odhaduji vision je výpočet podle kamery, vz je
rychlost v z-ové souřadnici, ref moc netuším a raw je měření ze sonaru. Celkem
pěkný je graf z „Test One”, kdy čtyřtulka startovala z auta:
Další skupinku proměnných tipuji na detekci a odhad velikosti překážek
(obstacle). Zatím jsem ale dostával u prvních dvou floatů jen samé nuly, tak je
zatím ignoruji.
Na grafu je pěkné, jak v jednu chvíli vision zaostává za sonarem — to se asi
už ultrazvuk odrážel od země, zatímco kamera ještě koukala na kapotu… TO BE
CONTINUED
10. května 2013 — NAVDATA_ALTITUDE_TAG cont.
Nejprve bych začal tím, co jsem před pár dny nakousl, ale už nestačil ráno
dodělat. Prošel bych tedy ještě další logy k
referenčnímu videu.
U druhého pokusu je celkem dobře vidět, jak se mírně zvedl (že by díra nebo
vyšlapaná tráva?) a pak už to šlo z kopce, náraz a vzhůru nohama sonar hlásil
1.5m.
Při posledním pokusu nejprve stoupal do 2m a pak to celkem zvládal,
i když se zem přibližovala. Z grafu lze také odhadnout, co že to ta
altitude_ref asi je. Vypadá to na „globální referenci” nebo „relativní
nadmořskou výšku”, kde start je 0.
Co mne potěšilo dokládá přiložená šachovnice, 2D pohled shora. Je tam vidět, že
při stoupání Heidi trošku odnášel vánek, ale že o tom věděla. Je tedy možné
zapojit nějaké korekce, které budou vycházet přímo z odometrie.
Za zmínku také stojí chvilkový výpadek sonaru těsně před přistáním.
Co dál?
Jak byla volná středa, tak jsem chvíli lítal s následujícím prográmkem:
def flyAtHeight( self, altitude, dist, timeout=20.0 ): print "flyAtHeight", altitude, dist, timeout refX = self.coord[0] refY = self.coord[1] zTolerance = 0.5 # +/- no action startTime = self.time while self.time-startTime < timeout: altSonar, altVision = altitude, altitude if self.altitudeData != None: altVision = self.altitudeData[0]/1000.0 altSonar = self.altitudeData[3]/1000.0 if max(altSonar, altVision) < altitude-zTolerance: self.moveXYZA( self.speed/2.0, 0.0, self.speed, 0.0 ) elif min(altSonar, altVision) > altitude+zTolerance: self.moveXYZA( self.speed/2.0, 0.0, -self.speed, 0.0 ) else: self.moveXYZA( self.speed, 0.0, 0.0, 0.0 ) if distance( (refX, refY), self.coord ) > dist: print "DIST REACHED" break
Asi by to šlo napsat lépe. Ve zkratce, když jsou měření vzdálenosti k zemi
malá, tak čtyřtulka začne stoupat a naopak, když jsou moc velká, tak začne
klesat. Měla by tedy s mírným zpožděním, a celkem velkou tolerancí, kopírovat
terén.
Ještě možná zmínim funkci moveXYZA():
def moveXYZA( self, vx, vy, vz, va ): "make one step update with proper orientation" self.movePCMD( -vy, -vx, vz, -va )
prostě už mne přestalo bavit dlouze přemýšlet nad tím, jakou že má Parrot tu soustavu
souřadnou … otočená znaménka a prohozené X a Y.
První pokusy jsem dělal s papírovým „skokanským můstkem”
skokanský můstek |
Trošku dramatičtější byl pak přelet auta. Zbaběle jsem odmontoval anténu, aby se
moc nepletla do vrtulí a sám se schoval dovnitř. Celkem sranda, jen jsem trošku
znejistěl, když jsem dronu po přeletu nikde neviděl a tak rychle mačkal
emergency stop … ale tou dobou už byla schovaná ve vysoké trávě.
Pokusy jsem ještě několikrát opakoval a pokud byly úspěšné, tak hodně na těsno.
Ono to teď z toho grafu je celkem dobře vidět — než překážku zaregistruje a
přidá nebo ubere, tak ho ta setrvačnost žene do kolize. Asi by bylo potřeba
ještě více „přidat plyn” pro pohyb v Z-ové souřadnici a zmenšit toleranci.
A co jinak?
Jinak to začíná být poměrně křeč. Příští víkend je
soutěž v Písku, venku prší/leje, takže
nevím jestli o tomto posledním víkendu budou nějaké testovací lety, učím se jak
kompilovat linuxový kernel a získat funkční modul usbserial.ko z
Parrot zdrojových
kódů (zatím neúspěšně), na seznamu týmů RO nic nového …
14. května 2013 — homologace 5m: FAILED!
O víkendu jsem trošku zkoušel prográmek, který se snažil držet ve směru startu
a X-ové osy. Bylo to hrozné. Teď jdu zkoumat detaily. Navíc přišel mail od
organizátorů Robotem Rovně, že
homologace začínají už v 8h a pro jejich úspěšné splnění je třeba ujet/uletět
5m. Mně ale potvora Heidi zahýbá … a hned po startu si to klidně otočí o 45
stupňů, takže ani tu homologaci by 5dní do soutěže nedala …
Na druhou stranu musím uznat, že v neděli celkem foukalo a bylo by to na celkem
pěkný windsurfing … tak schválně co si myslela, že se děje.
První start, 42. měření skok o 45 stupňů vlevo :(. Přirozená korekce byla tedy
zatáčet vpravo do růží, což vlastně čtyřtulka udělala.
{'vy': 5.758006319661097e-29, 'phi': 504.0, 'psi': -40628.0, 'battery': 60, 'altitude': 0, 'ctrl_state': 6, 'vx': -1.3149668872027192e-29, 'theta': 169.0, 'vz': 0.0} {'vy': -4.3075449891044615e-13, 'phi': 505.0, 'psi': -97467.0, 'battery': 60, 'altitude': 0, 'ctrl_state': 6, 'vx': 1.490124112990543e-08, 'theta': 187.0, 'vz': 0.0}
Vypadá to na první roztočení motorů a jako by 'phi' brala z kompasu, který je v
té chvíli úplně mimo.
Koukám na data z kompasu a strukturu navdata_magneto_t … ty raw data
vypadají úplně náhodně. Jak když otočíte indiány. Pro představu pár měření:
compass: -103 27 113 1135868020673378100847233746463621120.000000 95579191465795697321761957262393344.000000 -1394810.750000
compass: -103 27 113 897022365180776029934830915319496704.000000 113103193363350740568052382373511168.000000 -1394810.750000
compass: -103 27 113 897022365180776029934830915319496704.000000 113103193363350740568052382373511168.000000 -1394810.750000
compass: -96 26 114 7319102271164370434775037509632.000000 214.262695 -1394810.500000
… a podivovali se nad tím i jiní, viz
fórum.
Přiznám se, že to v tom úplně nevidím, ale … např. offsety jsou:
compass offset: 0xe0a1c1fcL 0x99d842f3L 0xc44e
kde poslední malé číslo naznačuje, že první dvě by měla být spíše záporná a
opravdu to jsou otočený indiáni.
Tak ne … je to něčím jiným. Ten alignment, ten mne jednou zničí! Tj. chyba
byla v parsovaní dat, kdy
values = struct.unpack_from("hhhffffffffffffcIfff", "".join(values))
po prvních třech shortech zarovná strukturu na 4 bajty a pak dostávám nesmysly.
Správně to má být
values = struct.unpack_from("=hhhffffffffffffcIfff", "".join(values))
… tak nevím, zda ten dnešní příspěvek vůbec publikovat. Závěr je, že kompas
není dobře nakalibrovaný a natočení čtyřtulky to výrazně ovlivní. Jak se to
bude chovat pak zatím netuším. Nutno otestovat.
20. května 2013 — Robotem Rovně
Byl jsem teď 4 dny offline, tak se omlouvám za malou odmlku. Heidi ale
nezahálela, zkoušela létat v nárazovém větru, kalibraci kompasu a konečně
soutěžila na „Robotem Rovně”. Tam jsem naší účast bral trošku jako divadlo
pro účastníky Cipískoviště, ale organizátoři to pojali
jinak a založili nám novou kategorii „Létající roboti” … a tak si Heidi
přivezla domu i medaili.
Z pohledu létání beru za největší úspěch, že čtyřtulka nikomu neublížila, když
úspěšně odstartovala, tak způsobila mexickou vlnu následovanou potleskem a
splnila i úkol překonat dosavadní
rekord
28 metrů Tomáše Krajníka z roku 2010. V průměru si ale vedla hůře, viz
letošní
výsledková listina. Dojmy a detaily z RR si nechám do článku, který snad
během týdne sepíšu. Tak ještě jedno převzaté foto. Předpokládám, že je to
zrovna situace, kdy si Heidi prosadila svou a odmítla se se mnou dale bavit,
ale z obrázku to není úplně zřejmé .
Hedi na startu - převzato z webu Radioklubu Písek |
p.s. ještě dobrá jedna dobrá zpráva na závěr — RoboOrienteering se pojede!
Teď jsou už
4 týmy a
možna ještě 2 přibudou…
23. května 2013 — Status quo
Do soutěže „RoboOrienteering” zbývají už jen tři týdny. Vedle vyřešení
problémů z Robotem Rovně je nutné
především implementovat detekci překážek. Ta je potřeba už pro samotnou
homologaci.
V plánu jsem měl jednak úpravu LKDemo z OpenCV a tak mne potěšila informace od
Davida Hermana z týmu Roboauto — jeho student něco podobného řešil v
bakalářské práci.
Používal sice první generaci AR Drone, ale problémy asi budou dost podobné.
Druhá varianta je použití sonaru, který ale zase vyžaduje rozchození USB serial
driveru. Jak najít a zkompilovat kernel jsem snad už pochopil, ale problém byl
(?) se správnou konfigurací. Heidi teď nemám doma, ale rozdíl mezi starou a
novější verzí mi dává zase naději:
martind@nexus:~$ file usbserial.ko usbserial.ko: ELF 32-bit LSB relocatable, ARM, version 1, BuildID[sha1]=0x06bdc0c7558101bc587b35393f570a792fbb80b5, not stripped vs. martind@nexus:~/drona$ file usbserial.ko usbserial.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), BuildID[sha1]=0x54754d367f5e3d6ea49a7e5fe024ad5b6db5d901, not stripped
Všechny moduly měly to „(SYSV)”, což je zkratka pro
Systém V. Nevěděl jsem, jak to
tam dostat, až jsem narazil na Building
and Installing USB/Serial Drivers. Po neděli uvidíme, zda to pomohlo. Jen
korekce linku na zdrojové kódy, který má být správně
https://devzone.parrot.com/projects/show/oss-ardrone2.
p.s. pamatujete, jak jsem řešil problém, jak přepnout na automatickou navigaci
na černobílou značku? Tak rozuzlení nejspíše je, že to v mém firmware 2.3.3.
vůbec nejde :-(. Viz
odpověď Grega …
26. května 2013 — metalog
Jirkovi Išovi trvalo skoro rok, než mne donutil zavést na Eduru metalogy. A
přitom je to práce cca na 1h a následně vám to značně usnadní život. O co se
tedy jedná? V kostce to je „logování logování” . A je pomalu na čase to
zavést i na Heidi …
Neprve motivace: Eduro mělo hned několik zdrojů/logů — komunikace po CANu,
NMEA data z GPS, obrázky z kamery, data z laseru, data z druhého laseru, data z
RFID tagů, data z joysticku a možná jsem ještě na něco zapoměl. Každý
jednotlivý log měl formát prefix_DATUM_CAS, ale DATUM a CAS nebyly nutně
identické, jak se jednotlivé senzory připojovaly. Pokud jich k přehrání bylo
třeba více, tak bylo nutné je nějak sjednotit a k tomu se hodí metalog.
A když už máte jednou metalog, tak si tam můžete napsat více než, kdy se který
senzor připojoval a pod jakým jménem souboru je uložený. Triviální je přidat
příkazovou řádku, máte-li krátký konfigurační soubor, jako je u
RoboOrienteeringu seznam waypointů, tak se vyplatí si jeho obsah do metalogu
zkopírovat. Při startu můžete připsat větu, co že by to mělo dělat a po
skončení připsat jak to v realitě dopadlo. A kdyby jste byli opravdu důslední
puntičkáři a před každým testem všechny zdrojáky komitovali do gitu či
mercurialu, tak můžete přidat i hash repository.
Pro zavedení metalogu na Heidi si ho nejprve vytvářím ručně sám. Testovací příklad
meta_130518_130615.txt vypadá takto:
navdata: logs\navdata_130518_130615.log.gz atcmd: logs\atcmd_130518_130615.txt video: video_130518_130617.bin video_rec: video_rec_130518_130617.bin
Všimněte si, že i tady od startu Heidi uteklo pár sekund, než se začala logovat
kamera …
Až do teď mne na Heidi z pohledu programu zajímala jenom navdata a vystačil
jsem si s tím i na soutěži Robotem Rovně. Teď
bych rád ale přidal další senzory (GPS, sonar), které budou chodit nezávisle
na navdata, začal zpracovávat kameru a konečně potřebuji průběžně uklízet kód,
aniž by se změnilo jeho chování (refactoring).To je natolik užitečná
zaležitost, že bych jí tady ještě rozepsal … i když už se asi budu opakovat
a někde na robotika.cz to určitě najdete.
U logů je důležité ukládat jak data ze senzorů, tak vaše samotné příkazy. V
případě AR Drone to je ukládání AT příkazů. Proč? Pokud program pouštíte a ladíte
na různých počítačích, tak tímto způsobem máte větší jistotu, že v obou
případech používáte stejný kód.
Další použití je již zmiňovaný refactoring: je to vlastně triviální test, že z
pohledu příkazů/rozhodnutí se nic nezměnilo. Také vám nic nebrání test pustit
na posledních 10 pokusů, pokud všechny běžely se stejným programem.
Ještě bych zmínil jednu deset let starou historku spojenou s přehráváním logů:
na robotu Daisy bylo řízení ze starého iPAQu. Kód byl psaný v
jazyce C, ale choval se jinak na robotu a jinak na notebooku (už jenom toto je
bez logu netriviální zjistit). S vysvětlením tenkrát přišel Zbyňek — k
navigaci jsme používali Monte-Carlo lokalizaci s
floatovou aritmetikou. Ta je na iPAQu řešena softwarově a notebooku hardwarově.
Matematický koprocesor ale vše počítá v double a teprve pak výsledek převádí na
float, zatímco softwarově byly i mezivýsledky floatové … pěkně, že? Přešli
jsme na double a od té doby to bylo 1:1. Nezapomenutelné ponaučení .
27. května 2013 — usbserial.ko
Test nového buildu modulu usbserial.ko jsem nechal až na neděli a dopadlo
to podle očekávání — nefungovalo to.
# insmod usbserial.ko insmod: can't insert 'usbserial.ko': invalid module format
Dvakrát sdílný ten popis není, ale možná existuje nějaký verbose parametr,
který jsem měl použít, ale nevypadá to. V použitém
návodu popisovali změnu verze
z „2.6.32.9” na „2.6.32.9-g0d605ac”, ale build mého 2.3.3 firmware má jinou
verzi! Konkrétně na droně najdu adresář /lib/modules/2.6.32.9-gbb4d210/ …
nová naděje . Doma jsem se udělal nový build a nastal
magický okamžik:
BusyBox v1.14.0 () built-in shell (ash) Enter 'help' for a list of built-in commands. # cd /data/video/ # mkdir driver2 # cd driver2/ # insmod usbserial.ko #
Pro ty, co ten úžasný pokrok nevidí, tak insmod už nenásleduje chybová
hláška . Pokud každý nový firmware potřebuje jinak zkompilované moduly, tak
to je možná i důvod, proč nejsou na webu běžně ke stažení …
Teď bych použil frázi „getting there but not there yet”. Ze zmiňovaného
návodu jsem pochopil, že budu
potřebovat ještě další moduly. Nápověda z Windows a dokumentace
GPS
GNS 5860 byla, že ten driver bude začínat „cp21” a opravdu se
zkompiloval i „cp210x.ko”. Insmod už fungoval bez problémů, ale USB zařízení
nebylo vidět. Zkusil jsem to snad 5x vypojit a zapojit než se hláška změnila:
# lsusb Bus 001 Device 001: ID 1d6b:0002 # lsusb Bus 001 Device 002: ID 10c4:ea60 Cygnal Integrated Products, Inc. Bus 001 Device 001: ID 1d6b:0002 #
Jestli toto má pak být spolehlivý robot, tak potěš … no nic. V dalším kroku
jsem si chtěl podle wiki na
Paparazzi nechat vypisovat NMEA data a zase nic:
# stty -F /dev/ttyUSB0 ispeed 38400 && cat < /dev/ttyUSB0 stty: /dev/ttyUSB0: cannot perform all requested operations
Na to, že jsem chtěl změnit jenom jeden parametr a nemohl změnit všechna mne
pak zaskočilo, když tu rychlost opravdu změnil, ale stále to není ono. Příkaz
„cat /dev/ttyUSB0” mi začal sypat tato data:
GPGGA,195048.644,5048.6133,N,00609.2?Err?493,E,0,0,,102.4,M,47.6,M,,*4B GPGSA,A,1,,,?Err?,,,,,,,,?Err?,,,?Err?,*1E $GPRMC,195048.644,V,5048.6133,N,00609.2493,E,0.00,0.00?Err?,260513,,,N*7F
což je lepší než nic, ale dobré to rozhodně není (pokud to nevidíte, tak jsou
tam ty divné ?Err?).
Z pohledu soutěže je GPS až druhotná a měl bych se spíše zaměřit na rozchození
modulu k sonaru.
USBISS
zařízení ale rovnou vyžaduje oboustrannou komunikaci a jak pokus s GPS
naznačuje, asi ani tam cesta moc přímá nebude.
28. května 2013 — /dev/ttyACM0
Dnes jsem narychlo vyzkoušel jinou GPS
(GPS BR-355 USB),
která ma Prolific driver (modul pl2303.ko) a ta na rychlosti 4800 fungovala
pěkně. Konečně ta chybová hláška stty: /dev/ttyUSB0: cannot perform all
requested operations se týká pravděpodobně klíčového slova ispeed a
rychlost samotná se vlastně stane nezávislý parametr a nastaví se.
Další test byl s USBISS — ono bych ho mezi /dev/ttyUSB* ani nenašel, i kdyby
to fungovalo. Zkusil jsem to na linuxu u kolegy v práci a tomu se vytvořilo nové zařízení
na /dev/ttyACM0 … celkem pěkné vysvětlení najdete
zde.
Inkrementální krůček už je řádově snažší než první krok a tak jsem oeditoval
.config:
martind@nexus:~/linux0523$ diff .config config-orig 1429c1429 < CONFIG_USB_ACM=m — > # CONFIG_USB_ACM is not set
zkompiloval moduly, zkopíroval vytvořený drivers/usb/class/cdc-acm.ko,
nahrál do drony a …
# cd /data/video/driver2/ # insmod cdc-acm.ko # ls /dev/ttyACM0 /dev/ttyACM0
Tak to bylo až podezřele snadné. Uvidíme, až z toho budu chtít přečíst alespoň
jeden bajt…
31. května 2013 — sonar SRF02
Marnost nad marnost,
vše je marnost … alespoň tak jsem to viděl před více jak 24h, ale už to
trošku vyprchalo.
Ve St večer jsem byl v práci u Tomáše a zapojovali jsme nový senzor do AR Drone
2: sonar. Nejprve Tomáš nahradil původní
USB
B konektor přímo za
USB
A konektor. Z pohledu nezávislého pozorovatele to nebylo až tak triviální a
sám bych se do toho rozhodně nepouštěl. Psal jsem před časem i výrobci, zda
neplánují změnu konektoru a odpověď byla If we ever used a different connector
it would be the mini B type. Na ten mini by už byly i
krátké redukce, tak možná
někdy bude integrace snazší.
Toto proběhlo dobře — Tomáš je důkladný a k žádnému prohození + a - nebo
datových kabelů nedošlo. Modul
USBISS
komunikoval a bez propojovacího kabelu jsem ušetřil hned několik gramů a hlavně
už nepřekážel. Už jenom úspěšnost tohoto kroku mne naznačuje, že úvodní
tvrzení je zavádějící, ale pojďme dál.
K převodníku jsem si koupil dva
sonary
SRF02. Jelikož jsou dva, tak je musíte každý jinak adresovat. Z továrny mají
přednastavanou adresu E0 a ta funguje. Po drobné úpravě
prográmek
v Pythonu (změnil jsem port z /dev/ttyUSB0 na COM19 a zakomentoval
os.system('clear')) vypisoval vzdálenosti v centimetrech, které na první
pohled vypadaly rozumně. Další protipříklad, že jsem to v úvodu přehnal.
V této fázi jsme to měli zabalit, spokojit se s jedním sonarem do HW verze 0,
udělat cca 10cm propojovací I2C kablík a přichytit sonar těsně nad kameru, kam
krásně pasuje. Ale ne, to hloupému Martinovi nestačí. On musí mít sonary hned
dva. Musí z drony hned dělat
predátora (to
asi znáte,
jak
mají ptáci oči … většinou stačí jeden pohled a víte, zda jsou to dravci
nebo lovná zvěř, tj. zda oči používají na stereo-vision nebo na pokrytí
pokud možno celých 360 stupňů pohledu).
Ke změně I2C adresy je třeba vyslat posloupnost kódů se zápisem do registru 0,
konkrétně 0xA0, 0xAA, 0xA5 a novou adresu zařízení, třeba 0xF2
(viz detailní
popis). Změnili jsme to a nic. Odpojili, připojili a nic. Koukali na to na
profi-I2C-analyzátoru, viděli všechny bajty i s potvrzením od zařízení a nic. A
to vše nějakou nezdravou dobu, až se žena doma divila, kde jsem tak dlouho
byl …
Kdybych to zkusil teď, tak by to určitě fungovalo, ale mne to už vůbec
nezajímá!!! … vidíte, ještě to úplně nevyprchalo, tak třeba po víkendu.
Jak jsem psal, pro HW verzi 0 to stačí. A jelikož Rychnov je už za 14dní, tak
je na čase udělat „HW freeze”. Prostě naučit se žít s tím, co člověk
momentálně má, zjistit co to má za mouchy a cca za týden udělat i „SW
freeze”, na nic nesahat a „jenom” testovat …
p.s. možná je tam nějaký problém s časováním, podobně jako jsem psal v
IARC blogu, a pomalu se přiznám, že takové
protokoly nemám rád …
2. června 2013 — voda
Tento víkend jsem toho na zahradě moc nenalétal. Je na čase implementovat „návrat
na základnu” — emergency tlačítko bych jinak použil nejvýše jednou …
... jen pro hydroplány a kachny |
5. června 2013 — stty
To byl zase zásek na několik hodin :-(. To je tak, když si někdo naivně myslí,
že poslat 5 bajtů, chvíli počkat, poslat další 4 bajty a přijmout 3 bajty je
práce na pár minut. Měla by být! V Pythonu je. Do čtyřtulky ale Python
nedostanu (není tam moc volného místa a nevěřím, že to vše hned bude fungovat),
takže hezky v Céčku. O co mi jde? Potřebuji naměřit vzdálenost pomocí
sonaru SRF02.
Pamatoval jsem si, že už kdysi jsem něco se seriovým portem pod linuxem dělal.
Chvíli jsem hledal až to našel na našich stránkách v článku
ATmega8 board . Napsal jsem si krátký prográmek:
#include "SerialCommLinux.h" int main() { SerialCommLinux com( "/dev/ttyACM0", B9600 ); int i, j, val[3]; BYTE sonarStep1[] = { 0x55, 0xE0, 0x00, 0x01, 0x51 }; BYTE sonarStep2[] = { 0x55, 0xE1, 0x02, 0x02 }; for( i = 0; i < 10; i++ ) { com.sendBuffer( sonarStep1, sizeof(sonarStep1)/sizeof(BYTE) ); com.sendBuffer( sonarStep2, sizeof(sonarStep2)/sizeof(BYTE) ); for( j = 0; j < 3; j++ ) val[j] = com.waitForByte( 100 ); printf( "sonar:\t%d\t%d\n", val[0], val[1]*256 + val[2] ); } return 0; }
a nejprve mi nešel zlinkovat. Po chvíli mi došlo, že gcc není to co pro C+ +
potřebuji a s g++ už kompilace proběhla bez problémů:
martind@nexus:~/sonar$ arm-linux-gnueabi-g++ -o sonar-arm SerialCommLinux.cpp sonarMain.cpp
Přepojit se na dronu, upload … a nic, přesněji:
# /data/video/sonar-arm sonar: -1 -257 sonar: -1 -257 sonar: -1 -257 sonar: -1 -257 sonar: -1 -257
tj. samé timeouts. Dobře raději to vyzkouším i ve Windows. U
článku jsou i další zdrojáky a projekt pro Vistual
Studio 2005 (také je to všechno z roku 2005), takže to šlo rychle (programování
mazáním). Pustil jsem to a zase nic. Ještě zmíním, co jsem změnil (přesněji to byly
ifdefy na __unix__ ): použil jsem SerialComm com( L"COM19:", 9600
); místo SerialCommLinux.
Tady jsem čerta tušil — Windows nemají rády COMy s číslem vyšším než 10 a
USB-ISS se detekoval na COM19. Jedna varianta je COM přemapovat, druhá je najít
řešení v kódu Navigátora a to je:
SerialComm com( "\\\\.\\COM19", 9600 );
Fajn, fungovalo, několik 65535, že sonar ještě nestihl nic naměřit (v té době
mi tam chybělo to čekání), takže novým kódem to není.
Ještě jsem nezmínil, že jsem původně chtěl kompilovaný kód úplně obejít a jenom
pomocí cat pěti a čtyřbajtového souboru na /dev/ttyACM0 si vynutit
měření sonaru a pomocí hexdump -n 3 si ho zase přečíst. LEDky blikaly
(tj. sonar vysílal), ale čtení se vždy bloklo. V kombinaci s mým Céčkovým
kódem to ale občas pár znaků přečetlo, takže nějaka naděje zůstala.
Včera jsem vzal modul do práce a zapojil ho do jednoho ze serverů … a
kupodivu stejné chování jako na droně . To byl úspěch, protože jsem po
každém kompilování nemusel přepojovat sítě a pod. Zkusil jsem pythonovský
prográmek pod linuxem a ten mi hned vracel měření ke zdi. Zase naděje. Pak
marné zápolení s parametry v kódu SerialCommLinux, abych výstup z stty
dostal stejné jako po puštění pythonovského programu:
martind@nexus:~/sonar/python$ stty -F /dev/ttyACM0 speed 19200 baud; line = 0; intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>; flush = <undef>; min = 0; time = 0; -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
Když jsem náhodné hackování vzdal, tak jsem narazil na webu na
linux_srf02.c,
zkompiloval a hned to fungovalo. Hurá!
Udělal jsem si ještě verzi pro ARM a jak myslíte, že do dnes ráno při testování
dopadlo? Nijak, program se bloknul a nic nevypsal. LEDky blikly, takže
minimálně se mu podařilo psát, ale nikoliv číst. Při pohledu na výpis:
# stty -F /dev/ttyACM0 speed 19200 baud; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -brkint -imaxbel
modří už vědí … a já zrudlý do červena už pomalu také. Je to modem, který
používá speciální znaky. Co se asi stane, když sonar naměří něco podobného
speciálnímu znaku?? Interpretuje to. Ta magie je v tom <undef>, tj.
„všechno vypnout”! Asi je na to nějaký speciální příkaz, já to dělal dřevácky
po jednom:
# stty -F /dev/ttyACM0 intr ^- quit ^- erase ^- kill ^- eof ^- start ^- stop ^- susp ^- rprnt ^- werase ^- lnext ^- flush ^-
a pak už to začalo fungovat. Vtipné. Prostě podle toho jak moc jste byli od
překážky to buď částečně fungovalo nebo ne …
A co jinak? Do soutěže zbývá týden a poslední víkend na testování. Ten ale
spíše strávím odstraňování důsledků záplav z minulého víkendu. No snad alespoň
tu homologaci dám…
7. června 2013 — AVI s raw H264 snímky
Včera jsem konečně zkonvertoval pár zajímavějších video záznamů z a „skrytě je
zveřejnil” zde. Přestože se na webu
dočtete, že H.264 + AVI is not a good move. You should go with MKV or MP4 as
your container, tak cesta existuje. Binární data snímků v H264 kódování jsou
uložena bez konverze (tedy bez dalších ztrát kvality) a s výsledkem si poradí
jak YouTube, tak třeba VideoLAN.
Výchozí pro mne byl příspěvek na Stack Overflow:
Raw
H264 frames in mpegts container using libavcodec. Sice už je postarší a se
současnou verzí ffmpeg si úplně nerozumí, ale můžete
se inspirovat radami z blogu
Deprecated
functions in ffmpeg library pro opravu dvou volání funkcí a jedné proměnné.
Pro kompilaci pod Windows použít, třeba jako já, připravené projekty a knihovny
v CVDrone. Jestli chcete přeskočit rovnou
k cíli, tak zde je upravený originální kód.
p.s. omlouvám se, že videa jsou bez zvuku (drona vrčení nenatáčí) a s
komponováním si budu hrát někdy příště …
10. června 2013 — Deterministická vlákna
Byla neděle, krátce před 17h. Udělal jsem pár oprav, které by si zasloužily
test venku. Slyším ale divný rachot … bouřka nebo bagr u sousedů? Oboje.
Vybíhám na louku dokud ještě neprší. V prvním testu (meta_130609_170501.log)
Heidi odmítne rozpoznat připojené USB zařízení. Letí celkem OK. Odpojit,
připojit a druhý pokus (meta_130609_170646.log). Pomalu se zvedá vítr, ale
sonar už běží a chodí z něj data. U třetího pokusu (meta_130609_170803.log) už
padají první kapky a začíná slejvák. Hážu dronu do kufru (auto stojí na louce)
a s notebookem běžím zpět do chaty. Nějak se zbláznila wifina, takhle blikat
jsem jí posledních 8(?) let neviděl a vypínám ho natvrdo. Po deseti minutách
žena hlásí, že na louce už je voda a to jak v pásech po kolech auta, tak
napříč. Vyrážím v holinách do bouřky přeparkovat. Klouže to, ale vody je zatím
jen cca 15cm a dostanu se k brance. Za dalších 10min se zahrada změnila v řeku
a je to v horším stavu než při kulminaci minulou neděli. Před tím se voda
sbírala celý den, teď to ale vše bylo za 20min … tak to je nudná realita a
teď zpět k té virtuální.
O čem jsem chtěl psát jsou „deterministická vlákna”. Není to úplně výstižné,
ale … jde o to, aby váš program mohl být více-vláknitý (multi-threaded) a
přitom, pro pozdější analýzu, se choval zcela deterministicky. Řešení, které
používám jsem přebral od Zbyňka, když ještě programoval
Esterku.
Princip je v zásadě celkem jednoduchý — oddělené vlákno se s hlavním
programem „potkává” jen v jednom bodě (míněno v jedné funkci) a v ten okamžik
se i logují předávaná data. Příkladem může být pomalé zpracování obrázku z
kamery, např. s cílem lokalizovat kontrolní kužel, a loguje se souřadnice v
obraze (nebo i další parametry, jako výška, šířka, věrohodnost, alternativní
cíle …). Při přehrávání/debugování hlavního programu pak už neběží „kamerové
vlákno”, ale pouze po X-krocích, kolik je X se také loguje, si hlavní program
přečte další data z logu.
Co jsem tento víkend podobným způsobem zapojoval byl sonar. Běží nezávisle s
telnet připojením, kdy na začátku ověřuje dostupnost /dev/ttyACM0 a pak čte
výsledky z výpisu z malého céčkového prográmku. Protože je rozdíl, jestli
jednou přečtete vzdálenost 0.5m a tu pak stále vracíte a situací, kdy stále
čtete 0.5m, tak ještě ke každému měření přidávám pořadový index. A už první
test přinesl své ovoce. Začátek souboru sonar_130608_190101.log vypadal
takto:
52 (0, 493) 45 (2, 138) 13 (3, 325) 41 (5, 46) …
Loguji textově. Data nejsou velká a na jejích dekódování nepotřebujete nic
speciálního. Střídá se řádek s počtem dotazů z hlavního programu, než dostanete
novou odpověď. Tedy po 52 dotazech (cca 0.25s od startu programu při 200Hz
update) dostal první měření od sonaru, které má index 0 a naměřenou vzdálenost
493cm. Princip je snad jasný.
A kde jsou tedy ty chyby? Nuže, sonarová měření by měla mít index souvislý, bez
děr. Ztratilo se měření s indexem 1, 4 a časem jsou tam i díry velikosti 10,
což při 10Hz znamená, že dorna celou sekundu nezískala informaci o překážkách!
Napadá mne, že chybí flush v programu, případně, že telnet má také nějaké
buffery a hned s každým bajtem nepospíchá … to je ještě třeba ověřit.
Můj homologační prográmek byl celkem triviální: když je překážka méně jak 1
metr daleko, tak zastav (hover), jinak leť požadovanou rychlostí rovně. S
drobnými poryvy větru a vrtochy čtyřtulky se ale klidně vyhnula velkému
skleníku (jo, byla to trošku destruktivní myšlenka pouštět jí tím směrem) a tak
jsem jí nasměroval do volného prostoru a snažil se ji zastavit máváním rukou
před sonarem. Marně. Buď nezastavila, nebo až o několik metrů dál … hmmm.
V programu jsem našel hned dvě velké hrubky (našel jsem je tak, že jsem měnil
limit pro zastavování a divil se, že se chování programu nijak nezměnilo, tedy
že přehrávání logu neassertovalo). První věc byla, že jsem zapomněl na zmiňovaný
index měření. V Pythonu, trošku překvapivě, lze porovnat N-tici se skalárem:
>>> (27, 391) < 1.0 False
takže má podmínka nebyla nikdy splněna. Druhou chybu asi také tušíte. Správně
tedy hned po přečtení dat ze sonarového vlákna zahazuji index a to druhé číslo
dělím 100.0 … jj, ty jednotky.
Mezi daty ze sonaru jsem měl ještě několik 0 a to je bylo špatné znamení :(.
Kouknu se ještě do dokumentace, ale předpokládám nepotvrzenou komunikaci na
I2C. Navíc teď koukám, že ty tři zmiňované pokusy v úvodu jsou všechny prázdné
a sonar nějak vůbec nefungoval, no nic, prima, ostatně já mám pondělky stejně
nejraději (těžká ironie). Pokračování až po úpravě C-prográmku a dalších testech
…
p.s. co si myslíte, že se stane, když uděláte paste do terminálu:
M:\hg\md\heidi\logs>m:\git\cvdrone\bin\vs2008\test.exe video_rec_130608_194358.bin?
… smažete si přehrávací program. Přeji pěkné pondělí …
11. června 2013 — 3 dny …
Do soutěže zbývají 3 dny. Nevypadá to růžově. Včera jsem ještě koukal, jak je
to v tom Pythonu s porovnáváním různých typů a je to tak, že N-tice bude vždy
větší než číslo. Díky tomu pak můžete setřídit pole (list), který obsahuje
různé typy — podrobnější vysvětlení najdete např.
zde.
Dále jsem si četl, jak je to s těma nulama při čtení sonaru … a je to divné.
Z dokumentace, mne
trošku vyděsila poznámka: You can take advantage of the fact that the SRF02
will not respond to any I2C activity whilst ranging. … to skoro nechci ani
vědět, jak tam chodí ty potvrzovací ACK. Doporučují číst verzi sonaru a
když je 0xFF, tak že ještě echo nepřišlo. To jsem do kódu vrátil (v
originálním
příkladu to bylo, ale přišlo mi to zbytečné). Teď loguji jak verzi sonaru, tak
potvrzení vyslání echa. Teoreticky by to měl být test spolehlivosti I2C v blízkosti
čtyř motorů — pokud dostanu jinou verzi sonaru než číslo 6, tak to zlobí.
Včera v noci jsem to ale už se zapnutými motory nezkoušel … bylo mi líto
sousedů (ale to se asi s blížícím termínem soutěže změní).
Další (nové) poučení je s detekcí USB zařízení. Nejen, že se občas
neobjeví, ale někdy lsusb trvá přes minutu! Myslel jsem, že se to nějak
kouslo, ale pak to skončilo. Připojil jsem se rovnou a obalil to zjišťováním
času:
# date && lsusb && date Sat Jan 1 00:08:25 UTC 2000 Bus 001 Device 001: ID 1d6b:0002 Sat Jan 1 00:09:34 UTC 2000 #
Pěkné, že? Teď mi skoro přijde na hlavu to zapojení sonaru přes
wifi-usb-seriak-i2c …
Pro uklidnění jsem ráno trošku „uklízel”. Zapojil si zobrazování sonaru do
vieweru (2 řádky) a doplnil čtení souboru s kontrolními body na
RoboOrienteering. Sám dobře vím, jaký je to stres v těch 10min vše spolehlivě
připravit, neprohodit X a Y a pod …
bohatě bude stačit to trojité bootování, aby sonar naběhl.
12. června 2013 — 2 dny (listy a větve)
Myslel jsem si, že největším problémem bude vyhýbání se kmenům stromů, ale
podle dnešních ranních testů v sídlištním parčíku to to vypadá, že to budou
spíše listy a drobné větvičky. Další pozorování je, že bych se měl naučit
číst a ne jenom přeskakovat řádky. Konkrétně větu: A value of 0 indicates
that no objects were detected. jsem včera nějak přehlédl. I2C potvrzení i
verze sonaru byla ve všech 1969 dnešních měřeních správně.
Včera večer jsem trošku testoval doma na chodbě a musím přiznat, že ten přechod
outdoor -> indoor ve mne vyvolával klaustrofobické pocity. Našel jsem dvě další
chyby, kterých jsem si v neděli nevšiml a je to pravděpodobně důvod, proč z
„předbouřkového” testu nemám jediné sonarové měření. V kódu mám, že pokud se
/dev/ttyACM0 najde, tak se rovnou pustí sonarový prográmek. Problém je, že
to systému trošku trvá, než /dev/ttyACM0 zpřístupní a tak se může stát, že
mi selže jeho konfigurace pomocí stty. Oprava je triviální — konfigurovat
je třeba v každém běhu.
Druhá chyba byla v podmínce, aby se čtyřtulka otáčela na místě pokud je směr k
cíli pod příliš velkým úhlem. Korekce pro navigaci v koridoru jí ale rychle
správně natočí a tak jsem tu nefunkčnost úplně přehlédl. Jo, jo, chyba, že jsem
to netestoval nejprve odděleně.
Co teď koukám do logů, tak v reálu to vypadalo lépe, než z pohledu robota. Pro
představu uploaduji krátké video kličkování
mezi stromy. A co na to sonar? All clear … a v té 45s jsem jí zastavil,
protože to sekání listů mne příliš znervózňovalo…
p.s. stromy v měření ze sonaru „vidět” jsou, ale je třeba se
koukat i 4m daleko (viz téměř neviditelné zelené tečky, čtverec=1m):
detekce stromů sonarem |
13. června 2013 — 1 den (letové koridory)
Toto asi bude poslední příspěvek před samotnou soutěží a jelikož nic moc nového
nemám, tak alespoň zmíním náznak plánu. Přemýšlel jsem co s tím jedno-sonarem
podniknout a chtěl bych vyzkoušet dva algoritmy: letové koridory a sken s
„náhodnou procházkou”.
Aktuální verze programu naviguje čtyřtulku v 1m širokém koridoru (podle
odometrie) a pokud se příliš vychýlí, tak dělá jak korekce do strany, tak
nahoru a dolu. Pokud Heidi získá pocit, že je před ní překážka, tak jedna z
možností je koridor „posunout” v Y-ové ose čtyřtulky a po nějakém čase či
vzdálenosti tento posun zase vrátit na nulu. Druhá varianta je, že v případě
blízké překážky, udělá otočku o 360 stupňů, zmapuje celé okolí v dané výšce a
vydá se směrem, kde je volno. Buď náhodně, nebo ideálně nějak v kombinaci s
cílem, kam má letět .
První verze je riskantní, protože při přesunu do „levého pruhu” může narazit
na překážku. Na homologaci a v parku, kde v dané výšce jako překážky převládají
kmeny stromů by to ale teoreticky mohlo fungovat. Druhá je zase zdlouhavá a ty
otáčky na místě jí úplně nejdou — snadno „odpluje” i nějaký metr stranou.
Ideálně bych použil kombinaci obou přístupů. Když už se dostanu na 1m od
překážky, tak si možná i kousek couvnout, scan, odskok a znova koridory. Ano,
žádná zmínka o kameře, LKDemo a zpracování bodů v obraze. Přiznám se, že jsem
to trošku zkoušel, ale moc mne to zatím nepřesvědčilo. Raději, ve zbývajícím
čase, zkusím vymačkat z toho jediného sonaru co se dá.
Ještě jedna, snad pozitivní, poznámka na závěr — jeden z rozdílů sonaru
umístěného na pozemním a létajícím robotu je, že sonar směřující dopředu na
létajícím robotu zem detekuje až ve větší vzdálenosti. To mi prvně úplně
nedošlo. Na Eduru je sonar cca ve 40cm a ve 2m už „vidí” trávu. Heidi ale
letí ve výšce cca 1.5m, tak si možná mohu dovolit důvěřovat i 4m měřením. Jak
je to v realitě až po víkendu…
14. června 2013 — aquaphobia
Dnes začalo pršet v 6:41. Vím to poměrně přesně, protože jsem venku stihl
udělat jeden jediný test se skenováním „na místě”. Je to v úvozovkách,
protože při otáčení se Heidi posunula cca 1.5m, nabourala do sloupku a spadla
na levou zadní vrtuli. Auto jsem přeparkoval tentokrát těsně vedle potoku, což,
pokud se nesesune břeh, vypadalo na jediné místo, kde minulé víkendy neproudily
„nové potoky”. Kde jsou ty časy, kdy mi déšť dělal radost …
Během raní směny jsem stihl udělat pár drobností: vylepšené stahování
nahrávaného videa (vypnu nahrávání, ale ještě chvíli volám update, dokud video
kanál netimeoutuje), asserty on/off (prostě když máte nový kód, tak je občas
chcete vypnout a je otrava stále jeden řádek dokola zakomentovávat), logování
stisku klávesy a ještě pár drobností.
U toho logování „ANY KEY” bych se ještě pozastavil. Všem vnucuji logování
jako neodiskutovatelný základ pro vývoj a ladění robotů a … asi jsem dříve
nečekal, že budu emergency tlačítko používat tak často, resp. skoro každý pokus
tak končí. Pokud máte ale asserty zapnuté, tak není na první pohled zřejmé, zda
se něco pokazilo, nebo běh programu je jiný (chybí ta informace, že je problém
a přecházíme na nouzové přistání). Původní zapojení funkce kbhit jsem jenom
trošku změnil:
self.console = SourceLogger( msvcrt.kbhit, filename ).get
Jinými slovy všechny výstupy funkce msvcrt.kbhit se uloží do souboru se jménem
filename. Pak je třeba ještě doplnit situaci, kdy log přehráváte:
self.console = SourceLogger( None, filename ).get
a v kódu používáte volání self.console(). V případě dnešního pokusu log vypadá
takto (má 18 bajtů):
0 0 1882 1 1
tj. drona udělala 1882 cyklů, než jsem zmáčknul emergency. Chcete-li i detaily,
tak zde je zdrojový kód sourcelogger.py.
(musím přestoupit, pause)
17. června 2013 — RO2013 mini info
Pokud chcete rychle vědět, jak to dopadlo, tak viz
výsledky. Pro ty,
co se těšili na videa z drony, mám ale špatnou zprávu :-( … po timeoutu
navdata socketu a jeho restartu se přeruší jak nahrávané video, tak i
streamované video :-(. Problém z Písku, kdy čtyřtulka visela na startu a nedalo
se s ní nic dělat než jí ve vzduchu chytnout a převrátit na záda, se mi tedy už
nestal (provede se ten restart komunikace), ale videa jak Heidi prolétá mezi
větvemi (občas, kolize byly častější) bohužel nemám.
Pro nedočkavce:
19. června 2013 — Simulátor
Řeším, jaké kusy textu nechat v hlavním článku a co přesunout do tohoto blogu,
kde se můžu snáze pitvat v detailech ... a tak úvod o simulaci přesouvám
sem. Blog bych asi ještě nechal tak cca 14 dní aktivní až skonči
Field Robot v Praze a bude chvíle na
,,doklizení''.
Do Rychnova jsem nakonec jel vlakem a získal tak další 3h na programování.
Jelikož ve vlaku to moc na létání není (i když scénář, kdy si drona bude umět
otevřít dveře přes červené tlačítko a celý vlak proletět zní jako výzva), tak
jsem si první hodinu napsal jednoduchý simulátor a zbytek času ladil v něm.
Proti simulátorům jsem obecně zaujatý, ale důvodem je spíše jejich „mámení”.
Ono je to pohodlnější než někam muset chodit s robotem, dobíjet baterky a pod.
Ale nesmí to tak skončit — simulátor nikdy není realita, ale může to být
dobrý pomocný nástroj a v některých fázích vývoje je to asi i nejlepší způsob,
jak „odladit znaménka” a nezničit při tom robota.
V simulaci jsem zjistil, že se mi Heidi vyhýbá vpravo, přestože jsem očekával,
že to bude vlevo a to bylo vše. Přidal jsem „simulaci větru”, což je hodně
nadnesené pojmenování pro posun o (dx,dy) v každém kroku, a začal ladit otáčení
na místě. Prostě není to na místě. A stačí i drobný větřík a čtyřtulka je po
360 stupňové otáčce někde úplně jinde.
Druhou úlohu, kterou jsem řešil, bylo vyhodnocení sonarového skenu. Hledal jsem
největší mezeru a tím směrem vyrazil.
7. července 2013 — Přistání z výšky 4 metrů
Původně jsem chtěl ještě přidat odstaveček o FRE (Field Robot Event), kde Heidi
nastoupila do Freestyle kategorie. Použil jsem tam totiž kód z
RoboOrienteeringu, ale moc zajímavá show to nebyla. Ostatně si to můžete přečíst
v připravovaném článku.
Daleko větší „drama” jsem ale zažil včera a získal tak další zkušenost, o
kterou bych se rád podělil. Chtěl jsem kamarádovi předvést létání čtyřtulky po
zahradě s parametry:
dirDist = ((0,1), (math.radians(90), 2), (math.radians(180), 2), (math.radians(-90), 2),)*3
tj. třikrát opakuj let 1m na východ, pak 2m na sever, pak 2m na západ a 2m na
jih. Nejprve jsem létal v hladině 1.5m, pak 2.5m a když to fungovalo, tak jsem
tam dal 4m. Naštěstí jsem rovnou nezkoušel 10m, i když jsem měl cukání.
Heidi udělala 3 kolečka a pak nic. Visela nad autem, že jsem si chvíli myslel,
že vypadla wifina. Nic takového. Pomalu se posouvala ve výšce cca 4m směrem nad
potok a na emergency tlačítko nereagovala! Vlastně je dobře, že u potoka máme
vrby, zamotala se do větví a prásk, „standardní” akrobatické přistání.
Nedalo mi to a pokus jsem zopakoval, akorát o trošku dál od potoka. A znova to
samé — drona visela ve 4m a jako by provokovala „chyťte si mne”. V této
výšce ale trik s převrácením na záda bez žebříku nedáte … a tak jsem byl rád,
když z ničehož nic spadla těsně vedle vrbového domečku.
Mám teď teorii, že drona nereaguje na příkaz automatického přistání, pokud je
výšce větší než X, kde X jsou možná ty čtyři metry. Je tedy třeba buď předělat
emergency na přechod na manuální řízení, nebo nejprve klesat do cca 2m …
11. července 2013 — control.altitude_max
Na fóru měl Vince
dobrou poznámku, že můj problém může být svázaný s nastavením maximální
povolené výšky. Defaultně je control.altitude_max nastaven na 3m a mně
drona odmítala přistát v 3.376m a 3.185m.
Včera jsem to zkusil změnit na 5m (tedy nastavuje se to v milimetrech — 5000)
a Heidi začala létat „strašně vysoko”, ale přistání fungovalo. Většinou. Byl
tam jeden výpadek spojení zrovna když byla hodně nakloněna vlevo. Vypadlo to za
sebou hned několikrát a náraz. Trošku mi to připomnělo Rychnov, kdy v jednom
okamžiku „zdrhla”. Změnil jsem tedy timeout na navdata (z testovací 1s na
0.1s) a to vypadá lépe, zatím.
Přidal jsem i jednoduché ovládání z klávesnice, ale test selhání přistání při
autonomním letu s nízko nastavenou maximální povolenou výškou jsem ještě
nedělal.
Ještě jedna dobrá zpráva na závěr: přišel mi mail od českého distributora
Parrot profitec.cz, že už dorazily GPS moduly a
větší baterky pro AR.Drone 2.0. Bohužel to není úplně levná sranda, ale
uvidíme. Mají jen pár kusů, takže pokud si to zvažujete pořídit v ČR, tak
neváhejte a zboží si rezervujte.
15. července 2013 — video odkazy
V pátek jsem dostal tři zajímavé odkazy, o které bych se rád podělil. První je
o čtyřtulce, resp. čtyřech vrtulích a řídicí elektronice, které se přidělají
„na cokoliv” a dá se s tím létat. Autor to předvádí na klávesnici, knize i
dětském prkně. Nechápu, jak se to popere s vyrovnáním váhy, ale nějak asi ano
… http://www.rozhlas.cz/leonardo/technologie/_zprava/1234092.
Druhý link je droně, zde rozuměj bezpilotní letadlo, které automaticky přistálo
na letadlové lodi a byl tak dosažen další milník ve vojenské robotice:
http://www.ibtimes.com/first-drone-lands-aircraft-carrier-salty-dog-pushes-limits-unmanned-aircraft-video-1342827
Třetí link je o čtyřtulce poháněné lidskou silou:
https://www.youtube.com/watch?v=syJq10EQkog. Padla tak Sikorsky Prize
(Human Powered Helicopter, $250000). Případne viz
Sky
News. Pro získání ceny se vrtulník musel po dobu jedné minuty udržet ve výšce
alespoň třech metrů …
16. července 2013 — nové hračky
Včera jsem si u českého
distributora Parrotu koupil dvě nové hračky: GPS/Flash Disk modul a 1500mAh
baterku. Tímto bych asi RoboOrienteeringový blog uzavřel — je to senzor,
který jsem potřeboval na začátku, před několika měsíci. Ani integrace nebude
zase triviální: potřebuji firmware 2.4.x (na fórech jsem viděl nejvyšší číslo
zatím 2.4.5) a to je ke stažení pouze přes iPhone. Pro Android to má být k
dispozici někdy v září a tak dlouho asi čekat nevydržím.
GPS modul — první dojem je, že je hrozně těžký! Samozřejmě přeháním, stejně
jako po pár měsících létání cítím každý vánek, tak váhu na droně rozlišuji v
gramech. Papírově má vážit 31g, reálně, když už ,,vyvíjím v kuchyni a je tu ta
micro-váha, 36g. Jen pro srovnání GPS GNS 5860 s TMC, co mám půjčenou z práce,
stojí zhruba polovičku a váží 16g. Co tam mají tak těžkého?? Proto asi ta velká
DO NOT OPEN, kterému možná ani já neodolám .
Zkusil jsem modul v notebooku — windows hlásili: „Obecný rozbočovač, disk,
...” a pak to chtělo drivery, které nemám. Jako disk to ale funguje a ve
složce Windows Parrot GPS drivers snad bude to co potřebuji. Install
failed, no nic. EXE tedy moc nepomohlo, ale s výběrem adresáře se zdají být
Windows spokojené a driver je tedy nainstalovaný.
Po připojení na dronu to vypadá takto:
# lsusb Bus 001 Device 004: ID 19cf:3000 Bus 001 Device 003: ID 0424:4050 Standard Microsystems Corp. Bus 001 Device 002: ID 0424:2640 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002
Moc z toho nevykoukám, jen že je tam více zařízení. Co mne potěšilo bylo, že po
připojení sonaru (i když fyzicky to vypadá strašně nepoužitelně) jsem dostal:
# lsusb Bus 001 Device 005: ID 04d8:ffee Microchip Technology, Inc. Bus 001 Device 004: ID 19cf:3000 Bus 001 Device 003: ID 0424:4050 Standard Microsystems Corp. Bus 001 Device 002: ID 0424:2640 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002
Tj. zatím hodně teoreticky bych mohl používat současně jak sonar, tak GPS a
nahrávat video na USB … ale to až někdy v nějakém jiném vlákně/blogu …
22. července 2013 — THE END
Dnes tedy už definitivní konec, s tím, že už vím, kde bude pokračování.
Vymyslel jsem si téma „trošku více prozkoumat video codec H.264”, kdy z
hrubých dat od AR.Drone 2.0 možná jde i něco vypozorovat o okolí. Uvidíme.
Pokud by vás to zajímalo, tak zde začíná III.
létající blog.
Sem bych ještě doplnil informaci o firmware 2.4.1, který lze buď stáhnout
přímo na iPhone, nebo volně leží na stránkách
digitalsirup.com.
Získal jsem firmware z obou zdrojů a výsledky jsou identické. Jenom jsem
dronu ještěý neflashnul, takže nové navdata s tagem číslo 27 (GPS, zatím
nezdokumentováno, první hack je na
paparazzi
webu) ještě nemám. Zatím není dostupné nové SDK a podle
fóra je těch změn
asi více, protože přestala např. fungovat
ROS ardrone_autonomy.
Předpokládám nějaké nové stavy jako „čekám na GPS” a to může se stavovým
automatem zamávat …
Tak díky za podporu a na viděnou na III.
létajícím blogu.