czech english

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:
  1. převeď GPS souřadnice do roviny a spočítej úhly a vzdálenosti
  2. 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)
  3. pulzně udržuj rychlost 1m/s (pokud je vyšší nastav úhel 0 jinak „20% výkon”)
  4. 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
  5. jinak pokud je překážka blíže jak 2m, posuň osu koridoru na další 4m letu o 1m vlevo
  6. během přechodu 0.5s ignoruj další překážky (aby nenasbíral nesmyslný offset ještě z původní překážky)
  7. 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:

Fandorama



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.
Nevím jak vás, ale mne tento výsledek:
rozhodně potěšil .

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
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
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
... 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
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.
------------ THE END ------------