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:
- Detaily tohoto projektu: https://fandorama.cz/projekty/921778164/sick-robot-day-2014/
- Stránky organizátorů: http://www.sick.com/group/DE/home/pr/events/robot_day/
Obsah:
- 140911 / Měsíc do soutěže
- 140916 / Zielscheibe
- 140924 / Barcode
- 140925 / Fandorama
- 140926 / Diversity
- 140929 / 4-8-černo-bílý svět
- 141001 / Verze 0?
- 141002 / Falešné cíle
- 141003 / Změna rozlišení
- 141004 / Dva cíle?
- 141005 / Čísla (5 dní)
- 141007 / Čtyřka a "sliding window" (zbývají 3 dny)
- 141008 / Bouračka a čipový smrťák (78 hodin)
- 141009 / Mix (25 hodin do odjezdu)
- 141010 / 1/2 verze 0 (10 hodin do odjezdu)
- 141012 / Game Over
- 141013 / Video (Stanislav Petrásek)
- 141014 / Foto (Stanislav Petrásek)
- 141015 / PARMA Team
- 141016 / Attempto Tübingen
- 141017 / Eduro 1.kolo
- 141021 / Eduro 2.kolo
- 141022 / Závěr
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_1 až KEY_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 |
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 |
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 |
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)
eXception, KaMaRo, R-Racing, Deep Cube, Hector, BARC, Flamingos, MART, Parma, Idefix, Gymspit, 01-robotics, Attempto, Alpaca/2 |
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)).
- SICK Robot Day 2014 - PARMA Team first run
- SICK Robot Day 2014 - PARMA Team second run
- Fotos: Fünfter "Sick Robot Day" in Waldkirch
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 |
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 .