czech english

SICK Robot Day 2014

fandorama blog a reportáž

Letos se již počtvrté koná soutěž „SICK Robot Day”. Vždy čtyři autonomní roboti se budou předhánět v expedici balíčků na místo určení. Vedle vzájemného vyhýbání se, budou muset roboti umět číst čárový kód a rozpoznávat čísla označující cílová místa. Blog update: 22/10 — Závěr


Pokud máte zájem, aby na tomto místě vznikala reportáž z přípravy Eduro Teamu a reportáž z následné soutěže, tak podpořte tento projekt. Výsledná částka pokryje cca desetinu nákladů na cestu Praha-Waldkirch.
P.S. chystáte-li se s vaším robotem soutěžit, tak se nám ozvěte a můžeme zkusit společné testování

Odkazy:

Obsah:



Blog

11. září 2014 — Měsíc do soutěže

Nejprve díky prvnímu fandorama stoupenci za podporu — opravdu se to sepisuje o řád lépe s myšlenkou, že existuje alespoň jeden člověk, kterého by to zajímalo . Do soutěže zbývá přesně měsíc a průběžná „dokumentace” se už mnohdy ukázala jako velmi přínosná …
Jak jsme na tom? Začal bych obrázekem z Edura:
Standa udělal jeden vzorek ve správné velikosti (font Ariel, papír A1). Z tohoto pohledu to vypadá krásně, ale … viděli jsme to už před čtyřmi lety ve velké sportovní hale, kde to bylo o mnoho horší. Na ten čtyři roky starý kód přesto navazujeme a pokud by vás zajímaly detaily, tak viz github:
Konkrétně se jedná o sickday2014.py a pro rozpoznávání čísel c/digits/mainDigits.cpp.
Zatímco v roce 2010 roboti hledali postupně čísla 123456789 resp. 876543210, letos musí být schopní vozit kostičky, přečíst na nich čárový kód a doručit je ke správnému cílovému místu. Správné doručení +1 bod, špatné -1 … tj. detekce musí fungovat alespoň na 90% aby robot dodávkou neztrácel .
Minulý týden jsme zkoušeli 1D čtečku čárových kódů a výsledky nebyly moc povzbudivé. Tento týden pak Jakub zkoušel kamerku na RaspberryPi s balíčkem python-bar a zatím to vypadá nadějně.
Momentálně se rozhodujeme mezi dvěma variantami a to, zda bude „nákladový prostor” vzadu na třetím kolečku Edura nebo vpředu, před kamerou. Jako korbu jsme použili plastový lavor s horním průměrem 32cm. Nejmenovaný člen týmu na něm zkoušel „nakládku” (podle pravidel organizátoři budou kostky vhazovat z výšky 1m) a ta nebohá nádoba vydržela myslím právě dva pokusy … no nic, lepicí páska a polstrování to teď jistí … ale do kuchyně budu muset pořídit jiný.

16. září 2014 — Zielscheibe

Jedním z úkolů nutných pro správnou nakládku a vykládku je rozpoznání navigačního terče. Předloha je k dispozici ke stažení. Jak terč vidí robot lze nahlédnout ze snímku z minula. Zde je pak ideální varianta:
Jak ho spolehlivě rozpoznat? Pokud je robot blízko a jsou výrazné jednotlivé kruhy (tj. alespoň dva pixely), tak lze používat kontury. Ty se mi hodí, protože je zároveň používáme pro rozpoznávání a klasifikaci čísel. Terč je tedy objekt, který obsahuje 12 „podobjektů”. Občas se dva oddíly nechtěně spojí, takže prozatímní filtr je 10 až 12 objektů.
Asi vás nepřekvapí, že se tím špatně detekuje i mnoho jiných objektů. Kontury se hledají v černobílém obrázku, který vzniká prahováním šedotónového. Pro SICK Robot Day 2010 byly používány tři prahy a bylo na Eduru si vybrat nebo spíše všechny výsledky spojit, aby našlo alespoň něco. Do stejného (Céčkového) kódu jsem přidal i funkci isItTarget(), která v případě úspěchu vrací 'X' a ohraničující obdélník. Obdélník byl vhodný pro čísla, ale na terč moc ideální není — přeci jenom tenké linie vlevo a vpravo se trošku rozpadají a lepší by bylo matchování kružnice.
První restrikce je zatím na součet obsahů vnitřních podobjektů. Cílem je odfiltrovat oblasti, kdy prahováním dostanu jenom 10 teček. Zatím mi to vychází zhruba na 2.5x … ostatně viz diff.
V dalším kroku mohu ověřovat podíly (vždy 4 podobjekty by měly být zhruba stejně veliké) nebo tu kruhovost. Máte-li nějaké tipy, tak beru . A kdyby jste dokázali rozpoznat cíl z větší vzdálenosti, kdy černé čáry pořádně nemají ani celý pixel, tak to beru určitě!

24. září 2014 — Barcode

Poslední týden jsem na fontě „SICK Robot Day” vůbec nic neudělal (čas a energie byla třeba na Robotour), ale ostatní ano. Jakub připravil RaspberryPi na automatický start a ruční shuthown, Standa připravil uchycení lavoru a nové čtečky a Tomáš sehnal na E-Bay novou všesměrovou čtečku Symbol Miniscan MS-3207 cca za 1000Kč i s dopravou. Čtečka se chová jako klávesnice, ale lze jí nakonfigurovat i jinak. Na Windows mi tedy začala psát do notepadu (i klidně kamkoliv jinam, kde bych to nechtěl) a na Eduro routeru byla dostupná jako vstupní zařízení. Pro mne to byla novinka, tak to zde trošku rozepíšu.
Čtečka je napájená přes USB. Po připojení se v systému objeví jako /dev/input/event0 a budete-li z tohoto zařízení číst, dostanete něco jako:
EE B2 21 54 D9 11 08 00 04 00 04 00 20 00 07 00
EE B2 21 54 E9 11 08 00 01 00 04 00 01 00 00 00
EE B2 21 54 F1 11 08 00 00 00 00 00 00 00 00 00
EE B2 21 54 0C 31 08 00 04 00 04 00 20 00 07 00
EE B2 21 54 17 31 08 00 01 00 04 00 00 00 00 00
EE B2 21 54 1C 31 08 00 00 00 00 00 00 00 00 00
EE B2 21 54 3C 44 0A 00 04 00 04 00 26 00 07 00
EE B2 21 54 48 44 0A 00 01 00 0A 00 01 00 00 00
EE B2 21 54 50 44 0A 00 00 00 00 00 00 00 00 00
EE B2 21 54 79 63 0A 00 04 00 04 00 26 00 07 00
Už při prvním pohledu je jasné, že se jedná o nějaké 16-bajtové bloky. Dobrá nápověda je článek Tutorial: Implementing a Device Plug-in a hlavně zde popisovaná struktura:
struct ExampleInput {
        unsigned int   dummy1;
        unsigned int   dummy2;
        unsigned short type;
        unsigned short code;
        unsigned int   value;
    };
dummy1 a ""dummy2" jsou asi časové známky, které nás teď netrápí. Důležitý je typ události (klávesnice), co se stalo (stisk, uvolnění, automatické opakování) a hodnota klávesy. Jsou na to vhodné enumy, které najdete třeba zde. EV_KEY je tedy 1 a KEY_1KEY_0 jsou hodnoty 2 až 11. Nula je tedy největší číslo, na klávesnici úplně vpravo. V kódu jsem převod na čísla ošidil pomocí minus 1 modulo 10.
Implementace probíhala klasicky: nejprve jsme si uložili soubor čtený z /dev/input/event0 (stejně tak můžete mít asi více čteček/klávesnic a rozlišit je např. podle /dev/input/by-path/pci-0000\:00\:0f.4-usb-0\:1\:1.0-event-kbd nebo /dev/input/by-id/usb- _Symbol_Technologies__Inc__2002_Symbol_Bar_Code_Scanner_ S.N\:6F36B0DE37628145B03BCEBE33D1596A_Rev\:NBRLPAAH3-event-kbd), ale event0 mi přišlo kratší a tak u toho i zůstaneme.
V druhé fázi jsme čtení a pochopení odladili z tohoto krátkého souboru a nakonec přidali vlákno, aby Eduro mohlo vesele dělat i jiné věci. Výsledný kód je pak na githubu.
Robot teď čeká na vhozenou kostku s čárovým kódem a po vhození se rozjede. Zatím vždy dozadu — asi překážejí kabely nebo se bere i spodní laser v úvahu. Je třeba projít včerejší logy…

25. září 2014 — Fandorama

Cestou do práce jsem přemýšlel, co si počnu s tímto rozepsaným blogem, pokud to už nikoho dalšího nebude zajímat. A po stažení mailů se to vyřešilo samo . Díky dalším dvěma fandorama stoupencům.
Zkoumám teď rozpoznávání navigačního terče. Data mám z 140916-1810 a zde je malá situační mapka z laserových skenů:
Mapka
Mapka
Je na ní vidět, že hlavní laser tou dobou byl ještě šikmo dolu a viděl podlahu cca v 1.5m. Jednotlivé čtverce jsou 1m2 a robot jel rovně. Šikmo vpravo je pak cedule s číslem a navigačním cílem (ve skutečné aréně nebude takto vystouplá). Robot tedy začínal cca 3m od cíle. Přehráváním logů vychází snímky 006 na dva metry a 010 na jeden metr. JPG jsou nezměněné, tj. OpenCV vám bude hlásit něco jako Corrupt JPEG data: 12 extraneous bytes before marker 0xd9 … prastarý problém s firmware kamery.
Toto jsou reálná data, co Eduro zpracovává. Musím uznat, že má Tomáš pravdu — při tomto rozlišení a nastavené kvalitě ukládání JPG obrázků není vidět skoro nic. Zde je pak detail výřezů:
Pro jeden metr by možná algoritmus s konturami fungoval (v mezikruží jsou cca 3 bílé pixely), ale pro dva metry už ne a ze třech je to spíše šeď.
Mimochodem dnes je na matfyzu přednáška Jiřího Matase: Detekce a lokalizace objektů v obrázcích, kdyby to někoho zajímalo … tématicky to zapadá .
Co s tím terčem? Předpokládejme, že vím jak jsem daleko a umím odhadnout jak velký by ten terč měl být v obrázku. Ze dvou metrů tedy hledám něco co vypadá jako 2D kód. Zkuste si sami threshold.py na ten kombinovaný obrázek. Např pro 172 dostanete:
Hledám tedy místo dané velikosti s hodně přechody.

26. září 2014 — Diversity

Včera večer jsem si chtěl zkusit to „velké množství hran na malou plochu”. Diversity asi není vhodný název, ale nějak jsem ten skriptík nazvat musel. Jelikož jsem v záplavě hranových detektorů (možná špatný link) narychlo nenašel co hledám, tak jsem si napsal brute force smyčku rovnou v Pythonu:
gray = cv2.cvtColor( img, cv2.COLOR_BGR2GRAY )
for i in xrange(512):
    for j in xrange(639):
        gray[i][j] = abs(gray[i][j] - gray[i][j+1])
Co myslíte, je to správně? No když se tak hloupě ptám, tak asi není. Toto byl výsledek:
V Pythonu se moc limity čísel netrápím, ale pozor, toto není čistý Python. Počítám v obrázku a odečítám dva unsigned char, výsledkem je unsigned char a jeho absolutní hodnota je tím pádem nezajímavá. Sigh. ale hned mi to nedošlo a ani varování od numpy mne večer netrklo: RuntimeWarning: overflow encountered in ubyte_s calars gray[i][j] = abs(gray[i][j] - gray[i][j+1]).
Teď je ten kód ještě trapnější, ale výstup už splňuje moje očekávání:
gray = cv2.cvtColor( img, cv2.COLOR_BGR2GRAY )
for i in xrange(512):
    for j in xrange(639):
        if gray[i][j] > gray[i][j+1]:
            gray[i][j] = gray[i][j] - gray[i][j+1]
        else:
            gray[i][j] = gray[i][j+1] - gray[i][j]
V počítačovém vidění je takový trik, že pokud chcete zjistit součet hodnot v daném výřezu, tak si nejprve vytvoříte Integral Image, což jsou de-facto součty jednotlivých pixelů ve směru vlevo a nahoru, a pak z hodnot v rozích požadovaného výřezu získáte hledaný součet v konstantním čase:
val = arr[i][j] + arr[i+H][j+W] - arr[i+H][j] - arr[i][j+W]
No zase tam budu mít nějakou chybu (další přetečení, kde se mi přenášel typ už jsem snad opravil), protože tento výsledek moc věrohodně nevypadá
(3406949942385949847274259724506409373226123066229344382388103611282506975322955
14175991374187982251080846555638663756982547895676770462859858759227679915633583
72284551589070057859281928315999379788390385324504567830310761192572935951313165
27290512633076378415710252333358154627935741845642888855717359032341506025086466
711802432L, (501, 629))
… ale je vidět, že Python s velkými čísly problém nemá. Tak jo, když se vyhnu exponenciálnímu růstu a součty udělám ve dvou for-cyklech, tak už výsledek vypadá rozumněji:
(8114, (202, 599))
A výsledek pro zvětšené okno na 20x20:
„Tak tudy ne pánové!” … ale uvidíme. Zde je použité diversity.py.

29. září 2014 — 4-8-černo-bílý svět

Už mne ta detekce navigačního terče dost štve. Vzal jsem si k srdci Jirkův komentář Kde nic není, ani smrt nebere. a šel na to z druhé strany, tj. hledal situaci, kdy detekce selhala nejblíže cíle. Bylo to na tomto poměrně velikém obrázku:
Detail pořádně nevidím, tak jsem si výřez (po prahování) několikrát zvětšil v malování a dostal:
zvětšený cíl po prahování hodnotou 100
zvětšený cíl po prahování hodnotou 100
A teď kontrolní otázka: „kolik tam vidíte kontur?”
No je tam zrada, jak jinak — záleží na tom, jestli se používá 4 nebo 8 sousednost.
vyteklá kontura
vyteklá kontura
Napsal jsem si i test bokem a dobrá zpráva byla, že to tam také nefungovalo . Tak jak je to v tom OpenCV sakra implementované?? Přes dokumentaci jsem se dostal k Stack Overflow, kde je link na článek z roku 1983 … It is well known that in order to avoid a topological contradiction 0-pixels must be regarded as 8- (4-) connected if 1-pixels are dealt with as 4- (8-) connected. Tak už je to známé i mně, i když kterou z těch dvou variant si v OpenCV vybrali nevím (a teď už to ani nechci vědět). Bezpečnější varianta je totiž tu černou trošku nafouknout. A tím se dostávám k matematické morfologii.
No a je tam zase další zrada — eroze ubírá, že jo? Ale čeho? Je objekt černý nebo bílý? Prostě je lepší ignorovat barvy a pamatovat si, že erode() bere minimum a dilate() maximum. Černá je 0, tj. použitím erode nafouknu černou a pak už se snad nemusím trápit 4- nebo 8- sousedností…

1. říjen 2014 — Verze 0?

Soutěž „SICK Robot Day 2014” je už příští víkend a myslíte, že už máme funkční verzí 0? Asi raději nebudu vypovídat bez přítomnosti svého advokáta
Dobře, takže nemáme ver0. Jaký je stav? Snad se blížíme k HW-freeze. Cože?! Vy ještě nemáte ani uzavřený hardware?! No jo no … vždyť to jsou jenom dva nejdůležitější předpoklady úspěchu. Ale pracuje se na obou frontách. Snad ve čtvrtek.
Teď se objevuje spousta drobností — pamatujete, jak Eduro minule po vhození kostky vždy couvalo a já podezříval vyčnívající kabely? Opak je pravdou. Hlavní laser je nyní vodorovně a v hale bylo dost místa, takže v některých směrech by naměřil i více jak 10 metrů. Pokud se paprsek nevrátí, je v datech 0 (int číslo v milimetrech). Když z toho uděláte minimum dostanete tuto nulu a jelikož „je to moc blízko překážky”, tak robot začne couvat.
Další chyba, na kterou mi to včera padalo snad 3x byl špatný předpoklad, že číslo je int. V roce 2010 byl na vstupu string 123456789 nebo 876543210 a zůstal po tom guláš. Vadí to konkrétně při zobrazování na display, kde je třeba zadávat dvojznakový string a součet string+int Python nemá moc rád.
Pokusy na volném prostranství byly celkem srandovní, nebereme-li v úvahu blížící se termín soutěže. O středovém „podavačském ostrůvku” není skoro nic známo (Detlef mi na to téma psal: Yes, we will build some kind of an island. We don't tell anything about the exact dimensions and the material this will be built from, simply because we don't know that by ourselves at the time given.), jenom že bude uprostřed volné plochy a budou tam ze čtyř stran terče s obručemi. Ver0 jede rovně (předpokládá, že nasměruji robota co nejpřesněji), v úhlu 90 stupňů vpředu hledá minimum a jakmile klesne vzdálenost k nejbližší překážce pod dva metry, tak přejde na approachFeeder(), který by měl hledat navigační cíl.
V reálu to vypadalo tak, že robot 2m od ostrůvku zastavil (asi očekávané chovaní, mám tam myslím stop), popojel a pak to strhnul typicky vpravo :-(. Proč to dělal musím zjistit z logů.
K registrovaným HW problémům zatím vybublává na povrch reset motorů (tipuji, že není dostatečně rychlá řídící smyčka a reset způsobí watchdog) a na konzoli jsem postřehl výpadek USB laseru:
Laser 6
Laser 7
Laser 8
Laser 9
Exception in thread Thread-7:
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
    self.run()
  File "/home/robot/python/laser.py", line 58, in run
    self._scanData, self._remissionData = self.internalScan()
  File "/home/robot/python/laser.py", line 111, in internalScan
    data = self.sendCmd( 'sRN LMDscandata' ).split()
AttributeError: 'NoneType' object has no attribute 'split'
Měli bychom teď být ve fázi intenzivního testování, kde budou podobné věci postupně vylézat, ale ani letos v této fázi nejsme.
Co jinak? Zkoušeli jsme vyšší rozlišení kamery. Acronet Vision mají jednotné API pro všechny své IP kamery a tak místo http://192.168.0.99/img.jpg můžete napsat něco složitějšího: http://192.168.0.99/image?res=full&x0=0&y0=0&x1=1600&y1=1200&quality=12&doublescan=0. V jednom (sedmém) testu jsem pokusně sbíral data 1600x1200 (místo 640x512) a první pozorování je, že jsou opravdu větší (cca 100kB místo 40kB na obrázek), ale zároveň to bude zdroj dalších komplikací. Kamera teď říká, kde v obrázku našla terč/číslo, ale ne jak je obrázek velký a jaký offset se použil. Stejně tak v hledání mám přednastavené nějaké ROI (Region Of Interest), takže pokud to trošku fungovalo, tak hledal terč jenom v jednom (špatném) kvadrantu … další věc k průzkumu a revizi.
Je to ještě trošku jinak — výsledný obrázek má rozlišení 1280x1024 (to bude asi ten parametr res=full) - je třeba nastudovat ten doc.
Standa včera udělal úchyt na RaspberryPi i s kamerou. Dohodli jsme se, že budeme slepě věřit všesměrové čtečce čárových kódů a RasPi kameru jsme nasměrovali raději dopředu. Ještě jsme zvažovali pohled bokem, ale to by z nás Standa už vyrostl. Stačí dodělat napájení (5V se na Eduru vypína STOP tlačítkem, takže nový oddělený regulátor), připojit Ethernet (poslední zdířka, kterou jinak používám na notebook), napsat komunikaci, zapojit do kódu Edura, pár měsíců testovat a je to . Omlouvám se za jedovaté komentáře … ale na druhou stranu kdy, když ne teď? Hned tak nás něco motivovat k dalším krokům nebude. Znamená to tedy, že štěstí letos budeme potřebovat ale opravdu hodně …

2. říjen 2014 — Falešné cíle

Člověk/robot se může pohybovat celkem rychle, ale když si zvolí špatný cíl, je to pak celé úplně k ničemu. Krásně je to vidět na prvním testu na volném prostranství:
Co Eduro tak vyvedlo z míry, že cca dva metry před cílem to strhlo vlevo? Víte jak se teď rozpoznává cíl? Viz mainDigits.cpp:285-288 — prostě se jen ověří, že rodič má právě 12 dětí a pokud sám nemá příliš velkou plochu, tak je to to ono. Přiznám se, že tuto postupnou aproximaci preferuji, on se protipříklad najde sám. A našel:
Teď bych upravil i tu jedinou omezovací podmínku na velikost plochy. Jsou pro to dvě motivace:
  • plánuji jezdit s vyšším rozlišením
  • chci aby to bylo odolné i proti rušivým vlivům z okolí (v úterý měl jiný terč přilepený na skříni a hlavní světlo házelo výrazný stín na podstavec)
Co bych rád zkusil je utřídění velikosti „dvanácti měsíčků”, rozdělení do tří skupin a vypsal. Co dostanu pro ten falešný cíl?
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5, 0.0, 9.0, 0.5]
To nevypadá dobře :-(. A výsledek je stejný když použiji moment 00 nebo přímo funkci contourArea. Proč ty nuly? Protože je to: the returned area and the number of non-zero pixels (doc). Divný,to by se muselo odkazovat na konkrétní obrázek??
Ale ono je to možná správně. Ten výsledek byl pro zmiňovaný špatný cíl. Pokud na vstupu je pěkně detekovaný terč, tak to vypadá o řád lépe
[16.5, 45.5, 17.0, 21.5, 41.0, 16.5, 16.5, 19.0, 18.0, 17.5, 44.0, 44.5]
přidám jeden sorted() a naznačím skupinky:
[16.5, 16.5, 16.5, 17.0,   17.5, 18.0, 19.0, 21.5,   41.0, 44.0, 44.5, 45.5]
Asi jste pochopili, že si zase hraji v Pythonu. Je to pohodlnější. Ten mezivýsledek najdete v gitu.
Co dál? Koukám na „skříňové pokusy se stínem” nám to nepomůže. Stín to vše svazuje dohromady a tak se do terče namíchají i další pod-kontury. Tak jiné, funkční, vzorky:
[21.0, 21.5, 22.5, 22.5,   24.0, 25.0, 26.5, 30.5,   51.0, 53.0, 65.0, 71.0]
[39.0, 39.5, 42.0, 46.0,   46.5, 49.0, 58.5, 68.0,   89.0, 99.0, 128.0, 137.5]
[32.5, 33.5, 37.5, 40.0,   41.5, 41.5, 52.5, 55.5,   75.0, 84.0, 117.0, 124.0]
[44.5, 50.0, 55.5, 59.0,   59.5, 61.5, 82.5, 83.5,   109.0, 125.5, 158.0, 174.5]
… druhý a třetí řádek je stejný snímek ale s jiným prahováním.
Tak co v těch číslech vidíte? Rozdíl mezi první a druhou skupinou mi nepřijde dost přesvědčivý a jsou možná dokonce promíchané. Asi nutné ověřit.
Nevím jak vám, ale mně se výsledek líbí . Už slyším ty skeptiky: „a co ostatní obrázky?” Když vy mne nenecháte se ani chvíli radovat …
No nic, trošku humpolácké změny na barevné vyplňování najdete zde.
A jé je … další:
[11.5, 17.0, 23.0, 23.5,   24.0, 32.5, 32.5, 36.5,   36.5, 68.5, 75.0, 90.0]
Asi je pomalu čas na snídani … a neměl bych zapomínat, že to musí skončit „produkčním kódem”, jinak nebude večer co testovat [v testovací frontě je už napájecí kabel na RasPi, výřez 640x512 ve vyšším rozlišení a ???)].

3. říjen 2014 — Změna rozlišení

Včera to vůbec nefungovalo: robot jel jakž takž na cíl, ale těsně u něj to strhnul vpravo. Opakovaně. Říkal jsem si, že to budou zase chybné detekce (nevím, zda jste viděli ten produkční kód … nic jsem včera nevymyslel, tak jsem tam dal co nejslabší podmínku, aby nejmenší z „dvanácti měsíčků” byl větší než 0). Ale tím to nebylo.
Vezmu to pěkně popořádku. Nejprve jsem změnil kód na stahování výřezu. Ověřil jsem, že obrázky mají opravdu slibovaných 640x512 a že by tedy neměl být problém s ROI a pod, co jsem zmiňoval minule. To bylo v pořádku.
Co ale nebylo správně, byla samotná detekce terče. Cca z 1m ho robot viděl, ale blíž už ne. Toto byl celkem jednoduchý fix a řekl bych „očekávané chování”. Rozlišení mám teď 2x vyšší, jak se změní minimální velikost detekovaného terče? 4x, tj. místo absolutního limitu 4000 by to tam chtělo 16000 pixelů (dal jsem 15000), ale to už mi moc jako omezující podmínka nepřijde … proto jsem si myslel, že je to nějakým duchem.
V dalším kroku jsme zapojili spojku a kabel na RasPi od Tomáše. Ujasnili jsme si po telefonu, že každý myslíme jinou levou stranu Edura, ale napěťový měnič a volné sloty na liště byly celkem jednoznačné. Fakt se takových zásahů bojím, ale Tomáš je důkladný a ťuk, ťuk, ťuk zatím vše vypadá OK.
RasPi naběhlo i se zamáčknutým STOP tlačítkem (na to ta spojka, předpokládám přežitek z Eurobota, kdy nesměla být napájena ani serva 5V), Jakub udělal pár snímků a šli jsme testovat na chodbu. Tam se Eduro odmítalo chovat slušně, ale RasPi za to nemůže. Udělali jsme asi jenom 2-3 pokusné jízdy, protože baterka už byla dost vybitá. To byl ale částečně důsledek úterního testování a ne nutně nového „žrouta”.
Doma jsem se zběžně podíval do logů, abych mohl klidně spát. Zatím žádného ducha jsem neviděl (ale nevylučuji, že tam přeci jenom někdy byl). Jeden ze zakopaných psů je v metodě approachFeeder():
for digit, (x,y,dx,dy) in a:
    if digit == 'X':
        angularSpeed = (320-(x+dx/2))/100.0
… prostě jsem regulaci odflákl, jak je mým zvykem, a při dvojnásobném rozlišení se to rozkmitalo natolik, že v posledním kmitu už robot ztratil cíl ze zorného pole. Pro představu požadované hodnoty ve stupních za sekundu byly:
-29.2208475517 logs/cam141002_185204_005.jpg
-48.128454791 logs/cam141002_185205_006.jpg
44.6907080202 logs/cam141002_185206_007.jpg
Hmm, ale stejně je to divné. V 008 snímku už terč nevidí, ale to nejspíš ještě reagoval na -48 (zatočení vpravo) a se zpožděnými snímky a nenulovou reakční dobou bylo vymalováno. Jakmile se robot natočil už příliš stranou, tak selhal přibližovací úhel a vydal se na cesty …
Je to potřeba udělat pořádně. Líbilo by se mi řešení jako u Heidi, kdy chvilkově můžu věřit odometrii a když mám přesné časové známky u obrázků, tak si z krátké historie pozic mohu dopočítat i historickou pozici cíle (v absolutních souřadnicích) a na něj se do dalšího snímku navigovat. Chtělo by to samozřejmě zkalibrovat kameru, aby ty odvozené úhly z obrázku byly reálné nebo alespoň přibližně reálné.
p.s. detekci terče z větší dálky zatím vyšší rozlišení nepomohlo … možná zvýšit kvalitu JPEGu? Nevím. Zůstává na TODO listu.
p.s.2 ještě jsem nezmínil poznámku od PavlaS (fandorama stoupenci tohoto článku jsou AlešH, MartinL a PavelS), jestli na detekci terče nepoužít Hough Circle Transform … celkem bych byl zvědavý na výsledky.
p.s.3 neodolal jsem a musel jsem to vyzkoušet — viz github … tak nakonec nějaké obrázky tedy budou i dnes:

4. říjen 2014 — Dva cíle?

Porušil jsem svoji interní dohodu a hraji si s počítačem i v sobotu. Ale přes den jsem se věnoval zahradě, tak snad … no neukecám to .
Včera jsem si trošku hrál s tou absolutní pozicí cíle a zatím se mi to moc nelíbí. Ona totiž ta absolutní poloha nějak moc skáče. Říkal jsem si, že je to možná tím, že střed určuji podle bounding boxu vnější kontury a ono při bočním pohledu to vypadá hodně nesymetricky.
Co teď zkouším je utřídění pod-kontur a vybrat střed těch nejmenších. To by snad mohlo být stabilnější. Co zatím vypadá rozumně, na rozdíl od ploch jednotlivých pod-kontur, je velikost bounding boxu, ale těch malých kontur. Viz diff (URL generováno off-line, tj. naslepo).
Přehrával jsem si logy a už jsem konečně viděl ducha, dokonce dvoj-ducha .
Což tedy dává pěkný test na TODO list — pokus se dvěma terči vedle sebe. Ono totiž přesně ta situace může u středového ostrůvku nastat a skákat z jednoho cíle na druhý by nebylo dobré …
185 [186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197] 12
73 [74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85] 12
Center (135, 63) area 3340.5
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 2.5, 2.5, 5.5]
[(1, 186), (1, 188), (1, 192), (1, 194), (1, 196), (2, 191), (2, 195), (3, 193),
 (6, 197), (8, 187), (15, 190), (16, 189)]
Center (534, 295) area 2248.5
[14.0, 14.0, 14.0, 31.0, 34.0, 35.0, 35.0, 41.0, 48.0, 49.5, 69.0, 192.0]
[(25, 75), (25, 76), (25, 80), (60, 81), (60, 85), (63, 79), (64, 82), (66, 83),
 (72, 84), (78, 74), (110, 77), (595, 78)]
Tak ty tečky vlevo nahoře by měly vypadnout kvůli nulové ploše a ten skutečný terč je takový pomíchaný. V ostrém běhu
logs/cam141002_181014_045.jpg	
[((4, (507,123,62,103)),(7, (52,54,14,21)),('X', (507,256,70,75)),),
((4, (506,123,63,103)),(1, (502,95,86,157)),),
((1, (396,139,32,125)),),]
Snímek 45 mi utekl, ale i ten následující nevypadá dobře + ty náhodně generovaná čísla … klid, klid …
Tak nevím, podle logu na snímku 46 žádný cíl nenašel, tak to je asi kontura od špatně detekovaného čísla??
Je tedy nějaký problémový snímek nebo není?
Toto je noční můra … když teď pouštím Céčkový kód pod Win7, tak dostávám na výstupu:
[((4, (507,123,62,103)),(7, (52,54,14,21)),('X', (507,256,70,75)),),
((4, (506,123,63,103)),(1, (502,95,86,157)),(3, (530,281,26,47)),),
((1, (396,139,32,125)),(1, (535,163,55,94)),(6, (500,100,83,147)),),]
Což má k identickému výstupu z Edura sakra daleko :-(. Alespoň 'X' výstup sedí a ten teď řeším. Otagovaný snímek je tak hrozný, že ho pro jednou vynechám.
Pro zlepšení nálady (chvilkové) jsem změnil přehrávání na rychlé, když není detekovaný cíl a na pomalé, když je — viz diff. Přidal jsem ještě limity na velikosti, jinak jsem viděl dost „krvavou” obrazovku.
Možná jsem měl dnešní příspěvek nazvat „Ať žijí duchové!”. Ono když se past lépe nastraží, tak jich začnou vyskakovat hned „desítky” (navíc je nutné vše kontrolovat pro různá prahování):
… a spousty dalších. Asi rovnou udělám i test na vnitřní kruh.
A byl tam ještě jeden splňující předpoklad, že kontura obsahuje právě 12 pod-kontur, kde čtyři největší jsou v krajích, kde však neseděl přísnější předpoklad, že i další čtyři jsou v dalších čtyřech krajích — práh 100:
p.s. přidal jsem i rekurzivní procházení logovaných obrázků … je to pohodlnější
p.s.2 vytvořil jsem i dvě videa s prahováním 60 a 80, ať máte představu na co celý večer koukám … upload ale až doma, tj. zítra večer.

5. říjen 2014 — Čísla (5 dní)

Nejprve slibované video ze včerejška:
Případně ještě jedno (stejné) video, ale s prahování nastaveném na 80.
Je pomalu na čase se podívat na to rozpoznávání čísel. Co si matně pamatuji před čtyřmi lety, tak základ byl rozpoznání obdélníkového rámce, který obsahoval právě jednu pod-konturu (číslo). Tím se úloha zjednodušila na rozlišení různých čísel od sebe … ale chyba lávky. Předpoklad, že rámce budou rozpoznatelné v Německu neplatil (zvlášť s pohledy proti prosklené stěně sportovní haly). Co si ještě trošku pamatuji je, že jsem i zkoušel různé momenty, o kterých jsem se kdysi učil ve škole, ale k rozpoznání mi moc nepomáhaly … tak jak jsem to tedy opravdu dělal? Koukám, že jsem zkoušel i nějaký matching podle vzoru … hmm … ostatně se můžete podívat sami, viz mainDigits.cpp.

Díry

První rozlišovací znak byl/je počet děr (přesněji úplně první test byl na minimální plochu a poměr výšky a šířky detekované kontury).
Pokud jsou 3 díry konec, vyhodit. Pokud 2 díry, tak se zjišťuje jejich obsah (po letošní zkušenosti s terčem bych zvolil raději minimální obdélníky). Zajímá mne podíl většího a menšího vůči vnějšku osmičky … to asi zní rozumně až na to, že i znak pro nekonečno (nebo reklama na „SICK rObOt day”) by byla také detekována jako osmička. Tj. přidal bych, že větší musí být dole a menší musí být v průmětu spodní.
Další „děravá čísla” jsou 4, 6, 9, 0. Zase jsem se rozhodoval na základě poměru obsahu díry a celé vnější kontury. Pokud byla díra malá a šla aproximovat trojúhelníkem, tak výsledek bylo číslo 4. Pokud byla díra velká, tak 0. A rozhodnutí, zda je číslo 6 nebo 9 jsem dělal přes Y-ovou souřadnici. Pobavil mne starý komentář:
// hole has bigger Y (BEWARE OF SWAPPED Y-Coordinates!!!
return 6;
Ok a co zbývající 1,2,3,5,7? Konvexní obal, no nazdar. A co je funkce cvConvexityDefects? Myslím si, že to jsou takové ty zálivy, ale najisto to nevím. Any deviation of the object from convex hull can be considered as convexity defect. OK, viz dokumentace a obrázek s rukou.
V dalším kódu hledám nejhlubší a druhý nejhlubší „defekt” (skoro bych raději použil „záliv”). Dále se tam „čaruje” s „délkou pobřeží” arcLength, velikostí „ústí” entryLength a konečně polohou největší „zátoky”.
if( best.depth > 2 * second.depth && arcLength > 0.4 * length && 
      x < 0 && arcLength > 4* entryLength )
    return 3;
if( best.depth > 8 * second.depth && x < 0 )
    return 1;
if( best.depth < 1.1 * second.depth && best.depth > rect.width/2.0)
    return 2;
if( arcLength > 5.0 * entryLength && y > 0 )
    return 5;
if( best.depth > 5 * second.depth && x < 0 )
    return 7;
return -1;
Hmm, evidentně jsem už tehdy propadal „obyčejnému šílenství” …

7. říjen 2014 — Čtyřka a "sliding window" (zbývají 3 dny)

Dnes nějak nestíhám ani dopisovat poznámky :-( …
Včera jsem zkoušel filtrovat co může a co nemůže být číslo. Vzal jsem „bounding box” kontury a když byla moc malá nebo moc velká nebo moc na kraji, tak ji zahazoval. Mimo jiné jsem si naivně myslel, že když okolo je bílý rám, tak tam musí být nějaká „pixelová mezera”?? Není. Je-li číslo trošku nakloněné deformací čočkou, tak žádný rám … dokonce spíš záporný.
Pak mi došlo, že jak stále jezdím s Edurem okolo té jediné čtyřky, tak z těch dat by mělo jít získat nějakou statistiku. Mne totiž nezajímají všechna čísla (nedej bože provokatérů s čísly na tričkách, nebo kameraman místní televize SamoDomo, kanál 3). Čísla musí být nějak fyzicky veliká, na podstavci dané výšky .. a to by se mělo dát spočítat! (nejlepší by samozřejmě bylo mít pořádně nakalibrovanou kameru, ale pro první představu toto snad postačí)
Proložil jsem to odhadnutou přímkou 0.6*y + 0.8*h - 144.0 s tolerancí 10 (koukám, že v C-čku jsem dal 20) a množství nesmyslných detekcí výrazně poklesl. Použil jsem jenom Y a výšku kontury protože robot muže vidět číslo i ze strany a to se mění hlavně X a šířka.
Ještě jeden graf poměru výšky a šířky detekovaných čtyřek:
Konec pauzy na oběd … testování večer, tj. pokračování zítra.

8. říjen 2014 — Bouračka a čipový smrťák (78 hodin)

Včera to dopadlo úplně jinak, než jsem očekával. Při prvním testu Eduro skončilo otočené úplně mimo obruč a při hledání čtyřky (mimochodem Standa připravil všechna čísla, ale na ty se už nedostalo) se spokojilo s nějakým náhodným stínem. Už alespoň čekalo těch 10 sekund rozsvícené (stále svítíme bíle, třeba „přebarvit na zelenou”).
Důvod byl naštěstí hned vidět z logu, kde terč ostře vlevo byl v „šachovnicovém prohlížeči” vpravo. Fixed. Horší to bylo s detekcí terče. Fakticky ho rozpoznal až 50cm od desky a to je sakra pozdě. Chodba byla tak tmavá, že tentokrát by paradoxně pomohlo erode() vypnout, ale pomohl bych si pouze o jeden snímek.
Další byla ta falešná čtyřka:
Musím tam dodat nějakou verifikaci, aby výsledek několikrát potvrdil, než se k němu definitivně upne.
Při vhození kostky jí čtečka správně nezaregistrovala. Snažil se klepat, s novým drsným povrchem to ale moc nešlo, a když pípla, tak se robot ještě chvíli klepal dal :-(.
# shake
while self.robot.barcodeData is None:
    self.driver.turn( angle=math.radians(45), angularSpeed=math.radians(90) )
    self.driver.turn( angle=math.radians(-90), angularSpeed=math.radians(90) )
    self.driver.turn( angle=math.radians(45), angularSpeed=math.radians(90) )
digit = self.robot.barcodeData
OK, ono to bylo myšleno, aby dokončil „taneček” a směroval zase rovně. Při tom „cukání” ale stejně ztrácí pozici a vyrazit naslepo hledat neznámo je asi také blbost. src_barcode_141007_173141.log moc výmluvný není:
1226
4
tj. po 1226 ticích (cca po minutě) načetl kód čtyřky. Není ale poznat, zda jednou nebo 10x po sobě. Změním to na index, tj. (4,1000) … offset 1000 neuškodí a já si snad nebudu plést co je číslo a co index. Však ono to pokazí zase něco jiného.
Druhá sada testů — opravena pravá/levá fungovala. Jel jsem navíc z dlouhé chodby
(stále nedořešený odlišný výsledek na PC … ten v devíti metrech vidí i osmičku)
Terč ale ani z blízka neviděl, takže skončil úplně mimo. V dalším pokusu jsem si uvědomil, že netestuji na úplně bezpečném místě … ale robota jsem doběhl:
V třetím pokusu se to stalo. Zde vidíte posmrtné snímky, které automat sbíral dál, i když už vše skončilo:
Robot narazil na obruč. Ta je z plechu, což je dobře i špatně. Dobře v tom smyslu, že po nárazu se snadno zdeformovala a kameře, kterou zasáhla těsně nad objektivem, nic neudělala. Špatně, protože se možná něco vyzkratovalo. Prostě jsem cítil ten nepříjemný zápach hořící elektroniky :-(.
Na první pohled nebylo nic vidět, ale smrad byl neodiskutovatelný. Kamera stále natáčela dál a kupodivu i počítač běžel a šel připojit. CAN už se nelogoval. Teď vidím, že ve třetím pokusu vůbec neběžel malý USB laser!?
LaserUSB - sndCmd ERROR 0
LaserUSB - sndCmd ERROR 1
LaserUSB - sndCmd ERROR 2
LaserUSB - sndCmd ERROR 3
LaserUSB - sndCmd ERROR 4
LaserUSB - sndCmd ERROR 5
LaserUSB - sndCmd ERROR 6
LaserUSB - sndCmd ERROR 7
LaserUSB - sndCmd ERROR 8
LaserUSB - sndCmd ERROR 9
… pěkné.
Nejprve jsme podezřívali serial-CAN bridge, ale na PC odpovídal, i když vzpomenout si jak to má být s tím DTR bylo náročné (v této konfiguraci bylo třeba vypnout a stejně tak i smazat dsrdtr=0). Po rychlých testech z notebooku robot popojel 20cm, tj. snad neshořely moduly na řízení motorů a i ostatní CAN moduly vypadaly na první pohled dobře.
Chtěl jsem se dívat na data sonaru, který nějak neblikal a ten vracel stabilních 11.14m. Tomáš si myslí, že je třeba nějak zapnout, ale já měl za to, že nikoliv. Prapůvodně jsem si říkal, že bych se takto měl vyhnout „náhodné procházce” po obvodu sálu, protože jinak robota sundá obruč (de facto přesně to co se stalo). To je zatím jedna záhada.
Tomáš nakonec vyndal Alixe (router = hlavní počítač) a jedno spáleniště našel! Odešel čip na RS232. Proč ale vzdal službu po sedmi letech zatím nikdo neví?
Standa ještě přiznal, že při zpevňování sloupku zapadla matička do podvozku (baterie, motory) — neměla by tam natropit neplechu, ale …
Další matné vzpomínky jsou na tu kameru — skoro mám pocit, že vnější kryt není uzemněný, nebo šroub u objektivu není, něco takového …
Do třetice, když jsem viděl ty schody a jak jezdíme po linoleu — nemohla to být statická elektřina??

P.S. sonar

Podle všeho sonar odešel už na FRE2014:
$ /c/Python27/python can.py logs/2014-06-18/task3/r140618_142431.log | 
grep "0x186 :" | uniq -c
    2965 0x186 : [255, 255]
vs.
$ /c/Python27/python can.py logs/2014-06-17/fre1/r140617_091547.log | 
grep "0x186 :" | uniq -c | head
       1 0x186 : [254, 23]
       1 0x186 : [86, 22]
       1 0x186 : [91, 24]
       1 0x186 : [70, 24]
       1 0x186 : [192, 24]
       1 0x186 : [86, 22]
       1 0x186 : [144, 25]
       1 0x186 : [43, 31]
       1 0x186 : [118, 26]
       1 0x186 : [151, 25]
A půlením intervalu se dostávám k r140617_132949.log, kdy to ještě fungovalo a r140617_143835.log (první soutěžní kolo), kdy už to nefungovalo. Že by převoz na oběd a zpět? Nebo nějaká sabotáž? Ve zkratce, včerejší kolizí to nebylo. cbd (což bylo dokázati)

9. říjen 2014 — Mix (25 hodin do odjezdu)

Nastupuje krize. Včera jsem se už v práci neovládal a mozek mi začínal spojovat různé myšlenky jako při schizofrenii (půlkou hlavy jsem v práci, ale druhou u robota). Tak nejprve včerejší poznámky, které „běžely na pozadí”:

Stabilita detekce značky cíle

Je to asi dobré cvičení z „počítačového vidění”. Jak jsem psal minule, tak chodba byla trošku tmavší a detekce u konkrétního obrázku o chlup nefungovala. Otázka tedy je, jak moc je to citlivé na prahování? Upravil jsem si kód na procházení všech hodnot a koukal na výsledek. Když je to moc bílé, rozpadlé, tak cíl neuvidíte. Když je to naopak moc černé, tak se to začne slejvat … může být problém i někde uprostřed?
Nevíte? Já také nevěděl, ale v Pythonu je to fakt radost ověřovat … stači přidat assert, resp. takovou past:
assert detectedAt == [] or detectedAt == range(detectedAt[0], detectedAt[-1]+1)
Jo, minimálně jeden snímek se chytil:
[38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 58, 59,
 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
 116, 117, 118, 119]
… případně si zkuste najít 56 a 57.

Oživení Edura

Tomáš přepájel čip na Alixovi a Eduro oživil. Jelikož je na rozdíl ode mne důkladný, tak rovnou udělal i image systému a připravil identickou desku jako zálohu. To je fajn .
Tomášovi patří i myšlenka na dokončení manévru u obruče. Robot není všesměrový, takže se snaží navigovat aby koukal na terč a vzdálenost od zdi byla 0.4 metru. To funguje pěkně (následuje otáčka 180 stupňů) pro kolmé nájezdy, ale co se šikmými? Chtěl jsem nějak měnit tu vzdálenost dojezdu, ale tam je riziko, že robot nabourá kamerou do obruče, není-liž pravda? A ten Tomášův trik je celkem jednoduchý: propočítat situaci a po otočení necelých 180 stupňů ještě couvnout .
Drobný detail je ta středoškolská matematika (teď se to možná bere už na základní škole??). Zase jsem měl včera mentální blok — chce to klid a pořádný obrázek. Ale ani pak to není zas tak úplně triviální (obruč je posunutá vůči stěně, laser je posunutý vůči středu otáčení, možná navíc neměří vzdálenost od středu, ale až od kraje …). No trvalo mi to implementovat snad hodinu (!) a ještě ani teď si nejsem jistý. I jsem si napsal unit test. Ostatně viz celý diff.
Zítra odjíždíme už v 9h ráno, protože cestou se budeme stavovat pro upraveného Falcona u AscTecu.
p.s. teď mi Tomáš poslal jeho odvození … je to o dost pěknější, tak předávám dál:

10. říjen 2014 — 1/2 verze 0 (10 hodin do odjezdu)

Výpočty v realitě úplně nefungovaly. Klasicky nebylo moc jasné, zda je problém v nepřesnosti měření, ve výpočtu nebo v realizaci manévru. Robot skoro vždy nacouvával do desky … takže by člověk naivně předpokládal chybu v couvání. Ale problém byl ve skutečnosti v otočení — Eduro přetočilo a tím pádem bylo blíž zdi a couvání to už jen dorazilo. Řešení, Jakubovo, bylo vlastně triviální: zpomalili jsme otáčení a pak vlastně nikdy Eduro nedotočilo. Trošku matoucí byl také zdeformovaný kruh, takže střed byl trošku jinde než se na první pohled zdálo.
No nic, trošku „plácám z hladu” … teď snad úplně první kostku nabere (viz diff). TODO je ověřit ty rozdíly v požadovaném otočení a v realizovaném (z odometrie). Jinak potvrzuji, že laser LMS100 vrací vzdálenost o cca 4cm kratší, tj. zhruba na od konce obalu.
S Jakubem jsme také vyzkoušeli narychlo zapojit RasPi jako XMLRPC server. Naházeli jsme funkce z kamery a detektoru na hromadu a v trošku jiném gitu naleznete SICK2014_main.py … podobnost se vzorovým příkladem z Pythonu je až obdivuhodná . Nasbírali jsme cca 200 obrázků z chodby polepené čísly … se možná někdo bude zítra divit, až dorazí do školy:

RasPI obrázky

Minimálně třetina obrázku je však dost rozmazaná.

Eduro obrázky

… tak už jenom dodělat to rozpoznávání čísel a tu kostku doručit … sigh … pokračování z Německa (resp. Francie, kde budeme ubytovaný).
p.s. OK, tak potvrzuji, že Eduro vědělo o tom, že přetáčí při vyšší rychlosti a při pomalé nedotáčelo (přidal jsem raději i timeouts na provedení akce):
—- Driver.turn(172) —-
—- Driver.turn result(-17) —-

—- Driver.turn(174) —-
—- Driver.turn result(-21) —-

—- Driver.turn(173) —-
—- Driver.turn result(-24) —-

—- Driver.turn(162) —-
—- Driver.turn result(-17) —-

—- Driver.turn(162) —-
—- Driver.turn result(-27) —-
vs.
—- Driver.turn(170) —-
—- Driver.turn result(2) —-

—- Driver.turn(167) —-
—- Driver.turn result(3) —-

—- Driver.turn(162) —-
—- Driver.turn result(3) —-

—- Driver.turn(-164) —-
—- Driver.turn result(-3) —-

—- Driver.turn(163) —-
—- Driver.turn result(3) —-

12. říjen 2014 — Game Over

Je po soutěži. Skončili jsme na čtvrtém místě. Zklamání? 900 EUR za třetí místo by bylo hezčí. Dělila nás od toho jedna správně doručená kostka … ale na rovinu, štěstí nám přálo už i tak — ostatně to můžete posoudit i sami .
Vzal bych to hezky popořádku (a schválně kdo to vydrží až do konce). V detailu to lze vysledovat podle historie gitu, tady je jen výřez od posledního blogu:
Date:   Sat Oct 11 13:59:33 2014 +0200
    SICK Robot Day - game1

Date:   Sat Oct 11 12:58:57 2014 +0200
    fixed duplicate division by 1000.0

Date:   Sat Oct 11 12:28:12 2014 +0200
    first island test (to be sick3)

Date:   Sat Oct 11 06:32:04 2014 +0200
    preparation for test with Digit trigger

Date:   Sat Oct 11 06:22:05 2014 +0200
    could this be the source of fatal delays?

Date:   Sat Oct 11 06:01:05 2014 +0200
    Dummy for debugging XMLRPC problems with RasPi communication … yes, I was warned

Date:   Sat Oct 11 05:47:32 2014 +0200
    some fixes and introduction of laserDataTimestamp

Date:   Sat Oct 11 05:46:23 2014 +0200
    quick single frame from log processing

Date:   Fri Oct 10 18:45:33 2014 +0200
    more robust 0, 6 and 9 detection

Date:   Fri Oct 10 18:06:43 2014 +0200
    re-enabled frame detection, minimal size and more strict 8 detection

Date:   Fri Oct 10 17:30:28 2014 +0200
    removed unused code

Date:   Fri Oct 10 13:31:49 2014 +0200
    search for alternative feeder in case of failure

Date:   Fri Oct 10 13:04:51 2014 +0200
    preparation for leaving island

Date:   Fri Oct 10 12:38:28 2014 +0200
    integration of RasPi (blind, not tested yet)

Date:   Fri Oct 10 09:20:12 2014 +0200
    first version0

Date:   Fri Oct 10 09:03:31 2014 +0200
    note, sys.exit() … no comment

Date:   Fri Oct 10 08:46:20 2014 +0200
    fixed(?) repeated barcode

Date:   Fri Oct 10 06:57:46 2014 +0200
    RasPi wrapper

Date:   Fri Oct 10 06:43:32 2014 +0200
    prepared simple follow wall for test

Date:   Fri Oct 10 06:10:39 2014 +0200
    target verification

Date:   Fri Oct 10 05:20:53 2014 +0200
    verify that barcode is new

Date:   Thu Oct 9 23:04:14 2014 +0200
    "dummy" timeouts and verbose info about turns

Date:   Thu Oct 9 22:03:07 2014 +0200
    version 0 - part 1 of 2
Časy a data jsou reálná a mezi tím bylo třeba něco naprogramovat. Získáte tak trošku představu, kdy začínala a končila směna .
V pátek 8-9h jsme ještě využili polepené vstupní haly školy a nasbírali více dat. Je srandovní, jak mi to teď přijde strašně dávno, a kdybych neměl v poznámkách spadlo to na viz vyse s „časovou známkou” 8:30, tak bych ani nevěřil, že duplicitu čárového kódu jsem řešil až v tak pozdní fázi. Místo 4 se hodnota proměnné self.robot.barcodeData změnila na (4,1003), tedy přečtený čárový kód a pořadí načtení +1000. Pokud ale čtečka selhala, typicky z důvodu že jsem zapomněl vhodit kostku nebo byla v nějaké nevhodné pozici, robot se jí snažil setřást rychlým cukáním. Hodnota None na začátku znamená ,zatím ještě nic nevím' … prostě tam byla špatně podmínka opravena v tomto commitu.
Co jsem dále v pátek ráno programoval byla verifikace cíle — musí během nájezdu alespoň jednou vidět cíl, jinak je pokus klasifikovaný jako neúspěšný a otáčení pod kruh by bylo nesmyslné. Přidal jsem parametr verifyTarget a když to poprvé nevyšlo, tak si couvl a zkusil to znova, ale podruhé už bez verifikace.
Zkoušel jsem to zase v tom hodinovém před-odjezdovém slotu a tam mi došlo, že je to takto k ničemu. Tím že si couvl se de-facto vrátil do stejné pozice ze které přijel. Šance, že si něčeho v druhém nájezdu všimne, je zanedbatelná. Později (viz diff z auta opravený pak v noci v hotelu) se robot vracel po oblouku, a když na něm nic neviděl, tak přešel na strategii hledání krmítka postupným pojížděním okolo zdi.
Jízda podél zdi byl další kus kódu z brzkého pátečního rána. Na nic extra nebyl čas a tak ve 2/3 laserového skenu (180 stupňů) hledal minimum (různé od nuly) definující nejbližší překážku, přičetl 90 stupňů, získaje tak směr kam by měl jet, a když to je více jak 45 stupňů, tak se otáčí na místě jinak jede pomalu vpřed. Ještě zde hrál roli parametr atDistance, tj. když je moc blízko překážky přidá úhlovou rychlost o 10deg/sec a když moc daleko, zase naopak ubere 10deg/dec … vše s tolerancí v pásu +/- 10cm, kdy nedělá nic.
Kupodivu tento algoritmus fungoval celkem pěkně, i Jirkovi se líbil , ale měl všechny očekávané problémy. Konkrétně když je na ploše mnoho testovacích robotů a agilních robotiků, tak při objíždění zdi se snadno dostanete z obvodu na vnitřní ostrůvek. Na to jsem si sice vymyslel „konvexní navigaci”, tj. nejbližší by se vzal bod na konvexním obalu skenu a pak dořešil vnitřní objekty, ale … „není čas marnit čas.” (ani nevím, ze kterého je to filmu)
Odjezd … a zapomněl jsem na „vtipnou” historku, kdy mi v pátek ráno kód neustále padal a já vůbec netušil čím to je:
Exception in thread Thread-2 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "/home/robot/python/laser.py", line 58, in run
  File "/home/robot/python/laser.py", line 164, in internalScan
  File "/home/robot/python/laser.py", line 160, in sendCmd
  File "/home/robot/python/laser.py", line 146, in receive
: expected a character buffer object
Exception in thread Thread-3 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "/home/robot/python/laser.py", line 58, in run
  File "/home/robot/python/laser.py", line 110, in internalScan
: 'NoneType' object has no attribute 'sleep'
Prostě naimportovaný modul time byl None?! Trvalo mi to pěkných pár drahocenných minut, než jsem našel zapomenutý sys.exit(). Typicky před každým commitem do gitu kontrouji diff, protože se to vyplatí (skoro bych tipoval, že v 20% případů tam najdu něco, co lze lépe upravit nebo je to vyslovené špatně a ten diff vše nové pěkně zvýrazní … myslím „želvičkový diff”), ale tady mi to prostě uteklo :-( (zůstal tam po ladění z kusu logu, kde jsem to nechtěl pouštět dál).
Už jsme v autě a vyrážíme na Mnichov pro upraveného Falcona. První část vyčerpávající dvanácti hodinové jízdy s mnoha dopravními zácpami jsme s Tomášem dělali malý „audit”:
  • overit extra couvani
  • kdyz selze detekce couvat do oblouku
  • filtrovani velikosti objektu pri najezdu na ostrov (uhel min/max a min vzdalenost)
  • couvat S-icko (ostre uhly)
  • overit zda neni numpy?
  • pokud nevidi terc tak centrovat na stred velkeho objektu?
  • misto timeouts pouzit ujetou vzdalenost u followWall
  • alternativa je udelat osu prekazek vlevo a vpravo
  • pokud nenajde terc, tak objizdeni rozdelit cca po 45deg
  • predpoklad ctverec, tak pak cilit na stred a ne na nejblizsi (def abs cil)
  • je treba si odjet od ostrova rovne, kdyz dostane cislo !!!
  • followWall, asi by mel delat cely sken, protoze robot muze jet zleva (!) a ja ho neuvidim
  • pri skenovani areny je treba prvni otocku udelat pomalou a druhou zpet rychlou
  • pokud dlouho nic nenajde (asi cely objezd?), tak otocit o 180 a delat to v opacnem smeru
  • neprepnout na nahodnou prochazku, kdyz ani potom nic??
  • dalsi varianta je zmenit vzorkovaci vzdalenost a vzdalenost od mantinelu
  • delat histogram a pulku?
  • oblast podle vzdalenosti
  • filtrovat z laseru detekovana cisla (ze odpovidaji velikosti) … jako postprocessing
  • po odjeti z ostrova, nedat tam jeste rozhlednuti 180
  • TODO turnLeft
… spíše to uvádím pro představu, že by ještě bylo co dělat a jsem teď líný k tomu doplňovat diakritiku. V zkratce jsme se bavili o tom, co se může pokazit už u samotné verze 0. Asi nejdůležitější bod byl je třeba si odjet od ostrova rovně, když dostane číslo, protože jinak se může stát, že nejbližší překážka bude ostrov a bude hledat čísla na ostrově, kde fakt nejsou.
Cestou jsem dopsal integraci RasPi, rozuměj funkce attachRasPi a start/requestStop, tj. výsledky s RasPi se tímto dostávají do proměnné robot.raspiData a lze je synchronně přehrát. V této fázi s nimi ale nic nedělám, jen je sbírám.
Dále to byla implementace opuštění ostrova, kdy jsem jak goVfh tak followWall rozšířil o parametr maxDistance + si odpočítával ujetou vzdálenost a timeout zůstal spíše jako pojistka.
Vznikl také nový kód na dohledávání terče u ostrova — chyba byla ve znamínku proměnné radius. Ověřeno nárazem do hotelového nábytku cca v jednu hodinu v noci.
Za zmínku stojí zavedení proměnné robot.laserDataTimestamp (mimochodem toto je už v den soutěže, ráno). Asi by to mělo smysl i u jiných senzorových datových typů, které se neobnovují s každém update() robota. Ve zkratce jsem potřeboval ověřit, že pracuji pouze na nových datech. Než porovnávat složitou strukturu, která v některých případech může být stejná i když je znova nasnímaná, tak raději porovnávám časové známky.
Toto mne „trošku” vyděsilo a je to rozhodně chyba v návrhu. Když běží VFH (Vector Field Histogram pro vyhýbání se překážkám), používá vlastní extension (kus kódu, kudy prochází všechna nová data nezávisle na hlavním kódu). Tyto extenze lze registrovat a když je to fakt nutné, i odregistrovat přes jejich registrované jméno. To je první část skládačky.
Druhá část rozbušky je pak detekce čísla napojená na zpracování dat z kamery. Když vidí hledané číslo, vyhodí výjimku DigitFound. Robot tedy může jezdit cik-cak, otáčet se, jezdit podél zdi, zkoušet spirály, prostě cokoliv a nemusí se starat v každém kroku „nepřišlo náhodou to číslo co ho hledáme?”. Když to ale dáte dohromady, tak máte problém … je to vlastně to samé, jako když máte pointery na alokovaná data v C++ a vyletí výjimka. Prostě jsem měl za to, že se může stát, že tam ta extenze hnije dál a s tím nějaké zbytečné výpočty. Zalepil jsem to dost ošklivě odregistrováním extenze v ošetření výjimky, i když už možná vůbec nebyla registrovaná.
DigitFound jsem ještě zneužil na rychlejší dohledávání cíle pro případ, kdy se to v prvním nájezdu nepovedlo. Různě couvá, natáčí se a jede podél zdi … a zase jak se detekce chytne, je třeba přerušit hledací činnost a „skočit na to”.
Ještě vás to baví číst? Když si teď zpětně představím co za tím bylo práce, kterou nikdo moc neocení … nic, další záznamy jsou už se soutěže. Tam bylo hned několik překvapení. Především aréna mi nepřišla tak velká (odkrokovali jsme to na 12m). Centrální ostrůvek měl tvar osmiúhelníku a terče byly na pěkném bílém pozadí. Asi největší překvapení bylo, že byla použita pouze čísla 1, 2, 3 a 4 a ta zůstala na stejných místech po celý den! Že to tak zůstane i na soutěži jsem se dozvěděl až cca 13:30 … no nic. Tj. úprava detekce 0, 6, 9 a přísnější detekce 8 byla k ničemu.
V hale jsme měli cca tři hodiny na testování. Bohužel jsme v této době i doprogramovávali detekci ostrova a některé chyby byly „likvidační”. Jedna byla s přepočítáváním dat ze SICKa (int v milimetrech), kdy z původního celého skenu jsem využil už shlukované kousky po deseti měřeních (5 stupňů) a dělil to chybně dvakrát.
Druhá byl detail, že jsem si jen chtěl vypisovat jakým směrem je ostrov ve stupních (math.degrees(islandDir)) a jenom kvůli tomuto debug výpisu to spadlo, protože islandDir byl None (ostrov nenalezen) a z toho se stupně spočítat nedají.
No nic, kohout už kokrhá a zbytek týmu se pomalu probouzí. V hotelu je hodně špatná WiFina, tak pokud to projde, tak zkusím protlačit alespoň tento text … [neprošlo to].
p.s. ten text je nějaký dlouhý a už nejsem schopen ho po sobě ani přečíst, tj. plánuji revizi [done]

Video (Stanislav Petrásek)

Eduro, 1. kolo

13. říjen 2014 — Video s komentářem

Přemýšlím co dřív. Video od Standy už jsem uploadoval včera večer. Pak tady mám množství jeho pěkných fotek, které jsem ale ještě neprobral. Kontaktoval jsem vítězný PARMA Team (můžete se např. podívat na jejich video z testování), jestli nám neprozradí svá tajemství jako před dvěma lety (anglická verze). Ale já si myslím, že tam žádné tajemství není třeba hledat — je prostě třeba testovat, testovat, testovat a čím je hřiště podobnější soutěžnímu tím lépe. Poznámka: je třeba mít co testovat.
Asi bych začal tím, jak je možné, že jsem tam s Edurem pobíhal v půlce kola?! Detlef, hlavní organizátor a tvůrce pravidel, totiž za mnou přišel a říkal, že pokud robot blokuje cílové místo déle než 1 minutu, robot musí být odstraněn a pokud tým chce, tak i restartován. To jsem nevěděl a v pravidlech to není. Je to ale ve FAQ:
Question: What happens, if a vehicle blocks a station for a longer period?
Answer: At filling stations nothing will happen, because these are equal, and at least one of them will be available for a robot, even in the case that all three of the rest are blocked by the other competitors.
Around the goal stations there will be a (human detectibly, on the floor) marked area (radius maximally 1 m). Within this area a robot may stay for one minute maximally. If this time is exceeded (regardless of whether the robot still moves or not) it must be removed immediately. If a restart is possible within the ongoing run, the team may freshly insert the vehicle at the original starting position.
OK, tak to nebyla protekce .
Co to tam tedy Eduro dělalo?? Začal bych tím, co si myslím, že se dělo „z nějšího pohledu”. To co jste viděli byla vlastně verze 0 — získat jeden bod. Robot vyrazil rovně ze startu, rozpoznal terč na podavači (4x ze 4 pokusů), vrátil se na obvod hřiště a hledal výsledné číslo s kódem:
while True:
    self.followWall( atDistance=1.5, timeout = 10.0, maxDist = 2.0 ) # TODO tune params
    self.driver.turn( math.radians(-90), angularSpeed = math.radians(20), timeout=20 )
    self.driver.turn( math.radians(90), angularSpeed = math.radians(40), timeout=20 )
tj. ve vzdálenosti 1.5m od kraje jeď maximálně dva metry a po deseti sekundách to vzdej. Pak se otoč pomalu 90 stupňů vpravo a zpět rychleji do původního směru jízdy.
Jakmile uviděl číslo, tak za ním přímo vyrazil. Kamera nebyla nakalibrovaná a současně čísla rozpoznával i hodně ze šikma. Definoval tedy špatně absolutní pozici cíle a přejel aniž by si všiml terče po pravé straně. Pro cílové místo chybělo pořádné ošetření neviděného cíle, takže si couvl 1m a když ho znova neviděl, tak to holt „vyklopil” i bez detekce.
Následovala jízda na ostrov, ale byl tak šikmo, že rovnou přepnul do stavu, že už na ostrově je … pozn. verze 0 by vlastně neměla řešit co dál a je to na tom poznat. U ostrova funguje lepší dohledávání cíle, tak chvíli hledal až našel a rozsvítil zelená světla (pro naložení kostky). Kostku ale už měl a tímto se mu podařilo „kouzelně” doručit tu první. Po 10s si kousek popojel a zjistil, že čtečka nenačetla kód. Robot přešel do stavu „shake” a snažil se kostkou zatřást tak aby jí detekoval … a to by mu trvalo hoooodně dlouho, protože tam žádná nebyla. Zároveň moc daleko nedojel, takže blokoval cílové místo.
Druhá jízda z prvního kola byla podobná, akorát si na číslo 4 najel lépe. Pravděpodobně zase selhal přechod od vyložení kostky do stavu k hledání ostrova a rovnou skočil na „jsem blízko ostrova” a směrování se nekonalo a jel prostě rovně.
Ve druhém kole byl začátek identický, ale byly tam dvě změny. Jednak cílové místo bylo blokované a co hůř Eduro si najelo levým kolem na kostku. Předpokládám, že pak zabral nějaký timeout a prostě to otočilo i když nebylo ideálně postavené. Následoval špatný přechod na ostrov a zase hledal podavač u kraje … až našel a přišel tím o jeden bod. Pak jsem se ptal, jestli to není stejná blokovaná situace jako v prvním kole a dozvěděl jsem se, že je „když tedy chcete”. Dodání druhé kostičky ke dvojce pak už bylo bezchybné (2 sekundy do konce zápasu) … ostatně na konci videa můžete vidět, že nedokážu projevit radost .
(Standovi došlo místo na kartě, tak natáčel alespoň telefonem, proto ta horší kvalita).
Tak jo, jdu si napracovat alespoň jednu hodinu z páteční pseudo-dovolené... pokračování zítra.

Foto (Stanislav Petrásek)

zatím nalezené kontakty:
p.s. oficiální výsledky zatím stále nejsou zveřejněné …
p.s.2 pro pobavení, než se to odroluje:

15. říjen 2014 — PARMA Team

Dnes jsem svůj časový slot už vyčerpal na anglické verzi tohoto článku, kde je teď kopie informací od PARMA Teamu (konečně jsem pochopil, proč měli název PARMA Parma ). Za zmínku stojí fakt, že čísla hledali nejprve přes rámečky a pak nasadili neuronovou síť. Mají tam i pěknou simulaci v ROSu a dvě videa (vlastně to jsou stejná kola, která Standa natáčel — v prvním je i Eduro a Osnabrück, ve druhém pak Tübingen (ti už přislíbili také krátký příspěvek)).
p.s. ve městě Parma/Itálie včera byly velké záplavy, tak nefungovaly ani mobily ani internet …
p.s.2 … myslím, že s tím testováním jsem se moc nemýlil — viz testovací video z 2. října 2014, které uploadovali před dvěma hodinami …

16. říjen 2014 — Attempto Tübingen

V angličtině teď máte další tým Attempto Tübingen, který celkově skončil na druhém místě. V prvním kole skóroval jako vítězný tým — 6 kostiček (mimochodem oficiální výsledky stále ještě nejsou k dispozici), ale v druhém kole selhal hardware a 5 minut propásli čekáním.
Ptal jsem se Sebastiana, jestli tam byly nějaké překvapení či zrady a odpověděl mi, že ten ostrůvek měl být čtverec a v realitě byl pravidelný osmiúhelník. A opravdu v pravidlech je: In the middle of the arena there are the filling stations. They are located at the 4 sides of a square island.
Za zmínku stojí, že tento tým je již dlouhodobým hráčem na poli RoboCupu (fotbal), SICK Robot Day 2010 vyhrál a vozí sebou správné náhradní díly = identického robota k okamžitému nasazení.

17. říjen 2014 — Eduro 1.kolo

3:58 nezní jako rozumný čas na vstávání, ale … stejně bych už neusnul. Je čas ohlédnout se zpět a projít co se přesně po té 14 hodině dělo.
V prvním kole robot vyrazil přímo na krmítko a detekoval cíl překvapivě brzy:
Approaching Feeder
Target at 1.706 logs/cam141011_141925_010.jpg
Target at 1.379 logs/cam141011_141926_011.jpg
Target at 0.837 logs/cam141011_141927_012.jpg
Target at 0.573 logs/cam141011_141928_013.jpg
Target at 0.487 logs/cam141011_141929_014.jpg
… až se mi to teď moc nechce věřit.
Stejný výsledek dostávám i při přehrávání s detekcí v Céčku, ale nikoliv v Pythonu :-( … Chytlo se to na práh 60 a to že to ve vieweru vidím až cca 1.5m od překážky (fakticky to asi bude těch 1.379m), tak to je způsobeno 1s zpožděním obrazu za realitou.
minDist 0.41 0.421 0.426
Suggestion:  170.759289364 -0.0262651978154
—- Driver.turn(170) —-
—- Driver.turn result(2) —-
Barcode before None
Barcode after (2, 1001)
LOOKING FOR digit = 2
Vzdálenosti min-levá, střed, min-pravá vypadají dobře a i otočení se mu celkem povedlo. Následně čtečka přečetla kód 2.
Eduro se na chvíli zastavilo z důvodu resetu motorů (watchdog) … to dělá často, když přechází na VFH — je to holt na hranici výpočetních schopností.
goVfh - maxDist reached
… traveled 3.02468329104 time 9.4
Následuje 8x followWall se dvěma výpadky (nejprve vypadl motor 2 a pak motor 1). A blížíme se k prvnímu problému:
FOUND 2 (2, (434, 121, 42, 95))
Approaching Feeder
done.
TARGET not verified!
Approaching Feeder
done.
minDist 0.916 0.841 0.408
Suggestion:  -166.099991286 -0.584368622273
—- Driver.turn(-166) —-
—- Driver.turn result(-2) —-
DIGIT 2 COMPLETED 180.75
Tak hned několik pozorování:
  • dvojka byla detekovaná pouze pro práh 80
  • hala má evidentně ještě další okna, které např. v předešlém obrázku dvojku rozpůlily
Zde je reference, aby jste neměli pocit, že je to celé nějak moc jednoduché
Tak jo, padá to na mou hlavu :-(. Já tam totiž měl z roku 2010 dvě podobné funkce goToVfhDigit() a goToDigit(). V té první se kouzlí s absolutní pozicí cíle, ale ve druhé, vhodné pouze na dojez, se už používá jen korekce úhlu. No a tu první funkci už vůbec nevolám — byla nahrazena objížděním po obvodu arény. Tj. jak ztratil dvojku ze zorného pole, tak bylo vše ztraceno.
Poslední šance, kdy by mohl vidět navigační terč byl tento záběr:
nedetekovaný cíl
nedetekovaný cíl
Zbytek už není zajímavý: otočil se, … i když opravdu byl tak daleko?!
Approaching Feeder
Target at 2.147 logs/cam141011_142230_198.jpg
Target at 1.945 logs/cam141011_142231_199.jpg
Target at 0.98 logs/cam141011_142232_200.jpg
done.
Zacouval si 40cm, místo aby dostal kostičku, tak o ní přišel a pak se 20x snažil zakroutit, aby přečetl čárový kód. Restart.
V druhé jízdě rozpoznal cíl v 1.29m, najel trošku šikmo (otočka 162 stupňů), cílová adresa 4 (tentokrát přechod bez resetu motoru), nutno objet 3/4 haly a
FOUND 4 (4, (383, 160, 30, 63))
Approaching Feeder
Target at 1.965 logs/cam141011_142819_198.jpg
DIGIT 4 COMPLETED 207.55
tj. Eduru trvalo více jak tři minuty doručit kostičku číslo 4.
Pak selhalo „opuštění hranice” a bylo vymalováno.
Video vytvořeno pomocí digit.py, akorát jsem použil původní obrázek místo černobílého.
p.s. narazil jsem na webu na Team Hector Darmstadt.

21. říjen 2014 — Eduro 2.kolo

Do druhého kola jsem zvažoval zapojit RasPi a detekci čísel na které pracoval Honza s Jakubem. Po chvilce procházení kódu jsem to ale vzdal. Proč?
  • RasPi rozpoznávalo pouze čísla, tj. bylo by třeba míchat výsledky z obou kamer kvůli terči
  • časování RasPi snímků bylo jiné, tj. bylo by třeba je jinak synchronizovat
  • při nájezdu na číslo se několikrát verifikovalo (ve třech snímcích muselo být číslo alespoň 2x), ale RasPi číslo někdy vidělo právě jednou
  • RasPi kamera nebyla zkalibrovaná (stejně jako Eduro kamera), tj. nebylo jasné jakému úhlu odpovídají jednotlivé pixely
  • rozpoznávání RasPi v kombinaci síťové komunikace bylo pomalejší
  • Eduro si pletlo 1 a 7, ale to nevadilo (RasPi bylo zatím bezchybné)
  • kombinace nebyla nikdy testovaná
Stále si myslím, že rozhodnutí bylo správné.
Eduro tedy jelo s identickým kódem jako v prvním kole. Správně nabralo kostku, přečetlo cílovou adresu čtyřku a objelo půlku haly. Rozpoznalo ceduli s číslem čtyři, ale chyba lávky:
Zápas s ležící kostkou asi nakonec vyhrál timeout, který byl ale nastavený na jednu minutu = dlouho. Ještě poznámka, že Eduro kostku vidělo spodním laserem, ale i kdybych to věděl předem, tak nevím co s tím. Rozumné řešení byla radlice, jak jí měla většina úspěšných týmů.
Pak se ale stala ještě druhá nepříjemnost — zase špatné opuštění hranice arény, auto-sugesce ostrova a nadšený návrat ke čtyřce vedoucí ke ztrátě bodu. A pak nekonečný „Shake”, na který se už nemůžu koukat.
Pak mi ještě udělalo radost úspěšné doručení čísla 2 v čase 97s od startu. Myslím, že 3s poté byl konec hry.
Závěr? Jak si můžete přečíst v anglické verzi první i druhý tým dal 6 kostek alespoň v jednom kole. Ta poslední dvojka byla v 1/4 oblouku, tj. skoro nejblíž … prostě my bychom s touto strategií na první dvě příčky nemohli dosáhnout. A co to třetí místo? No kdyby … byly ryby …

22. říjen 2014 — Závěr

Asi bych už tento blog pomalu uzavřel. Nejprve ještě jednou díky třem fandorama stoupencům, kteří mne vyhecovali to, možná až příliš podrobně a nesrozumitelně, sepisovat. Zde je alespoň odkaz na jejich roboty z robotika.cz archivu:
Včera jsem došel k závěru, že na oficiálních stránkách SICKu hned tak něco nebude (a nezlobil bych se, kdyby díky Murphyho zákonům to tam dnes dali ). Tj. na Alešův dotaz: Chybí snad už jen kompletní výsledky (alespoň kdo byl třetí a s jakým skóre) … jsem psal organizátorům (kdo byl třetí a že doručili tři kostky vím, ale vyměnil jsem si ještě pár mailů s eXception a oni ani netušili, kolik kostek se jim počítalo):
… the "official" results are as follows:

Parma as well as Attempto Tübingen got 6 Points. Parma got the first place only
because their result in the other run (normally not counted, but here used as
a tie break) was slightly better than in the case of Attempto (5 resp. 3).

3rd place Deep Cube Osnabrück with 3 points.

4th came EDURO with 2 points.

5th eXception München: 1 point.

All the others didn't finish with a positive score.
Z tohoto pohledu jsme byli celkem dobrý ne . Jo ta sebechvála …
Pavel psal (trošku vytrženo z kontextu): Co máš proti jazyku C? Osobně spíše pořád nemůžu přijít na chuť Pythonu.

Python vs. Céčko

Python mám rád a dobře se mi v něm píše. Céčko mne občas svazuje (myslím tím takové to C++, ale blízké Céčku) — včera jsem něco v práci programoval a ty extern a DLL nesmysly a problémy s linkováním a má/musí to být const aby to šlo zavolat z jiných funkcí a převod enumu na stringy, abych si mohl vypsat, co že ta kódová hodnota 3 je … nečekal bych, že se to ze mne bude tak valit .
Ne váženě — ono to není Python vs. C, ale Python + C. Používám oboje a když nevím co dělám (většinu času), tak si to raději prototypuji v Pythonu. A ono to často u těch prototypů skončí. Poslední dobou nedám dopustit na externí C knihovny jako je OpenCV2 a NumPy … ano, je to volání stejných funkcí jako v C, ale např. poskládat video ze všech obrázků v podadresářích bych v C tak snadno nedal.
Přenositelnost mezi stroji už beru jako samozřejmost, že na ní pomalu zapomínám. Programuji pod Win7 a většina skriptů běží pod Linuxem, včetně prográmků pro Eduro. Kompilace, knihovny pro linkování, Makefile to je vše v úvodní fázi „opruz”.
Jak jsou věci odladěné a domyšlené v Pythonu, jasné datové typy a je požadavek na zrychlení, tak bych dnes nejnutnější kusy přepsal do Céčka a měl to jako Python extension (snad se tomu tak říká). I jsem uvažoval, že bych u Edura přepsal to VFH (Vector Field Histogram na vyhýbání se překážkám z dat laseru), který už nestíhá (možná to dokonce Jirka kdysi udělal). Za tu o něco větší rychlost ale rychle zaplatíte: když jsem napsal detekci zelené v C pro Heidi (chtěl jsem zkusit, jak je to těžké), tak jsem obratem rozbil Jakubovi jinak přenositelný kód (pod Linuxem bylo třeba nastavit cesty na OpenCV zdroje nebo něco podobného).
Ve zkratce používám oboje, ale raději mám Python.
… je to konec článku? Asi jo, tak ještě poděkování dalším členům letošního týmu: Milanovi, Standovi, Tomášovi, Jakubovi a Honzovi. A škole — ČZU.
Robotům zdar .

Pošlete email redakci.
Všechny materiály, které máme k dispozici, jsou již součástí článku, na který reagujete (tj. pokud tam tedy není např. plánek na stavbu, je to proto, že nic takového nemáme).

Vaši zprávu se bohužel nepodařilo odeslat, ale můžete nám napsat sami na adresu

Vaše zpráva byla úspěšně odeslána

Pro odeslání formulář je třeba mít zapnutý javascript.