Robot Recycling Rally

Transcription

Robot Recycling Rally
Eurobot 2007 – Final design
Eurobot 2007 – Endeligt design
Rapporten er udarbejdet af:
Martin Juhl Jørgensen (s042353)
Vejleder(e):
Nils Andersen
Ole Ravn
Ørsted•DTU
Automation
Danmarks Tekniske Universitet
Elektrovej
Bygning 326
2800 Kgs. Lyngby
Denmark
www: www.iau.dtu.dk
Tel: (+45) 45 25 35 50
Fax: (+45) 45 88 12 95
Udgivelsesdato:
27. juni 2007
Klasse:
Offentlig
Bemærkninger:
Denne rapport er indleveret som led i opfyldelse af kravene for
opnåelse af bachelorgraden på Danmarks Tekniske Universitet.
Rapporten repræsenterer 15 ECTS point.
Rettigheder:
© Martin Juhl Jørgensen, 2007
Forord
Denne rapport er afslutningen på mit bachelorprojekt indenfor elektroteknologi. Projektet har bragt mig vidt omkring på flere måder. Projektet har været
mere praktisk end de fleste andre projekter jeg har lavet i min tid på DTU,
det har været en lærerig proces. Samtidig bragte projektet os til Frankrig hvor
dette års Eurobot konkurrence blev afholdt. Det har været en god oplevelse at
være med til Eurobot konkurrencen og møde flere ligesindede studerende fra
andre lande. Det er i hvert fald ikke svært at forstå hvorfor det er de samme
folk der bliver ved med at vende tilbage år efter år.
Udover vores vejledere Nils Andersen og Ole Ravn, så har Christian Andersen været til stor hjælp for projektet. I særdeleshed når kameraet eller laserscanneren ikke makkede ret.
Kongens Lyngby, 27. juni 2007
Martin Juhl Jørgensen
s042353
iii
Indhold
Forord
iii
Indhold
iv
1
Indledning
1
2
Analyse af Eurobot 2007
2.1 Affaldshåndtering . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Orientering & navigering . . . . . . . . . . . . . . . . . . . . . .
2.3 Forhindringer . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4
8
8
3
Robot design - Mekanik
3.1 Dåse og flaske mekanik . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Batterihåndtering . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Laserscanner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
9
10
10
4
Robot design - Elektronik
4.1 SMR komponenter . . . . .
4.2 Startsnor . . . . . . . . . . .
4.3 Børstemotor . . . . . . . . .
4.4 Laserscanner . . . . . . . . .
4.5 Farve-sensorer . . . . . . . .
4.6 Batteri-sensor . . . . . . . .
4.7 Detektering af modstander .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
12
12
13
13
14
16
Software
5.1 SMRdemo server . . . .
5.2 Start & slut funktioner .
5.3 Fejlhåndtering . . . . . .
5.4 Basale kørselsfunktioner
5.5 Kamera . . . . . . . . . .
5.6 Dåse og flaske aflevering
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
18
18
18
19
20
23
Designevaluering
6.1 Designkoncepter
6.2 Mekanik . . . . .
6.3 Elektronik . . . .
6.4 Autonomitet . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
30
30
31
5
6
7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Konklusion
33
Litteratur
35
Appendiks
37
iv
Indhold
A Regler & FAQs
A.1 Regler . . . . . .
A.2 FAQ 1 . . . . . .
A.3 FAQ 2 . . . . . .
A.4 FAQ 3 . . . . . .
A.5 Approval Sheet
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
B SMR-CL
C Kildekode
C.1 haupt.c . . . . . .
C.2 klient.h . . . . . .
C.3 klient.c . . . . . .
C.4 myfunc.h . . . . .
C.5 myfunc.cpp . . .
C.6 Definitions.h . . .
C.7 Communication.h
C.8 Communication.c
C.9 Servostyring.h . .
C.10 Servostyring.c . .
39
39
67
74
79
83
87
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
95
95
113
114
116
118
129
130
130
132
132
K APITEL
Indledning
Eurobot er en international robotkonkurrence, hvor folk fra hele verden kommer for at dyste mod hinanden og dele erfaringer. Udfordringerne varierer fra
år til år og temaet for Eurobot 2007 er “Recycling”. Robotterne skal indsamle, sortere og smide affald ud i bestemte beholdere. Affaldet består af dåser,
flasker og batterier. Banen kan ses på figur 1.1.
Figur 1.1: Eurobot 2007 banen
De design der var på tegnebrættet er dels beskrevet i [HJJ07] og dels beskrevet af Shayantharan Sivarajalingam (s042297), Østed•DTU ultimo juni
2007. Der blev derefter arbejdet med et af disse designkoncepter. Det planlagte
design, beskrevet af Brian Hansen (s042307) i [Han07], blev dog skrottet grundet tidsmæssige årsager. Den endelige robot, den som denne rapport handler
om, er baseret på en robot der tidligere har deltaget i Eurobot konkurrencen.
Valget faldt på robotten der var med til Eurobot 2006, blandt andet fordi den
overholder kravene til omkredsen, da samme regler var gældende til Eurobot
2006. Et mål er at den skulle ombygges således at den originale version kan
genskabes uden for meget besvær.
1
1
K APITEL
Analyse af Eurobot 2007
Banen til Eurobot 2007 er vist på figur 1.1. Robotten starter i enten det røde
eller det blå hjørne, og spiller som den pågældende farve. Kurvene hvor det
sorterede affald skal afleveres er i det modsatte hjørne af starthjørnet. Batterierne skal derimod afleveres i skålen på midten af banen. Skålen har en tilfældig placering blandt tre mulige. Robotten skal aktiveres af en snor med en
længde på mindst en halv meter. Hver kamp varer 90 sekunder og når tiden
er gået skal robotten selv stoppe og slukke for alle motorer. Derudover skal
robotten også forsynes med en nødstopknap så dommerne kan skride ind,
skulle det være nødvendigt.
Som det kan ses på figur 1.1 er der på banen placeret 20 dåser, 20 flasker
og 3 batterier i to trekanter. Derudover er der placeret en flaske, en dåse og
to batterier i midten af banen. Flaskerne og dåserne er farvekodet, hhv. grøn
og gul så robotterne nemmere kan genkende dem. Ydermere er de fyldt med
skum der sørger for at de holder formen under kampen. Hver flaske og dåse
afleveret i deres respektive kurve giver et enkelt point. Batterierne er det eneste magnetiske affald på banen og de er farvet enten blå eller rød. Batterierne
må således kun opsamles de af den robot der kører med samme holdfarve.
For hvert batteri afleveret i skålen giver det to point. Holder robotten på modstanderens batteri kan man blive diskvalificeret.
Et af kravene til robotten er dens omkreds. I startposition må omkredsen
ikke overstige 120 cm, mens den i udfoldet tilstand må være op til 140 cm. Robotten må først folde sig ud efter startsnoren er hevet og kampen er i gang. Se
figur 2.1 for definitionen fra de officielle regler. Robotten må have en maksi-
Figur 2.1: Definition på omkredsen fra de officielle regler
3
2
4
KAPITEL 2. ANALYSE AF EUROBOT 2007
mal højde på 35 cm, men skal være udstyret med en solid mast i 45 cm højde.
Masten er beregnet til at modstander holdet kan montere et radiofyr, et såkaldte beacon, til at lokalisere den anden robot. Udover det beacon man må
sætte på sin modstander er der mulighed for at placere yderligere tre beacons.
Se figur 1.1 for placeringerne.
Udover at kunne samle og sortere affald, skal robotten også kunne detektere modstander robotten og vise velvilje til at stoppe for at undgå kollisioner.
Hvis robotten ikke stopper, eller med vilje påfører modstanderen skade vil
robotten blive diskvalificeret.
Udfordringerne kan koges ned til følgende fem discipliner:
• Robot størrelsen. Da flaskerne og dåserne er rimelig store i forhold til
størrelseskravene, er dette en af de sværeste udfordringer ved Eurobot
2007.
• Indsamlingen af affald. Affaldets position og retning er ukendt, og vil
med meget stor sandsynlighed ændre sig mange gange i løbet af en
kamp.
• Affaldet skal sorteres og afleveres i deres respektive beholdere. Batteri beholderens position er den eneste ukendte, men affaldet skal i alle
tilfælde løftes 3-5 cm op for at afleveres. Affaldet kan dog skelnes fra
hinanden ved deres størrelse, farve, vægt og magnetiske egenskaber.
• Detektering af forhindringer. Modstander robotten er den største forhindring i kampen, den anden er batteribeholderen.
• Robust design. Under kampen kan forholdene ændre sig meget for robotten, især lysforholdene siger erfaringerne [SJHJ05, RTJH06].
Se bilag A for det endelige udkast af de officielle regler.
2.1
Affaldshåndtering
Affaldet kan deles op i to grupper, flasker og dåserne, og batterierne. Opdelingen bunder i størrelsen på emnerne; flaskerne og dåserne har tilnærmelsesvis
samme diameter på lige omkring 60 mm. Batterierne er derimod mindre og
tungere. Til gengæld er de også meget magnetiske. Flaskerne og dåserne kan,
grundet deres tilnærmelsesvis samme diameter, behandles med samme mekanisme i mange tænkelige tilfælde. Der er dog en del problemer med flaskerne
på grund af deres udformning, flaskehalsen har det med at sidde fast. Dåserne er næsten helt cylindriske hvilket gør det noget nemmere at håndtere dem.
De er derimod næsten halvt så lange som flaskerne, hvilket vil sige at der, alt
efter mekanismen, kan snige sig to dåser ind i stedet for en.
For at se hvordan flaskerne og dåserne reagerer under en kamp, blev en
SMR1 sat til at køre en vilkårlig rute på banen. I praksis viste det sig at flaskerne og dåserne havde en tendens til at rulle op langs banderne efter en hel
kamp. Derudover blev det også observeret at flaskerne og dåserne var meget
letpåvirkelige. Da kun robottens egen rute er kendt kan der ikke regnes med at
flaskerne og dåserne ligger stille og rolig, lige til at samle op. Det stiller krav til
1 Small
Mobile Robot
2.1. AFFALDSHÅNDTERING
5
at indsamlingsmekanismen er tolerant overfor forstyrrende elementer, såsom
dåser og flasker der rulle rundt.
Hvis man vælger kun at gå efter batterier kan man højest score 4×2 point =
8 point. Hvis vi går ud fra at halvdelen af dåserne og halvdelen af flaskerne
bliver beslaglagt af modstanderen, er der maksimalt 10 × 1 point = 10 point
point fra både flaskerne og dåserne at hente. Blandt andet derfor har vi har
valgt at gå efter alle typer affald. Det vil forhåbentlig sprede pointene ud på
de forskellige typer affald, og hjælpe at vi ikke står i en situation hvor vi ikke
kan tage mere affald fordi modstanderen har brugt samme taktik. Vi kunne
selvfølgelig have valgt at gå kun efter batterierne, men de er svære at få øje på
blandt alt det andet affald grundet deres størrelse.
Dåse og flaske mekanik
Vi har valgt at satse på en simpel mekanisk løsning der kan klare både flasker
og dåser. En af de første tanker vi fik var at skubbe affaldet hen til kurvene,
hvorefter det enten kunne blive skubbet eller f.eks. skovlet op i kurven. For
at kunne skubbe affaldet rundt på banen skal vi sørge for at det ikke smutter
fra robotten når den bakker, drejer eller bare kører lige ud. Tankegangen er at
dåserne og flaskerne meget gerne vil rulle, selv hvis de bliver påvirket af en
kraft helt nede ved jorden. Det kan f.eks. realiseres med en bøjle som skitseret
på figur 2.2. Vores mock-up test viste at der skulle rimelig meget til før affaldet
Figur 2.2: Dåse og flaske indsamling
brød ud når det først var fanget. Testen viste også at affaldet ikke var til at få
indfanget ved bare at køre hårdt ind i det. Det vil sige at for at få en dåse eller
flaske indfanget bliver robotten nød til at presse den op i mod f.eks. en væg,
da den ellers vil rulle foran bøjlen.
Problemet med at have flaskerne og dåserne udenfor robotten er dels sorteringen og dels afleveringen. Idet der kun kan ligge én flaske eller to dåser
ad gangen, er problemet med sorteringen begrænset til at detektere hvilken
type affald robotten har fanget. Flaskerne og dåserne skal afleveres over en
6
KAPITEL 2. ANALYSE AF EUROBOT 2007
4-5 cm høj væg, så det er nødvendigt med en mekanisme der kan transportere
affaldet over væggen. Der blev prøvet med to forskellige mekanismer:
Roterende pind der vipper affaldet over væggen. Simpel mekanisme der vil
kræve en servomotor og en pind. Den har det minus at robotten skal tæt
på væggen før den kan aflevere en dåse eller en flaske.
Børste der roterer med høj hastighed og fejer affaldet over væggen. Ulempen
er at der skal børsten skal presse dåsen/flasken mod væggen før det
virker overbevisende.
Efter at have prøvet sig frem med en testopsætning af hver mekanisme viser
det sig i praksis at være nemmere at få børsten til at virke. Løsningen kræver at
flasken skal presses godt op mod væggen så motoren får ordentligt fat, hvilket
betyder at styringen af robotten skal være rimelig tolerant ved aflevering af
affald.
Til at finde ud af hvilken type affald der er tale om, bruger vi et webkamera. Selvom lysforholdene ændre sig drastisk i løbet af en kamp, så er det ikke
så kritisk når man kun skal detektere farve forskelle.
Batterihåndtering
Batterimekanismen blev udviklet til den planlagte robot [Han07], og da vi
synes at det er langt den bedste måde at samle batterierne op på har vi også
brugt mekanismen til den endelig robot.
Testkørseler, se tabel 2.1, har vist at en tragt i langt de fleste tilfælde virker
upåklageligt. Testen er kørt hvor batteriet er placeret således at robotten vil
køre ind i det ved kørsel ligeud. Batterierne var derudover placeret og roteret
vilkårligt. I de fleste tilfælde har batteriet lagt sig fint forenden af tragten uden at sidde fast. De gange hvor det går galt er det fordi batteriet har sat sig
fast på tværs af tragten der hvor den snæver sig ind. Dette kan løses ved at
installere en form for sensor der kan detektere hvornår et batteri sidder fast,
og foretage en manøvre så batteriet kommer helt ind. I en anden test har vi
Tilfældig placering
0. forsøg (%)
88,2
Fanget (%)
100
Mistet (%)
0
Tabel 2.1: Opsummerede resultater af batteritragt-testen (vilkårlig orientering).
netop afprøvet en manøvre vi kom frem til eksperimentelt. Den går ud på at
vi bakker lidt, drejer en anelse og derefter fortsætter ligeud. Resultaterne af
manøvren kan er vist i tabel 2.2. I testen er batterierne lagt så de lægger sig
fast i tragten, hvorefter robotten skulle udføre manøvren. Som det kan ses får
robotten næsten fat i alle batterierne efter et enkelt forsøg, og sammenholdt
med resultaterne fra tabel 2.1 ser løsningen meget lovende ud.
Idéen med batteritragten er at indsamlingen af batterier skal ske passivt,
altså at kørslen ikke afbrydes fordi robotten skal hen og aflevere et batteri. Da
robotten maksimalt må tage 4 batterier op, resten er modstanderens, fylder
en batteribeholder ikke meget. Et hurtigt overslag er 4 × 3, 3 cm ≈ 13, 5 cm,
2.1. AFFALDSHÅNDTERING
Flad side mod venstre forfra
Flad side mod højre forfra
Plus-side mod højre forfra
7
1. forsøg (%)
96
100
100
Fanget (%)
96
100
100
Mistet (%)
4
0
0
Tabel 2.2: Opsummerede resultater af batteritragt-testen (fastsiddende batteri).
hvor de 3, 3 cm er diameteren på et type D batteri. Da spillereglerne siger
at man ikke må holde på en modstanders batteri, bliver robotten nød til at
være i stand til at frasortere modstanderens batterier. Rent mekanisk kan det
gøres ved at have en lem for enden af tragten der enten er åben eller lukket
alt efter om batteriet er hhv. modstanderens eller ej. Derved undgår man at
batteriet batteriet fortsætter ud, som det vil være tilfældet hvis der ingen lem
var. Batterierne er farvekodet og til at kende forskel på farverne har vi ladet
os inspirere af Team DTU fra Eurobot 2006 [RTJH06]. De brugte to lysdioder
og en fotocelle til at se om der dels er et objekt og dels hvilken farve det har.
Batterierne skal afleveres i en skål med en kant højde på 3 cm. For at få
batteriet op i den højde, når det ligger i tragten, var der flere idéer i spil. Udgangspunktet var at udnytte batteriets magnetiske egenskaber. Det er mekanisk simplere end at f.eks.gribe om batteriet. Idéerne blev kogt ned til følgende, se figur 2.3:
(a) Lodret løft, op gennem lem
(b) Skråt løft
Figur 2.3: Idéer til batteriopsamlingen.
Lodret løft: En magnet sættes fast på en tandrem. Når batteriet ligger klar
køres magneten ned, fanger batteriet og kører op igen. Batteriet vil blive
transporteret op igennem to hængsler, der åbner i opad, og fortsætte lige
indtil der er nok plads til at hængslerne kan lukke igen. Samtidig bliver
batteriet holdt igen, således at det bliver skubbet af magneten. Det vil
resultere i at batteriet vil falde ned på de to hængsler og rulle så langt
frem som det kan i batteribeholderen.
8
KAPITEL 2. ANALYSE AF EUROBOT 2007
Skråt løft: For enden af en stang/arm fastgøres en magnet. Når batteriet ligger klar i tragten, kører armen ned indtil magneten får fat batteriet. Herefter hejser armen batteriet op ad en skrå plade. Når batteriet når toppen
af pladen vil batteriet svinge sig fri fra magneten og ned i beholderen.
Begge mekanismer er blevet testet med nogle simple mock-up modeller, men
hverken fuldt automatiseret og kørende. Det lodrette løft, figur 2.3(a), er noget
svære at lave mekanisk end løsningen nummer to.
2.2
Orientering & navigering
For at kunne navigere rundt på banen bliver robotten nødt til at kunne orientere sig. Det blev tidligt besluttet at orienteringen skulle bestå af odometri og
en laserscanner. Kamera vision blev hurtigt udelukket da tidligere års erfaringer på IAU har vist at de skiftende lysforhold under kampen er meget svære
at tage højde for og få til at virke robust. På både banen og modstanderen er
der plads til at opstille de såkaldte beacons til at hjælpe med at stedbestemme robotten. Et beacon kan f.eks. bruge infrarødt lys eller radiosignaler til at
bestemme afstanden til robotten. At lave sådan et system kræver i midlertidig meget tid, især for at gøre systemet robust. På den baggrund er brugen af
beacons fravalgt.
En metode til at finde ud af hvor robotten befinder sig er odometri, der
kort sagt går ud på at måle den kørte afstand på hjulene. Da IAU bruger odometri til SMR’erne, og det har vist sig at være tilstrækkeligt robust, findes
alle værktøjerne i vid udstrækning allerede. Odometri udmærker sig med høj
præcision ved langsom kørsel og relative korte afstande, men ved længere
kørsler bliver vinklen meget usikker da vinkelfejlen akkumuleres i løbet af
kørselen. En løsningen er at opdatere den absolutte vinkel og/eller position
ved brug af kendte landmærker. Da banen er lille og simpel, de to eneste forhindringer er modstander robotten og batteriskålen, kan robotten klare sig i
langt stykke ved brug af kun odometrien. Derudover er det kun når der skal
afleveres batterier at robotten skal bruge præcisionskørsel. Det gør det vinkelopdateringen mindre kritisk.
Det blev tidligere nævnt at robotten også er udstyret med en laserscanner.
Laserens tre funktioner er; dels at korrigere odometrien, at scanne banen for
affald og sidst finde batteriskålen i midten af banen.
2.3
Forhindringer
Det blev først overvejet om robotten skulle udstyres med en kofanger til dels
at formindske skaden ved påkørseler, men også til detektering af dem. Den
blev dog afvist til fordel af IR-afstandssensorer af flere grunde. Reglerne er
lidt uklare på det område og siger at robotten skal udvise vilje til at stoppe.
Det har vi valgt at tolke som at robotten skal reagere inden kontakt med modstanderen. Det vil selvsagt være umuligt med en kofanger da det er noget
sparsomt med plads i robotten. Derudover har IAU stortset standardiseret IRafstandssensorerne, hvilket gør det uhyggelig nemt at arbejde med dem uden
at skulle bruge for meget tid på dem.
K APITEL
Robot design - Mekanik
Robotten fra 2006 er stort set bevaret intakt. Robotten blev skrællet ned til stort
set kun det overordnede skelet, vel og mærke uden at ødelægge nogen dele.
Skulle det ønskes kan den forholdsvis nemt bygges om til dens oprindelige
funktion.
3.1
Dåse og flaske mekanik
Robotten havde nogle arme der foldede sig ud efter start, da de ikke har nogen
praktisk betydning er de fjernet. Uden armene er der plads til forøge omkredsen ca. 5 cm inden start og yderligere ca. 10 cm efter start. Det er akkurat lige
nok til at kunne montere en bøjle som vist i figur 2.2 på side 5. Da bøjlen går
for langt ud i forhold til start kravene, er det nødvendigt at den kan folde sig
ud efter start. Det mekaniske simpleste er at bøjlen rotérbar omkring den akse
hvor den sidder fast på robotten, og sætte en kile i klemme. Kilen er sat fast
til startsnoren, og vil løsne bøjlen når snoren trækkes. Selvom det betyder at
bøjlen sidder løst under kampen har det vist sig at det ikke betyder noget for
dens funktion.
Da der sidder en børstemotor på robotten i forvejen, som man kan bruge
til afleveringen af flasker og dåser, har det været et spørgsmål om at indstille
bøjlen så den virker optimalt. Se billedet i figur 3.1.
Figur 3.1: Dåse- og flaske indsamling, og aflevering med børstemotoren
9
3
10
3.2
KAPITEL 3. ROBOT DESIGN - MEKANIK
Batterihåndtering
Der akkurat var plads til installere batteritragten i bunden af robotten uden at
bore eller fræse i robotten.
Det blev indset den første løsningen ikke var en reel mulighed, grundet
pladsmangel i robotten. Løsning nummer to blev afprøvet med forskellige typer arme for at se hvilken der ville være den bedste. Hvis armen kun skulle
bestå af en lige stang, som i vores mock-up, ville den stikke langt ud fra robotten. Derfor eksperimenterede vi med arme der havde flere led. Den bedste var
en to-delt arm, forbundet med en fjeder for at efterligne den samme lineære
bevægelse som stangen. Resultatet kan ses på billedet i figur 3.2. Som det kan
Figur 3.2: Batterimekanismen
ses blev den endelige konstruktion noget anderledes end den originale idé
der er illustreret på figur 2.3(b). Løsningen blev modificeret så en servomotor
kunne bruges som drivkraft.
På billedet kan det også ses at for enden af batteribeholderen er der en
roterende låge. Lågen er styret af en servomotor.
3.3
Laserscanner
Da den originale robot fra Eurobot 2006 kørte med samme type laserscanner
er der allerede lavet en beskyttende holder til laseren. Det mindst element
på banen er et type D batteri med dens diameter på 3,2 cm. Højden til selve
laserhovedet er ca. 2,3 cm over banen, hvilket er lavt nok til at se alle elementer
på banen.
K APITEL
Robot design - Elektronik
Udover det mekaniske er der også taget udgangspunkt i Eurobot 2006 robotten med henblik på elektronikken. Systemet er opbygget omkring et mini-ITX
bundkort tilsluttet IAUs SMR komponenter.
4.1
SMR komponenter
Fordelen ved SMR komponenterne er at de er let tilgængelige, gennemtestet
og stabile. I robotten er der blevet brugt følgende SMR-komponenter:
Strømforsyning der leverer 12 V til alle SMR-modulerne og motorerne.
Bus-converter der forbinder bundkortet og SMR-modulerne ved at konvertere signalerne mellem de to forskellige seriel protokoller RS-485 ⇐⇒
RS-232 ??.
Motorcontroller ×2, en til hvert hjul. Udover at styre hjulene giver motorcontrollerne også information om hvert hjuls position som bruges til odometri, og til at se om startsnoren er trukket.
Linjesensor-kortet består blandt andet af otte fotoceller og ni lysdioder, der
alle sidder på linje. Modulet bruges normalt til at finde og f.eks. følge
linjer, men på robotten bruger vi det som en grænseflade for lysdioder
og fotoceller.
IR-sensor-kortet er en grænseflade mellem IR-sensorerne og SMR-bussen.
Servo-kortet styrer servomotorerne på robotten. Kortet blev lavet til Eurobot
2005 [SJHJ05] og blev revideret til Eurobot 2006 [RTJH06].
“kick”-kortet er lavet til en fodboldspillende robot [VCPSKT06]. Robotten
bruger kortet til at styre børstemotoren via servokortet.
laserscanneren er forbundet direkte til bundkortet via USB.
webkameraet er ligesom laserscanneren forbundet via USB til bundkortet.
En oversigt over forbindelserne kan ses på illustrationen i figur 4.1. Alle SMRkomponenterne er brugt i deres originale tilstand på nær linjesensorkortet,
der stammer fra Eurobot 2006 robotten. Alle lysdioder og fotoceller er blevet
erstattet med stik så de kan placeres hvor det er passende. Det har betydet at
forbindelserne til fotocellerne og dioderne ikke har været lige så stabil, som
hvis de var loddet direkte på printet.
11
4
12
KAPITEL 4. ROBOT DESIGN - ELEKTRONIK
Figur 4.1: Elektroniske forbindelser mellem de forskellige komponenter.
4.2
Startsnor
I følge reglerne skal robotten startes på afstand ved at hive i en snor. Robotten havde i forvejen et startsnor-system og det viste sig at være meget stabilt
under Eurobot 2006 [RTJH06], derfor blev det besluttet at beholde systemet.
Selve kablet består af en snor bundet til et RCA-stik. Stikket kortslutter to ben
på venstre motorcontroller hvilket sætter status-bit 7 høj.
4.3
Børstemotor
Til at aflevere dåserne og flasker bruges der en børste der er sat til en DCmotor. Modsat Eurobot 2006 robotten skal motoren køre den modsatte vej
rundt og skal kunne tændes og slukkes fra softwaren.
For at kunne styre motoren er der blevet brugt et print fra en fodboldspillende robot [VCPSKT06]. Printet omsætter et lavspændingssignal fra f.eks.
en mikroprocessor til en spænding der er stor nok til at drive en DC-motor.
Selve styre signalet kommer fra et ledigt ben på mikroprocessoren der styrer
servomotorerne, så for at kunne tænde og slukke for børstemotoren skal ben
PORTA7 sættes henholdsvis høj og lav.
4.4. LASERSCANNER
4.4
13
Laserscanner
Robotten er udstyret med en URG-04LX USB laserscanner fra Hokuyo. Med
en præcision på ±10mm og en opløsning på 0.36◦ er det en højpræcisions
og højopløsnings laser. Da der på IAU er der allerede udviklet software der
understøtter denne type laser, og da IAU har gode erfaringer med laseren
[RTJH06] faldt valget på denne laserscanner. Laserscanneren falder under kategorien “Laser Safety Class 1” og dermed opfylder den Eurobot 2007 reglerne
(se bilag A) vedrørende styrken på lasere der må tages i brug.
Da den samme laserscanner var brugt i robotten fra Eurobot 2006 skulle
der ikke laves nogle modifikationer til robotten for at få laseren til at virke.
4.5
Farve-sensorer
Designet kræver at robotten kan kende forskel på dels egne og modstanderens
batterier, og dels flasker og dåser.
Batterier
Da den eneste forskel på batterierne er deres farve kræver det at robotten har
en form for syn. Der blev valgt en simpel løsningen bestående af en lysdiode og to fotoceller. Dioden og fotocellerne kan kobles direkte til linesensorkomponenten. Som det kan ses på illustrationen i figur 4.2 er de to fotoceller
Figur 4.2: Farvesensor.
monteret overfor hinanden og lysdioden sidder ved siden af den ene. Ideen
er at den ene sensor skal kunne detektere en farveændring og den anden skal
kunne se om der ligger et batteri eller ej. Når der kommer et batteri ind i tragten vil batteriet afbryde lyset fra dioden til fotocellen på den anden side, og
dermed vil den virke som en batterisensor. På grund af at det røde batteri reflekterer den røde lysdiodes lys i lang højere grad end det blå batteri, kan den
fotocelle se røde batterier. Det viser sig at det blå batteri slet ikke giver udslag.
Et rødt batteri vil give udslag på begge fotoceller hvorimod et blåt batteri kun
vil kunne ses på at lyset bliver afbrudt til den ene fotocelle. På den baggrund
kan vi finde ud af om det er et rødt eller blåt batteri der ligger i tragten ved
følgende boolsk-algebra:
Blå = F1 F2
Rød = F1 F2
14
KAPITEL 4. ROBOT DESIGN - ELEKTRONIK
hvor F1|2 er defineret ved grænseværdier. Grænseværdierne afhænger af kalibreringen, men som det kan ses på graferne i figur 4.3 er det tydeligt at der
er tale om henholdsvis intet batteri, et blåt batteri og et rødt batteri.
(a) Blåt batteri i tragt
(b) Rødt batteri i tragt
Figur 4.3: Batteri test.
Flasker og dåser
Da flaskerne og dåserne ligger foran robotten under transporten, er det nødvendigt at kunne skelne mellem dem for at kunne putte dem i de korrekte
kurve. Der kan ikke bruges samme metode med lysdiode og fotocelle som ved
batteri farve-detektering, der er alt for store udsving på sensoren på grund
af lysforhold og afstanden. Istedet bruges der et standard USB webkamera.
IAUs erfaringer [RTJH06, SJHJ05] er at det generelt er for ustabilt at bruge kamerabaseret navigering på grund af lysforholdene under konkurrencen. Da
kameraet ikke skal bruge til navigering men til at se farveforskelle er det ikke
et lige så stort problem. For at undgå eventuelle problemer med lys udsendt i
det infrarøde spektrum, blev der til kameraet valgt en optik med et infrarødt
filter. På figur 4.4 er vist det påmonterede webkamera.
4.6
Batteri-sensor
Som nævnt i kapitel 2 under Batterihåndtering kan det hænde at batterierne
sætter sig fast på tværs i tragten. For at få batteriet fri kræver det at robotten
udfører en specifik manøvre, hvilket kræver at robotten skal vide hvornår et
batteri sidder fast i tragten.
Den første løsning byggede på samme princip som bliver brugt til at se om
der ligger et batteri for enden af tragten; en lysdiode lyser fra den ene side over
på en fotocelle i den modsatte side af tragten. Når et batteri kommer forbi eller
sætter sig fast vil lyset blive afbrudt, og dermed blive opdaget. Det har dog
vist sig at være omstændigt at få metoden til at virke pålidelig i længere tid ad
gangen. Fejlen er i stor grad blevet tildelt lysforholdene i tragtens udmunding,
andelen af lys udefra er langt større end andelen af lys fra dioden.
I stedet blev en IR-afstandssensor påsat op over tragtens indsnævring, se
billedet på figur 4.5. Da afstanden til banen er stort set konstant er blot at
4.6. BATTERI-SENSOR
Figur 4.4: Webkameraet ses her fast gjort med gule strips
Figur 4.5: IR-Sensoren sidder over tragten, i det kritiskeområde
15
16
KAPITEL 4. ROBOT DESIGN - ELEKTRONIK
kigge efter en afstandsændring. Løsningen med IR-afstandssensoren har vist
sig mere robust end den først tiltænkte fotocelle/lysdiode løsning.
4.7
Detektering af modstander
På IAU bruger SMR’erne som standard infrarøde afstandssensorer til at se
forhindringer med. Derfor har det været oplagt at bruge disse sensorer da de
har vist sig effektive og nemme at arbejde med. Som på SMR’erne er der blevet
påsat tre IR-afstandssensorer i fronten af robotten, de kan ses på billedet i figur
4.6.
Figur 4.6: I toppen kan de tre IR-afstandsensorer ses.
På billedet kan det ses at alle tre IR-sensorer er sat til at pege fremad og
ikke ud til siderne. Da sensorerne nogle gang kan blive snydt af refleksioner
og farver, er det derfor mest sikkert at kræve at to sensorer samtidigt kan se
modstander robotten. Det kan kun lade sig gøre fordi robotterne skal være
tilpas store ifølge reglerne, så de ikke kan forveksles med andre objekter på
banen.
Stolperne i målhjørnerne og midtbanden er dækket af reflektivt tape. Det
har de ulemper at de infrarødesensorer dels opfatter afstanden til refleksen
som meget kortere end den egentlig er, og dels får sensorerne meget nemt øje
på refleksen. Praktisk talt er det umuligt at have sensorerne til at pege lige
ud da IR-sensorerne hele tiden vil tro at modstanderen er nær, selvom det
er en refleks robotten har fået øje på. Problemet er blevet løst delvist ved at
dreje IR-sensorerne ned mod jorden og derved indskrænke deres synsfelt, og
delvist i softwaren. Når robotten kommer tættere på stolperne vil refleksen,
og stolperne for den sags skyld, komme ind i synsfeltet og kan fejlagtigt blive
opfattet som modstanderen. Men når robotten er så tæt på kanten kan det helt
udelukkes at der er en modstander i mellem robotten og kanten, det vil sige
IR-sensorerne kan ignoreres indtil robotten igen drejer væk fra kanten.
K APITEL
Software
Computeren på robotten kører en specielt tilpasset version af GNU/Linux for
at fungere på IAUs SMR’er. Til at kommunikere med SMR-modulerne har IAU skrevet programmet SMRdemo. I den sammenhæng har de også lavet et
script-sprog kaldet SMR-CL, se bilag B for vejledning, til at styre robotten med
simple kommandoer som forward 1, der kører robotten 1 meter frem. SMRCL er dog ikke særligt avanceret sprog, jvf. bilag B, og det er derfor mere praktisk at bruge et programmeringssprog som C til mere elegante og omfattende
programmer. Da SMRdemo kan køre i server tilstand, og da alle de basale
funktioner er implementeret, blev det besluttet at kode hovedprogrammet i
C og lade det forbinde sig til SMRdemo serveren. Kommunikationen mellem
C programmet og SMRdemo serveren foregår ved hjælp af nogle funktioner
skrevet i C kode (bilag C.2) til Eurobot 2005 [SJHJ05], der brugte samme program opdeling. Hele kildekoden kan ses i bilag C.
Figur 5.1: Hardware/software oversigt
Følgende funktioner er skrevet i haupt.c, bilag C.1, med mindre andet er
skrevet.
17
5
18
5.1
KAPITEL 5. SOFTWARE
SMRdemo server
Når SMRdemo kører i server tilstand opfører programmet sig en smule anderledes end ved normal brug. Når en ny kommando modtages tildeles den
et unikt ID, som er et fortløbende nummer, og den lægges bagerst i kommandokøen. Når en kommando er udført sender SMRdemo svar tilbage med det
tilsvarende ID og en stopbetingelse. Stopbetingelsen kan enten være at kommandoen blev udført, eller også er det en brugerdefineret stopbetingelse. Klienten kan angive en tidshorisont når der forspørges om nye begivenheder,
events. Hvis der ikke er nogen stopbetingelser indenfor tidshorisonten sender serveren et event timeout så klienten ved at der er gået for lang tid.
5.2
Start & slut funktioner
void initialize(); linje 250 – 258
Funktionen sender udelukkende SMR-CL kommandoer til SMRdemo. Først
bliver SMRdemos logfunktion sat til at logge odometri-, linesensor- og irsensordata. Dernæst bliver alle servomotorerne sat til start position og børstemotoren stoppet.
void finalize(); linje 250 – 258
Funktionen sender SMR-CL kommandoer der sætter servomotorerne til den
ønskede slut position. Sluk derudover for dels motorerne og dels for børstemotoren.
void waitForCable(); linje 284 – 316
Først tjekker funktionen om startkablet sidder i stikket, ved hjælp af en løkke.
Når det bliver detekteret at startkablet er isat går funktionen videre til næste
løkke hvor der bliver tjekket for om startkablet er hevet ud. I begge løkker
bliver der taget gennemsnittet af værdien $motorstatusr for at sikre sig
at der ikke er tale om en strøm/bit-spike et sted i systemet. Til sidst starter
funktionen den nedtællings alarm der er påkrævet af reglerne, på 90 sekunder.
Alarmen er sat til kalde catchAlarm() som et SIGALRM signal, når den er
udløbet.
void catchAlam(int sig); linje 273 – 279
sig er signaltypen, her vil den dog altid være SIGALRM.
Når denne funktion bliver kaldt betyder det at kampen er ovre, derfor kaldes finalize() for at slukke for alle bevægende dele på robotten. Derefter
bliver forbindelsen til SMRdemo afsluttet og programmet afsluttes.
5.3
Fejlhåndtering
SMRdemo venter på at SMR-CL kommandoerne er udført før næste kommando bliver udført. Det kan dog gå galt når der køres på grund af præcisionen
eller udvendige begivenheder, f.eks. hvis robotten bliver bedt om at køre 0.005
5.4. BASALE KØRSELSFUNKTIONER
19
cm så rykker den sig ikke ud af stedet, og da den tjekker odometrien for at se
om der nogensinde blev kørt den korte afstand så viser odometrien at robotten
ikke har flyttet sig og programmet går en uendelig løkke. Hvis først robotten
er sat til at køre f.eks. 2 meter frem, så er det også vigtigt at den stopper hvis
den ser modstanderen således at programmet kan reagere på forhindringen.
Hvor det første eksempel kan blive fanget af et event timeout, så kræver
det andet eksempel at der bliver indsat stopbetingelser for at tage højde for at
programmerne kører asynkront.
Hvis robotten kører ind i noget eller hvis hjulene bliver blokeret på anden måde, sender serveren i stedet for motioncontrol blocked. SMRdemo tillader ikke robotten at køre videre før den har modtaget kommandoen resetmotors. For at rydde kommandokøen kan der sendes flushcmds.
På grund af måden SMRdemo virker internt er det nødvendigt også at kalde
targethere for at robotten ikke tror at den er et andet sted end den er.
void getID(id); linje 771 – 776
Som skrevet tildeler SMRdemo, i server tilstand, hver modtaget kommando
med et unikt nummer. Dette nummer bliver returneret når en kommando er
modtaget. For at gemme dette id i variablen id, kaldes getID(id) lige umiddelbart efter der er sendt en SMR-CL kommando.
int isStopped(id, stopcond); linje 759 – 766
Parameteren id kan fåes ved brug af getID(). Derimod afhænger stopcond
parameteren af rækkefølgen på de stopbetingelser afgivet af kommandoen,
som f.eks. ved forward(), hvor netop stopbetingelsen for detektering af
modstanderen er 2.000000 da det er betingelse nummer 2.
Funktionen returnerer 1 når eventet indholder både id og stopcond, ellers
bliver 0 returneret.
int checkStopConditions(id); linje 1445 – 1503
Parameteren id er det unikke SMR kommando id getID() gemmer.
Funktionen er basalt en løkke der først afbrydes når der er modtaget et
nyt event fra SMRdemo serveren der matcher en af de typer der testes for
i løkken. Der bliver først testet for om motorerne er blokerede, dernæst om
modstanderen er at få øje på, så testes der om der sidder et batteri fast i tragten, dernæst testes der for om kommandoen er udført og sidst testes der om
det er et event timeout.
Funktionen returnerer et enum af typen event der kan have følgende værdier: cmd_complete, motors_blocked, battery_stuck, opponent_detected
eller event_timeout.
5.4
Basale kørselsfunktioner
Hjælpe funktionerne forward(), turn() og turnr() blev introduceret for
at øge læsbarheden af koden, og for at gøre den mere struktureret ved at samle
stopbetingelserne et sted.
20
KAPITEL 5. SOFTWARE
void forward(dist, speed); linje 406 – 410
Parametrene dist og speed svarer til SMR-CLs, se bilag B. Derudover bliver
der også sat to stopbetingelser. Den første betingelse er til at håndtere hvis IRsensoren i tragten spotter et batteri. Den anden stopbetingelse ser om mindst
to af de tre front IR-sensorer ser en modstander tæt på. Grænseværdierne for
hver af IR-sensorerne er givet ved konstanterne IRBAT_THR, IRLEFT_THR,
IRMIDDLE_THR og IRRIGHT_THR, hvor den første grænseværdi er for IRsensoren i batteritragten.
void turn(angle, using_rad, speed); linje 415 – 420
Parametrene angle og speed svarer til SMR-CLs, se bilag B. Parameteren
using_rad bruges som en boolsk variable for at tjekke om vinklen er angivet
i radianer eller i grader.
void turnr(radius, angle, using_rad, speed); linje 425
– 430
Parametrene radius, angle og speed svarer til SMR-CLs, se bilag B. Parameteren using_rad bruges som en boolsk variable for at tjekke om vinklen
er angivet i radianer eller i grader.
void getPosition(); linje 1157 – 1164
Funktionen gemmer robottens odometri position og vinkel i en datastruktur
i C programmet. Fra SMRdemo bliver variablene $odox, $odoy og $odoth
gemt i curLoc, en global struct der indeholder koordinaterne x, y og θ.
5.5
Kamera
Robotsyn i form af laser og kamera har været og er til stadighed under udvikling af Christian Andersen ved IAU, Ørsted•DTU. Der er udviklet dels en
laser-server (ulmsserver) og dels en kamera-server (ucamserver). Begge
servere er ment til brug sammen med en TCP/IP klient som f.eks. telnet eller den klient der også er lavet som et eksempel (uclient). I SMRdemo er
serverne delvist understøttede, det vil sige at kunne nogle funktioner giver
returværdier som SMRdemo kan forstå. For at sende en kommando til lasereller kamera-serveren bruges henholdsvis SMR-CL kommandoerne laser og
vision.
Kameraet skal bruges til først at se om robotten har fanget noget affald,
og dels skal det bruges til at skelne om affaldet er en dåse eller en flaske. Den
funktionalitet er implementeret i plugin-modulet myfunc, et eksempel plugin
der følger med aurobotservers. Koden følger samme struktur som resten
af plugin-modulet hvilket er i form af hjælpefunktioner der klarer fortolkning
af kommandoen, imens selve udregningen klares i en anden funktion. Her
gennemgåes kun selve udregningen da hjælpefunktionen er godt dokumenteret i bilag C.4. Fra klienten kan funktionen kaldes med kommandoen BOC.
5.5. KAMERA
21
calcBottleOrCan(); myfunc.cpp linje 565 – 719
I figur 5.2(a) er vist det billede som kameraet ser, læg mærke til at bøjlen er
slået ned. For ikke at komme til at detektere affald der er udenfor bøjlen el-
(a) Ubearbejdet udsyn
(b) Udsyn med ROI
Figur 5.2: Robottens udsyn.
ler detektere noget inden i robotten, bliver der som standard kun kigget på
arealet fra bøjlen og ind til børsten. Et sådan område kaldes også et Range Of
Interest eller ROI. ROI området kan dog redefineres med areal-parametrene
w og h, og med offset-parametrene x og y. På billedet i figur 5.2(b) er ROI
markeret med en rød firkant.
Dåserne og flaskerne hver deres farve henholdsvis gul og grøn. Farveintensiteterne af en flaske og en dåse i både RGB og i YUV domæne er vist i figur
5.3. Det ses at det er nemmest at skelne mellem den gule og den grønne farve
i YUV diagrammet og derfor vil YUV formatet blive brugt til udregningerne.
Hver pixel indenfor ROI bliver tjekket for om både U og V koordinaterne
er indenfor et tolerance område defineret af parametrene thresholdCanU,
thresholdCanV, thresholdBottleU og thresholdBottleV. Hvis en pixel
er indenfor en af de to områder bliver den talt med som enten en dåse eller en
flaske pixel. Når alle pixel indenfor ROI er gennemløbet bliver sandsynligheden for om der er en dåse og/eller en flaske tilstede, udregnet som
P =
optalt antal pixel
,
tolerance antal
hvor tolerance antal er givet af parametrene areaCan og areaBottle. De
udregnede sandsynligheder for fem forskellige tilfælde kan ses i tabel 5.1. De
syv tilfælde er når der ikke ligger noget affald foran robotten, når robotten har
fanget henholdsvis en dåse og en flaske, når en flaske eller dåse står vinkelret
på robotten, og de sidste to tilfælde er når der ligger henholdsvis en dåse
eller en flaske lige foran bøjlen. Som det fremgår af tabellen kan der altså med
rimelighed afgøres hvornår der ligger en flaske og hvornår der ligger en dåse
indenfor bøjlen.
For grafisk at kunne analysere hvad der bliver detekteret bliver hver pixel
farvet i forskellige farve alt om det er en flaske eller en dåse pixel. Ydermere
bliver Center of Gravity også markeret. Eksempler kan ses på billederne i figur
5.4.
For at SMRdemo kan forstå resultatet af SMR-CL kommandoen vision
skal svaret være i formatet
22
KAPITEL 5. SOFTWARE
(a) UV-diagram for dåse
(b) RGB-diagram for dåse
(c) UV-diagram for flaske
(d) RGB-diagram for flaske
Figur 5.3: Farvespektra for en dåse og en flaske, taget med funktionerne UV og
CHROMA i uclient.
<vision vis0="værdi0" . . . vis9="værdi9"/>
De to eneste værdier robotten skal bruge for er sandsynligheden for om der
ligger en flaske eller/og en dåse. Derfor bliver tekststrengen
<vision vis0="pCan" vis1="pBottle"/>\n",
hvor pCan og pBottle bliver erstattet med de faktiske værdier, sendt til SMRdemo. I SMRdemo kan værdierne læses ud med $vis0 og $vis1.
void hasItem(); linje 882 – 909
Funktionen sender følgende SMR-CL kommando til SMRdemo for at få input
fra webkameraet:
5.6. DÅSE OG FLASKE AFLEVERING
Intet affald
Dåse, fanget
Flaske, fanget
Dåse, vinkelret
Flaske, vinkelret
Dåse, foran bøjlen
Flaske, foran bøjlen
23
pCan
0.000
0.992
0.002
0.520
0.004
0.506
0.002
pBottle
0.000
0.000
1.642
0.000
0.000
0.000
0.009
Tabel 5.1: Udregnede sandsynligheder for at der ligger en dåse eller en flaske,
med standard toleranceværdier.
(a) Dåse
(b) Flaske
Figur 5.4: Et par eksempler med BOC kommandoen.
vision "BOC thresholdCanU=CanU_THR
thresholdCanV=CanV_THR
thresholdBottleU=BottleU_THR
thresholdBottleV=BottleV_THR"
, hvor CanU_THR, CanV_THR, BottleU_THR og BottleV_THR er konstanter.
Som alle andre sensorer bliver kommandoen kaldt seks gange og resultatet
midlet således at usikkerheden og fejl minimeres. Gennemsnittene avg_pCan
og avg_pBottle tjekkes derefter om de er større end tolerance værdierne PROB_CAN
og PROB_BOTTLE. Er det tilfældet, antages det at affaldet er af den type der
har den største sandsynlighed. Hvis begge værdier er under tolerance konstanterne antages at det der ikke er fanget noget affald.
Funktionen sætter den globalt defineret enum variabel item til enten can,
bottle eller none hvis der ikke er fanget noget affald.
5.6
Dåse og flaske aflevering
Afleveringen af flasker og dåser består af to funktioner: toBasket() og deliver().
24
KAPITEL 5. SOFTWARE
toBasket(); linje 913 – 977
Når en flaske eller dåse er indfanget med collectItem()1 , bliver toBasket()
kaldt umiddelbart efter. Overordnet set kører funktionen robotten på plads
foran den affaldskurv hvor det indfangede affald skal afleveres. Det gøres
ved at kalde gotoPosition(bin);2 der får robotten til at køre hen til den
korrekte kurv og vende sig mod den, derefter køres der 15 cm tætter på.
Til at undersøge hvilken stopbetingelse der har stoppet robotten bruges
checkStopConditions(id) som tidligere beskrevet. Begivenhederne deles op i tre tilfælde; blokerede motorer, kommando udført, og andre. Hvis
kommandoen er udført afsluttes funktionen ved at sætte den globale variabel
toBasket_done til 1. Hvis motorerne er blokerede bakker robotten 10 cm og
prøver derefter igen. I de andre tilfælde prøver den at sende gotoPosition
kommandoen igen.
void deliver(); linje 982 – 1039
Funktionen er ment at blive kaldt efter toBasket() for at sikre at robotten
er tæt ved affaldskurvene.
Når kaldt, vil funktionen sende kommandoen drive til SMRdemo der
får robotten til at køre ligeud uden at stoppe. Det vil sige at den eneste måde den kan stoppe på er ved at motorerne bliver blokeret eller ved at stoppe
den direkte ved at modtage et event_timeout. Når motorerne bliver blokeret antages det derfor at robotten har ramt kanten eller noget affald der
ligger i vejen. Da børstemotoren kan skyde affaldet over noget affald der eventuelt skulle ligge i vejen, er dette intet problem. Robotten bliver derefter
sat til at bakke 2 cm, det er nødvendigt for at kunne starte børstemotoren uden at ligge pres på affaldet. Først når børstemotoren er oppe i omdrejninger
kan der ligges pres på. Når robotten har bakket bliver børstemotoren tændt
med SMR-CL kommandoen rs485send 10 8. Robotten kører derefter 2 cm
frem, for at lægge pres på affaldet, venter et sekund og slukker børstemotoren
med rs485send 10 9. Nu skulle affaldet gerne være afleveret og robotten
bakker 10 cm, for gøre sig fri fra kanten så den kan dreje.
For at sikre sig at affaldet rent faktisk er blevet afleveret eller at robotten
ikke har fanget mere affald af samme type, kaldes funktionen hasItem().
Hvis det viser sig at robotten stadig har noget affald af samme type som den
lige har afleveret, forsøger den forfra med at aflevere det.
Når funktionen er færdig bliver den globale variabel deliver_done sat til 1.
Børstemotor
I kapitel 4.3 blev det nævnt at for at kunne styre børstemotoren, skulle ben
PORTA7 sættes høj og lav i servo-mikroprocessoren.
For at kunne tale med SMRdemo er der i stil med resten af Communication.c
(bilag C.7) blevet indført to nye flags; kick_dc_on_f lag og kick_dc_of f _f lag.
De er blevet tilføjet som henholdsvis kommando 8 og 9, hvilket vil sige at de
fra SMRdemo kan kaldes med kommandoen rs485send 10 x, hvor x er
kommando nummeret. De to flags aktiverer henholdsvis kick_dc_on() og
1 Beskrevet
2 Beskrevet
af Brian Hansen (s042307) [Han07]
af Shayantharan Sivarajalingam (s042297), ultimo juni 2007
5.6. DÅSE OG FLASKE AFLEVERING
25
kick_dc_off() i Servostyring.c (bilag C.9). Funktionen kick_dc_on()
sætter således blot ben PORTA7 høj, og kick_dc_off() sætter benet lav.
K APITEL
Designevaluering
Dette kapitel vil handle om det endelige robotdesign set i perspektiv til de
konkurrerende holds robotter der deltog i Eurobot 2007 konkurrencen. Da det
er en konkurrence har holdene holdt tæt med deres design ideer, de eneste
ledestråde har været gennem de spørgsmål folk har stilet i de officielle F.A.Q.
(se bilag A).
6.1
Designkoncepter
Hvor vores robot er designet med henblik på at samle alle tre typer affald op,
var det ikke normen blandt de deltagende hold. De fleste hold koncentrerede
sig kun om dåser og batteri, og en del udelukkende om enten dåser eller batterier. Tendensen var at de hold der gik efter flasker også gik efter både dåser
og batterier.
Dåser & flasker
Som man kan forvente af sådan en konkurrence gik mange af designprincipperne igen. Vores koncept med at indfange affaldet med en bøjle blev dog ikke
set brugt af noget andet hold, så der kan ikke blive nogle direkte sammenligning. Til gengæld var det udbredt at køre op mod kanterne for at få affaldet
ind i robotten, selv de par af de robotter der endte i finale runderne brugte
denne løsning. En anden udbredt metode at få affaldet ind i robotten på var
at bruge et system af børster, som i en vaske hal, der til tider kunne præstere
at skyde affaldet ind i robotten. En sådan robot er vist på figur 6.1. En af de
mest udbredte metoder til indsamlingen af dåserne og flaskerne var at bruge
en roterende skovl eller børste, se billerne i figur 6.2. Nogle af dem kunne
detektere når en flaske prøvede at komme op eller sad fast, og kunne derefter
give slip på den igen. Det var de samme hold der kun gik efter dåser og ikke
flasker. De hold der prøvede at få flasker op med denne metode endte ofte
deres kampe med at en flaske sad fast. Omkring halvdelen af de robotter der
brugte denne metode var nødsaget til at køre op mod kanten for at få dåsen
eller flasken helt ind, hvorimod den anden halvdel klarede sig fint uden.
En lige så udbredt metode til at aflevering af dåserne og flaskerne var at
skyde dem af sted på tværs af banen. Den åbenlyse fordel ved denne metode
er at robotten sparer den tid det vil tage at køre frem og tilbage til affaldskurven. I praksis viste det sig ofte at være en dårlig løsning, i hvert fald var
der mange af robotterne der kun ramte kurvene hver anden eller hver tredje
gang. Der var nogle robotter der ramte modstander robotten, hvilket kunne
have været fatalt for nogle af de medvirkende robotter, og nogle få skød så
27
6
28
KAPITEL 6. DESIGNEVALUERING
Figur 6.1: Club Elek der endte på en 3. plads.
Figur 6.2: Felbot benyttede sig af et møllehjul.
6.1. DESIGNKONCEPTER
29
meget ved siden af kurvene at de kunne have ramt tilskuerne. Kun få at de
skydende robotter havde problemer med selve skydemekanismen.
Batterier
Magneter var den klart mest fortrukne metode at samle batterierne op med.
Den mest innovative batteri opsamlings løsning må have været det engelske
holds løsning. De havde monteret en roterende magnet, og en roterende pind.
Når batteriet blev fanget af magneten drejede den rundt så batteriet kom højere op i robotten, hvorefter pinden ville skubbe batteriet af magneten. Ikke
nok med at denne løsning var effektiv, var den også betydelig mere kompakt
og mere simpel end den løsning der er brugt i dette projekt. En anden metode
var at bruge den roterende skovl, som robotterne også brugte til dåse og flaske opsamlingen, til at skovle batterierne op. Det var dog ikke alle der havde
kraft og præcision nok til at kunne få batterierne op med skovlen.
Blandt de hold der indsamlede batterier var det omkring halvdelen, der
som i vores robot, gemte batterierne inden i robotten og afleverede dem senere, og halvdelen der afleverede batteriet med det samme.
De specielle
Der var to robotter der skilte sig ud fra mængden, navnlig det franske hold
der vandt Eurobot 2007 RCVA, og den spanske Ackrobot der fik designprisen.
RCVAs robot var udstyret med to identiske arme, en på hver side, der hver
havde en sugekop for enden. Robotten kunne således tage en flaske eller dåse
og gemme den i toppen af robotten hvor der i alt var plads til fire flasker
eller dåser, to på hver side. Armene blev også brugt til at aflevere affaldet i
Figur 6.3: RCVA, vinderen af Eurobot 2007 i færd med at tage en flaske.
kurvene. På figur 6.3 er der et billede af den vindende robot. RCVA klarede
sig ofte uden problemer, men i finalerunden hvor den virkelig blev udfordret
var det tydeligt at der kunne være problemer med opsamlingen af flasker og
30
KAPITEL 6. DESIGNEVALUERING
dåser når de trillede idet sugekoppen prøvede at få fat. Havde sugekoppen
først fået fat var det stykke affald så godt som afleveret, det gik sjældent galt.
Vinderen af designprisen, Ackrobot, brugte også en robot arm. Forskellen fra RCVAs robotarme var at Ackrobots robotarm havde en langt større
frihedsgrad og at det er en såkaldt portalrobot. På billedet i figur 6.4 ses Ackrobot. Trods Ackrobots avanceret robotarm og objekt genkendelse software
Figur 6.4: Acrobot og sin avanceret robotarm
endte den på en delt 25. plads. Når den virkede, gik det virkelig hurtigt med
at få afleveret affaldet. Problemet så dog ud til at være med objektgenkendelsen og ikke selve robotarmen.
6.2
Mekanik
Konkurrencen bar præg af en generel høj mekanisk indsigt. De fleste robotter benyttede sig af smarte og til tider meget avanceret mekanik. Mange af de
mekanisk virkelig smarte robotter endte i finale runderne, men der var også
undtagelser som f.eks. med Ackrobot der aldrig nåede så langt. På den anden
side var der også mange robotter der lignede noget hastværk, og som ikke
var særligt robuste. Robotterne µ der endte på en 9. plads og MIBE der endte på en 7. plads, var begge mekaniske simple og konstruktionerne så noget
tvivlsomme ud.
6.3
Elektronik
Hvor de fleste hold var mekaniske stærke, var det de færreste der ikke havde
elektroniske problemer. Der er kun en ting der er værre end at sidde og debugge kode kort for en kamp, det er at debugge elektriske kredsløb. Her viste
SMR-komponenterne deres værd ved i kraft af at være gennemtestet og utrolige stabile. Ligeledes kunne det ses at hold der havde deltaget i flere år og
genbrugte komponenterne klarede sig generelt bedre end deres modstandere.
6.4. AUTONOMITET
31
F.eks. kan det nævnes at alle i top tre har genbrugt mange komponenter fra
de tidligere år.
De fleste robotter brugte mikrocontrollere til at styre robotten. Overfor et
PC-baseret system er der flere fordele:
• Hurtigere opstart, hvilket gør det nemmere at håndtere robotten under
konkurrencen
• Mindre strømforbrug, gør dels levetiden længere eller muliggør mindre
batterier.
• Mikrocontrollerne er fysik langt mindre end et PC-baseret system.
Et PC-baseret system skalerer dog langt bedre og er mere kraftfuld.
Det var udbredt at bruge både IR-sensorer, fotoceller, kameraer, sonarer,
støddæmpere og simple kontakter, der så ikke ud til at være en overvægt at
den ene eller den anden type. Blandt de mere eksotiske sensorer var laserscanneren, også vores robot også er udstyret med, og beacons. De beacon der
blev brugt var alt lige fra laser/spejl opsætning til radiobølger til infrarødt lys.
Næsten alle hold der brugte beacon havde problemer med dem på eller andet
tidspunkt i løbet af konkurrencen.
6.4
Autonomitet
Konkurrencen bygger på at robotterne er selvtænkende i en vis udstrækning.
Det blev dog klart under finalerunderne at man kunne langt uden at robotten
var helt autonom. Den før omtalte robot µ kørte i ring ved sin kurv for at lede
efter affald, men der var intet affald på dens side af banen. Det vil sige at den
kørte rundt i håb om at finde noget at samle op, men kunne ikke se at affaldet
lå længere væk.
Mere generelt kan det siges at konkurrencen sagtens kunne klares uden
at robotten var helt autonom. De hold vis robot var autonom klarede sig dog
generelt bedre end dem vis ikke gjorde, men der var også undtagelser. Det
kom til syne når kollisioner skulle undgås.
Antikollision
Det virkede som de fleste hold ikke havde brugt megen tid på Obstacle Avoidance, selvom det blev fremhævet meget tydeligt i F.A.Q. #3 (Se bilag A.4). Det
var alt lige fra detekteringen af modstanderen til håndteringen der gik galt.
Mange hold havde problemer med det reflekstape der sidder på stolperne,
det fik robotten til at fejlbedømme afstanden til modstanderen. Der kun er to
udfald ved fejlbedømmelser; enten tror robotten at den er tættere på end den
i virkeligheden er og prøver derfor at udføre sin undvigelsesmanøvre, eller så
tror robotten at modstanderen er længere væk og kører frontalt ind i den. Det
så ikke umiddelbart ud til at være betinget af hvilken type afstandssensor der
blev brugt, både blandt de hold de gik godt for og de hold det gik skidt for.
Halvdelen, hvis ikke flere, kampe endte med at robotterne så hinanden og
stoppede. Hvis ikke begge robotter stoppede helt op, så gjorde modstanderens
robot, det var næsten mere regelen end undtagelsen. Sammenholdt med det
faktum at en del robotter fejlbedømte afstanden til modstanderen og troede at
32
KAPITEL 6. DESIGNEVALUERING
den var tættere på, betød at nogle robotter gik helt i stå selvom modstanderen
bevægede sig rundt omkring i det andet hjørne af banen.
K APITEL
Konklusion
Robotten der tidligere har medvirket i Eurobot 2006 er blevet ombygget således at den kan gennemføre Eurobot 2007. Ombygningen er foretaget i sådan
en grad at robotten let kan ombygges til det originale design. Robotten har
vist sit værd ved at være i stand til at indsamle, sortere og aflevere alle tre
typer affald.
Det stod klart fra starten at det ville være svært at kunne håndtere alle
typer affald da der er tale om relative store elementer i forhold robottens størrelse. Derudover voldte flaskerne de største problemer på grund af kraveudformningen omkring flaskehalsen, den har en tildens til at sætter sig fast.
Derudover bliver det vanskeliggjort at indsamle affaldet i fred da der under
konkurrence forholdene til tider er halv-destruktive modstandere. Efter at have deltaget i Frankrig stod det også klart at vi ikke var de eneste der havde
haft problemer med at affaldet. Faktisk var vi blandt den lille mængde hold
der kunne klare alle typer affald, og endnu med en endnu simplere løsning
end mange af de andre.
Ved det planlagte design1 var fordelene at flaskerne og dåserne kunne opsamles ude på banen, og dels at den ville kunne opbevare et par dåser eller
flasker så der kunne spares noget kørselstid. Efter konkurrencen vil jo dog
satse mere på det endelige design på baggrund af det simple men effektive
affalds-indsamling. Begge design bruger samme batteri indsamlings princip,
nemlig ved at rette batteriet op ved en tragt og derefter samle det op med
et batteri i en skål. I praksis virkede både tragten og opsamlingsmekanismen
efter planen.
Det lykkedes at bruge webkameraet til at genkende dåser og flasker, og gør
derfor sorteringen af dåser og flasker vellykket. Derudover er funktionerne
deliver() og toBasket() afprøvet og ser ud til at virke fejlfrit. Desværre
opstod der software problemer der har været svære at opspore og løse. Muligvis ligger problemet i funktionen checkStopConditions(), men det har
været svært at genskabe den samme fejl gang på gang.
1 Gennemgået
af Brian Hansen (s042307), Ørsted•DTU
33
7
Litteratur
[Div07]
Diverse. Automation’s wiki. http://www.iau.dtu.dk/
wiki, 2007. Hjemmeside per 18/6-2007.
[Han07]
Brian Hansen. Eurobot 2007 – planlagt design. Ørsted•DTU,
2007.
[HJJ07]
Brian Hansen og Martin Juhl Jørgensen. Forprojekt til eurobot
2007. Ørsted•DTU, 2007.
[RTJH06]
Martin Rødgaard, Peter Tjell og Claes Jæger-Hansen. Eurobot
2006. Ørsted•DTU, 2006.
[SJHJ05]
Søren Svane Jensen, Søren Hansen og Morten Jønsson. Eurobot
2005. Ørsted•DTU, 2005.
[VCPSKT06] Jørn Villesen Christensen, Mikkel Peter Stæhr og Michael Kølbæk Thomsen. Robots for robocup. Ørsted•DTU, 2006.
35
Appendiks
37
A PPENDIKS
Regler & FAQs
A.1
Regler
39
A
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
Robot Recycling Rally
Waste, Sort & Win!
The robot which sorts the most waste into correct bins will be the winner.
1/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
1. Scope
The following game rules are applicable to all the national qualifications and the final of EUROBOT
2007 autonomous robot contest.
EUROBOT is a amateur robotics contest open to world-wide teams of young people, organised either in
student projects, in independent clubs, or in an educational project. A team is composed of several
people. . A team must be made up of two or more active participants. Team members may be up to
(including) 30 years old, each team may have one supervisor for which this age limit does not apply.
The contest aims at interesting the largest public to robotics and at encouraging the hands on, group
practice of science by young people. EUROBOT and its national qualifications are intended to take
place in a friendly and sporting spirit.
More than an engineering championship for young people, EUROBOT is a friendly pretext to free
technical imagination and exchange ideas, know-how, hints and engineering knowledge around a
common challenge. Creativity is at stake and interdisciplinarity requested. Technical and cultural
enrichment is the goal.
Participation to the competitions assumes full acceptation of these principles as well as the rules and
any interpretation of them that will be made by the refereeing committee (throughout the year) and
by the referees (during the matches). The referees’ decisions are final and may not be challenged,
unless an agreement is reached between all the parties involved.
EUROBOT is a contest taking place in Europe, but is open to other countries. The countries presenting
more than three teams shall organise a national qualification (or national cup), in order to select three
teams among them. The selection will typically include the two most competitive teams. But it is left
to each national organisation committee to agree on a possible alternative to competitiveness for
selecting its last team. For example, the third team can be chosen by a jury according to other
qualities valued by the contest as: best-concept, creativity, fair-play, etc.
EUROBOT values, fair play, solidarity, technical knowledge sharing and creativity both through
techniques and project management more than competition.
The happy selected teams during the national robotics cups of Algeria, Austria, Belgium, Czech
Republic, Germany, France, Italy, Roumania, Serbia, Spain, Switzerland, United Kingdom and any 2007
new selection will meet their international counterparts in May 2007 from Thursday 17th to Sunday
20th, in La Ferté-Bernard (France) to compete for the EUROBOT final.
EUROBOT is born in 1998, in the wake of the French Cup of Robotics, following the constitution of a
similar competition in Switzerland. Today, to stand with the international spreading of the contest,
and to structure the spirit of exchange and co-operation that exists between the different organisers,
all have gathered into a European association.
2/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
The association, officially born on May 2004, is named EUROBOT. You can find its statutes on our
website: www.eurobot.org . All individuals and structures sharing our values are very welcome, either
to support, or join as volunteers in the different organising groups.
It shall be noticed that most of the national qualification are open to foreign teams but in the limit of
their resources, and that many teams organise their own friendly tournaments. It shall be finally
noticed that multinational teams are welcome.
EUROBOT and its national selections are attended mostly by volunteers of all nationality who believe in
the educational value of the experience, and are for most former participants themselves.
Welcome!
And have a nice adventure!
3/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
1.1. Contents
1.
Scope .....................................................................................................................2
1.1.
2.
Contents ............................................................................................................... 4
Basic rules ...............................................................................................................6
2.1.
3.
Referees ............................................................................................................... 6
Playing area and element definition ...............................................................................6
3.1. General notes ......................................................................................................... 6
3.1.1. Tolerances ....................................................................................................... 6
3.2.
The playing area...................................................................................................... 7
3.3.
Starting Areas ......................................................................................................... 8
3.4.
Border .................................................................................................................. 8
3.5.
Beacon supports / Reflectors....................................................................................... 8
3.6. Waste / Placement of Waste ....................................................................................... 8
3.6.1. Aluminium cans ................................................................................................. 8
3.6.2. Plastic bottles ................................................................................................... 9
3.6.3. Batteries ......................................................................................................... 9
3.6.4. Placement of the waste ....................................................................................... 9
3.7. Bins and basket ..................................................................................................... 10
3.7.1. Bins.............................................................................................................. 10
3.7.2. Basket........................................................................................................... 10
4.
The robots ............................................................................................................. 10
4.1. General notes ....................................................................................................... 10
4.1.1. Visibility........................................................................................................ 11
4.2. Limitations and safety issues ..................................................................................... 11
4.2.1. Fair-play........................................................................................................ 11
4.2.2. Safety ........................................................................................................... 11
4.3. Mandatory equipment .............................................................................................
4.3.1. For starting the robot........................................................................................
4.3.2. Emergency OFF button.......................................................................................
4.3.3. Automatic shutdown .........................................................................................
4.3.4. Obstacle avoidance system..................................................................................
12
12
12
12
12
4.4.
Robot Dimensions .................................................................................................. 12
4.5.
Energy Sources...................................................................................................... 13
4.6.
Control Systems..................................................................................................... 14
4.7.
Robot localisation beacon support .............................................................................. 14
4/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
4.8.
5.
Technical poster.................................................................................................... 15
Beacons ................................................................................................................ 15
5.1.
General Comments ................................................................................................. 15
5.2.
Robot Localisation Beacon ........................................................................................ 17
5.3.
Fixed beacons ....................................................................................................... 17
5.4.
Communication signals ............................................................................................ 17
6.
Match timeline........................................................................................................ 18
6.1.
Robot identification................................................................................................ 18
6.2.
Start procedure ..................................................................................................... 18
6.3.
Match sequence..................................................................................................... 19
6.4. Score calculation ...................................................................................................
6.4.1. Points ...........................................................................................................
6.4.2. Penalties .......................................................................................................
6.4.3. Scratching ......................................................................................................
7.
19
19
20
20
Contest main timeline............................................................................................... 21
7.1. Approval .............................................................................................................
7.1.1. Physical examination and team interview................................................................
7.1.2. Practical trials ................................................................................................
7.1.3. Notes on the approval process..............................................................................
21
21
21
21
7.2.
Qualification round ................................................................................................ 22
7.3.
Final round .......................................................................................................... 23
8.
Appendices ............................................................................................................ 24
8.1.
Playing area drawing............................................................................................... 24
8.2.
Reflective tape ..................................................................................................... 25
8.3.
Polyurethane Foam ................................................................................................ 26
8.4.
Painting references ................................................................................................ 26
8.5. Safety ................................................................................................................
8.5.1. On-board voltage .............................................................................................
8.5.2. Compressed-air systems .....................................................................................
8.5.3. Lasers ...........................................................................................................
8.5.4. Powerful light .................................................................................................
5/27
26
26
27
27
27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
2. Basic rules
The following rules are applicable to the Eurobot Open 2007 autonomous robot contest. It is expected
that the national qualifications will conform to most of these rules. However, participants in every
specific country are advised to check with their National Organization Committee for differences.
This year, the robots are sorting waste. There are three kinds of waste to find: bottles, cans and
batteries. Only one robot is allowed per team in a match. The matches involve two teams and last 90
seconds.
Each team is associated with a colour, red or blue . Each team has two bins: one for bottles and one
for cans. In addition, there is one, shared, basket for the batteries.
Each robot finds some garbage on the table, transports it to the correct bin, deposits it, and returns to
look for some more garbage.
2.1. Referees
Each match will be overseen by two referees. For the finals, at least one of the two referees will be
from a country different from both of the competing teams.
The referees are intended to help the teams, as well as interpret and apply the rules during the
competition and approval phase. Teams are encouraged to contact the referees with questions about
the rules or the competition process.
3. Playing area and element definition
3.1. General notes
A reference of parts and products used to make the game components is included in an appendix at the
end of this document.
3.1.1.
Tolerances
The organisers are committed to build the playing area to the highest degree of accuracy. But they do
allow for the following fabrication tolerances:
•
2% with respect to the playing field construction,
•
5% with respect to the playing element construction,
•
10% with respect to painted markings.
6/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
No complaints related to fabrication variations within the above tolerances will be considered.
The teams are warned that the paint finish of the table may vary from one playing area to another and
may degrade during the competition.
As we discover problems with the rules, the definition of the field and game components may be
modified over the course of the year. We strongly advise participating teams to regularly consult our
web site www.eurobot.org in the ‘FAQ’ section for potential amendments.
Please note: the above tolerances apply to the playing field and other components of the game. Robots
and the localisation beacons prepared by the participating teams may be required to be more precise.
3.2. The playing area
The playing field is 210 cm wide and 300 cm long. It is painted in grey anthracite. There are 4 bins and
one basket for depositing the waste. Each robot has 2 bins, one each for cans and bottles, at one
corner of the table. There is also a basket for the batteries. This is placed randomly and fixed to the
table at the start of the match, and is used by both robots for depositing the batteries.
Starting aera of
the blue team
Beacon
supports
Median line
(colours symmetry)
2 fixed
positions
Bottles
Starting
aera of
the red
team
Cans
Bins of the red
team
Basket
3 random
positions
7/27
Bottles
Cans
Bins of the blue
team
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.3. Starting Areas
The starting areas are on the corners of the table opposite the bins. Each starting area is a square of
500mm sides in the respective team’s colour (red or blue). The robots are placed touching the two
borders on either side of their start areas at the beginning of the match.
3.4. Border
The border is 70mm high (above the table level) and 22mm wide. The border in front of the bins is
slightly lower, 50mm for the can bins, and 40mm for the bottle bins.
The border is half painted in blue and red (symetrically, with the boundary in the middle of the long
side). The blue bins and red start-area are on the blue side, and the red bins and blue start-area are on
the red side.
3.5. Beacon supports / Reflectors
At each of the four table corners, and in the middle of the short sides are installed beacon supports for
the localisation beacons (see the table plan).
The beacon supports consist of an 80mm square platform supported 350mm above the table surface.
The platform is covered with Velcro (“snaggable” or “hard” side).
The beacon support mast is 10mm wide, painted black.
Cylinders about 22mm in diameter and 280mm high are located in front of the two masts on the
corners where are located the bins. They are covered with reflective tape (see appendix for
specifications of the tape). Another cylinder with reflective tape is located in the middle of the
opposite border (between the two starting areas). It is 280mm high from the border.
3.6. Waste / Placement of Waste
There are 50 total pieces of waste, of three types: 21cans, 21 bottles and 8 batteries.
3.6.1.
Aluminium cans
There are 21 cans on the table: 20 random and 1 fixed. They are aluminium cans of 330ml volume,
type sweet drinks with gas. The sides of the cans are painted yellow (RAL 1018). The tops and bottoms
of the cans are left unpainted (metal). In order to improve the stability and the
solidity of the cans, they are filled with polyurethane foam (see appendix). The
cans are 115mm high and 60mm in diameter on the major aera.
60mm
115mm
The cans are not magnetics.
8/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.6.2.
Plastic bottles
There are 21 transparent plastic (PET) bottles: 20 random and 1 fixed. The colour of PET is clear but
not determined. The plastic bottles are 500ml size, type sweet drinks with gas. The bottles are empty,
and without caps and rings. The original label is removed and a uniform green insulatingadhesive tape
of 50mm wide is placed instead. The label is located between 100 and 150mm high from the bottom of
the bottle. The bottles are 230mm high and 60mm in diameter at the label emplacement.
230mm
60mm
115mm
3.6.3.
100mm
Batteries
There are 8 batteries, 4 red and 4 blue. Three of each color are
fixed and one of each is
random. The batteries are Type “D” or “LR20”, 1.5V. The body of the battery is 55mm high and the
positive terminal 5mm high. The batteries are discharged. Only undamaged batteries
without corrosion may be used.
The original label is covered with an insulating adhesive tape of uniform colour (red or
blue). The adhesive tape is 50mm wide and placed from 4mm from the bottom (the
negative terminal) of the battery.
3.6.4.
Placement of the waste
There are 5 equidistant positions (every 350mm) on the median line of the table: 2 fixed positions and
3 random positions. The fixed positions are for a can and for a bottle. The position nearest the starting
area is for the can. The second position is for the bottle. The three other random positions are for a
red battery, a blue battery and the basket. Before the match a randomly drawn card is used to
determine the position of those three elements.
Another 46 waste items (20 cans, 20 bottles and 6 batteries) are placed on the table with the aid of
triangular frames. First the frames are placed (see schema of the table) on each side of the table.
Then, three batteries of a colour are placed inside and on every corner of the opposite triangle of the
starting aera. After, the 10 cans and 10 bottles are put in each frame, randomly, lain down. The side
interior of this equilateral triangle is 850mm. Each triangle is at 300mm from the middle line of the
table (border interior of the triangle, one face parallel to the line.
One black point indicates the localization of the three fixed batteries of each triangle, the fixed bottle
and the fixed can.
9/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.7. Bins and basket
3.7.1.
Bins
The bins are outside the table on two corners of the table, facing the audience and opposite the robot
starting areas. There are two bins at each of the two corners, 500mm long and 250mm wide. The
opening of the bin is level with the table border. The bin in front (on the long side) of the table is for
cans, the border of the table is 50mm high in front of this bin. The other bin is for bottles, and the
table border is 40mm high in front of this bin. Each of the bins should be deep enough to potentially
accommodate all the correct waste. The bins must be transparent (plexiglass, net, transparent plastic
bags), so that the audience can see the contents.
The top of the bins is 350mm high from the playing area and slop down to 200mm high.
The top of the bins is covered by the same insulating adhesive tape of uniform colour and 50mm wide
(red or blue) of the batteries.
3.7.2.
Basket
There is a “basket”, randomly placed on the middle line of the table and fixed to the table at the
beginning of the match by a screw (∅6). The screw is at the center of the basket and determined its
position. The basket is a hollow cylinder, 200mm in diameter and 30mm tall, with 10mm walls and
open at the top. The interior depth is 25mm. It is white in colour. The position of the basket is
indicated by the card drawn at the start of each match
4. The robots
4.1. General notes
•
Each team can engage at most one robot.
•
The robot is a fully autonomous machine. It shall carry its own power source, actuators and
control system.
•
The robot is only allowed to communicate with the localisation beacons (see beacons, below).
•
During the match no remote controlled action is allowed: the robot runs strictly on its own.
10/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
4.1.1.
Visibility
The refereeing committee encourages the team to make the interior parts of their robot visible.
In the finals Eurobot, two rectangular spaces of 100x70 mm are required for stickers (numbers of the
teams and sponsors of the event, printed by the organizer). The space of the stickers is free but they
must appear on two different faces of the robot.
4.2. Limitations and safety issues
4.2.1.
Fair-play
The aim is to share a friendly time and play as many matches as possible. Therefore, any action not
directly in line with the match spirit as laid out in this document or harmful for match development
will be penalised. The goal of the match is not to prevent the other robot from playing.
In this spirit, teams shall not follow strategies that are, for example, meant to:
•
block the opponent robot’s access to an element or area of the playing field
•
deliberately designing the robot (colour, shape) in order to confuse the opponent robot
•
deliberately cause damage to the opponent robot, the playing area, or any of the playing field
elements.
In particular, none of the colours mentioned in these rules for playing field elements may be used on
the robot.
4.2.2.
Safety
•
The robots should not have any protruding or sharp parts that may be able to inflict damage or
that can be dangerous.
•
The use of liquid products, corrosive products, pyrotechnic materials or living beings in the
robot is forbidden.
•
All the systems on the robots shall respect existing national and European laws and
specifications. Specifically, the systems used shall comply with legal safety regulations and
must not endanger the participants or the public both during matches and backstage .
•
As a general rule, any device or system considered as potentially dangerous by the referee will
be rejected, and must be removed from the robot prior to competition, or result in
disqualification.
11/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
4.3. Mandatory equipment
All robots must include the following systems, or they will not be approved for competition.
4.3.1.
For starting the robot
This starting device shall be easily accessed on the robot. It shall be triggered by pulling a cord at least
500mm long. This cord shall not remain attached on the robot after it has been started. Any other
systems (remote control, manually activated toggle switch, etc…) will not be approved.
4.3.2.
Emergency OFF button
The robot must include an emergency off button, at least 20mm in diameter (for example a safety
button). It shall be placed in a conspicuous position in a zone that is not dangerous and that is
immediately accessible to the referee at any time during the match, on the top of the robot. Pressing
the emergency button shall result in immediate shutdown of all the robot’s actuators, leaving them
limp (not actively braked).
4.3.3.
Automatic shutdown
Each robot shall accommodate a system which shall stop the robot automatically at the end of the 90
second match duration. “Stop” implies complete shutdown of all actuators. Robots moving after the
end of the match will be penalized or disqualified.
4.3.4.
Obstacle avoidance system
The teams are required to equip their robots with an obstacle avoidance system. The system is
intended to prevent collisions between robots during a match. The system is intended to react to the
opponent robot. It could be realized through contact (e.g.: physical bumper sensor) or contact free
(e.g.: infra-red, laser, sonar, camera) sensors. It may make use of the localization beacon (see below)
placed on the opponent robot. If a bumper sensor is used, it must be sensitive enough, and the robot
reaction fast enough, to reduce the impact of a collision. The obstacle avoidance system will be tested
in a trial during the robot’s approval.
4.4. Robot Dimensions
The teams are allowed to design their robot with deployable mechanisms. If such mechanisms are
used, the robot shall typically unfold them after the match start signal.
The perimeter of the robots is defined as the convex envelope which fits the vertical projection of the
robot on the ground.
The perimeter of the robot in its starting configuration shall not exceed 120cm.
12/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
The perimeter of the robot in a fully deployed configuration shall not exceed 140cm at any time during
the match.
Those perimeters are dimensions without waste.
The height of the robot shall not exceed 35cm, excluding the beacon supporting mast (see beacons,
below), possible sensor equipment within the beacon support mast’s envelope (see beacons, below)
and possibly the pressing area of the emergency stop button.
All other systems, including mandatory systems, must be contained within the volume specified above.
All parts of the robot must remain physically connected – therefore the robot cannot leave parts of
itself on the playing area.
Starting position
≤ 120cm
≤ 140cm
Deployed configuration
4.5. Energy Sources
•
Permitted energy sources include springs, pressurised gas (but see limits, below!), solar cells
(note that the competition will be held indoors!), all types of commercially available batteries
and power cells,
•
Prohibited energy sources include all types of combustion engines, rocket engines, hydrogen
fuel cells, or any other type of burning or pyrotechnics, living beings and radioactive energy
sources of all types
13/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
•
If in doubt about your unusual energy source, ask the refereeing committee ahead of time!
•
With respect to batteries use only models with solid electrolyte in order to prevent any
problems with corrosive liquids
•
It is strongly recommended for teams to possess several battery sets and to design for easy
access in the robot for their replacement. The teams are reminded to have spare, fullycharged batteries available at all times. The teams shall be capable of playing two matches in
succession. Note that this includes the necessary “setup time”, when the robot is powered on
and waiting to start, but the match has not yet begun.
4.6. Control Systems
The teams may use any kind of robot control system (analogue, microprocessors, microcontrollers,
computers, programmable logic, etc).
Those systems must be fully integrated into the robot.
The control system must permit the robot to play a match as either colour. Ideally, this can be easily
set just before the match.
The control system must permit the robot to pass the approval phase (see approval, especially with
respect to obstacle avoidance).
4.7. Robot localisation beacon support
It is strongly recommended to design the robot with a support to accommodate a localisation beacon
prepared by the opposing team.
If desired, the support can be designed to be detachable, so that it is only used if the opponent needs
it. In this case the design must allow the support to be quickly attached before the match.
Finally, a team may choose not to set its robot with a beacon support. In this case, if the opponent
provides a beacon and wants to use it during the match, the team will be disqualified for not having
the support.
The beacon support shall at anytime comply with the following constraints:
•
It is a 80x80 mm square surface, located 430mm above the floor level. The structure
supporting this platform must stay within the vertical projection of this platform. This mast
cannot host any parts of the robot other than sensors. The mast shall be robust and rigid
enough to support the opponent’s beacon in a stable fashion. The team is responsible for the
robustness of its mast.
•
The platform surface of the support shall be fully covered with Velcro ("snaggable" or “hard”
face)
14/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
•
The support shall be located close to the horizontal centre of the robot. In robot non deployed
configuration, the distance between the support and the maximum robot extension on one side
shall not be less than 50% of the equivalent distance on the opposite side.
4.8. Technical poster
Each team is required to provide a technical poster during the approval phase.
This poster shall present information related to the design of the robot (drawings, technical
references, design specification, etc.). It should be at least DIN A1 in size, and ideally should be
printed. The poster is intended to promote exchange and communication between teams.
Effort should be made to make the poster understandable to a technical audience. Ideally the poster
should include pictures and diagrams to help explain the concepts.
The poster must also include:
•
the name of the team
•
the names of the team members
•
the nationality of the team
This poster will be displayed in the team area of the competition. An English version of the poster must
be supplied. Optionally, the team can provide other language versions as well.
The poster shall be supplied to the Eurobot association in PDF Format. The chosen resolution of the
PDF must guarantee all texts to remain readable. The file size of the PDF should remain below 10MB.
The team explicitly confers all rights to the Eurobot organization to use the poster, in whole or in part,
in any way desired. In particular, but without being limited to this, the Eurobot organization will
publish the poster on its website, and may use it for marketing purposes. The team is responsible for
ensuring that it has the rights to all graphics and texts used in their poster.
The PDF Version of the poster may be sent to Eurobot beforehand via your National Organisation
Committee, or may be provided on two CD-ROMs at the competition, during the approval for your
robot.
5. Beacons
5.1. General Comments
•
Beacons are meant to help the robot to locate itself on the playing area and to locate the
opponent robot’s position
15/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
•
Beacons are not allowed to obstruct the opposing robot (communication, weight...). If there is
any doubt that they may deliberately disturb the development of the match, the team will not
be allowed to use them.
•
Three fixed beacon supports are placed each end side of the playing area: one at the centre,
the two others on each corner (see the drawing in the appendix). They are black and placed at
a height of 350mm above table level. The masts of the beacon supports are round, 10mm in
diameter, and covered with reflective tape (see appendix).
•
The beacons’ undersides are covered with Velcro (soft "smooth" face) as a way to fasten them
on their assigned support.
•
The beacons (robot localisation or fixed ones) shall remain on their support throughout the
matches.
•
The use of beacons is optional and they shall be designed and built by the teams.
•
All safety standards applicable to robots are also applicable to the beacons.
Fixed beacon (8x8x16)
Mast (area for sensors only)
Robot localisation beacons (8x8x8)
35
all dimension in Centimetres
16/27
43
51
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
5.2. Robot Localisation Beacon
•
One localisation beacon can be fitted onto the other robot, in order to locate it. This beacon
will be fitted on the beacon support provided for this purpose by the opponent robot.
•
Only one localisation beacon is allowed per team.
•
The maximum size for a robot localisation beacon is an 80mm edge cube.
•
The elements used for the beacon design shall be useful. The referee may request if necessary
that the team opens its beacon casing for inspection and verification.
•
The robot localisation beacon top shall be able to support the flag module identifying the robot
allocated colour.
5.3. Fixed beacons
•
Each team can use a maximum of three beacons, to be placed on the provided supports around
the playing area.
•
A team can place its beacons on the beacons support which is in the middle of his starting area
and on the 2 beacons supports which are in the other side of the playing area, at the two ends
of it.
•
Only the 2 beacons on the same side can be linked together by a wire. This optional wire shall
not disturb the development of the match.
•
The beacons must remain within a square base of 80x80 mm and can be 160 mm high.
5.4. Communication signals
•
In order to avoid interference between the teams, it is recommended to encode the
communication signals. We strongly recommend that teams using infrared devices take into
account the strong ambient light used during the competition. Moreover, this illumination may
vary during the competition depending on the time and on the area.
•
We also mention that the competition staff uses high frequency radio devices during the
contest.
•
No protest regarding interference problems will be taken into account. The beacons must be
able to deal with the conditions that may change depending on the moment and their location
during the contest.
17/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
6. Match timeline
6.1. Robot identification
•
For each match, the robots are allocated a colour marking built as a small flag module: red or
blue. The use of this marking is to help the public to associate at any instant a robot with its
team.
•
The flag module mass is negligible. It is placed directly on the robot beacon support, or
directly on the robot (see chapter about the beacon support).
•
If the robot does not provide a beacon support, it must provide a 8x8cm square surface
covered with Velcro at the top of the robot to place the flag marker on.
6.2. Start procedure
•
A colour (red or blue) and therefore a side of the playing area are allocated to the team before
each match.
•
Only two members from each team are allowed access to the playing area for robot
preparation.
•
Both teams have 3 minutes to put their robot on the starting positions, they do this
concurrently.
•
The robots are placed on the table, entirely within their starting areas, and touching the two
table borders adjacent to the starting area.
•
After the 3 minutes of preparation, no more intervention or transmission of external
information to the robot is allowed.
•
When both teams indicate they are ready, the referee will determine random positions for the
two batteries and the basket. This is done by drawing from a set of cards. The referre set the
elements on the playingfield area. During this procedure, the teams don't have the right to
touch their robot.
•
The referee asks the participants whether they are ready and if they have any remarks about
the placement of all the game elements. No objection regarding the placement will be
accepted after this.
•
At the start signal given by the referee, the robot is activated by one of the team members.
The robot shall then run on its own in a fully autonomous way.
18/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
•
Any team which does not scrupulously follow this starting procedure (anticipated or delayed
start) is charged with a false start. A new start shall be given with a new random layout for the
game elements.
•
The referees reserve the right to start the robots themselves.
6.3. Match sequence
•
Robots have 90 seconds to score as many points as possible. This must be accomplished in
complete autonomy.
•
It is prohibited to remove garbage from the bins.
•
The team members are not allowed, in any way, to touch the robots, the playing area or any of
the fixed game elements during a match. Any action made without the referees consent will
lead to disqualification for the current match. The team will then lose all the points it may
have scored during the match.
•
If the robot leaves the playing area, it can't be put back in it. The match is not replayed and
the other robot is allowed to finish the match normally.
•
A robot that deliberately pushes its opponent out of the playing area is disqualified.
•
At the end of the match the robots must stop (shutdown of all actuation) by themselves. If the
robot does not shut down by itself, a referee will push the emergency stop button to stop the
robot.
•
The referees will count the points without touching the robots. Then they will announce the
score.
•
The team members are allowed to touch the robots and leave the game only with the explicit
consent of the referees after common agreement on the score.
6.4. Score calculation
6.4.1.
Points
Points are counted after the match is over. After the match, the waste in the bins and the batteries in
the basket are checked.
•
For the correctly sorted waste:
Each team gets one point for each bottle in its bottle bin.
Each team gets one point for each can in its can bin.
19/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
•
Incorrectly sorted waste is handled as follows:
The first four incorrectly sorted waste items give no point, because a bad sorted bin is not
accepted by a recycling company. Each additional incorrectly sorted waste item beyond the
first four items counts one point for the opposing team.
•
Each battery in the basket gives three points for the team of its colour.
6.4.2.
Penalties
A penalty results in the removal points from the score of the team at the end of the match. Any actions
not complying with the spirit of the rules may be penalized by the referees. For example, the referees
may assign penalties in the following cases:
•
When a robot violently collides with its opponent
•
When a robot is considered dangerous to the table, the audience or its opponent
•
When a robot deliberately prevents its opponent to reach a game element
•
If a robot’s shutdown system fails to work
•
If a robot intentionally or systematically throws waste outside of the table
•
If a robot removes waste from its opponents bins
Warning: this list is not exhaustive! Additional penalties can be applied if the referees consider this
justified.
6.4.3.
Scratching
The referees will scratch a team:
• That has not come on time at the backstage waiting room for matches;
• That takes more than 3 minutes to get ready on the playing area;
• Whose robot has not completely left the starting aera.
• Whose robot doesn't have a mobile beacon support, when its opponent requests and requires one.
• Whose robot shows a deployment or an action that has not been previously approved by the
referees, or any deliberate action not in line with the rules.
A team being scratched during a match loses all the points gathered during this match. The opposing
team carries on with the match and keeps its points.
20/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
7. Contest main timeline
7.1. Approval
To participate in the tournament a robot must be approved. Approval is mandatory. For logistical
reasons, and reasons of fairness, there is a deadline for approval. All teams must approve their robots
before this deadline. Robots that are not approved may not participate in the tournament.
To be approved, the robot must pass two tests: a physical examination and practical trials.
7.1.1.
Physical examination and team interview
The referee examines the robot and interviews the team to check the following:
•
That the robot complies with the rules (the robot should be capable of demonstrating all of its
possible actions and deployment configurations to help verification).
•
That the team provides a technical file (see paragraph 4.8).
•
That the team understands the rules and the spirit of the tournament
•
That the emergency stop button works, and all actuators are shut down when it is pressed
7.1.2.
Practical trials
That under match conditions, without opponent:
7.1.3.
o
The robot is capable of leaving the start area
o
The robot is able to win a match, without opposition within 90s
o
The robot’s shutdown system works properly
o
The robot’s obstacle avoidance system works: The referee can test the system, by
placing an obstacle in the robot’s path. The obstacle may be slightly to the side of the
robot. This obstacle is a fake robot. It has a beacon support like the opponent robot,
which may be used by the team if desired. The robot must avoid the obstacle,
demonstrating to the referee in a convincing way that it is reacting to the obstacle.
Notes on the approval process
It is mandatory to keep referees informed of any major modifications (functionality, size, etc.) made
after approval. The referees will check the modifications and re-approve the robot.
21/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
Actions used during the match which were not demonstrated during the approval process can lead to a
disqualification.
Referees can require a robot to subject itself to another approval process at any time during the
competition, if there is any doubt about its compliance to the rules.
7.2. Qualification round
The Eurobot organization will try to organize at least five matches for each team during the
qualification round. The results of the qualification round decide which teams go through to the final
round.
The qualification score is determined by adding the points accumulated during each match with bonus
points, as follows:
•
4 points for a victory,
•
2 points for a draw,
•
1 for a defeat,
•
0 for a scratched match
A score of 0 to 0 is considered to be a double defeat. Hence, each team gets only 1 bonus point
When the qualification rounds are over, the teams are sorted using their qualification points count.
The teams that have the same points count are sorted by comparing the points accumulated during
each match without adding the bonus points. The organisers may, if necessary, request extra matches.
22/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
7.3. Final round
At Eurobot, the first 16 teams from the qualifying phase are selected for the final round. In a national
competition the final round may be smaller, depending on the number of registered teams.
During the final phase, matches are on a knockout basis. The matches for the final round are organised
as shown in the diagram below.
In the event of a double defeat, a draw or a double disqualification the match is replayed immediately.
If this second match is also a double defeat, a draw or a double disqualification, the winner will be
determined by the position at the end of the qualification rounds.
Quarter-Final
1 meet 16
Final
Semi-Final
..........
8 meet 9
..........
5 meet 12
..........
3rd place final
.........
4 meet 13
3 meet 14
..........
6 meet 11
..........
7 meet 10
..........
2 meet 15
23/27
.........
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
8. Appendices
8.1. Playing area drawing
Dimensions are given in mm and are subject to the general tolerances defined (see Tolerances, above).
Top View
Bin for
bottles
Bin for
cans
Median line (one
basket, two
batteries, one
bottle, one can)
24/27
Bin for
cans
Bin for
bottles
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
Face View
Bin for
bottles
Bin for
115mm
cans
Bin for
cans
Bin for
cans
Right view
Bin for
bottles
Bin for
bottles
8.2. Reflective tape
This is made of an adhesive retroreflector tape 0,2mm thick and 25mm wide, white in coulor. Its part
number is #XUZB05 at “Telemecanique”. The tape is distributed online by “Radiospares” (“RS
Electronics”) under part 324-1591 (1m length).
25/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
8.3. Polyurethane Foam
The polyurethane foam is used to strengthen and to stabilize the cans. It is saled in every do-it-yourself
store.
8.4. Painting references
Element
Colour
Paint Type
Paint
Brightness
Reference
Arena floor
Grey
(Anthracite)
Acrylic
Satin
RAL 7016
Blue start area,
blue border, blue
batteries
Blue (sky)
Acrylic
(Adhésive tape)
Satin
RAL 5015
(Type RAL
5015)
Red start area,
red border, red
batteries
Red (fire)
Acrylic
(Adhesive tape)
Satin
RAL 3000
(Type RAL
5015)
Basket
White
Acrylic
Satin
RAL 9010
Bottles
Green
(bright)
Adhesive tape
Satin
Type 879
PF
Cans
Yellow
Acrylic
Satin
RAL 1018
8.5. Safety
Below you will find a list of safety regulations. This list is not exhaustive - the referees’ decisions are
final on the dangerousness.
As a general rule, the teams shall develop systems that satisfy design and manufacturing criteria that
do not endanger the team or the audience both in the pits and during the matches.This is also why you
must ensure that your systems comply with applicable laws for technical devices.
8.5.1.
On-board voltage
All robots must comply with the legal standards concerning “low voltage”. Therefore, the internal
voltage of the robots shall not exceed 48 V.
26/27
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
8.5.2.
Compressed-air systems
All pressure systems must comply with applicable laws. In France this shall be in accordance with the
“Conseil Général des Mines” (French safety and approval board).
Decree 63 of January 18, 1943 and Ministerial Order of July 25, 1943 (French legislation):
•
Maximum pressure: 4 Bars
•
Maximum Pressure x Tank Volume product: 80 bar lt.
Further information may be found on http://www.industrie.gouv.fr/sdsi/ (for France).
8.5.3.
Lasers
Max output power for lasers shall be lower than 1mW (0dBm). Technical documentation of the laser
device may be required at the approval. It must be supplied in French, English or German.
8.5.4.
Powerful light
In case of a high intensity source being used, the light intensity shall be dangerous for the human eye
in case of direct illumination. Note: Some powerful LED devices can exceed this limit.
27/27
A.2. FAQ 1
A.2
FAQ 1
67
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
Robot Recycling Rally
FAQ 1
Introduction
This FAQ is divided into two sections: “Corrections”, containing information which replace or add
precisions to the official rules for 2007, and “Answers to common questions”, which contains official
answers to some of the most common questions posted on the forum or asked by email.
Corrections
3.6.1 Aluminium Cans
The cans are 115mm high and have a 66mm diameter around most of the can’s length. For the
Eurobot final, the cans are silk-screen printed entirely in yellow and have a vertical line of 5mm from
top to bottom without colour (metallic).
3.6.2 Plastic bottles
The bottles are 230mm high and have a 65mm diameter at height of the label
3.7.1 Bins
The bottoms of the bins (the part below the table) are made of hard plexiglass and include a door so
that the content can be removed. The other parts are made of netting (like the nets to protect fruit
trees from birds). The netting is tight.
1/6
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
3.7.2 Basket
The basket is a hollow cylinder, 200mm in diameter (external diameter) and 30mm tall, with 10mm
walls.
4.2.1 Fair-play
This sentence is missing: No system is allowed which attach the robot to the playing-field (eg: suction
cups). At any time during the match, the force required to lift the robot must not exceed its own
weight.
5.1 General Comments
The masts of the beacon supports are not covered by reflective tape. The cylinders about 22mm in
diameter and 280mm high are located in front of the two masts, on the corners where the bins are
located. They are covered by reflective tape (see paragraph 3.5)
Answers to common questions
Q1) Is the number of waste transported in the robot limited?
A1) No, there is no limitation on the amount of waste transported by the robot.
Q2) Is it allowed to put waste in the opponent’s bins? Or to help the opponent to put objects in her
bins?
A2) Yes, it is allowed for well sorted waste. The points are for the other robot and are counted at the
end of the match. But be careful, don’t obstruct the way of the robot to its bins and don’t put cans in
the bottles’ bin and bottles in the cans’ bins. In this case, you can be disqualified.
We encourage the fair-play but try to solve the problem posed (to sort the waste in your bins), not a
different problem!
Q3) Can we intentionally put incorrect waste into opponent bins?
A3) No it is forbidden, and you can be disqualified if you do that.
2/6
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
Q4) Is it allowed to throw waste?
A4) Yes of course, but only in the bins.
Q5) Is it authorized to withdraw the opponent’s batteries from the basket?
A5) No, it is forbidden.
Q6) a. Can we touch/move the batteries of the other team?
b. It is possible to catch and keep the batteries of the other team?
c. Can we remove the cans/bottles out of the bins of the other team?
A6) a) yes, but they have to be accessible for the other robot.
b) Yes but only during a short time. The robot cannot keep the opponent’s batteries for a long time. It
will be penalised if it seems to be a strategy.
c) No it is forbidden.
Q7) What happens if we put batteries in the bin for cans or bottles? Is that "incorrectly sorted
waste" or does it mean nothing?
A7) It is ‘incorrectly sorted waste”. If the batteries are to the opponent team, you will get penalties or
even disqualification.
Q8) Is it allowed to push waste towards the baskets? They will be considered in the perimeter of
the robot?
A8) Yes it is allowed; They are not considered in the perimeter of the robot.
Q9) What happens if a battery is on the edge of the basket? Is it counted in the basket?
A9) No, it doesn’t count.
3/6
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
Q10) Can one store the bottles in a plastic bag and deposit the bottles and plastic bag in the bin or
only the bottles necessarily should be put, without the plastic bag? How about cans?
A10) No, the robot has to stay in one part, so no detaching bags from the robot.
Q11) Waste will not be counted as being in the perimeter of the robot: can one store waste above
the top of the robot?
A11) Yes it is allowed to store waste between 35cm and 43cm above the ground, provided it does not
interfere with beacon systems. In particular, there must be clear line of sight between a beacon on the
robot beacon platform and the beacons on the side of the playing field.
Q12) The bottles will be very fragile because open. Would it be possible to fill them with
polyurethane foam in order to make them a little more solid?
A12) No, the bottle will not be filled with foam, and will not have their caps attached. They are solid
enough.
Q13) Which type of battery will be used?
A13) Alkaline batteries will be used. They are magnetic.
Q14) What is the reference of the green adhesive band?
A14) It is available in every DIY shop. It is an extra-adhesive tape, watertight (or waterproof), resisting
to high traction, UV and bad weather. It is a tape for reparation, protection, water tightness,
reinforcement, packaging... It is possible to cut by hand. The colour is bright green.
Q15) For the localization system we are developing this year, we will use a dedicated electronic
board. Is it possible to place this board on the mast (right under the support, and without
exceeding 80x80 mm)?
A15) It is allowed if it is a part of the localisation system. Any sensor or similar systems are allowed
there, including associated electronics, but not actuation systems.
4/6
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
Q16) The borders are 7cm tall, and the diameter of the bottles and cans is 66mm. That leaves only
one small centimetre of margin to the robots to make the distinction between a wall to be avoided
and some waste.) Can you make the border taller?
A16) No.
Q17) How will our obstacle avoidance system be tested?
A17) The obstacle avoidance system will be examined during approvals, and may be tested in a trial on
the game table. In the trial, the system should be able to successfully avoid a static dummy obstacle
(30cm high cylinder, 20cm diameter, between 2kg and 3kg weight) placed at a random distance in
front of the robot on the table. If desired, you will be able to place a beacon on the dummy obstacle,
which has a beacon platform.
Q18) If the other robot is 7cm tall and our infra-red based detection systems (for example) are
located 20 cm above the ground, how could it be detected? What if my bumpers don’t touch the
opponent robot? If the opponent robot has a very particular shape, it might not be reliably
detected!
A18) You must try to make your obstacle avoidance system as robust as possible. Obviously, a very
small opponent robot (e.g.: smaller than a bottle!) needs not be avoided. Your system will be
examined, and might be tested as described above. Make sure your system works with a simple
obstacle like that. For robots with a hollow structure, if you want to be safe, we suggest you to add
bodywork, made of cardboard for instance. This will increase the visibility of your robot to IR and sonar
based systems. In the same idea, you should avoid painting your robot in black since it could confuse IR
based detection systems.
Q19) What happen if a bottle or a can rolls out of place when the referees remove the triangle?
A19) We put it back in the triangle.
Q20) The borders are painted in red/blue; is it only the interior side or the tops of the borders too?
A20) Only the interior border is painted in blue/red.
Q21) Can the robot ram the piles of waste at the start?
A21) Yes, but if there is damage to the waste, you might be penalized.
5/6
Eurobot open 2007
Robot Recycling Rally
Official Rules 2007
Q22) a) Does my beacon mast have to be rigid?
b) Does that mean the mast may turn/swivel, if it stays in place?
c) May my mast include moving sensors (like a swivelling laser or mirror)?
A22) a) Yes, totally.
b) No, the mast may not turn or swivel either, it must be completely rigid.
c) Yes, you may, but these may not move the mast, or occlude the area on top of the mast. Mirror
systems may not be designed to deliberately confuse the opponents.
6/6
74
A.3
APPENDIKS A. REGLER & FAQS
FAQ 2
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
Robot Recycling Rally
FAQ 2
Introduction
This FAQ is divided into two sections: “Corrections”, containing information which replace or add
precisions to the official rules for 2007, and “Answers to common questions”, which contains official
answers to some of the most common questions posted on the forum or asked by email.
Corrections
3.5 Beacon support/ Reflectors
The cylinders covered with reflective tape are 21,3mm of diameter instead of 22mm. The top of
the cylinders is 350mm high from the playing area. So the cylinders located on the corners where are
the bins are 310mm high (because the border is 40mm high). The other cylinder with reflective tape
located in the middle of the opposite border (between the two starting area) is 280mm high. The
three cylinders are covered with reflective tape. But the masts of the beacon supports are not
covered by reflective tape. (see the pictures page 4)
3.6.2 Plastic bottles
The label is located between 100 and 150 mm high from the bottom of the bottle. There is a mistake in
the drawing. The value "115mm" on the drawing, should be "150mm”.
1/4
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.7.1 Placement of the waste
Position of the batteries: are they inside or outside the triangle just before the beginning of the match?
In the text of the rules (paragraph 3.6.4), it is written "inside" and in the draw, they are "outside".
What is the correct position of the batteries?
The batteries will be outside the triangle just before the beginning of the match.
For the installation, we use the followed procedure: (see the four pictures)
- triangle in place, we put the waste inside (Picture 1 and picture 2)
- the triangle is removed, and batteries are placed at this time on the dots painted on the playing field
(Picture 3 and Picture 4).
Picture 1
Picture 2
Picture 3
Picture 4
2/4
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.7.2 Basket
There is a “basket” randomly placed on the middle line of the table and fixed to the table at
the beginning of the match by a screw (6mm diameter).
For the screw is not 6mm but 8mm. The basket is a hollow cylinder, 194mm in exterior diameter
and 30mm tall, with 4mm walls and open at the top.
Answers to common questions
Q1: The rules says that "The top of the bins is covered by the same insulating adhesive tape of
uniform colour and 50mm wide (red or blue) of the batteries".
Since the bin is 350mm high, what do we have to assume?
1. the gate is 300mm high and then there is a 50mm bar covered with tape (or)
2. the gate is 350mm high and then there is a 50mm bar covered with tape, for a global height of
400mm
Another question. Since bins are made with net (in the upper part), do we have to assume that
also each vertex is covered with the tape (as the drawing in the front page of the rules suggests)? If
this is the case, what is the size of such a covering?
A1: The gate is 350mm high. The bin is made with net that is maintained with a rigid bar with a
negligeable thick (10 or 12mm maximum). Only this bar is covered with the adhesive tape (borders of
the opening). (see below the pictures of the bins)
3/4
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
4/4
A.4. FAQ 3
A.4
FAQ 3
79
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
Robot Recycling Rally
FAQ 3
Introduction
This FAQ regroup some advices from the refereeing committee and some precisions on the playing field
for Eurobot final 2007.
Notes
1. Obstacle Avoidance System
Your obstacle avoidance system will be tested during homologation, as described in the rules.
The rules require you to “react to the obstacle”. During the National competitions, we have observed
that many robots interpret this to mean: “Stop until the way is clear.”
If your robot employs this strategy, please consider what will happen when it meets another robot
employing the same strategy! (Hint: Answer: Nothing will happen, both robots will stop, the match is
effectively over -  )
So, please program your robot to do something other than just stop if it detects an obstacle. For
example, your robot could:
1.Back away
2.Turn around, go the other way
1/4
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
3.Head either left or right around the obstacle
Note that this is a recommendation based on observed matches, not a rule. Your robot will not be
penalized for being boring and just stopping.
2. Homologation Program
During the national competitions it was observed that many robots had difficulty with the
homologation.
For the homologation it is recommended that you design special “homologation software” for your
robot. Your robot does not have to homologate with the full program used during competition matches.
You can write a simpler, specific homologation program.
Also, we recommend having separate programs for the point scoring and the obstacle avoidance parts
of the homologation.
To speed up the homologation process, all teams are required to perform the physical homologation of
their robots within 2h of arrival at La Ferté Bernard. When you arrive, sign in, get your pit and
accommodation, unpack your robot at the pit, and then get a referee to approve your robot.
3. Strategy: Keep it simple!
Employ simple strategies! Eurobot is less than 2 weeks away. If your super-complex robot involving
computer vision, q-learning and a six degree of freedom waste processing system is not yet working,
perhaps it is time to simplify your design!
In many national competitions the simpler robots proved more reliable.
4. Blowing the Waste
The rules do not prohibit blowing the waste across the table. Blowing items of waste individually is
certainly allowed. However, blowing all the waste (randomly) across the table is not the idea of the
competition, and depending on what happens, your robot could even be penalized! This will be the
case if, for example, waste is blown off the table, waste is blown into the incorrect opponent bin, or
the waste is blown in such a fashion that the opponent robot cannot access it (blocking). Play fair, give
the opponent his chance!
5. Technical poster
Chapter 4.8 of the rules.
The poster shall be supplied in PDF Format. The chosen resolution of the PDF must guarantee all texts
to remain readable. The file size of the PDF should remain below 10MB, on a key USB (USB flash
drives). A computer will be at the pre-approvals. The referees will ask you your poster.
2/4
Eurobotopen 2007
Robot Recycling Rally
Official Rules 2007
6. Playing field and playing element of the French Cup and Eurobot final
The weight of the batteries is between 130g and 150g.
The basket is a hollow cylinder, 200mm in diameter and 30mm tall, with 10mm walls and open at the
top. The interior depth is 25mm.
For the Eurobot final and the French Cup, t he cans are silk-screen printed entirely in yellow and have
a vertical line of 5mm from top to bottom without colour (metallic).
The bin with the net :
The net will tight.
3/4
A.5. APPROVAL SHEET
A.5
Approval Sheet
83
Eurobot 2007
Robot Recycling
Rally
N°Pit :
Team Name :
Referees :
PRE-APPROVED
NUMBER OF TESTS ON THE
TABLE
APPROVED
Points :
1 Structure of the Main Robot
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
1.11
Before the match starts, the unfolded convex envelope that fits the vertical projection of the robot onto the
ground does not exceed 120 cm.
The perimeter of the robot in fully deployed configuration doesn’t exceed 140 cm at any time during the
match.
The height of the robot never exceeds 35 cm.
The robot has an obstacle avoidance system.
The robot hosts a beacon support measuring 8x8cm, located at 43cm high and covered with Velcro (soft
"snaggable" face).
This beacon support is robust enough to host the opponent’s beacon and to interpret its data. It is located at
the centre of the robot as much as possible and contains only systems connected to sensors.
The robot is composed of interdependent elements (and shall not leave parts or elements on the playing
field).
The robot is a totally autonomous machine with embedded power supply, actuators, and control systems.
The robot has an emergency power off switch, installed within the limits of the dimensions of the robot. It
must be put in evidence by a red distinguishing mark of at least 20 mm in diameter and must be placed in
evidence in a not dangerous zone and of immediate and vertical access for the referee at any time of the
match. This switch must interrupt the power for driving motors and actuators.
The robot has a starting device which must be easily accessed and triggered in a single movement by a wire
at least 50cm long.
The robot has 2 sets of batteries or sufficient long-life batteries.
1.13
1.14
The robot will not cause intentional damage to the opponent robot and/or to the playing field or to people in
the attendance.
The robot doesn’t hold any element that would intentionally jam the opponent robot or that would hinder the
game. It doesn’t use accessories, colours or drawing looking like playing area elements in an attempt to lure
the opponent robot.
The robot has no protruding or sharp part that may be able to inflict damages or that can be dangerous.
The robot doesn’t make use of any corrosive or pyrotechnic products, nor spraying of liquids.
1.15
1.16
1.17
The robot is only allowed to communicate with the beacons, if they are used.
The robot never totally prevents its opponent to access the waste, the bins and the basket.
Any pressure system complies with the applicable french regulation (PV<80 and 4 bar at output).
1.18
Any laser complies with the constraint: max optical output power : 1mW (0dBm).
1.19
No anchoring system is allowed (suction….) Consequently, at any time during the match, the necessary force
to lift up the robot shall not be exceed its own weight.
1.12
At this point, the robot is said pre-approved.
Eurobot 2007
Robot Recycling
Rally
2 Beacons (skip this section if the robot has none)
2.1
2.2
2.3
2.4
2.5
Each beacon fits in 8x8x8cm (embedded beacon) and 8x8x16cm (static beacon) . One side of the beacons is covered
with Velcro (soft snagging face); the top face of the embedded beacon is covered with Velcro (hard snagging face).
Beacons may in no way serve to jam or hinder the opponent robot.
Embedded beacon (1 maximum per opponent robot) shall be totally autonomous and independent.
Static beacons (3 maximum) must globally be autonomous but 2 of them may be connected together by a wire link. In
that case, the wire shall not hinder the game progress.
Any beacon using laser complies with the constraint: maximum optical output power : 1mW (0dBm).
3 Technical file
3.1
3.2
The team provides an A1 poster to display in its pit.
The team provides a CD-ROM containing a maximum of 10Mo of data. On the CD are mentioned: the name of the
team, the name of the school/university/club, the pit number.
4.1.
4.2
4.3
Under match conditions (1min30), free of opponent, the robot is able to win a match in 5 attempts maximum and to
leave his departure area.
The robots doesn’t damage the playing field nor the waste, nor the bins and the basket during the attempts.
The robot has an obstacle avoidance system. This system should be able to successfully avoid a static dummy
obstacle (30 cm high cylinder, 20 cm diameter, between 2 and 3 kg weight) placed at a random distance in its path
on the table.
4.4
The robot has a timer in order to make it stop and stay in position at the end of the match time (1min 30).
4.5
The strategy of the team does not have actions against the fair unfolding of the games. Referees could, if they
consider it happens, give a penalty to the team.
Robot is not dangerous for the audience.
4 Game rules
4.6
4.7
4.8
4.9
Team members agree to accept the decisions of the referees (decisions may overpass the rules).
Teams are informed about the procedures of the match (start procedure, game phases, point validity, score
counting).
Team members are informed that only 2 people of each team are allowed on stage.
Comments :
A PPENDIKS
SMR-CL
87
B
SMR-CL.
Small Mobile Robot Control Language, SMR-CL is a simple interpreted language
intended for control of mobile robots. The language supports sequences of basic robot
actions with multiple stop criterion as well as standard mathematical expressions. The
system has two kinds of variables system variables that reflects the state of the vehicle
and user variables that are created the first time they are used in an assignment clause.
The language is intended to be used in the tactical layer just over the control layer i.e. it is
fast enough to shift between control strategies and react to state changes in real time. The
hope is that it will be able to bridge the gab between the hard real-time demands of the
control layer and the soft realtime demands of the planning (strategic) layer. The
language may be used in two ways either as scripts run directly from text files or as a
command language through a socket interface. Most commands are available in both
modes but a few are only available in one of the modes.
Basic format.
The language is line oriented i.e. it is interpreted line by line. The basic format is
command parameters [@v velocity] [@a acceleration] [: stopconditions]
where [ ] means optional.
command
parameters
is the desired command
is a number of parameters required by the command. The parameters can
be numbers, variables or string litterals (characters within " " )
velocity
desired vehicle velocity in m/s (variable or number)
acceleration desired acceleration in m/s2 (variable or number)
stopconditions
( expression ) [ | (expression)]*
a list of ORed stopconditions, the command will end if one or more of the
conditions are true.
The system variable $condition will hold the number of the first true
condition (from left)
Examples:
fwd 2.0 @v0.5 @a0.05
move forward 2 m with acceleration 0.05 m/s2 max velocity 0.5 m/s
drive @v0.5 :($drivendist > 4)| ($cmdtime > 12)
drive at velocity 0.5 m/s until 4 m is driven or time used is 12 seconds
turn 90
turn 90 degress around center
Motion control commands
The following motion control commands exist:
all commands will use current velocity and acceleration references as max values
fwd
turn
d
b ["rad"]
move forward d meters
turn b degrees (radians if "rad" )around center ( between the
driven wheels)
turnr r b ["rad"] turn b degrees(radians if "rad") with turning radius r m
drive [x y th]
drive with current speed along the line defined by point (x,y) and
direction th. If x,y and th are omitted the current position and
direction of the vehicle is used
stop
stop vehicle and keep position and direction
idle
stop vehicle and keep speed at zero.
followline "type"
follow line using the method described by type:
bl
left side of black line
bm
middle of black line
br
right side of black line
wl, wm, wr as above with white line.
followwall "side" dist
follow a wall to the side of the vehicle indicated by side:
l left , r right
dist distance to wall in meters
resetmotors
resets the motor modules
ignoreobstacles
make the vehicle ignore obstacles in the next command
Examples
% square program1 (comments are indicated with the % character)
fwd 1 @v0.3
turn 90
fwd 1
turn 90
fwd 1
turn 90
fwd 1
turn 90
The vehicle runs in a square with side length 1m and max velocity 0.3 m/s
Flow control.
The following flow control statements are implemented:
The label, goto and if statements are only available in scripting mode.
label "labelname"
goto "labelname" continues execution at the line with label "labelname"
if (exp) "labelname" jump to "labelname" if expression is true ( not zero)
switch (exp)
statements
these statements are executed if exp < 0.5
case 1
statements
these statements are executed if 0.5 < exp < 1.5
case 2
statements
these statements are executed if 1.5 < exp < 2.5
case n
statements
endswitch
these statements are executed if n-0.5< exp< n+0.5
The switch statement must not be nested.
%
the rest of the line after % is a comment
example:
% square program2
n=4
label "start"
fwd 1 @v0.3
turn 90
n=n-1
if (n >0) "start"
Expressions.
The language supports normal arithmetic expressions:
+- * /
> >= < <= == !=
|
logical or
&
logical and
()
=
assignment
Functions.
sin(x)
cos(x)
tan(x)
atan(x)
atan2(y,x)
ln(x)
exp(x)
sqrt(x)
abs(x)
Example:
x=1.0
y=3
a=2.5*sin(x)+sqrt(y)
Logging of Data.
The language supports simultaneus logging of up to 9 variables. Logging is started with
the log command and the result is stored in the text file 'log' in the current directory when
the run is stopped. The variables are sampled every 0.01 seconds and stored as a line for
each sample time i.e. they may be loaded into e.g Matlab or Excel.
log "varname" ["varname"]*
Example:
log "$odox" "odoy" "$odoth"
eval exp [; exp]*
wait time
Miscellaneous.
print the results of the expressions on the screen in scriptmode and
returns the values in socket mode.
makes the program wait for time seconds
vision “command text”
sends the “command text” to the cameraserver if started. The
server might return data in the default variables $vis0 to $vis9
If the command text is $string the string generated by the latest
stringcat command will be used
laser “command text”
sends the “command text” to the laserserver if started. The server
might return data in the default variables $l0 to $l9
If the command text is $string the string generated by the latest
stringcat command will be used.
stringcat parameters
concatenates the parameters to a string saved in $string. If a
parameter
is a string it is added unchanged if the parameter is a number
or a variable it is converted to a string and added. The command is
intended to be used with the “laser” or “vision” commands
example:
stringcat “send “ 9 “ apples”
will generate the string “send 9 apples”
Socket interface.
The socket interface is also lineorientated. The interface consists of the following special
commands:
getevent [time-out] fetches the next event in the event queue. If the queue is empty the
command will return after 'time-out' seconds with the message
'eventtimeout'. If no time-out is given the command will return
immediately.
putevent "text "
generates an event with the text 'userevent text' where text is the
text entered between the "'s
flushcmds
flushes all commands from the command queue
logoff
logs off and leaves the robot ready for a new logon
exit
logs off and stop the robot controlprogram
addwatch “name” type :( expression)
puts a watch in the watch table. If expression becomes true an
event 'watch name fired time' , where name is the name given in
addwatch and time is the time where the expression became true.
When a command is sent to the socket the robot will respond with 'IDnn queued' where
nn is a unique number. Execution of the command will generate a number of events that
may be retrieved with the command 'getevent' . If the command is finished in one sample
the event Idnn assignment will be generated. If the command takes more samples to
execute the start of execution will be signalled with 'IDnn started' and end of execution
with 'IDnn stopcond xx' where xx is the value of the stopcondition.
System variables.
Odometry:
$odox
$odoy
$odoth
$odovelocity
$ododist
x-coordinate of vehicle position (m)
ycoordinate of vehicle position (m)
direction of vehicle (rad)
velocity of vehicle (based on odometry measurements)
distance driven since start of vehicle (m)
$drivendist
distance driven during the current command (m)
IR-sensors:
all distances are measured from the sensor itself.
$irdistleft
distance (m) measured by the left side sensor
$irdistfrontleft
distance (m) measured by the front left sensor
$irdistfrontmiddle
distance (m) measured by the front middle sensor
$irdistfrontright
distance (m) measured by the front right sensor
$irdistright
distance (m) measured by the right side sensor
$cmdtime
$batteryvoltage
$supplyvoltage
$time
$motionsstatus
$motorstatusr
$motorstatusl
Linesensor:
$line0 to $line7
$linepos
$blacklinefound
$crossingblackline
time spent in the current command (sec)
batteryvoltage (v) lowpass filtered with a time constant of a second
voltage of the external power supply (v) lowpass filtered with a
time constant of 0.1 second
system time in seconds (Linux time of day)
status telling if the robot is stopped by an obstacle
motor status for the right motor
motor status for the left motor
linesensor values
position of found line
true if a black line is detected ( used to find a line approched from
the side)
true if a black line is crossing the line the vehicle follows
Robot Control Program.
The program implementing SMRCL is called smrdemo. It is started by logging on to the
robot using ssh and starting the program from the terminalwindow.
smrdemo [options] [scriptfile]
The program has the following options:
-c calibration. This will start a calibration menu where the linesensor, the irsensor and
the odometry may be calibrated. The calibration results will be saved in files
in the directory calib which must exist before calibration.
-t n start the program as a socket server on port 31000+n. (n is an integer)
-s n start the program with a simulated smr
-v off
runs the program in silent mode (no printing on the screen).
A PPENDIKS
Kildekode
C.1
1 #
#
#
#
#
6
#
haupt.c
include
include
include
include
include
< s i g n a l . h>
< s t d l i b . h>
< s t d i o . h>
< s t r i n g . h>
<math . h>
include " k l i e n t . h "
/ / Konstanter
# define SPEED_LOW 0 . 1
11 # define SPEED 0 . 2
# define SPEED_HIGH 0 . 3
# define TURNR 0 . 2 5
16 # define
# define
# define
# define
# define
21 # define
# define
# define
# define
START_OFFSET_X 0 . 1 8 5
START_OFFSET_Y 0 . 1 8 5
START_OFFSET_TH 3 . 1 4 1 5 / 4
BIN_OFFSET_X 0 . 4 0
BIN_OFFSET_Y 0 . 3 0
ITEM_OFFSET_X 0 . 0 4
ITEM_OFFSET_Y 0 . 0 4
ARENA_X 2 . 1
ARENA_Y 3
26 # define LASER_X_OFFSET 0 . 0 7 9
# define LASER_Y_OFFSET 0 . 0 9 8
# define DODGE_OFFSET 0 . 6
31 # define COLLECT_DIST 0 . 1 5
# define TIME_ROUND 90
# define PI 3 . 1 4 1 5
/ / P a r a m e t e r s som s k a l t w e a k ’ e s . . . : :
# define IRBAT_THR 0 . 1 5
# define IRLEFT_THR 0 . 3 8
# define IRMIDDLE_THR 0 . 3 8
# define IRRIGHT_THR 0 . 3 8
41 # define LINE_THR 1
# define RED_THR 4 . 8
36
# define
# define
46 # define
# define
# define
# define
51
CanU_THR
CanV_THR
PROB_CAN
BottleU_THR
BottleV_THR
PROB_BOTTLE
120
130
0.7
120
125
0.7
/ / Minimum væglængde
# define WALL_MIN 0 . 2
# define CMD_COMPLETE " 0 . 0 0 0 0 0 0 "
# define IRBAT_BLOCKED " 1 . 0 0 0 0 0 0 "
56 # define IRFRONT_BLOCKED " 2 . 0 0 0 0 0 0 "
# define p r i n t L o c ( l o c ) p r i n t f ( " L o c a t i o n \" " # l o c " \ " : (%f , %f , %f ) \n " , l o c . x , l o c . y , l o c . th )
# define p r i n t I t e m ( ) p r i n t f ( " Item : %s\n " , item ? ( item == can ? " can " : " b o t t l e " ) : " none " ) ;
61 # define round ( x ) ( ( x−f l o o r f ( x ) >= 0 . 5 ) ? c e i l f ( x ) : f l o o r f ( x ) )
/ / Srtuct t i l angivelse af positioner
typedef s t r u c t {
95
C
96
66
APPENDIKS C. KILDEKODE
float x ;
float y ;
f l o a t th ;
} location ;
71 void
void
void
void
void
76
void
initialize () ;
setColorVar ( ) ;
waitForCable ( ) ;
catchAlarm ( i n t ) ;
finalize () ;
start () ;
/ / SMRCL commands
81 void forward ( f l o a t d i s t , f l o a t speed ) ;
void turn ( f l o a t angle , i n t using_rad , f l o a t speed ) ;
void t u r n r ( f l o a t radius , f l o a t angle , i n t using_rad , f l o a t speed ) ;
/ / Obstacle avoidance
86 i n t isOpponentDetected ( ) ;
void dodgeOpponent ( ) ;
// Batterifunktioner
int isBatteryDetected ( ) ;
91 i n t i s B a t t e r y S t u c k ( ) ;
int batteryColor ( ) ;
void g r a b B a t t e r y ( ) ;
void f r e e B a t t e r y ( ) ;
void d e l i v e r B a t t e r y ( ) ;
96
/ / F l a s k e− og d å s e f u n k t i o n e r
void hasItem ( ) ;
void d e l i v e r ( ) ;
void t o B a s k e t ( ) ;
101 void c o l l e c t I t e m ( l o c a t i o n itemLoc ) ;
void scanIt ems ( ) ;
/ / V i n k l e r og o d o m e t r i
f l o a t normAngle ( f l o a t v ) ;
106 void updateOdometry ( ) ;
// Posiotionsfunktioner
void g e t P o s i t i o n ( ) ;
void g o t o P o s i t i o n ( l o c a t i o n Loc ) ;
111
/ / F u n k t i o n e r t i l h å n d t e r i n g a f e v e n t s f r a Smrdemo
void getID ( char ∗) ;
i n t isStopped ( char ∗ , c o n s t char ∗) ;
i n t checkStopConditions ( ) ;
116
/ / I n i t i a l i s e r i n g a f v a r i a b l e r mv .
i n t ON = 1 , GAME_ON = 1 , IN_PROCESS = 1 ;
i n t s t a r t _ d o n e = 0 , scanItems_done = 0 , c o l l e c t I t e m _ d o n e = 0 , whichType_done = 0 ;
121 i n t toBasket_done = 0 , d e l i v e r _ d o n e = 0 ;
int motorsBlocked_flag = 0 , o b s t a c l e _ f l a g = 0 , batteryTrapped_flag = 0 ;
i n t dodgeing = 0 ;
float dist = 1;
char msg [STRING_LENGTH] = " \0 " ;
126 f l o a t ans = 0 ;
enum c o l o r s {BLUE , RED} teamColor = BLUE ;
enum items { none , can , b o t t l e } item ;
enum e v e n t s { cmd_complete =1 , motors_blocked , b a t t e r y _ s t u c k , opponent_detected , e v e n t _ t i m e o u t } ;
131
l o c a t i o n s t a r t L o c , curLoc , b o t t l e B i n , canBin , b a t t e r B i n , bins , t e s t 1 , t e s t 2 , b a t S t a r t ;
float
float
136 f l o a t
float
int
int
141 i n t
int
int
scanx , scany , s c a n t h ;
d , alpha ;
xbatmin = 0 . 1 , xbatmax = 2 . 9 , ybatmin = 0 . 1 , ybatmax = 1 . 9 ;
basketx = 0 ;
noMoreItems = 1 ;
obstacleTimes = 0 ;
k = 0;
batNo = 0 ;
basketFound_flag = 0 ;
kl i en tt yp e kt ;
146
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
i n t main ( i n t argc , char ∗∗argv ) {
/ / Tolker inputtet fra terminalen
C.1. HAUPT.C
151
156
161
166
171
176
/ / S i k r e r a t programmet i k k e s t a r t e r h v i s d e r e r a n g i v e t en f a r v e som i k k e f i n d e s
i f ( a r g c == 4 ) {
k t . hostname = argv [ 1 ] ;
k t . p o r t = 31000 + a t o i ( argv [ 2 ] ) ;
i f ( strcmp ( argv [ 3 ] , " blue " ) == 0 ) {
teamColor = BLUE ;
}
e l s e i f ( strcmp ( argv [ 3 ] , " red " ) == 0 ) {
teamColor = RED ;
}
else {
p r i n t f ( " Usage : haupt <host > <port > <colour >\n " ) ;
exit (1) ;
}
}
else {
p r i n t f ( " Usage : haupt <host > <port > <colour >\n " ) ;
exit (1) ;
}
k l _ c o n n e c t (& k t ) ;
i f ( kt . error )
exit (1) ;
/ / Sætter r e l e v a n t e konstanter afhængig af farven
setColorVar ( ) ;
initialize () ;
waitForCable ( ) ;
181
186
97
/ / V e n t e r på a t s t a r t s n o r e n b l i v e r t r u k k e t ud
while (GAME_ON) {
i f ( IN_PROCESS ) {
/∗ i f ( m o t o r s B l o c k e d _ f l a g ) {
/ / motorsBlocked () ;
IN_PROCESS = 0 ;
GAME_ON = 0 ;
} else i f ( batteryTrapped_flag ) {
batteryTrapped () ;
IN_PROCESS = 0 ;
191
196
} else i f ( deliver_done ) {
scanItems_done = 0;
collectItem_done = 0;
whichType_done = 0 ;
toBasket_done = 0;
deliver_done = 0;
IN_PROCESS = 0 ;
201
} e l s e i f ( toBasket_done ) {
d e l i v e r ( ) ; / / A f l e v e r f l a s k e n e l l e r dåsen .
IN_PROCESS = 0 ;
206
} else if ( collectItem_done ) {
t o B a s k e t ( ) ; / / Kør t i l den r i g t i g e k u r v .
IN_PROCESS = 0 ;
211
} e l s e i f ( toWall_done ) {
c o l l e c t I t e m ( ) ; / / Saml f l a s k e
e l l e r d å s e op .
IN_PROCESS = 0 ;
216
} else
i f (1) {
IN_PROCESS = 0 ;
221
226
} else i f ( start_done ) {
/ / s c a n I t e m s ( ) ; / / Data f r a l a s e r e n b r u g e s t i l a t f i n d e den n æ s t e i t e m .
IN_PROCESS = 0 ;
} e l s e ∗/ i f ( ! s t a r t _ d o n e ) {
start () ;
IN_PROCESS = 0 ;
}
231
else {
p r i n t f ( " J e g ved i k k e hvad j e g s k a l gøre . . . ! \ n " ) ;
IN_PROCESS = 0 ;
GAME_ON = 0 ;
98
APPENDIKS C. KILDEKODE
}
}
236
IN_PROCESS = 1 ;
}
241
finalize () ;
p r i n t f ( " c l o s i n g \n " ) ;
k l _ d i s c o n n e c t (& k t ) ;
exit (0) ;
246 }
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
void i n i t i a l i z e ( ) {
kl_send (& kt , " l o g \" $odox \" \" $odoy \" \" $odoth \" \" $ l i n e 0 \" \" $ l i n e 4 \" \" $ i r d i s t r i g h t \"
\" $ i r d i s t f r o n t r i g h t \" \" $ i r d i s t f r o n t m i d d l e \" \" $ i r d i s t f r o n t l e f t \"\n " ) ;
kl_send (& kt , " rs485send 10 1\n " ) ; / / Sæt b a t t e r i s e r v o a r m e n t i l k l a r p o s i t i o n
kl_send (& kt , " rs485send 10 4\n " ) ; / / Luk b a t t e r i b a g p l a d e n
kl_send (& kt , " rs485send 10 6\n " ) ; / / Luk b a t t e r i h o l d e r e n
kl_send (& kt , " rs485send 10 9\n " ) ; / / S l u k b ø r s t e m o t o r e n
256
kl_send (& kt , " i d l e \n " ) ; / / S t o p m o t o r e r n e
}
251
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
261 void f i n a l i z e ( ) {
kl_send (& kt , " rs485send 10 1\n " ) ; / / Sæt b a t t e r i
kl_send (& kt , " rs485send 10 4\n " ) ; / / å b e n b a t t e r i
kl_send (& kt , " rs485send 10 7\n " ) ; / / å b e n b a t t e r i
kl_send (& kt , " rs485send 10 9\n " ) ; / / S l u k b ø r s t e
266
kl_send (& kt , " i d l e \n " ) ; / / S t o p m o t o r e r n e
}
servoarmen t i l
bagpladen
holderen
motoren
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / The s i g n a l h a n d l e r c l e a r s t h e f l a g and r e−e n a b l e s i t s e l f .
/ / R e s e t s e r v o s and m o t o r s , and d i s c o n n e c t s
void catchAlarm ( i n t s i g ) {
GAME_ON = 0 ;
s i g n a l ( s i g , catchAlarm ) ;
276
finalize () ;
k l _ d i s c o n n e c t (& k t ) ;
exit (0) ;
}
271
281
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Sikrer at robotten ikke kører før s t a r t k a b l e t b l i v e r trukket
void waitForCable ( ) {
int i =0;
286
i n t go_on = 0 ;
i n t avg = 0 ;
291
296
301
306
311
/ / wait f o r the c a b l e to be i n s e r t e d
while ( ! go_on ) {
f o r ( i = 1 ; i < 6 ; i ++) {
kl_send (& kt , " e v a l $ m o t o r s t a t u s r \n " ) ;
avg += a t o i ( k t . answer ) ;
}
go_on = ( avg / ( i −1) == 1 2 8 ) ? 1 : 0 ;
avg = 0 ;
}
/ / wait f o r the c a b l e to be p u l l e d
go_on = 0 ;
while ( ! go_on ) {
f o r ( i = 1 ; i < 6 ; i ++) {
kl_send (& kt , " e v a l $ m o t o r s t a t u s r \n " ) ;
avg += a t o i ( k t . answer ) ;
}
go_on = ( avg / ( i −1) == 0 ) ? 1 : 0 ;
avg = 0 ;
}
/ / E s t a b l i s h a h a n d l e r f o r SIGALRM s i g n a l s .
s i g n a l (SIGALRM, catchAlarm ) ;
/ / S e t an a l a r m t o go o f f i n a l i t t l e w h i l e .
alarm (TIME_ROUND) ;
316 }
klarposition
C.1. HAUPT.C
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
/ / Sætter r e l e v a n t e p o s i t i o n e r afhængig af hvilken f a r v e r o b o t t e n t i l h ø r e r
321 /∗ Works l i k e a charm 1 1 / 5 2 3 : 3 4 ; −) ∗/
void s e t C o l o r V a r ( ) {
//
//
(0 ,0) i s blue corner , the arena i s the 1. quadrant
//
326
switch ( teamColor ) {
c a s e RED :
s t a r t L o c . y = ARENA_Y − START_OFFSET_Y ;
s t a r t L o c . x = 0 + START_OFFSET_X ;
331
s t a r t L o c . th = −START_OFFSET_TH ;
b o t t l e B i n . y = 0 + BIN_OFFSET_Y ;
b o t t l e B i n . x = ARENA_X − BIN_OFFSET_X ;
b o t t l e B i n . th = −PI / 2 ;
336
canBin . y = 0 + BIN_OFFSET_Y ;
canBin . x = ARENA_X − BIN_OFFSET_X ;
canBin . th = 0 ;
341
346
351
b i n s . y = 0 + BIN_OFFSET_Y ;
b i n s . x = ARENA_X − BIN_OFFSET_X ;
b i n s . th = −PI / 4 ;
test1 . x = 1.5;
test1 .y = 1.5;
t e s t 1 . th = 0 ;
test2 . x = 0.5;
test2 .y = 2.5;
t e s t 2 . th = (3∗ PI ) / 4 ;
batterBin . x = 0 . 0 ;
batterBin . y = 1 . 5 ;
b a t t e r B i n . th = 0 . 0 ;
356
break ;
361
366
c a s e BLUE :
s t a r t L o c . y = 0 + START_OFFSET_Y ;
s t a r t L o c . x = 0 + START_OFFSET_X ;
s t a r t L o c . th = START_OFFSET_TH ;
b o t t l e B i n . y = ARENA_Y − BIN_OFFSET_Y ;
b o t t l e B i n . x = ARENA_X − BIN_OFFSET_X ;
b o t t l e B i n . th = PI / 2 ;
canBin . y = ARENA_Y − BIN_OFFSET_Y ;
canBin . x = ARENA_X − BIN_OFFSET_X ;
canBin . th = 0 ;
371
b i n s . y = ARENA_Y − BIN_OFFSET_Y ;
b i n s . x = ARENA_X − BIN_OFFSET_X ;
b i n s . th = PI / 4 ;
376
381
386
test1 . x = 0.5;
test1 .y = 1.5;
t e s t 1 . th = −PI / 8 ;
test2 . x = 0.5;
test2 .y = 0.5;
t e s t 2 . th = −PI / 4 . 0 ;
batterBin . x = 0 . 0 ;
batterBin . y = 1 . 5 ;
b a t t e r B i n . th = 0 . 0 ;
break ;
}
391
396
/ / s e t odometry to s t a r t l o c a t i o n
s p r i n t f ( msg , " s e t \" $odox \" %f \n " , s t a r t L o c . x ) ;
kl_send (& kt , msg ) ;
s p r i n t f ( msg , " s e t \" $odoy \" %f \n " , s t a r t L o c . y ) ;
kl_send (& kt , msg ) ;
s p r i n t f ( msg , " s e t \" $odoth \" %f \n " , s t a r t L o c . th ) ;
kl_send (& kt , msg ) ;
kl_send (& kt , " t a r g e t h e r e \n " ) ;
curLoc = s t a r t L o c ;
401 }
99
100
APPENDIKS C. KILDEKODE
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Gør d e t mere b e k v e m t a t s k r i v e s m r c l−kommandoer
406 void forward ( f l o a t d i s t , f l o a t speed ) {
s p r i n t f ( msg , " fwd %f @v%f : ( $ i r d i s t r i g h t >%f ) | ( ( $ i r d i s t f r o n t l e f t <%f & $ i r d i s t f r o n t m i d d l e
<%f ) |( $ i r d i s t f r o n t m i d d l e <%f & $ i r d i s t f r o n t r i g h t <%f ) |( $ i r d i s t f r o n t r i g h t <%f &
$ i r d i s t f r o n t l e f t <%f ) ) \n " , d i s t , speed , IRBAT_THR , IRLEFT_THR , IRMIDDLE_THR ,
IRMIDDLE_THR , IRRIGHT_THR , IRRIGHT_THR , IRLEFT_THR ) ;
//
s p r i n t f ( msg , " fwd %f @v%f \n " , d i s t , s p e e d ) ;
kl_send (& kt , msg ) ;
}
411
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Gør d e t mere b e k v e m t a t s k r i v e s m r c l−kommandoer
void turn ( f l o a t angle , i n t using_rad , f l o a t speed ) {
416
char ∗ rad = using_rad ? " \" rad \" " : " " ;
s p r i n t f ( msg , " turn %f %s @v%f \n " , angle , rad , speed ) ;
kl_send (& kt , msg ) ;
}
421
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Gør d e t mere b e k v e m t a t s k r i v e s m r c l−kommandoer
void t u r n r ( f l o a t radius , f l o a t angle , i n t using_rad , f l o a t speed ) {
426
char ∗rad = using_rad ? " \" rad \" " : " " ;
s p r i n t f ( msg , " t u r n r %f %f %s @v%f \n " , radius , angle , rad , speed ) ;
kl_send (& kt , msg ) ;
}
431
436
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
/ / De f ø r s t e i n d l e d e n d e kommandoer
/ /KODEN HERUNDER ER KUN EN TEST−KODE
void s t a r t ( ) {
char id [STRING_LENGTH ] ;
p r i n t f ( " \n================\ n s t a r t ( ) \n================\n " ) ;
/ / R e s e t m o t o r s and p l a c e t a r g e t h e r e ,
/ / a s we h a v e moved t h e r o b o t a f t e r s t a r t i n g t h e SMRdemo s e r v e r
/ / which r e s u l t s i n b l o c k e d m o t o r s
kl_send (& kt , " r e s e t m o t o r s \n " ) ;
kl_send (& kt , " t a r g e t h e r e \n " ) ;
441
446
item=can ;
toBasket ( ) ;
getID ( id ) ;
p r i n t f ( " event : %d\n " , checkStopConditions ( id ) ) ;
deliver ( ) ;
getID ( id ) ;
p r i n t f ( " event : %d\n " , checkStopConditions ( id ) ) ;
451
p r i n t f ( ">−− End −−>\n " ) ;
456
start_done = 1;
GAME_ON = 0 ;
kl_send (& kt , " rs485send 10 7\n " ) ;
sleep ( 3 ) ;
461
}
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / T j e k k e r om d e r s i d d e r e t b a t t e r i f a s t i t r a g t e n
/ / Returnerer 1 h v i s sandt , e l l e r s 0 .
int isBatteryStuck ( ) {
int battery_stuck = 0 , i = 1;
471
f l o a t s e n s o r = 0 . 0 , avg = 0 . 0 , sum = 0 . 0 ;
466
f o r ( i = 1 ; i < 6 ; i ++) {
/ / i r−s e n s o r e n s i d d e r i p o r t e n t i l den h ø j r e i r−s e n s o r på en n o r m a l SMR−r o b o t
kl_send (& kt , " e v a l $ i r d i s t r i g h t \n " ) ;
s s c a n f ( k t . answer , "%f " ,& s e n s o r ) ;
sum += s e n s o r ;
}
avg = sum/( i −1) ; / / Gennemsnit a f fem s a m p l e s
p r i n t f ( " i r d i s t r i g h t value = %f \n " , avg ) ;
476
481
b a t t e r y _ s t u c k = ( avg > IRBAT_THR ) ? 1 : 0 ; / / P a s s e r e s g r æ n s e v æ r d i e n ?
return battery_stuck ;
}
C.1. HAUPT.C
101
486
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / T j e k k e r om d e r d e r l i g g e r e t b a t t e r i i bunden a f t r a g t e n .
/ / Returnerer 1 h v i s sandt , e l l e r s 0 .
491 i n t i s B a t t e r y D e t e c t e d ( ) {
int battery_detected = 0 , i = 1;
f l o a t s e n s o r = 0 . 0 , avg = 0 . 0 , sum = 0 . 0 ;
f o r ( i = 1 ; i < 6 ; i ++) {
kl_send (& kt , " e v a l $ l i n e 0 \n " ) ; / / S e n s o r e n e r k o b l e t t i l l i n e 0 −p o r t e n
s s c a n f ( k t . answer , "%f " ,& s e n s o r ) ;
sum += s e n s o r ;
}
avg = sum/( f l o a t ) ( i −1) ; / / Gennemsnit a f fem s a m p l e s
b a t t e r y _ d e t e c t e d = ( avg < LINE_THR ) ? 1 : 0 ; / / P a s s e r e s g r æ n s e v æ r d i e n ?
496
501
return battery_detected ;
}
506
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / T j e k k e r om b a t t e r i e t i t r a g t e n m a t c h e r den t i l d e l t e f a r v e
/ / R e t u r n e r e r RED h v i s r ø d t , BLUE h v i s b l å t og −1 h v i s d e r i k k e l i g g e r n o g e t b a t t e r i i t r a g t e n
int correctBatteryColor ( ) {
511
i n t c o l o r = BLUE , c o r r e c t C o l o r = 0 , i = 0 ;
f l o a t s e n s o r = 0 . 0 , avg = 0 . 0 , sum = 0 . 0 ;
i n t r e s u l t = −1;
f o r ( i = 1 ; i < 6 ; i ++) {
kl_send (& kt , " e v a l $ l i n e 4 \n " ) ; / / S e n s o r e n e r k o b l e t
s s c a n f ( k t . answer , "%f " ,& s e n s o r ) ;
sum += s e n s o r ;
}
avg = sum/( f l o a t ) ( i −1) ; / / Gennemsnit a f fem s a m p l e s
516
t i l l i n e 0 −p o r t e n
521
c o l o r = ( avg > RED_THR) ? RED : BLUE ;
p r i n t f ( " Color : %d\n " , c o l o r ) ;
526
c o r r e c t C o l o r = ( c o l o r == teamColor ) ? 1 : 0 ;
r e s u l t = i s B a t t e r y D e t e c t e d ( ) ? c o r r e c t C o l o r : −1 ;
p r i n t f ( " R e s u l t : %d\n " , r e s u l t ) ;
return r e s u l t ;
531 }
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / S e k v e n s a f kommandoer som s t y r e r armen n å r den s k a l s a m l e e t b a t t e r i op f r a t r a g t e n .
536 void g r a b B a t t e r y ( ) {
i n t grabbed = 0 ;
/ / B l i v e r v e d med a t p r ø v e t i l d e r i k k e e r e t b a t t e r i i t r a g t e n mere
while ( ! grabbed ) {
541
546
/ / K ø r e r f r e m f o r a t s i k r e a t b a t t e r i e t e r i bunden a f t r a g t e n
kl_send (& kt , " i d l e \n " ) ;
s p r i n t f ( msg , " d r i v e @v%f : ( $cmdtime > 0 . 3 ) \n " ,SPEED_LOW) ;
kl_send (& kt , msg ) ;
kl_send (& kt , " i d l e \n " ) ;
551
/ / Servokommando : Sænk arm
kl_send (& kt , " rs485send 10 2\n " ) ;
/ / Vent t i l kommandoen e r u d f ø r t
sleep ( 3 ) ;
556
/ / Servokommando : Hæv arm
kl_send (& kt , " rs485send 10 3\n " ) ;
/ / Vent t i l kommandoen e r u d f ø r t
sleep ( 3 ) ;
561
/ / Servokommando : Arm t i l u d g a n g s p o s i t i o n
kl_send (& kt , " rs485send 10 1\n " ) ;
/ / Vent t i l kommandoen e r u d f ø r t
sleep ( 2 ) ;
/ / T j e k om d e r s t a d i g e r e t b a t t e r i i t r a g t e n .
if ( ! isBatteryDetected ( ) ) {
grabbed = 1 ;
batNo ++;
p r i n t f ( " Grabbed\n " ) ;
}
566
}
}
102
APPENDIKS C. KILDEKODE
571
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / Afviser batteri af forkert farve
void r e j e c t B a t t e r y ( ) {
576
char id [STRING_LENGTH ] ;
/ / Åben lem i b a g e n d e
kl_send (& kt , " i d l e \n " ) ;
kl_send (& kt , " rs485send 10 5\n " ) ;
581
while ( i s B a t t e r y D e t e c t e d ( ) ) {/
/ / K ø r s e l f o r a t f o r b a t t e r i e t igennem å b n i n g e n
forward ( 0 . 0 8 ,SPEED_LOW) ;
kl_send (& kt , " i d l e \n " ) ;
turn ( 5 0 , 0 ,SPEED_LOW) ;
kl_send (& kt , " i d l e \n " ) ;
forward ( 0 . 1 , SPEED_LOW) ;
getID ( id ) ;
586
/ / T j e k f o r f e j l der måtte o p s t å under k ø r s l e n
/ / samt r e g i s t r e r n å r kommandoen e r u d f ø r t
switch ( checkStopConditions ( id ) ) {
c a s e cmd_complete :
/ / Kommandoen e r u d f ø r t og lemmen l u k k e s i g e n
kl_send (& kt , " i d l e \n " ) ;
kl_send (& kt , " rs485send 10 4\n " ) ;
return ;
break ;
591
596
601
c a s e motors_blocked :
break ;
case battery_stuck :
break ;
606
c a s e opponent_detected :
break ;
case event_timeout :
break ;
611
}
}
/ / Lemmen l u k k e s
kl_send (& kt , " rs485send 10 4\n " ) ;
616
}
621
626
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / F r i g ø r e l s e s m a n ø v r e som k ø r e s h v i r e t b a t t e r i s i d d e r f a s t i t r a g t e n .
void f r e e B a t t e r y ( ) {
char id [STRING_LENGTH ] ;
enum e v e n t s event ;
/ / D o b b e l t−t j e k om b a t t e r i e t
while ( i s B a t t e r y S t u c k ( ) ) {
siider fast
631
/ / S e k v e n s a f kommandoer f o r a t f r i g ø r e b a t t e r i e t
forward ( −0.1 ,SPEED_LOW) ;
turn ( 1 0 , 0 ,SPEED_LOW) ;
forward ( 0 . 3 , SPEED_LOW) ;
getID ( id ) ;
636
/ / T j e k f o r f e j l der måtte o p s t å under k ø r s l e n
/ / samt r e g i s t r e r n å r kommandoen e r u d f ø r t
event = checkStopConditions ( id ) ;
641
646
switch ( event ) {
c a s e motors_blocked :
/ / S e k v e n s a f kommandoer h v i s m o t o r e r n e b l i v e b l o k e r e t
forward ( −0.3 ,SPEED ) ;
forward ( 0 . 2 , SPEED_LOW) ;
getID ( id ) ;
checkStopConditions ( id ) ;
break ;
c a s e cmd_complete :
break ;
651
case battery_stuck :
break ;
c a s e opponent_detected :
C.1. HAUPT.C
103
break ;
656
case event_timeout :
break ;
}
}
661 }
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / F i n d e r b e h o l d e r e n t i l b a t t e r i e r n e på banen og a f l e v e r e r dem
void d e l i v e r B a t t e r y ( ) {
666
char id [STRING_LENGTH ] ;
batStart . x = 0.5;
batStart . y = 1.5;
b a t S t a r t . th = 0 . 5 ;
671
i f ( b a t t e r B i n . x == 0 . 0 ) {
gotoPosition ( batStart ) ;
676
/ / Kører i n d t i l motorerne b l i v e r b l o k e r e t
s p r i n t f ( msg , " fwd 2 @v%f \n " ,SPEED_LOW) ;
kl_send (& kt , msg ) ;
getID ( id ) ;
681
kl_send (& kt , " g e t e v e n t 10\n " ) ;
p r i n t f ( "%s " , k t . answer ) ;
switch ( checkStopConditions ( id ) ) {
c a s e motors_blocked :
/ / Konkluderer hvor b a t t e r i b e h o l d e r e n er p l a c e r e t
getPosition ( ) ;
686
i f ( curLoc . x > 0 . 5 ) {
i f ( curLoc . x > 0 . 7 5 ) {
i f ( curLoc . x > 1 . 0 ) {
i f ( curLoc . x > 1 . 4 ) {
p r i n t f ( " The b a s k e t was not found ! ! ! " ) ;
}
}
else {
batterBin . x = 1 . 1 ;
basketFound_flag = 1 ;
}
}
else {
batterBin . x = 0.85;
basketFound_flag = 1 ;
}
}
else {
batterBin . x = 0 . 6 ;
basketFound_flag = 1 ;
}
691
696
701
706
711
s p r i n t f ( msg , " fwd −0.3 @v%f \n " ,SPEED ) ;
kl_send (& kt , msg ) ;
getID ( id ) ;
break ;
716
c a s e cmd_complete :
break ;
case battery_stuck :
break ;
721
c a s e opponent_detected :
break ;
case event_timeout :
break ;
726
}
731
/ / Hvis b e h o l d e r e n b l e v f u n d e t b l i v e r b a t t e r i e r n e l æ s s e t a f i den
i f ( basketFound_flag ) {
batterBin . x = batterBin . x + 0.15;
batterBin . y = batterBin . y + 0 . 2 ;
g o t o P o s i t i o n ( b a t t e r B i n ) ; / / Drops t h e b a t t e r i e s o f f i n t h e b a s k e t
736
kl_send (& kt , " rs485send 10 7\n " ) ;
kl_send (& kt , " wait 0 . 5 \ n " ) ;
kl_send (& kt , " rs485send 10 6\n " ) ;
104
741
APPENDIKS C. KILDEKODE
batNo = 0 ;
}
e l s e { / / E l l e r s s m i d e s d e b l o t e t s t e d på banen
gotoPosition ( batterBin ) ;
kl_send (& kt , " rs485send 10 7\n " ) ;
kl_send (& kt , " wait 0 . 5 \ n " ) ;
kl_send (& kt , " rs485send 10 6\n " ) ;
746
batNo = 0 ;
751
}
}
}
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / T j e k k e r om s e r v e r e n h a r g i v e t e t s v a r s v a r e n d e t i l d e t a k t u e l l e j o b−i d .
/ / Returnerer 1 hvis sandt
i n t isStopped ( char∗ id , c o n s t char∗ stopcond ) {
char tmp [STRING_LENGTH ] ;
761
s t r c p y ( tmp , id ) ;
s t r c a t ( tmp , " stopcond " ) ;
s t r c a t ( tmp , stopcond ) ;
s t r c a t ( tmp , " \n " ) ;
r e t u r n strcmp ( k t . answer , tmp ) == 0 ;
766 }
756
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / H e n t e r d e t a k t u e l l e j o b−i d .
771 void getID ( char ∗id ) {
char i d b u f [STRING_LENGTH ] ;
s t r c p y ( idbuf , k t . answer ) ;
i d b u f [ k t . answer_len −7] = ’ \0 ’ ;
s t r c p y ( id , i d b u f ) ;
776 }
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / F o r s ø g e r a t i n d f a n g e en f l a s k e e l l e r d å s e
781 void c o l l e c t I t e m ( l o c a t i o n itemLoc ) {
char id [STRING_LENGTH ] ;
int state = 0;
f l o a t xMin = 0 . 0 , yMin = 0 . 0 ;
f l o a t thMinX = 0 . 0 , thMinY = 0 . 0 ;
786
f l o a t deltaX = 0 . 0 , deltaY = 0 . 0 ;
l o c a t i o n getLoc ;
p r i n t f ( " \n================\ n c o l l e c t I t e m ( ) \n================\n " ) ;
791
796
801
806
811
816
821
/ / U n d e r s ø g e r h v i l k e n væg d e r e r nærmest
i f ( (ARENA_X/ 2 . 0 − itemLoc . x ) > 0 ) {
/ / Væg v e d minimum y
xMin = itemLoc . x ;
thMinX = PI ;
d e l t a X = itemLoc . x + COLLECT_DIST ;
}
else {
/ / Væg v e d maksimum y
xMin = ARENA_X − itemLoc . x ;
thMinX = 0 ;
d e l t a X = itemLoc . x − COLLECT_DIST ;
}
i f ( (ARENA_Y/ 2 . 0 − itemLoc . y ) > 0 ) {
/ / Væg v e d minimum x
yMin = itemLoc . y ;
thMinY = −PI / 2 . 0 ;
d e l t a Y = itemLoc . y + COLLECT_DIST ;
}
else {
/ / Væg v e d maksimum x
yMin = ARENA_Y − itemLoc . y ;
thMinY = PI / 2 . 0 ;
d e l t a Y = itemLoc . y − COLLECT_DIST ;
}
/ / Finder udgangspositionen t i l opsamlingen
getLoc = itemLoc ;
i f ( xMin < yMin ) {
getLoc . x += d e l t a X ;
C.1. HAUPT.C
105
getLoc . th = thMinX ;
826
}
else {
getLoc . y += d e l t a Y ;
getLoc . th = thMinY ;
}
831
g o t o P o s i t i o n ( getLoc ) ;
/ / T j e k k e r om e t e l e m e n t a l l e r e d e e r b l e v e t o p s a m l e t v e d e t t i l f æ l d e
hasItem ( ) ;
836
/ / F o r s ø g e r i n d t i l e l e m e n t e t e r s a m l e t op
while ( item == none ) {
i f ( s t a t e == 0 ) {
kl_send (& kt , " d r i v e @v0 . 1 \ n " ) ;
getID ( id ) ;
p r i n t f ( " \nID : %s\n " , id ) ;
}
841
switch ( checkStopConditions ( id ) ) {
c a s e motors_blocked :
i f ( s t a t e == 0 ) {
forward ( −0.2 ,SPEED ) ;
getID ( id ) ;
s t a t e ++;
}
else {
sleep ( 1 ) ;
forward ( −0.15 ,SPEED_LOW) ;
getID ( id ) ;
}
break ;
846
851
856
c a s e cmd_complete :
i f ( s t a t e == 1 ) {
/ / Det t j e k k e s om d e r e r i n d f a n g e t e t e l e m e n t e f t e r r u t i n e n
hasItem ( ) ;
state = 0;
}
break ;
861
866
case battery_stuck :
break ;
c a s e opponent_detected :
break ;
871
case event_timeout :
break ;
}
876
}
collectItem_done = 1;
}
881
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / B r u g e r webcam t i l a f d e t e k t e r e h v o r v i d t d e r e r i n d f a n g e t en f l a s k e r
void hasItem ( ) {
f l o a t pCan = 0 . 0 , p B o t t l e = 0 . 0 ;
f l o a t avg_pCan = 0 . 0 , a v g _ p B o t t l e = 0 . 0 ;
int i = 0;
e l l e r dåse
886
f o r ( i = 1 ; i < 6 ; i ++) {
s p r i n t f ( msg , " v i s i o n \"BOC thresholdCanU=%d thresholdCanV=%d t h r e s h o l d B o t t l e U=%
d t h r e s h o l d B o t t l e V=%d\"\n " ,CanU_THR, CanV_THR , BottleU_THR , BottleV_THR ) ;
kl_send (& kt , msg ) ;
kl_send (& kt , " e v a l $ v i s 0 ; $ v i s 1 \n " ) ;
s s c a n f ( k t . answer , "%f %f " ,&pCan , &p B o t t l e ) ;
avg_pCan += pCan ;
a v g _ p B o t t l e += p B o t t l e ;
}
avg_pCan /= ( f l o a t ) ( i −1) ;
a v g _ p B o t t l e /= ( f l o a t ) ( i −1) ;
891
896
i f ( avg_pCan > PROB_CAN || a v g _ p B o t t l e > PROB_BOTTLE)
{
item = ( avg_pCan > a v g _ p B o t t l e ) ? can : b o t t l e ;
}
else {
item = none ;
}
printItem ( ) ;
901
906
}
106
APPENDIKS C. KILDEKODE
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / K ø r e r t i l f l a s k e − og d å s e b e h o l d e r n e f o r a t a f l e v e r e
911 void t o B a s k e t ( ) {
char id [STRING_LENGTH ] ;
l o c a t i o n bin = b i n s ;
i n t go_on = 0 ;
p r i n t f ( " Item : %s " , item ? ( item == can ? " can " : " b o t t l e " ) : " none " ) ;
p r i n t f ( " b i n s . th : %f \n " , b i n s . th ) ;
916
i f ( item == can ) {
bin = canBin ;
}
e l s e i f ( item == b o t t l e ) {
bin = b o t t l e B i n ;
}
921
926
g o t o P o s i t i o n ( bin ) ;
forward ( 0 . 1 5 , SPEED_LOW) ;
getID ( id ) ;
while ( ! go_on ) {
/ / T j e k k e r f o r f e j l d e r m å t t e o p s t å u n d e r k ø r s l e n samt r e g i s t r e r n å r kommandoen
er udført
switch ( checkStopConditions ( id ) ) {
c a s e motors_blocked :
forward ( −0.1 , SPEED ) ;
getPosition ( ) ;
break ;
931
936
c a s e cmd_complete :
go_on = 1 ;
break ;
941
case battery_stuck :
break ;
c a s e opponent_detected :
break ;
946
case event_timeout :
break ;
}
g o t o P o s i t i o n ( bin ) ;
forward ( 0 . 1 5 , SPEED_LOW) ;
getID ( id ) ;
951
}
go_on = 0 ;
956
toBasket_done = 1 ;
}
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Afleverer det indfangede element
void d e l i v e r ( ) {
p r i n t f ( " \n================\ n d e l i v e r ( ) \n================\n " ) ;
char id [STRING_LENGTH ] ;
966
int state = 0;
i n t moreItems = 1 ;
enum items old_item = item ;
961
while ( moreItems ) {
971
if (! state ) {
kl_send (& kt , " d r i v e @v0 . 1 \ n " ) ;
}
976
981
986
991
getID ( id ) ;
switch ( checkStopConditions ( id ) ) {
c a s e motors_blocked :
if (! state ) {
forward ( −0.02 ,SPEED ) ;
p r i n t f ( " bak , ID=%s\n " , id ) ;
s t a t e ++;
}
break ;
c a s e cmd_complete :
/ / S t a r t b ø r s t e n og k ø r f r e m i g e n
kl_send (& kt , " rs485send 10 8\n " ) ;
p r i n t f ( " s t a r t b ør s t e \n " ) ;
forward ( 0 . 0 2 ,SPEED_LOW) ;
p r i n t f ( " fremad\n " ) ;
C.1. HAUPT.C
107
s t a t e ++;
break ;
case battery_stuck :
break ;
996
c a s e opponent_detected :
break ;
1001
case event_timeout :
break ;
}
p r i n t f ( " s t a t e = %d\n " , s t a t e ) ;
1006
i f ( s t a t e == 2 ) {
s l e e p ( 1 ) ; / / Ven e t ø j e b l i k på a f l e v e r i n g e n
kl_send (& kt , " rs485send 10 9\n " ) ; / / s l u k b ø r s t e m o t o r
p r i n t f ( " s l u k b r s t e \n " ) ;
forward ( −0.1 ,SPEED ) ;
p r i n t f ( " bak\n " ) ;
1011
p r i n t f ( "AFLEVERET ! ! ! ON = 0\n " ) ;
/ / T j e k om v i h a r f a n g e t n o g e t mere , a f samme t y p e v e l a t mærke
hasItem ( ) ;
1016
moreItems = ( item ! = none && old_item == item ) ? 1 : 0 ;
old_item = item ;
state = 0;
1021
}
}
deliver_done = 1 ;
1026 }
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / K o n v e r t e r e r v i n k l e r t i l smrdemo ’ s i n t e r v a l f r a −PI t i l PI
1031 f l o a t normAngle ( f l o a t v ) {
r e t u r n v − 2 ∗ PI ∗ round ( v/(2∗ PI ) ) ;
}
1036
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / Opdaterer de t r e o d o m e t r i v a r i a b l e r
void updateOdometry ( ) {
f l o a t r = 0 . 0 , th = 0 . 0 , t h _ s t a r t = 0 . 0 , th_end = 0 . 0 , l = 0 . 0 ;
float v = 0.0 , f = 0.0 , u = 0.0;
1041
1046
/ / Nye v a r i a b l e r
f l o a t thNorm = 0 . 0 , thSum = 0 . 0 , t h R e a l = 0 . 0 ;
f l o a t rCur = 0 . 0 , r R e a l = 0 . 0 , r O f f s e t = 0 . 0 ;
f l o a t varValue = 0 . 0 ;
char varToUpd [STRING_LENGTH] = " " ;
kl_send (& kt , " flushcmds\n " ) ;
1051
1056
1061
1066
p r i n t f ( " updateOdometry ( ) \n " ) ;
/ / Scan e f t e r l i n j e s t y k k e r og gem p a r a m e t r e
kl_send (& kt , " l a s e r \" s f p o l a r _ w a l l \"\n " ) ;
kl_send (& kt , " l a s e r \" s f p o l a r _ w a l l \"\n " ) ;
kl_send (& kt , " l a s e r \" s f p o l a r _ w a l l \"\n " ) ;
kl_send (& kt , " l a s e r \" s f p o l a r _ w a l l \"\n " ) ;
p r i n t f ( " s v a r : %s\n " , k t . answer ) ;
kl_send (& kt , " e v a l $ l 0 ; $ l 1 ; $ l 2 ; $ l 3 ; $ l 4 \n " ) ;
p r i n t f ( " s v a r : %s\n " , k t . answer ) ;
s s c a n f ( k t . answer , "%f %f %f %f %f " ,& t h _ s t a r t ,& th_end ,& r ,& th ,& l ) ;
p r i n t f ( " Theta−s t a r t : %f \n " , t h _ s t a r t ) ;
getPosition ( ) ;
p r i n t L o c ( curLoc ) ;
/ / Beregner robottens f a k t i s k e o r i e n t e r i n g
thNorm = normAngle ( th ) ;
thSum = normAngle ( curLoc . th+thNorm ) ;
1071
1076
/ / Umulige v i n k l e r . . .
i f ( thNorm == PI || thNorm == −PI || l < WALL_MIN) {
return ;
}
/ / P o s i t i v x−r e t n i n g
108
APPENDIKS C. KILDEKODE
e l s e i f ( ( thSum > −PI /4) && ( thSum < PI /4) ) {
t h R e a l = −thNorm ;
rCur = ARENA_X − curLoc . x ;
r O f f s e t = ARENA_X;
s p r i n t f ( varToUpd , " $odox " ) ;
}
/ / N e g a t i v y−r e t n i n g
e l s e i f ( ( thSum < −PI /4) && ( thSum > −3∗PI /4) ) {
t h R e a l = −PI /2 − thNorm ;
rCur = curLoc . y ;
rOffset = 0.0;
s p r i n t f ( varToUpd , " $odoy " ) ;
}
/ / P o s i t i v y−r e t n i n g
e l s e i f ( ( thSum > PI /4) && ( thSum < 3∗ PI /4) ) {
t h R e a l = PI /2 − thNorm ;
rCur = ARENA_Y − curLoc . y ;
r O f f s e t = ARENA_Y;
s p r i n t f ( varToUpd , " $odoy " ) ;
}
/ / N e g a t i v x−r e t n i n g
e l s e i f ( ( thSum > 3∗ PI /4 && thSum < PI ) || ( thSum < −3∗PI /4 && thSum > −PI ) || thSum ==
PI || thSum == −PI ) {
i f ( thNorm > 0 ) {
t h R e a l = PI − thNorm ;
}
else {
t h R e a l = −PI − thNorm ;
}
rCur = curLoc . x ;
rOffset = 0.0;
s p r i n t f ( varToUpd , " $odox " ) ;
}
/ / Grænsetilfælde
else {
/ / Intet gøres
return ;
}
1081
1086
1091
1096
1101
1106
1111
/ / B e r e g n e r a f s t a n d e n f r a r o b o t t e n s centrum t i l den d e t e k t e r e d e væg
v = a t a n f ( LASER_X_OFFSET / LASER_Y_OFFSET ) ;
f = s q r t (pow( LASER_X_OFFSET , 2 ) + pow( LASER_Y_OFFSET , 2 ) ) ;
1116
/ / De t o t i l f æ l d e
i f ( thNorm > v ) {
u = thNorm − v ;
rReal = r − f ∗ sin (u) ;
} else {
u = v − thNorm ;
rReal = r + f ∗ sin (u) ;
}
1121
1126
/ / U n d e r s ø g e r om en o p d a t e r i n g e r n ø d v e n d i g
i f ( r R e a l ! = rCur ) {
varValue = ( r O f f s e t > 0 . 0 ) ? r O f f s e t − r R e a l : r R e a l ;
s p r i n t f ( msg , " s e t \"%s \" %f \n " , varToUpd , varValue ) ;
kl_send (& kt , msg ) ;
s p r i n t f ( msg , " s e t \" $odoth \" %f \n " , t h R e a l ) ;
kl_send (& kt , msg ) ;
}
p r i n t f ( " r R e a l = %f , t h R e a l = %f \n " , rReal , t h R e a l ) ;
1131
1136
}
1141
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / Henter r o b o t t e n s a k t u e l l e p o s i t i o n
void g e t P o s i t i o n ( ) {
f l o a t x , y , th ;
1146
kl_send (& kt , " e v a l $odox ; $odoy ; $odoth\n " ) ;
s s c a n f ( k t . answer , "%f %f %f " ,&x ,&y,& th ) ;
curLoc . x = x ;
curLoc . y = y ;
curLoc . th = th ;
1151 }
/ /−−−−− B e s k r e v e t a f B r i a n Hansen −−−−−
/ / F i n d e r den n æ r m e s t e e l e m e n t e r som s k a l s a m l e s op
1156 void scanIt ems ( i n t n C l o s e s t ) {
f l o a t r = 0 . 0 , th = 0 . 0 , l = 0 . 0 ;
p r i n t f ( " \n================\nscanItems ( ) \n================\n " ) ;
C.1. HAUPT.C
109
1161
kl_send (& kt , " flushcmds\n " ) ;
1166
1171
/ / K a l d e r l a s e r s c a n n e r e n p a r a m e t r e n e f o r den n ’ t e n æ r m e s t e f l a s k e
s p r i n t f ( msg , " l a s e r \" s f n e a r e s t _ i t e m %d\"\n " , n C l o s e s t ) ;
kl_send (& kt , msg ) ;
kl_send (& kt , msg ) ;
kl_send (& kt , msg ) ;
kl_send (& kt , msg ) ;
p r i n t f ( " s v a r : %s\n " , k t . answer ) ;
kl_send (& kt , " e v a l $ l 0 ; $ l 1 ; $ l 2 \n " ) ;
p r i n t f ( " s v a r : %s\n " , k t . answer ) ;
s s c a n f ( k t . answer , "%f %f %f " ,& r ,& th ,& l ) ;
e l l e r dåse
scanItems_done = 1 ;
1176 }
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
/ / K ø r e r r o b o t t e n f r a den nuværende p o s i t i o n t i l en ny
1181 void g o t o P o s i t i o n ( l o c a t i o n newLoc ) {
enum e v e n t s event ;
char id [STRING_LENGTH ] ;
int gotoPosition_done = 0 ;
i n t c o r r e c t B a t t e r y = 0 , blocked_count = 0 ;
1186
f l o a t v = 0 . 0 , dx = 0 . 0 , dy = 0 . 0 ;
f l o a t phase = 0 . 0 ;
i n t timeout_count = 0 ;
p r i n t f ( " \n================\n g o t o P o s t i o n ( ) \n================\n " ) ;
1191
1196
while ( ! g o t o P o s i t i o n _ d o n e ) {
/ / Hent nuværende p o s i t i o n
getPosition ( ) ;
p r i n t L o c ( curLoc ) ;
p r i n t L o c ( newLoc ) ;
/ / Beregn v i n k e l
dx = newLoc . x − curLoc . x ;
dy = newLoc . y − curLoc . y ;
1201
i f ( dx < 0 ) {
phase = PI ;
} else {
phase = 0 ;
1206
}
v = normAngle ( a t a n f ( dy/dx ) + phase ) ;
1211
alpha = v − curLoc . th ;
p r i n t f ( " v = %f \n " , v ) ;
1216
/ / Drej
turn ( alpha , 1 , SPEED ) ;
getID ( id ) ;
p r i n t f ( " alpha = %f \n " , alpha ) ;
1221
/ / Vent t i l d r e j e t e r u d f ø r t
while (ON) {
kl_send (& kt , " g e t e v e n t 2\n " ) ;
i f ( isStopped ( id ,CMD_COMPLETE) ) {
ON = 0 ;
}
}
ON = 1 ;
1226
/ / Hent p o s i t i o n i g e n
getPosition ( ) ;
p r i n t L o c ( curLoc ) ;
1231
/ / Beregn a f s t a n d
d = s q r t f ( powf ( ( newLoc . x − curLoc . x ) , 2 ) + powf ( ( newLoc . y − curLoc . y ) , 2 ) ) ;
1236
/ / Kør
forward ( d , SPEED_HIGH) ;
getID ( id ) ;
1241
/ / T j e k f o r f e j l der måtte o p s t å under k ø r s l e n
/ / samt r e g i s t r e r n å r kommandoen e r u d f ø r t
event = checkStopConditions ( id ) ;
p r i n t f ( " event = %d\n " , event ) ;
switch ( event ) {
110
APPENDIKS C. KILDEKODE
1246
c a s e motors_blocked :
blocked_count ++;
forward ( −0.15 ,SPEED ) ;
i f ( blocked_count > 3 ) { / / T i l l a d kun a t m o t o r b l o k e r i n g t r e
gange
gotoPosition_done = 1 ;
forward ( −0.1 ,SPEED ) ;
}
break ;
1251
c a s e cmd_complete :
gotoPosition_done = 1 ;
1256
break ;
case battery_stuck :
1261
correctBattery = correctBatteryColor ( ) ;
i f ( c o r r e c t B a t t e r y == 1 ) {
p r i n t f ( " Grapping b a t t e r y \n " ) ;
grabBattery ( ) ;
}
e l s e i f ( c o r r e c t B a t t e r y == 0 ) {
p r i n t f ( " R e j e c t i n g b a t t e r y \n " ) ;
rejectBattery () ;
}
1266
1271
break ;
c a s e opponent_detected :
kl_send (& kt , " flushcmds\n " ) ;
kl_send (& kt , " t a r g e t h e r e \n " ) ;
1276
p r i n t f ( " Dodge . . \ n " ) ;
getPosition ( ) ;
p r i n t L o c ( curLoc ) ;
dodgeOpponent ( ) ;
p r i n t f ( " Dodged ! \ n " ) ;
1281
break ;
case event_timeout :
i f ( timeout_count <3) {
timeout_count ++;
}
else {
forward ( −0.15 ,SPEED ) ;
gotoPosition_done =1;
1286
1291
}
break ;
}
1296
}
1301
/ / Drej
getPosition ( ) ;
turn ( newLoc . th−curLoc . th , 1 , SPEED ) ;
getID ( id ) ;
while (ON) {
kl_send (& kt , " g e t e v e n t 4\n " ) ;
i f ( isStopped ( id ,CMD_COMPLETE) ) {
ON = 0 ;
}
}
1306
ON = 1 ;
getPosition ( ) ;
p r i n t L o c ( curLoc ) ;
1311
}
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
/ / F u n k t i o n e n a f g ø r om i r−s e n s o r e r n e d e t e k t e r e r en f j e n d e
i n t isOpponentDetected ( ) {
float sensor_right = 0.0 , avg_sensor_right = 0 . 0 ;
f l o a t sensor_middle = 0 . 0 , avg_sensor_middle = 0 . 0 ;
1321
float sensor_left = 0.0 , avg_sensor_left = 0 . 0 ;
int i = 0;
int result = 0;
1316
1326
f o r ( i = 1 ; i < 1 0 ; i ++) {
/ / De t r e f r o n t s e n s o r e r b r u g e s
kl_send (& kt , " e v a l $ i r d i s t f r o n t r i g h t ; $ i r d i s t f r o n t m i d d l e ; $ i r d i s t f r o n t l e f t \n " )
;
s s c a n f ( k t . answer , "%f %f %f " ,& s e n s o r _ r i g h t ,& sensor_middle ,& s e n s o r _ l e f t ) ;
C.1. HAUPT.C
111
a v g _ s e n s o r _ r i g h t += s e n s o r _ r i g h t ;
avg_sensor_middle += sensor_middle ;
a v g _ s e n s o r _ l e f t += s e n s o r _ l e f t ;
1331
}
a v g _ s e n s o r _ r i g h t /= ( f l o a t ) ( i −1) ; / / Gennemsnit a f n i v æ r d i e r
avg_sensor_middle /= ( f l o a t ) ( i −1) ;
a v g _ s e n s o r _ l e f t /= ( f l o a t ) ( i −1) ;
1336
getPosition ( ) ;
/ / T a g e r h ø j d e f o r p e r s o n e r o . l i g n . o m k r i n g banen
i f ( curLoc . x > DODGE_OFFSET && curLoc . x < ARENA_X − DODGE_OFFSET && curLoc . y >
DODGE_OFFSET && curLoc . y < ARENA_Y − DODGE_OFFSET) {
r e s u l t = ( a v g _ s e n s o r _ r i g h t < IRRIGHT_THR || avg_sensor_middle < IRMIDDLE_THR
|| a v g _ s e n s o r _ l e f t < IRLEFT_THR ) ? 1 : 0 ;
}
else {
result = 0;
}
1341
1346
return r e s u l t ;
}
1351
/ /−−−−− B e s k r e v e t a f S h a y a n t h a r a n S i v a r a j a l i n g a m −−−−−
/ / R o b o t t e n s r e a k t i o n h v i s en f j e n d e e r d e t e k t e r e t
void dodgeOpponent ( ) {
p r i n t f ( " \n================\ndodgeOpponent ( ) \n================\n " ) ;
1356
char id [STRING_LENGTH ] ;
enum e v e n t s event ;
f l o a t angle = 0 . 0 ;
1361
/ / D o b b e l t−t j e k om f j e n d e n s t a d i g e r d e r
while ( isOpponentDetected ( ) ) {
p r i n t f ( " Opponent s t i l l t h e r e ! \ n " ) ;
getPosition ( ) ;
p r i n t f ( " Current l o c a t i o n : \ n " ) ;
p r i n t L o c ( curLoc ) ;
1366
1371
1376
1381
/ / D r e j væk f r a den n æ r m e s t e væg
i f ( curLoc . th > PI / 4 . 0 && curLoc . th < 3 . 0 ∗ PI / 4 . 0 ) {
angle = ( curLoc . x > ARENA_X/ 2 . 0 ) ? PI / 2 . 0 : −PI / 2 . 0 ;
}
e l s e i f ( curLoc . th < −PI / 4 . 0 && curLoc . th > −3.0∗ PI / 4 . 0 ) {
angle = ( curLoc . x > ARENA_X/ 2 . 0 ) ? −PI / 2 . 0 : PI / 2 . 0 ;
}
e l s e i f ( ( curLoc . th >= 3∗ PI /4 && curLoc . th <= PI ) || ( curLoc . th <= −3.0∗ PI / 4 . 0
&& curLoc . th >= −PI ) ) {
angle = ( curLoc . y > ARENA_Y/ 2 . 0 ) ? PI / 2 . 0 : −PI / 2 . 0 ;
}
e l s e i f ( curLoc . th >= −PI /4 && curLoc . th <= PI /4) {
angle = ( curLoc . y > ARENA_Y/ 2 . 0 ) ? −PI / 2 . 0 : PI / 2 . 0 ;
}
else {
angle = PI ;
}
p r i n t f ( " Dodge Angle : %f \n " , angle ) ;
1386
1391
1396
/ / Kør udenom f j e n d e n
kl_send (& kt , " flushcmds\n " ) ;
kl_send (& kt , " t a r g e t h e r e \n " ) ;
kl_send (& kt , " i g n o r e o b s t a c l e s \n " ) ;
turn ( angle , 1 , SPEED ) ;
forward ( 0 . 5 , SPEED ) ;
turn(−angle , 1 , SPEED ) ;
forward ( 0 . 5 , SPEED ) ;
getID ( id ) ;
event = 0 ;
1401
1406
/ / Vent t i l kommandoen e r u d f ø r t
while ( event ! = cmd_complete ) {
event = checkStopConditions ( id ) ;
p r i n t f ( " Event : %d\n " , event ) ;
switch ( event ) {
c a s e motors_blocked :
forward ( −0.1 ,SPEED ) ;
getID ( id ) ;
return ;
break ;
112
APPENDIKS C. KILDEKODE
1411
c a s e cmd_complete :
break ;
case battery_stuck :
break ;
1416
c a s e opponent_detected :
break ;
1421
case event_timeout :
break ;
}
}
}
1426 }
1431
/ /−−−−− B e s k r e v e t a f Martin J u h l J ø r g e n s e n −−−−−
/ / H å n d t e r i n g a f f e j l og a n d r e e v e n t s
i n t checkStopConditions ( char ∗id ) {
enum e v e n t s event = 0 ;
p r i n t f ( " checkStopConditions\n " ) ;
1436
while ( ! event ) {
kl_send (& kt , " g e t e v e n t 100\n " ) ;
// Batteri sidder fast
i f ( isStopped ( id , IRBAT_BLOCKED) ) {
forward ( 0 . 1 , SPEED_LOW) ;
kl_send (& kt , " i d l e \n " ) ;
1441
/ / Vent f o r a t være s i k k e r på a t b a t t e r i e t r e n t f a k t i s k s i d d e r f a s t
p r i n t f ( "IRBAT_BLOCKED\n " ) ;
sleep ( 1 ) ;
p r i n t f ( " s l e e p i n g over\n " ) ;
if ( isBatteryStuck ( ) ) {
p r i n t f ( " f r e e b a t t e r y \n " ) ;
freeBattery () ;
}
1446
1451
event = b a t t e r y _ s t u c k ;
}
1456
/ / Fjenden er d e t e k t e r e t
e l s e i f ( isStopped ( id , IRFRONT_BLOCKED) ) {
event = opponent_detected ;
}
1461
/ / Blokerede motorer
e l s e i f ( strcmp ( k t . answer , " m o t i o n c o n t r o l blocked\n " ) == 0 ) {
p r i n t f ( " Motors blocked\n " ) ;
kl_send (& kt , " i d l e \n " ) ;
kl_send (& kt , " flushcmds\n " ) ;
kl_send (& kt , " r e s e t m o t o r s \n " ) ;
kl_send (& kt , " t a r g e t h e r e \n " ) ;
1466
event = motors_blocked ;
1471
}
1476
/ / Kommandoen e r u d f ø r t
e l s e i f ( isStopped ( id ,CMD_COMPLETE) ) {
event = cmd_complete ;
}
/ / Event timout
e l s e i f ( strcmp ( k t . answer , " e v e n t t i m e o u t\n " ) == 0 ) {
kl_send (& kt , " i d l e \n " ) ;
kl_send (& kt , " flushcmds\n " ) ;
kl_send (& kt , " i d l e \n " ) ;
p r i n t f ( " Dead by timeout\n " ) ;
1481
event = e v e n t _ t i m e o u t ;
1486
}
}
r e t u r n event ;
}
C.2. KLIENT.H
C.2
klient.h
# i f n d e f KLIENT_DOT_H
# define KLIENT_DOT_H
#
5 #
#
#
#
#
10 #
#
#
#
#
15
#
include
include
include
include
include
include
include
include
include
include
include
< s t d i o . h>
< s t d l i b . h>
< u n i s t d . h>
<sys/t y p e s . h>
<sys/ s o c k e t . h>
< n e t i n e t / i n . h>
<netdb . h>
< f c n t l . h>
< s t r i n g . h>
<pthread . h>
< s i g n a l . h>
define STRING_LENGTH 100
typedef s t r u c t
20 {
/ / User i n p u t :
char ∗hostname ;
int port ;
25
// Internal variables :
char answer [STRING_LENGTH ] ;
char queue [STRING_LENGTH ] [ STRING_LENGTH ] ;
i n t answer_len ;
i n t queue_cnt ;
30
/ / Error value :
int error ;
/ / R e t u r n s a number d i f f e r e n t f r o m 0 i f an e r r o r o c c u r s
35
/ / Output v a l u e :
i n t sockfd ;
} klienttype ;
void
40 void
void
void
void
kl_connect ( klienttype ∗k l i e n t ) ;
kl_disconnect ( klienttype ∗klient ) ;
kl_send ( k l i e n t t y p e ∗ k l i e n t , char ∗cmd) ;
k l _ w a i t ( k l i e n t t y p e ∗ k l i e n t , char ∗event ) ;
kl_cmdwait ( k l i e n t t y p e ∗ k l i e n t , char ∗cmd) ;
45 # endif / / KLIENT_DOT_H
113
114
C.3
APPENDIKS C. KILDEKODE
klient.c
# include " k l i e n t . h "
void k l i e n t _ i n i t ( k l i e n t t y p e ∗ k l i e n t ) ;
5 void k l _ c o n n e c t ( k l i e n t t y p e ∗ k l i e n t )
{
s t r u c t sockaddr_in serv_addr ;
s t r u c t h o s t e n t ∗host_param ;
i f ( ( k l i e n t −>sockfd = s o c k e t ( AF_INET , SOCK_STREAM, 0 ) ) == −1)
{
f p r i n t f ( s t d e r r , " Can not c r e a t e s o c k e t \n " ) ;
k l i e n t −>e r r o r = 1 ;
return ;
}
10
15
i f ( ( host_param = gethostbyname ( k l i e n t −>hostname ) ) == NULL)
{
f p r i n t f ( s t d e r r , " Can not connect t o %s\n " , k l i e n t −>hostname ) ;
k l i e n t −>e r r o r = 2 ;
return ;
}
20
bzero ( ( char ∗) &serv_addr , s i z e o f ( serv_addr ) ) ;
serv_addr . s i n _ f a m i l y = AF_INET ;
bcopy ( ( char ∗) host_param−>h_addr , ( char ∗) &serv_addr . sin_addr . s_addr , host_param−>h_l engt h
);
serv_addr . s i n _ p o r t = htons ( k l i e n t −>p o r t ) ;
25
i f ( connect ( k l i e n t −>sockfd , ( s t r u c t sockaddr ∗) &serv_addr , s i z e o f ( serv_addr ) ) ! = 0 )
{
f p r i n t f ( s t d e r r , " E r r o r while t r y i n g t o connect t o s o c k e t on : %s , p o r t : %d\n " , k l i e n t −>
hostname , k l i e n t −>p o r t ) ;
k l i e n t −>e r r o r = 3 ;
return ;
}
30
35
klient_init ( klient ) ; / /
k l i e n t −>e r r o r = 0 ;
return ;
Initialize
klient
}
40
void k l _ d i s c o n n e c t ( k l i e n t t y p e ∗ k l i e n t )
{
send ( k l i e n t −>sockfd , " e x i t \n " , 5 , 0 ) ;
45
usleep (100000) ;
c l o s e ( k l i e n t −>sockfd ) ;
k l i e n t −>e r r o r = 0 ;
return ;
50 }
void kl_send ( k l i e n t t y p e ∗ k l i e n t , char ∗cmd)
{
int len ;
55
l e n = send ( k l i e n t −>sockfd , cmd , s t r l e n (cmd) , 0 ) ;
60
i f ( l e n ! = s t r l e n (cmd) )
k l i e n t −>e r r o r = 1 ;
else
k l i e n t −>e r r o r = 0 ;
k l i e n t −>answer_len = r e c v ( k l i e n t −>sockfd , k l i e n t −>answer , STRING_LENGTH, 0 ) ;
k l i e n t −>answer [ k l i e n t −>answer_len ] = ’ \0 ’ ;
65 # i f d e f KLIENT_DEBUG
p r i n t f ( "ANS: l e n = %d || %s " , k l i e n t −>answer_len , k l i e n t −>answer ) ;
# endif
return ;
70 }
void k l _ w a i t ( k l i e n t t y p e ∗ k l i e n t , char ∗event )
{
do
75
{
kl_send ( k l i e n t , " g e t e v e n t 10000\n " ) ;
} while ( strcmp ( k l i e n t −>answer , event ) ! = 0 ) ;
80
k l i e n t −>e r r o r = 0 ;
return ;
C.3. KLIENT.C
}
85
void kl_cmdwait ( k l i e n t t y p e ∗ k l i e n t , char ∗cmd)
{
char i n b u f [STRING_LENGTH] = { 0 } , i d b u f [STRING_LENGTH] = { 0 } ;
kl_send ( k l i e n t , cmd) ;
s t r c p y ( idbuf , k l i e n t −>answer ) ;
i d b u f [ k l i e n t −>answer_len −7] = ’ \0 ’ ;
s t r c a t ( idbuf , " stopcond " ) ;
90
do
{
kl_send ( k l i e n t , " g e t e v e n t 10000\n " ) ;
s t r c p y ( inbuf , k l i e n t −>answer ) ;
i f ( k l i e n t −>answer_len > 1 0 )
i n b u f [ k l i e n t −>answer_len −10] = ’ \0 ’ ;
/ / p r i n t f ( " INBUF : %s || IDBUF : %s \n " , i n b u f , i d b u f ) ;
} while ( strcmp ( idbuf , i n b u f ) ! = 0 ) ;
95
100
k l i e n t −>e r r o r = 0 ;
return ;
}
105 void k l i e n t _ i n i t ( k l i e n t t y p e ∗ k l i e n t )
{
k l i e n t −>answer_len = 0 ;
k l i e n t −>queue_cnt = 0 ;
110
return ;
}
115
116
C.4
4
9
14
19
APPENDIKS C. KILDEKODE
myfunc.h
/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
∗
C o p y r i g h t (C) 2006 by DTU ( C h r i s t i a n A n d e r s e n )
∗
∗
j c a @ o e r s t e d . d t u . dk
∗
∗
∗
∗
T h i s program i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / o r m o d i f y ∗
∗
i t u n d e r t h e t e r m s o f t h e GNU L e s s e r G e n e r a l P u b l i c L i c e n s e a s
∗
∗
p u b l i s h e d by t h e F r e e S o f t w a r e F o u n d a t i o n ; e i t h e r v e r s i o n 2 o f t h e
∗
∗
L i c e n s e , o r ( a t y o u r o p t i o n ) any l a t e r v e r s i o n .
∗
∗
∗
∗
T h i s program i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
∗
∗
b u t WITHOUT ANY WARRANTY; w i t h o u t e v e n t h e i m p l i e d w a r r a n t y o f
∗
∗
MERCHANTABILITY o r FITNESS FOR A PARTICULAR PURPOSE . S e e t h e
∗
∗
GNU L e s s e r G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
∗
∗
∗
∗
You s h o u l d h a v e r e c e i v e d a c o p y o f t h e GNU L e s s e r G e n e r a l P u b l i c
∗
∗
L i c e n s e a l o n g w i t h t h i s program ; i f not , w r i t e t o t h e
∗
∗
Free Software Foundation , Inc . ,
∗
∗
59 Temple P l a c e − S u i t e 3 3 0 , B o s t o n , MA 02111 −1307 , USA .
∗
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
/∗ M o d i f i e d by Martin J u h l J ør g e n s e n
3 May 2007
∗
∗ To u s e f o r t h e E u r o b o t 2007 c o m p e t i t i o n .
∗
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
24 # i f n d e f UFUNC_COG_H
# define UFUNC_COG_H
# include < c s t d l i b >
29 # include <urob4/ufunctioncambase . h>
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
34
/∗∗ c a l l e d when s e r v e r makes a d l o p e n ( ) ( l o a d s p l u g i n i n t o memory ) ∗/
void libraryOpen ( ) ;
/∗∗ c a l l e d when s e r v e r makes a d l c l o s e ( ) ( u n l o a d s p l u g i n f r o m memory ) ∗/
39 void l i b r a r y C l o s e ( ) ;
/∗∗
Needed f o r c o r r e c t l o a d i n g and l i n k i n g o f l i b r a r y ∗/
void _ _ a t t r i b u t e _ _ ( ( c o n s t r u c t o r ) ) libraryOpen ( void ) ;
44 void _ _ a t t r i b u t e _ _ ( ( d e s t r u c t o r ) ) l i b r a r y C l o s e ( void ) ;
/∗∗
A l l o w s s e r v e r t o c r e a t e o b j e c t ( s ) o f t h i s c l a s s ∗/
e x t e r n "C" UFunctionCamBase ∗ c r e a t e F u n c ( ) ;
/∗∗
49 . . . and t o d e s t r o y t h e c r e a t e d o b j e c t ( s ) ∗/
e x t e r n "C" void d e l e t e F u n c ( UFunctionCamBase∗ p ) ;
54
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/∗∗
T e s t camera f u n c t i o n t o d e m o n s t r a t e handling o f one f u n c t i o n
59 COG
w i t h an ROI ( r e g i o n o f i n t e r e s t − x , y , w, h ) , a t r e s h o l d .
The f u n c t i o n a l l o c a t e s an i m a g e i n image−p o o l ,
c o n v e r t s t h e raw i m a g e t o an RGB i m a g e .
T e s t s a l l p i x e l s i n t h e r e q u e s t e d r e g i o n and
64 c a l c u l a t e s t h e c e n t e r o f g r a v i t y o f t h e p i x e l s
that are above the s p e c i f i e d t r e s h o l d ( in the red channel ) .
Bark
Just sends a reply to the c l i e n t
69
@author C h r i s t i a n A n d e r s e n
∗/
c l a s s MyFunction : public UFunctionCamBase
{
74 public :
/∗∗
C o n s t r u c t o r ∗/
MyFunction ( ) ;
/∗∗
79
D e s t r u c t o r ∗/
v i r t u a l ~MyFunction ( ) ;
/∗∗
C.4. MYFUNC.H
Name o f f u n c t i o n
The r e t u r n e d name i s i n t e n d e d a s i n f o r m a t i v e t o c l i e n t s
and s h o u l d i n c l u d e a v e r s i o n number ∗/
v i r t u a l c o n s t char ∗ name ( ) ;
/∗∗
Returns l i s t o f handled f u n c t i o n s in
o n e s t r i n g s e p a r a t e d by a s p a c e .
e . g . r e t u r n "COG" .
The f u n c t i o n s must b e u n i q u e on t h e s e r v e r . ∗/
v i r t u a l c o n s t char ∗ commandList ( ) ;
/∗∗
R e t u r n s l i s t o f p r o v i d e d r e s s o u r c e s by t h i s module
The f u n c t i o n s must b e u n i q u e on t h e s e r v e r . ∗/
v i r t u a l UResBase ∗ g e t R e s s o u r c e ( c o n s t char ∗ resID )
{ r e t u r n NULL; } ;
/∗∗
S h o u l d r e t u r n a s p a c e s e p a r a t e d l i s t o f r e s s o u r c e s t h a t may
b e p r o v i d e d by t h i s f u n c t i o n .
Note ! i f o t h e r f u n c t i o n s e n h a r i t f r o m t h i s c l a s s t h e same r e s s o u r c e may b e
p r o v i d e d by t h a t c l a s s , s o when t h e c o r e a n n o u n c e s r e s s o u r c e u p d a t e , p l e a s e
u s e t h e p r o v i d e d r e s s o u r c e ( t o a v o i d d u p l i c a t e s ) ∗/
v i r t u a l c o n s t char ∗ r e s o u r c e L i s t ( )
{ return " " ; } ;
/∗∗
S e t s h a r e d r e s o u r c e ∗/
v i r t u a l bool s e t R e s o u r c e ( UResBase ∗ r e s o u r c e , bool remove )
{ r e t u r n UFunctionCamBase : : s e t R e s o u r c e ( r e s o u r c e , remove ) ; } ;
/∗∗
Function t e s t s i f a l l shared r e s o u r c e s are loaded
f o r f u l l f u n c t i o n a l i t y ∗/
v i r t u a l bool g o t A l l R e s o u r c e s ( char ∗ missingThese , i n t missingTheseCnt )
{ r e t u r n UFunctionCamBase : : g o t A l l R e s o u r c e s ( missingThese , missingTheseCnt ) ; } ;
/∗∗
Handle incomming command
( i n t e n d e d f o r command s e p a r a t i o n )
Must r e t u r n t r u e i f t h e f u n c t i o n i s h a n d l e d −
o t h e r w i s e t h e c l i e n t w i l l g e t a f a i l e d − r e p l y ∗/
v i r t u a l bool handleCommand ( UServerInMsg ∗ msg , void ∗ e x t r a ) ;
84
89
94
99
104
109
114
119
private :
/∗∗
F u n c t i o n t o h a n d l e t h e b a r k f u n c t i o n ∗/
124
bool doBark ( UServerInMsg ∗ msg ) ;
/∗∗
E x t r a c t m e s s a g e p a r a m e t e r s and c a l l ’ c a l c u l a t e C O G ( ) ’ ∗/
bool c e n t e r O f G r a v i t y ( UServerInMsg ∗ msg , UImage ∗ pushImg ) ;
/∗∗
129
C a l c u l a t e t h e c e n t e r o f g r a v i t y (COG) .
The COG i s c a l c u l a t e d w i t h i n a r e g i o n o f i n t e r e s t ( ROI )
f o r a l l p i x e l w i t h r e d v a l u e s a b o v e t h e s p e c i f i e d t h r e s h o l d . ∗/
bool calculateCOG ( UServerInMsg ∗ msg , / / c l i e n t r e f e r e n c e e t c
UImage ∗ rawImg , / / YUV raw i m a g e
134
i n t roiX , i n t roiY , i n t roiW , i n t roiH , / / ROI
int threshold ) ; / / t h r e s h o l d
/∗∗
E x t r a c t m e s s a g e p a r a m e t e r s and c a l l ’ c a l c B o t t l e O r C a n ( ) ’ ∗/
bool bottleOrCan ( UServerInMsg ∗ msg , UImage ∗ pushImg ) ;
/∗∗
C a l c u l a t e t h e p r o b a b i l i t y t h a t t h e r e i s a can o r a b o t t l e ,
trapped in the brace . I t i s c a l c u l a t e d within a region o f i n t e r e s t
( ROI ) f o r a l l p i x e l w i t h v a l u e s a b o v e t h e s p e c i f i e d t h r e s h o l d . ∗/
bool c a l c B o t t l e O r C a n ( UServerInMsg ∗ msg , / / c l i e n t r e f e r e n c e e t c
UImage ∗ rawImg , / / YUV raw i m a g e
i n t roiX , i n t roiY , i n t roiW , i n t roiH , / / ROI
i n t areaCan , i n t a r e a B o t t l e , / / a r e a t h a t must b e
/ / covered in coloured
// pixels before triggering
i n t thresholdCanU , i n t thresholdCan , / / t h r e s h o l d s Cans
int thresholdBottleU , int thresholdBottleV ) ; / / t h r e s h o l d s b o t t l e s
139
144
149
bool edge ( UServerInMsg ∗ msg , UImage ∗ pushImg ) ;
154
};
# endif
117
118
C.5
APPENDIKS C. KILDEKODE
myfunc.cpp
/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
∗
C o p y r i g h t (C) 2006 by DTU ( C h r i s t i a n A n d e r s e n )
∗
∗
j c a @ o e r s t e d . d t u . dk
∗
∗
∗
∗
T h i s program i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / o r m o d i f y ∗
∗
i t u n d e r t h e t e r m s o f t h e GNU L e s s e r G e n e r a l P u b l i c L i c e n s e a s
∗
∗
p u b l i s h e d by t h e F r e e S o f t w a r e F o u n d a t i o n ; e i t h e r v e r s i o n 2 o f t h e
∗
8 ∗
L i c e n s e , o r ( a t y o u r o p t i o n ) any l a t e r v e r s i o n .
∗
∗
∗
∗
T h i s program i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
∗
∗
b u t WITHOUT ANY WARRANTY; w i t h o u t e v e n t h e i m p l i e d w a r r a n t y o f
∗
∗
MERCHANTABILITY o r FITNESS FOR A PARTICULAR PURPOSE . S e e t h e
∗
13 ∗
GNU L e s s e r G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
∗
∗
∗
∗
You s h o u l d h a v e r e c e i v e d a c o p y o f t h e GNU L e s s e r G e n e r a l P u b l i c
∗
∗
L i c e n s e a l o n g w i t h t h i s program ; i f not , w r i t e t o t h e
∗
∗
Free Software Foundation , Inc . ,
∗
18 ∗
59 Temple P l a c e − S u i t e 3 3 0 , B o s t o n , MA 02111 −1307 , USA .
∗
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
/∗ M o d i f i e d by Martin J u h l J ør g e n s e n
3 May 2007
∗
∗ To u s e f o r t h e E u r o b o t 2007 c o m p e t i t i o n .
∗
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
23
# include " myfunc . h "
3
# include <ugen4/uimage2 . h>
28
//
//
//
//
/////////////////////////////////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////////////
33 void libraryOpen ( void )
{ / / c a l l e d when s e r v e r o p e n s t h i s p l u g i n ( i . e . c a l l s d l o p e n ( ) )
p r i n t f ( " Opening MyFunction L i b r a r y \n " ) ;
/ / add c o d e a s n e e d e d
// for global lo gf il es etc . . .
38 }
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
void l i b r a r y C l o s e ( void )
43 { / / c a l l e d when s e r v e r u n l o a d s t h i s p l u g i n ( i . e . c a l l s d l c l o s e ( ) )
p r i n t f ( " Clos ing MyFunction l i b r a r y \n " ) ;
/ / add c o d e a s n e e d e d
}
48
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// library interface
/ / u s e d by s e r v e r when f u n c t i o n i s l o a d e d
UFunctionCamBase∗ c r e a t e F u n c ( )
53 { / / c r e a t e an o b j e c t o f t h i s t y p e
//
/∗∗ @todo ’ MyFunction ’ w i t h y o u r c l a s s n a m e , a s u s e d i n t h e h e a d e r f i l e ∗/
//
r e t u r n new MyFunction ( ) ;
58 }
void d e l e t e F u n c ( UFunctionCamBase∗ p )
{ / / d e l e t e the object
delete p ;
63 }
68
//
//
//
//
/////////////////////////////////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////////////
MyFunction : : MyFunction ( )
{
/ / i n i t i a l i z a t i o n o f v a r i a b l e s in c l a s s − as needed
73 }
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
MyFunction : : ~ MyFunction ( )
78 {
/ / p o s s i b l y remove a l l o c a t e d v a r i a b l e s h e r e − i f needed
}
C.5. MYFUNC.CPP
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
83
c o n s t char ∗ MyFunction : : name ( )
{
r e t u r n " m y _ f i r s t _ p l u g i n −1.53 ( 2 0 0 5 by C h r i s t i a n Andersen ) HaCkEd By JuHl " ;
}
88
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
93
c o n s t char ∗ MyFunction : : commandList ( )
{
r e t u r n "COG bark canny BOC" ;
}
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
bool MyFunction : : handleCommand ( UServerInMsg ∗ msg , void ∗ e x t r a )
98 {
/ / message i s unhandled
bool r e s u l t = f a l s e ;
/ / T e s t f o r t h e h a n d l e d commands , and c a l l a f u n c t i o n t o do t h e j o b
/ / t h e tagname i s n o t c a s e s e n s i t i v e − s e e t h e l i b r a r y d o c u m e n t a t i o n f o r
/ / ’ S e r v e r I n M s g ’ and t a g o f t y p e ’ USmlTag ’ − t o g e t a v a i l a b l e f u n c t i o n l i s t .
103
i f ( msg−>t a g . isTagA ( "COG" ) )
r e s u l t = c e n t e r O f G r a v i t y ( msg , ( UImage ∗) e x t r a ) ;
e l s e i f ( msg−>t a g . isTagA ( " bark " ) )
r e s u l t = doBark ( msg ) ;
e l s e i f ( msg−>t a g . isTagA ( " canny " ) )
108
r e s u l t = edge ( msg , ( UImage ∗) e x t r a ) ;
e l s e i f ( msg−>t a g . isTagA ( "BOC" ) )
r e s u l t = bottleOrCan ( msg , ( UImage ∗) e x t r a ) ;
else
sendDebug ( msg , "Command not handled ( by me) " ) ;
113
return r e s u l t ;
}
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
118 bool MyFunction : : doBark ( UServerInMsg ∗ msg )
{ / / send a s h o r t r e p l y back to the c l i e n t r e q u e s t e d the ’ bark ’
c o n s t i n t MRL = 1 0 0 ;
char r e p l y [MRL] ;
bool ask4help ;
123
char helpValue [ 3 0 ] ;
/ / c h e c k f o r p a r a m e t e r s − one p a r a m e t e r i s t e s t e d f o r − ’ h e l p ’
/ / t h e h e l p v a l u e i s i g n o r e d , e . g . i f h e l p =" b a r k " , t h e n
/ / the value " bark " w i l l be in the ’ helpValue ’ s t r i n g .
ask4help = msg−>t a g . g e t A t t V a l u e ( " help " , helpValue , 3 0 ) ;
128
/ / a s k 4 h e l p = f a l s e , i f no ’ h e l p ’ o p t i o n w e r e a v a i l a b l e .
i f ( ask4help )
{ / / c r e a t e t h e r e p l y i n XML−l i k e ( h t m l − l i k e ) f o r m a t
s n p r i n t f ( reply , MRL, "<%s r e p l y = ’ I w i l l not help you t o bark ! ’/ >\n " ,
msg−>t a g . getTagName ( ) ) ;
133
}
else
{ / / c r e a t e t h e r e p l y i n XML−l i k e ( h t m l − l i k e ) f o r m a t
s n p r i n t f ( reply , MRL, "<%s what = ’No reason t o bark a t me. ’/ >\n " ,
msg−>t a g . getTagName ( ) ) ;
138
}
/ / send t h i s s t r i n g as the r e p l y to the c l i e n t
sendMsg ( msg−>c l i e n t , r e p l y ) ;
/ / return t ru e i f the f u n c t i o n i s handled with a p o s i t i v e r e s u l t
return true ;
143 }
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
bool MyFunction : : c e n t e r O f G r a v i t y ( UServerInMsg ∗ msg , UImage ∗ pushImg )
148 { / / e x t r a c t p a r a m e t e r s f i r s t
bool r e s u l t = f a l s e ;
/ / decode vars
char attName [MAX_SML_NAME_LENGTH ] ;
c o n s t i n t VBL = 1 0 0 ;
153
char a t t V a l u e [VBL ] ;
int n ;
/ / parameters default value
i n t roi X = 2 0 ;
i n t roi Y = 1 0 ;
158
i n t roiW = 8 0 ;
i n t roiH = 1 0 0 ;
int threshold = 100;
i n t deviceNum = −1;
char posName [MAX_MOUNT_NAME_SIZE] = " " ;
163
/ / c a m e r a and s o u r c e i m a g e v a r i a b l e s
UCamPush ∗ cam = NULL; / / c a m e r a
UImage ∗ img = pushImg ; / / i m a g e
bool ask4help = f a l s e ;
119
120
168
173
178
183
188
193
198
203
208
213
218
223
228
233
238
243
248
APPENDIKS C. KILDEKODE
c o n s t i n t MRL = 2 0 0 ;
char r e p l y [MRL] ;
//
/ / extract parameters
/ / t h i s i s o n e o f two m e t h o d t , t h i s o n e t a k e s a l l p r o v i d e d p a r a m e t e r s o n e a t a t i m e
/ / and r e t u r n s i t s name ( attName ) and v a l u e ( a t t V a l u e ) , and you must t e s t f o r t h e name and
/ / e x t r a c t t h e v a l u e from t h e p r o v i d e d s t r i n g .
//
while ( msg−>t a g . g e t N e x t A t t r i b u t e ( attName , a t t V a l u e , VBL) )
{ / / camera d e v i c e
i f ( ( strcasecmp ( attName , " d e v i c e " ) == 0 ) or
( strcasecmp ( attName , " posName " ) == 0 ) )
{ / / e i t h e r number o r s t r i n g
n = s s c a n f ( a t t V a l u e , "%d " , &deviceNum ) ;
i f ( ( n ! = 1 ) and ( s t r l e n ( a t t V a l u e ) > 0 ) )
s t r n c p y ( posName , a t t V a l u e , MAX_MOUNT_NAME_SIZE) ;
}
/ / range o f i n t e r e s t parameters
e l s e i f ( strcasecmp ( attName , " help " ) == 0 )
ask4help = t r u e ;
e l s e i f ( strncasecmp ( attName , " width " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiW ) ;
e l s e i f ( strncasecmp ( attName , " h e i g h t " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiH ) ;
e l s e i f ( strcasecmp ( attName , " y " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiY ) ;
e l s e i f ( strcasecmp ( attName , " x " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiX ) ;
e l s e i f ( strncasecmp ( attName , " t h r e s h o l d " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &t h r e s h o l d ) ;
}
//
i f ( ask4help )
{ / / i t was j u s t a r e q u e s t f o r on−l i n e h e l p
sendMsg ( msg−>c l i e n t , " <help s u b j e c t =\"COG help \">\n " ) ;
sendMsg ( msg−>c l i e n t , "−−−− A v a i l a b l e COG o p t i o n s : \ n " ) ;
sendMsg ( msg−>c l i e n t , " d e v i c e =N
from d e v i c e ’N ’ , i . e . /dev/videoN\n " ) ;
sendMsg ( msg−>c l i e n t , " posName=name from camera ’name ’ , e . g . l e f t f o r l e f t camera\n " ) ;
Top−l e f t p o s i t i o n o f Range Of I n t e r e s t ( ROI ) \n " ) ;
sendMsg ( msg−>c l i e n t , " x=X y=Y
sendMsg ( msg−>c l i e n t , "w=W h=H
Width and h e i g h t o f ROI\n " ) ;
Threshold f o r p i x e l use ( 0 t o 2 5 5 ) \n " ) ;
sendMsg ( msg−>c l i e n t , " t h r e s h o l d =B
sendMsg ( msg−>c l i e n t , "
( r e t u r n s c e n t e r o f g r a v i t y p o s i t i o n f o r a r e a ) \n " ) ;
sendMsg ( msg−>c l i e n t , "
( Uses image pool img=0 ( with a r e a ) and img=1 ( o r i g i n a l ) ) \n " ) ;
sendMsg ( msg−>c l i e n t , "−−−\n " ) ;
sendMsg ( msg−>c l i e n t , " </help >\n " ) ;
s en d In f o ( msg , " done " ) ;
}
else
{ / / i f s e r v e r e v e n t push , t h e n i m a g e i s a v a i l a b l e i n c a l l
/ / i f not , t h e n g e t an i m a g e f r o m c a m e r a
i f ( img == NULL)
{ / / no image , s o g e t r e q u e s t e d c a m e r a
i f ( g o t A l l R e s o u r c e s ( reply , MRL) )
{
i f ( deviceNum >= 0 )
/ / g e t c a m e r a f r o m d e v i c e number
cam = camPool−>getCam ( deviceNum ) ;
e l s e i f ( s t r l e n ( posName ) > 0 )
/ / e l s e g e t c a m e r a f r o m c a m e r a p o s i t i o n name
cam = camPool−>getCam ( posName ) ;
else
/ / e l s e use d e v i c e 0
cam = camPool−>getCam ( 0 ) ;
r e s u l t = ( cam ! = NULL) ;
if ( result )
{ / / g e t i m a g e b u f f e r f r o m image−p o o l
img = imgPool−>getImage ( cam−>getDeviceNumber ( ) , t r u e ) ;
/ / g e t an i m a g e f r o m c a m e r a
/ / g e t an i m a g e f r o m s t r e a m and l o a d i t i n t o ’ img ’
r e s u l t = cam−>getImageSnapshot ( img , f a l s e ) ;
}
else
f p r i n t f ( s t d e r r , "No camera found\n " ) ;
}
else
f p r i n t f ( s t d e r r , " R e s s o r e c e s a r e missing , ( no %s ) \n " , r e p l y ) ;
}
else
r e s u l t = true ;
//
i f ( not r e s u l t )
/ / s e n d s t a n d a r d XML−p a c k e d r e p l y t o c l i e n t − l i k e :
/ / <COG warning ="No i m a g e a v a i l a b l e "/ >\n
sendWarning ( msg , "No image a v a i l a b l e " ) ;
else
C.5. MYFUNC.CPP
{ / / image i s a v i a l a b l e
calculateCOG ( msg , img , roiX , roiY , roiW , roiH , t h r e s h o l d ) ;
}
253
}
return r e s u l t ;
}
258
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
bool MyFunction : : calculateCOG ( UServerInMsg ∗ msg ,
UImage ∗ rawImg ,
i n t roiX , i n t roiY , i n t roiW , i n t roiH ,
int threshold )
{
UImage ∗ raw2 ;
UImage ∗ img0 ; / / RGB f o r m a t i m a g e
268
UImage ∗ img1 ; / / RGB f o r m a t i m a g e
UImage ∗ imgBW ; / / RGB f o r m a t i m a g e
double sx = 0 ; / / sum o f x v a l u e s
double sy = 0 ; / / sum o f y v a l u e s
int sxi , syi ;
273
int n = 0;
/ / count o f p i x e l s
int r , c ;
UPixel ∗ pix ; / / p o i n t e r t o a p i x e l
//
c o n s t i n t MRL = 1 0 0 ;
278
char r e p l y [MRL] ;
char s [ 3 0 ] ;
//
unsigned char ∗y , ∗u , ∗v , m;
263
283
288
293
298
303
308
313
318
323
328
333
//
/ / g e t an i m a g e s t r u c t u r e f r o m t h e i m a g e p o o l − s h a r e d by a l l f u n c t i o n s
/ / i m a g e i s c r e a t e d on f i r s t c a l l ( i f s e c o n d p a r a m e t e r i s t r u e )
//
//
/ / Make a l o w p a s s f i l t e r e d i m a g e u s i n g and openCV f u n c t i o n
//
/ / g e t an i m a g e f r o m p o o l t o s t o r e a work c o p y o f i m a g e
/ / t h i s w i l l b e i m a g e 10 i n i m a g e p o o l−l i s t
img0 = imgPool−>getImage ( 1 0 , t r u e ) ;
/ / g e t a n o t h e r image from p o o l t o s t o r e smoothed image
/ / t h i s w i l l b e i m a g e 11 i n i m a g e p o o l−l i s t
img1 = imgPool−>getImage ( 1 1 , t r u e ) ;
/ / c o n v e r t raw YUV i m a g e t o RGB ( a c t u a l l y BGR, a s t h i s i s s t a n d a r d i n openCV )
img1−>copy ( rawImg ) ;
img1−>toBGR ( ) ;
img1−>setName ( " img1 " ) ;
/ / f i l t e r i m a g e u s i n g a g a u s s i o n low p a s s f i l t e r
cvSmooth ( img1−>cvArr ( ) , img1−>cvArr ( ) , CV_GAUSSIAN, 3 , 0 , 0 ) ;
//
/ / use f i l t e r e d image
/ / l i m i t a r e a t o w i t h i n image
roi X = maxi ( 0 , mini ( roiX , img1−>width ( ) − 1 ) ) ;
roi Y = maxi ( 0 , mini ( roiY , img1−>h e i g h t ( ) − 1 ) ) ;
i f ( ( ro iX + roiW ) > ( i n t ) img1−>width ( ) )
roiW = img1−>width ( ) − roi X ;
i f ( ( ro iY + roiH ) > ( i n t ) img1−>h e i g h t ( ) )
roiH = img1−>h e i g h t ( ) − roi Y ;
//
//
/ / now c a l c u l a t e t h e COG w i t h i n t h e ROI
f o r ( r = 0 ; r < roiH ; r ++)
{ / / get p o i n t e r to f i r s t p i x e l in area
/ / on l i n e ’ r ’
pix = img1−>g e t P i x R e f ( r + roiY , ro iX ) ;
/ / t h e n c o n t i n u e w i t h t h e n e x t p i x e l s on i m a g e l i n e
f o r ( c = 0 ; c < roiW ; c ++)
{ / / t e s t i f a v e r a g e p i x e l −v a l u e i s a b o v e t r e s h o l d
i f ( ( ( pix−>p1 + pix−>p2 + pix−>p3 ) /3) > t h r e s h o l d )
{ / / summ t h e p i x e l p o s i t i o n
n++;
sx += ( double ) ( roiX + c ) ;
sy += ( double ) ( roiY + r ) ;
/ / change the c o l o r o f t h i s p i x e l
/ / t o mark , t h a t i t i s a b o v e t r e s h o l d .
pix−>p2 = 2 5 5 ; / / g r e e n v a l u e
pix−>p1 = 1 2 8 ; / / b l u e v a l u e
}
/ / advance p i x e l p o i n t e r to next p i x e l
pix ++;
}
}
i f (n > 0)
{ / / c a l c u l a t e Center of Gravity
121
122
338
343
348
353
358
363
368
373
378
383
388
393
398
403
408
413
418
APPENDIKS C. KILDEKODE
sx /= ( double ) n ;
sy /= ( double ) n ;
}
//
/ / p a i n t a r e c t a n g e l i n image , t o mark t h e t e s t e d a r e a
/ / u s i n g an o p e n CV f u n c t i o n
c v R e c t a n g l e ( img1−>cvArr ( ) ,
/ / image
c v P o i n t ( roiX , roi Y ) ,
/ / one c o r n e r
c v P o i n t ( roi X + roiW , ro iY + roiH ) , / / s e c o n d c o r n e r
CV_RGB( 2 5 5 , 0 , 0 ) ,
/ / c o l o u r ( R , G, B )
1 , 8 , 0) ;
/ / l i n e −width , c o n n e c t i v i t y , o f f s e t
/ / convert result to integer
s x i = roundi ( sx ) ;
s y i = roundi ( sy ) ;
/ / paint cross at center of gravity
cvLine ( img1−>cvArr ( ) , c v P o i n t ( s x i −10, s y i −10) ,
c v P o i n t ( s x i +10 , s y i +10) ,
CV_RGB( 0 , 0 , 2 5 5 ) , 1 , 8 , 0 ) ;
cvLine ( img1−>cvArr ( ) , c v P o i n t ( mini ( img1−>width ( ) −1, s x i +10) , maxi ( 0 , s y i −10) ) ,
c v P o i n t ( maxi ( 0 , s x i −10) , mini ( img1−>h e i g h t ( ) −1, s y i +10) ) ,
CV_RGB( 0 , 0 , 2 5 5 ) , 1 , 8 , 0 ) ;
/ / t e l l i m a g e p o o l t o f l a g i m a g e a s u p d a t e d , ( s o t h a t any p e n d i n g push
/ / commands can b e e f f e c t u a t e d ( a f t e r t h i s f u n c t i o n i s f i n i s h e d ) .
img1−>imgUpdated ( ) ;
/ / s a v e r e s u l t i n bmp f o r m a t − f i l t e r e d i m a g e w i t h r e s u l t m a r k i n g s
rawImg−>saveBMP ( " t e s t i m g−org . bmp" ) ;
img1−>saveBMP ( " t e s t i m g−f i l t . bmp" ) ;
//
/ / send r e p l y
/ / c o n v e r t i m a g e t i m e s t a m p t o a s t r i n g i n f o r m a t hh :mm: s s . ddd ( t o s t r i n g s )
img0−>imgTime . getTimeAsString ( s , t r u e ) ;
/ / f o r m a t r e p l y i n XML s t y l e a s a s i n g l e t a g w i t h a t t r i b u t e s and v a l u e s .
s n p r i n t f ( reply , MRL, " <COG x=\"% f \" y=\"% f \" time=\"%s \"/>\n " , sx , sy , s ) ;
sendMsg ( msg−>c l i e n t , r e p l y ) ;
//
/ / t h e r e s t i s j u s t t o d e m o n s t r a t e some i m a g e m a i p u l a t i o n s
//
/ / c o n v e r t t o BW f o r some openCV m a i p u l a t i o n i n BW
imgBW = imgPool−>getImage ( 1 3 , t r u e ) ;
imgBW−>copy ( rawImg ) ;
/ / c o n v e r t t o BW
imgBW−>toBW ( ) ;
/ / f l a g as updated
imgBW−>imgUpdated ( ) ;
/ / copy s u p p o r t d a t a t o image 0
/ / − i n c l u d i n g s i z e i m a g e t i m e , name s e r i a l number e t c .
/ / but not t h e image p i x e l s
img0−>copyMeta (imgBW, t r u e ) ;
img0−>setName ( " img0−edge " ) ;
/ / d e t e c t e d g e s u s i n g a ( openCV ) canny f i l t e r
/ / − and s t o r e s r e s u l t i n img0
cvCanny (imgBW−>cvArr ( ) , img0−>cvArr ( ) , 0 . 5 , 0 . 5 , 3 ) ;
/ / f l a g as updated
img0−>imgUpdated ( ) ;
/ / s a v e t h e edge image
img0−>saveBMP ( " t e s t i m g−canny . bmp" ) ;
//
//
/ / some i m a g e m a n i p u l a t i o n p i x e l by p i x e l i n YUV420 f o r m a t
/ / ( i n YUV420 u and v h a s h a l f r e s o l u t i o n o n l y )
/ / r e s u l t i s s a v e d a s t e s t i n g −c o l o u r . bmp
/ / enhances c o l o r in the region :
/ / x=50 ( column ) y=60 ( row ) ( t o p l e f t ) t o ( x =350 y =310 − b o t t o m r i g h t )
//
raw2 = imgPool−>getImage ( 1 2 , t r u e ) ;
raw2−>copy ( rawImg ) ;
raw2−>setName ( " raw2−c o l o r " ) ;
f o r ( r = 6 0 ; r < mini ( raw2−>getHeight ( ) , 3 1 0 ) ; r +=2)
{
y = raw2−>g e t Y l i n e ( r ) ;
u = raw2−>g e t U l i n e ( r /2) ;
v = raw2−>g e t V l i n e ( r /2) ;
f o r ( c = 5 0 ; c < mini ( 3 5 0 , raw2−>getWidth ( ) ) ; c +=2)
{ / / swap U and V
m = ∗v ;
∗v = ∗u ;
∗u = m;
/ / a d v a n c e y p o i n t e r by 2 p i x e l s
y += 2 ;
/ / a d v a n c e U and V by o n e p i x e l
u++;
v ++;
}
}
/ / f l a g as updated
C.5. MYFUNC.CPP
123
raw2−>imgUpdated ( ) ;
/ / save
raw2−>saveBMP ( " t e s t i n g−c o l o r . bmp" ) ;
//
return true ;
423
}
428
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
433
438
443
448
453
458
463
468
473
478
483
488
493
498
503
bool MyFunction : : bottleOrCan ( UServerInMsg ∗ msg , UImage ∗ pushImg )
{ / / extract parameters f i r s t
bool r e s u l t = f a l s e ;
/ / decode vars
char attName [MAX_SML_NAME_LENGTH ] ;
c o n s t i n t VBL = 1 0 0 ;
char a t t V a l u e [VBL ] ;
int n ;
/ / parameters default value
i n t roi X = 6 0 ;
i n t roi Y = 0 ;
i n t roiW = 2 2 ;
i n t roiH = 9 4 ;
i n t areaCan = 1 5 0 0 ;
int areaBottle = 750;
i n t thresholdCanU = 1 2 0 ;
i n t thresholdCanV = 1 3 0 ;
int thresholdBottleU = 120;
int thresholdBottleV = 115;
i n t deviceNum = −1;
char posName [MAX_MOUNT_NAME_SIZE] = " " ;
/ / c a m e r a and s o u r c e i m a g e v a r i a b l e s
UCamPush ∗ cam = NULL; / / c a m e r a
UImage ∗ img = pushImg ; / / i m a g e
bool ask4help = f a l s e ;
c o n s t i n t MRL = 2 0 0 ;
char r e p l y [MRL] ;
//
/ / extract parameters
/ / t h i s i s o n e o f two m e t h o d t , t h i s o n e t a k e s a l l p r o v i d e d p a r a m e t e r s o n e a t a t i m e
/ / and r e t u r n s i t s name ( attName ) and v a l u e ( a t t V a l u e ) , and you must t e s t f o r t h e name and
/ / e x t r a c t t h e v a l u e from t h e p r o v i d e d s t r i n g .
//
while ( msg−>t a g . g e t N e x t A t t r i b u t e ( attName , a t t V a l u e , VBL) )
{ / / camera d e v i c e
i f ( ( strcasecmp ( attName , " d e v i c e " ) == 0 ) or
( strcasecmp ( attName , " posName " ) == 0 ) )
{ / / e i t h e r number o r s t r i n g
n = s s c a n f ( a t t V a l u e , "%d " , &deviceNum ) ;
i f ( ( n ! = 1 ) and ( s t r l e n ( a t t V a l u e ) > 0 ) )
s t r n c p y ( posName , a t t V a l u e , MAX_MOUNT_NAME_SIZE) ;
}
/ / range o f i n t e r e s t parameters
e l s e i f ( strcasecmp ( attName , " help " ) == 0 )
ask4help = t r u e ;
e l s e i f ( strncasecmp ( attName , " width " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiW ) ;
e l s e i f ( strncasecmp ( attName , " h e i g h t " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiH ) ;
e l s e i f ( strcasecmp ( attName , " y " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiY ) ;
e l s e i f ( strcasecmp ( attName , " x " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &roiX ) ;
e l s e i f ( strcasecmp ( attName , " areaCan " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &areaCan ) ;
e l s e i f ( strcasecmp ( attName , " a r e a B o t t l e " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &a r e a B o t t l e ) ;
e l s e i f ( strcasecmp ( attName , " thresholdCanU " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &thresholdCanU ) ;
e l s e i f ( strcasecmp ( attName , " thresholdCanV " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &thresholdCanV ) ;
e l s e i f ( strcasecmp ( attName , " t h r e s h o l d B o t t l e U " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &t h r e s h o l d B o t t l e U ) ;
e l s e i f ( strcasecmp ( attName , " t h r e s h o l d B o t t l e V " ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &t h r e s h o l d B o t t l e V ) ;
}
//
i f ( ask4help )
{ / / i t was j u s t a r e q u e s t f o r on−l i n e h e l p
sendMsg ( msg−>c l i e n t , " <help s u b j e c t =\" B o t t l e or Can help \">\n " ) ;
sendMsg ( msg−>c l i e n t , "−−−− A v a i l a b l e BOC o p t i o n s : \ n " ) ;
sendMsg ( msg−>c l i e n t , " d e v i c e =N
from d e v i c e ’N ’ , i . e . /dev/videoN\n " ) ;
sendMsg ( msg−>c l i e n t , " posName=name
from camera ’name ’ , e . g . l e f t f o r l e f t camera\n
");
Top−l e f t p o s i t i o n o f Range Of I n t e r e s t ( ROI ) \n "
sendMsg ( msg−>c l i e n t , " x=X y=Y
);
124
APPENDIKS C. KILDEKODE
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
);
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
sendMsg ( msg−>c l i e n t ,
s en d In f o ( msg , " done " )
508
513
}
else
{ //
//
if
{
518
523
528
533
538
543
"w=W h=H
" areaCan=Ac
" a r e a B o t t l e =Ab
Width and h e i g h t o f ROI\n " ) ;
Amount o f p i x e l s t h a t should d e f i n e a can\n " ) ;
Amount o f p i x e l s t h a t should d e f i n e a b o t t l e \n "
Threshold f o r p i x e l use ( 0 t o 2 5 5 ) \n " ) ;
" thresholdCanU=B
Threshold f o r p i x e l use ( 0 t o 2 5 5 ) \n " ) ;
" thresholdCanV=B
" t h r e s h o l d B o t t l e U =B
Threshold f o r p i x e l use ( 0 t o 2 5 5 ) \n " ) ;
" t h r e s h o l d B o t t l e V =B
Threshold f o r p i x e l use ( 0 t o 2 5 5 ) \n " ) ;
"
( r e t u r n s e i t h e r ’ f a l s e ’ , ’ b o t t l e ’ or ’ can ’ ) \n " ) ;
( Uses image pool img=0 ( with a r e a ) and img=1 ( o r i g i n a l ) ) \n " ) ;
"
"−−−\n " ) ;
" </help >\n " ) ;
;
i f s e r v e r e v e n t push , t h e n i m a g e i s a v a i l a b l e i n c a l l
i f not , t h e n g e t an i m a g e f r o m c a m e r a
( img == NULL)
/ / no image , s o g e t r e q u e s t e d c a m e r a
i f ( g o t A l l R e s o u r c e s ( reply , MRL) )
{
i f ( deviceNum >= 0 )
/ / g e t c a m e r a f r o m d e v i c e number
cam = camPool−>getCam ( deviceNum ) ;
e l s e i f ( s t r l e n ( posName ) > 0 )
/ / e l s e g e t c a m e r a f r o m c a m e r a p o s i t i o n name
cam = camPool−>getCam ( posName ) ;
else
/ / e l s e use d e v i c e 0
cam = camPool−>getCam ( 0 ) ;
r e s u l t = ( cam ! = NULL) ;
if ( result )
{ / / g e t i m a g e b u f f e r f r o m image−p o o l
img = imgPool−>getImage ( cam−>getDeviceNumber ( ) , t r u e ) ;
/ / g e t an i m a g e f r o m c a m e r a
/ / g e t an i m a g e f r o m s t r e a m and l o a d i t i n t o ’ img ’
r e s u l t = cam−>getImageSnapshot ( img , f a l s e ) ;
}
else
f p r i n t f ( s t d e r r , "No camera found\n " ) ;
}
else
f p r i n t f ( s t d e r r , " R e s s o r e c e s a r e missing , ( no %s ) \n " , r e p l y ) ;
}
else
r e s u l t = true ;
//
i f ( not r e s u l t )
/ / s e n d s t a n d a r d XML−p a c k e d r e p l y t o c l i e n t − l i k e :
/ / <COG warning ="No i m a g e a v a i l a b l e "/ >\n
sendWarning ( msg , "No image a v a i l a b l e " ) ;
else
{ / / image i s a v a i l a b l e
c a l c B o t t l e O r C a n ( msg , img , roiX , roiY , roiW , roiH , areaCan , a r e a B o t t l e , thresholdCanU ,
thresholdCanV , t h r e s h o l d B o t t l e U , t h r e s h o l d B o t t l e V ) ;
}
548
553
558
}
return r e s u l t ;
}
563
568
573
578
583
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
bool MyFunction : : c a l c B o t t l e O r C a n ( UServerInMsg ∗ msg ,
UImage ∗ rawImg ,
i n t roiX , i n t roiY , i n t roiW , i n t roiH ,
i n t areaCan , i n t a r e a B o t t l e ,
i n t thresholdCanU , i n t thresholdCanV ,
int thresholdBottleU , int thresholdBottleV )
{
UImage ∗ img1 ; / / RGB f o r m a t i m a g e
double sxCans = 0 , s x B o t t l e s = 0 ; / / sum o f x v a l u e s
double syCans = 0 , s y B o t t l e s = 0 ; / / sum o f y v a l u e s
i n t sxiCans , syiCans ;
int sxiBottles , syiBottles ;
i n t nCans = 0 , n B o t t l e s = 0 ;
/ / count o f p i x e l s
int r , c ;
f l o a t pCan = 0 . 0 , p B o t t l e = 0 . 0 ; / / p r o b a b i l i t i e s
UPixel ∗ pix ; / / p o i n t e r t o a p i x e l
//
c o n s t i n t MRL = 1 0 0 ;
char r e p l y [MRL] ;
char s [ 3 0 ] ;
//
//
C.5. MYFUNC.CPP
588
593
598
603
608
613
618
623
628
/ / g e t an i m a g e s t r u c t u r e f r o m t h e i m a g e p o o l − s h a r e d by a l l f u n c t i o n s
/ / i m a g e i s c r e a t e d on f i r s t c a l l ( i f s e c o n d p a r a m e t e r i s t r u e )
//
//
/ / Make a l o w p a s s f i l t e r e d i m a g e u s i n g and openCV f u n c t i o n
//
/ / g e t a n o t h e r image from p o o l t o s t o r e smoothed image
/ / t h i s w i l l b e i m a g e 20 i n i m a g e p o o l−l i s t
img1 = imgPool−>getImage ( 2 0 , t r u e ) ;
/ / Copy raw YUV i m a g e
img1−>copy ( rawImg ) ;
img1−>toYUV ( ) ;
img1−>setName ( "BOC" ) ;
/ / f i l t e r i m a g e u s i n g a g a u s s i o n low p a s s f i l t e r
cvSmooth ( img1−>cvArr ( ) , img1−>cvArr ( ) , CV_GAUSSIAN, 3 , 0 , 0 ) ;
//
/ / use f i l t e r e d image
/ / l i m i t a r e a t o w i t h i n image
roi X = maxi ( 0 , mini ( roiX , img1−>width ( ) − 1 ) ) ;
roi Y = maxi ( 0 , mini ( roiY , img1−>h e i g h t ( ) − 1 ) ) ;
i f ( ( ro iX + roiW ) > ( i n t ) img1−>width ( ) )
roiW = img1−>width ( ) − roi X ;
i f ( ( ro iY + roiH ) > ( i n t ) img1−>h e i g h t ( ) )
roiH = img1−>h e i g h t ( ) − roi Y ;
//
//
/ / now c a l c u l a t e t h e BOC w i t h i n t h e ROI
f o r ( r = 0 ; r < roiH ; r ++)
{ / / get p o i n t e r to f i r s t p i x e l in area
/ / on l i n e ’ r ’
pix = img1−>g e t P i x R e f ( r + roiY , ro iX ) ;
/ / c o n v e r t BGR t o YUV p i x e l
/ / ∗ p i x = p i x −>asYUV ( PIX_PLANES_BGR ) ;
/ / t h e n c o n t i n u e w i t h t h e n e x t p i x e l s on i m a g e l i n e
f o r ( c = 0 ; c < roiW ; c ++)
{ / / t e s t i f a v e r a g e p i x e l −v a l u e i s a b o v e t r e s h o l d
i f ( ( pix−>u < thresholdCanU ) && ( pix−>v > thresholdCanV ) )
{ / / sum t h e p i x e l p o s i t i o n
nCans ++;
sxCans += ( double ) ( roiX + c ) ;
syCans += ( double ) ( roiY + r ) ;
/ / change the c o l o r o f t h i s p i x e l
/ / t o mark , t h a t i t i s a b o v e t r e s h o l d .
pix−>u = 1 9 8 ;
pix−>v = 0 ;
633
}
e l s e i f ( ( pix−>u < t h r e s h o l d B o t t l e U ) && ( pix−>v < t h r e s h o l d B o t t l e V ) )
{ / / sum t h e p i x e l p o s i t i o n
n B o t t l e s ++;
s x B o t t l e s += ( double ) ( roiX + c ) ;
s y B o t t l e s += ( double ) ( roiY + r ) ;
638
/ / change the c o l o r o f t h i s p i x e l
/ / t o mark , t h a t i t i s a b o v e t r e s h o l d .
pix−>u = 0 ;
pix−>v = 7 0 ;
643
}
/ / advance p i x e l p o i n t e r to next p i x e l
pix ++;
648
}
}
653
658
663
i f ( nCans > 0 )
{
/ / c a l c u l a t e t h e p r o b a b i l i t y o f a can
pCan = ( f l o a t ) nCans / ( f l o a t ) ( areaCan ) ;
/ / c a l c u l a t e Center of Gravity
sxCans /= ( double ) nCans ;
syCans /= ( double ) nCans ;
}
i f ( nBottles > 0)
{
/ / calculate the probability of a b o t t l e
pBottle = ( float ) nBottles / ( float ) ( areaBottle ) ;
/ / c a l c u l a t e Center of Gravity
s x B o t t l e s /= ( double ) n B o t t l e s ;
s y B o t t l e s /= ( double ) n B o t t l e s ;
668
}
//
/ / p a i n t a r e c t a n g e l i n image , t o mark t h e t e s t e d a r e a
/ / u s i n g an o p e n CV f u n c t i o n
c v R e c t a n g l e ( img1−>cvArr ( ) ,
/ / image
125
126
APPENDIKS C. KILDEKODE
c v P o i n t ( roiX , roiY ) ,
/ / one c o r n e r
c v P o i n t ( roi X + roiW , ro iY + roiH ) , / / s e c o n d c o r n e r
CV_RGB( 2 5 5 , 0 , 0 ) ,
/ / c o l o u r ( R , G, B )
1 , 8 , 0) ;
/ / l i n e −width , c o n n e c t i v i t y , o f f s e t
673
/ / convert result to integer
sxiCans = roundi ( sxCans ) ;
syiCans = roundi ( syCans ) ;
s x i B o t t l e s = roundi ( s x B o t t l e s ) ;
s y i B o t t l e s = roundi ( s y B o t t l e s ) ;
678
683
/ / paint cross at center of gravity
cvLine ( img1−>cvArr ( ) , c v P o i n t ( sxiCans −10, syiCans −10) ,
c v P o i n t ( sxiCans +10 , syiCans +10) ,
CV_RGB( 2 5 5 , 0 , 0 ) , 1 , 8 , 0 ) ;
cvLine ( img1−>cvArr ( ) , c v P o i n t ( mini ( img1−>width ( ) −1, sxiCans +10) , maxi ( 0 , syiCans −10) ) ,
c v P o i n t ( maxi ( 0 , sxiCans −10) , mini ( img1−>h e i g h t ( ) −1, syiCans +10) ) ,
CV_RGB( 2 5 5 , 0 , 0 ) , 1 , 8 , 0 ) ;
688
/ / paint cross at center of gravity
cvLine ( img1−>cvArr ( ) , c v P o i n t ( s x i B o t t l e s −10, s y i B o t t l e s −10) ,
c v P o i n t ( s x i B o t t l e s +10 , s y i B o t t l e s +10) ,
CV_RGB( 0 , 2 5 5 , 0 ) , 1 , 8 , 0 ) ;
cvLine ( img1−>cvArr ( ) , c v P o i n t ( mini ( img1−>width ( ) −1, s x i B o t t l e s +10) , maxi ( 0 , s y i B o t t l e s −10) ) ,
c v P o i n t ( maxi ( 0 , s x i B o t t l e s −10) , mini ( img1−>h e i g h t ( ) −1, s y i B o t t l e s +10) ) ,
693
698
CV_RGB( 0 , 2 5 5 , 0 ) , 1 , 8 , 0 ) ;
/ / t e l l i m a g e p o o l t o f l a g i m a g e a s u p d a t e d , ( s o t h a t any p e n d i n g push
/ / commands can b e e f f e c t u a t e d ( a f t e r t h i s f u n c t i o n i s f i n i s h e d ) .
703
img1−>imgUpdated ( ) ;
/ / s a v e r e s u l t i n bmp f o r m a t − f i l t e r e d i m a g e w i t h r e s u l t m a r k i n g s
/ / send r e p l y
/ / c o n v e r t i m a g e t i m e s t a m p t o a s t r i n g i n f o r m a t hh :mm: s s . ddd ( t o s t r i n g s )
img1−>imgTime . getTimeAsString ( s , t r u e ) ;
/ / f o r m a t r e p l y i n XML s t y l e a s a s i n g l e t a g w i t h a t t r i b u t e s and v a l u e s .
s n p r i n t f ( reply , MRL, " < v i s i o n v i s 0 =\"% f \" v i s 1 =\"% f \"/>\n " , pCan , p B o t t l e ) ;
sendMsg ( msg−>c l i e n t , r e p l y ) ;
708
713
//
//
718
s n p r i n t f ( r e p l y , MRL, "<BOC pCan=\"% f \" p B o t t l e =\"% f \" t i m e=\"%s \"/ >\n " , pCan , p B o t t l e , s ) ;
sendMsg ( msg−>c l i e n t , r e p l y ) ;
return true ;
}
723
728
733
738
743
748
753
// / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / /
// / / / / / / / / / / / / / / / /
bool MyFunction : : edge ( UServerInMsg ∗ msg , UImage ∗ pushImg )
{
bool r e s u l t = f a l s e ;
/ / decode vars
char attName [MAX_SML_NAME_LENGTH ] ;
c o n s t i n t VBL = 1 0 0 ;
char a t t V a l u e [VBL ] ;
int n ;
/ / parameters default value
int sobel = 5;
double t h r e s h o l d 1 = 0 . 5 ;
double t h r e s h o l d 2 = 6 0 0 0 ;
i n t deviceNum = −1;
char posName [MAX_MOUNT_NAME_SIZE] = " " ;
/ / c a m e r a and s o u r c e i m a g e v a r i a b l e s
UCamPush ∗ cam = NULL; / / c a m e r a
UImage ∗ img = pushImg ; / / i m a g e
bool ask4help = f a l s e ;
c o n s t i n t MRL = 2 0 0 ;
char r e p l y [MRL] ;
//
/ / extract parameters
/ / t h i s i s o n e o f two m e t h o d t , t h i s o n e t a k e s a l l p r o v i d e d p a r a m e t e r s o n e a t a t i m e
/ / and r e t u r n s i t s name ( attName ) and v a l u e ( a t t V a l u e ) , and you must t e s t f o r t h e name and
/ / e x t r a c t t h e v a l u e from t h e p r o v i d e d s t r i n g .
//
while ( msg−>t a g . g e t N e x t A t t r i b u t e ( attName , a t t V a l u e , VBL) )
{ / / camera d e v i c e
i f ( ( strcasecmp ( attName , " d e v i c e " ) == 0 ) or
( strcasecmp ( attName , " posName " ) == 0 ) )
{ / / e i t h e r number o r s t r i n g
n = s s c a n f ( a t t V a l u e , "%d " , &deviceNum ) ;
i f ( ( n ! = 1 ) and ( s t r l e n ( a t t V a l u e ) > 0 ) )
C.5. MYFUNC.CPP
758
763
768
773
778
783
788
793
798
803
808
813
818
823
828
833
838
127
s t r n c p y ( posName , a t t V a l u e , MAX_MOUNT_NAME_SIZE) ;
}
/ / range o f i n t e r e s t parameters
e l s e i f ( strcasecmp ( attName , " help " ) == 0 )
ask4help = t r u e ;
e l s e i f ( strncasecmp ( attName , " s o b e l " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%d " , &s o b e l ) ;
e l s e i f ( strncasecmp ( attName , " t h r e s h o l d 1 " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%l f " , &t h r e s h o l d 1 ) ;
e l s e i f ( strncasecmp ( attName , " t h r e s h o l d 2 " , 1 ) == 0 )
s s c a n f ( a t t V a l u e , "%l f " , &t h r e s h o l d 2 ) ;
}
//
i f ( ask4help )
{ / / i t was j u s t a r e q u e s t f o r on−l i n e h e l p
sendMsg ( msg−>c l i e n t , " <help s u b j e c t =\"Canny edge d e t e c t i o n help \">\n " ) ;
sendMsg ( msg−>c l i e n t , "−−−− A v a i l a b l e Canny o p t i o n s : \ n " ) ;
sendMsg ( msg−>c l i e n t , " d e v i c e =N
from d e v i c e ’N ’ , i . e . /dev/videoN\n " ) ;
sendMsg ( msg−>c l i e n t , " posName=name
from camera ’name ’ , e . g . l e f t f o r l e f t camera\n " ) ;
sendMsg ( msg−>c l i e n t , " s o b e l =S
The S o b e l f a c t o r { 1 , 3 , 5 , 7 } \ n " ) ;
Threshold one\n " ) ;
sendMsg ( msg−>c l i e n t , " t h r e s h o l d 1 =B
sendMsg ( msg−>c l i e n t , " t h r e s h o l d 2 =B
Threshold two\n " ) ;
( Uses image pool img=0 ( with a r e a ) and img=1 ( o r i g i n a l ) ) \n " ) ;
sendMsg ( msg−>c l i e n t , "
sendMsg ( msg−>c l i e n t , "−−−\n " ) ;
sendMsg ( msg−>c l i e n t , " </help >\n " ) ;
s en d In f o ( msg , " done " ) ;
}
else
{ / / i f s e r v e r e v e n t push , t h e n i m a g e i s a v a i l a b l e i n c a l l
/ / i f not , t h e n g e t an i m a g e f r o m c a m e r a
i f ( img == NULL)
{ / / no image , s o g e t r e q u e s t e d c a m e r a
i f ( g o t A l l R e s o u r c e s ( reply , MRL) )
{
i f ( deviceNum >= 0 )
/ / g e t c a m e r a f r o m d e v i c e number
cam = camPool−>getCam ( deviceNum ) ;
e l s e i f ( s t r l e n ( posName ) > 0 )
/ / e l s e g e t c a m e r a f r o m c a m e r a p o s i t i o n name
cam = camPool−>getCam ( posName ) ;
else
/ / e l s e use d e v i c e 0
cam = camPool−>getCam ( 0 ) ;
r e s u l t = ( cam ! = NULL) ;
if ( result )
{ / / g e t i m a g e b u f f e r f r o m image−p o o l
img = imgPool−>getImage ( cam−>getDeviceNumber ( ) , t r u e ) ;
/ / g e t an i m a g e f r o m c a m e r a
/ / g e t an i m a g e f r o m s t r e a m and l o a d i t i n t o ’ img ’
r e s u l t = cam−>getImageSnapshot ( img , f a l s e ) ;
}
else
f p r i n t f ( s t d e r r , "No camera found\n " ) ;
}
else
f p r i n t f ( s t d e r r , " R e s s o r e c e s a r e missing , ( no %s ) \n " , r e p l y ) ;
}
else
r e s u l t = true ;
//
i f ( not r e s u l t )
/ / s e n d s t a n d a r d XML−p a c k e d r e p l y t o c l i e n t − l i k e :
/ / <COG warning ="No i m a g e a v a i l a b l e "/ >\n
sendWarning ( msg , "No image a v a i l a b l e " ) ;
else
{ / / image i s a v a i l a b l e
UImage ∗ img0 ; / / RGB f o r m a t i m a g e
UImage ∗ imgBW ; / / RGB f o r m a t i m a g e
//
c o n s t i n t MRL = 1 0 0 ;
char r e p l y [MRL] ;
char s [ 3 0 ] ;
//
//
/ / g e t an i m a g e s t r u c t u r e f r o m t h e i m a g e p o o l − s h a r e d by a l l f u n c t i o n s
/ / i m a g e i s c r e a t e d on f i r s t c a l l ( i f s e c o n d p a r a m e t e r i s t r u e )
//
//
/ / Make a l o w p a s s f i l t e r e d i m a g e u s i n g and openCV f u n c t i o n
//
/ / g e t an i m a g e f r o m p o o l t o s t o r e a work c o p y o f i m a g e
/ / t h i s w i l l b e i m a g e 10 i n i m a g e p o o l−l i s t
img0 = imgPool−>getImage ( 1 4 , t r u e ) ;
128
APPENDIKS C. KILDEKODE
/ / c o n v e r t t o BW f o r some openCV m a i p u l a t i o n i n BW
imgBW = imgPool−>getImage ( 1 5 , t r u e ) ;
imgBW−>copy ( img ) ;
/ / c o n v e r t t o BW
imgBW−>toBW ( ) ;
/ / f l a g as updated
imgBW−>imgUpdated ( ) ;
/ / copy s u p p o r t d a t a t o image 0
/ / − i n c l u d i n g s i z e i m a g e t i m e , name s e r i a l number e t c .
/ / but not t h e image p i x e l s
img0−>copyMeta (imgBW, t r u e ) ;
img0−>setName ( " canny edge " ) ;
/ / d e t e c t e d g e s u s i n g a ( openCV ) canny f i l t e r
/ / − and s t o r e s r e s u l t i n img0
cvCanny (imgBW−>cvArr ( ) , img0−>cvArr ( ) , t h r e s h o l d 1 , t h r e s h o l d 2 , s o b e l ) ;
/ / f l a g as updated
img0−>imgUpdated ( ) ;
/ / send r e p l y
/ / c o n v e r t i m a g e t i m e s t a m p t o a s t r i n g i n f o r m a t hh :mm: s s . ddd ( t o s t r i n g s )
img0−>imgTime . getTimeAsString ( s , t r u e ) ;
/ / f o r m a t r e p l y i n XML s t y l e a s a s i n g l e t a g w i t h a t t r i b u t e s and v a l u e s .
s n p r i n t f ( reply , MRL, " <Canny time=\"%s \"/>\n " , s ) ;
sendMsg ( msg−>c l i e n t , r e p l y ) ;
843
848
853
858
863
}
}
return r e s u l t ;
868
}
C.6. DEFINITIONS.H
C.6
129
Definitions.h
# include <avr/ i o . h>
# include <avr/ s i g n a l . h>
/∗ s i g n a l ( i n t e r r u p t ) v e c t o r h a n d l i n g ∗/
# include <avr/ i n t e r r u p t . h> /∗ i n t e r r u p t f l a g s e . g . TIMSK ∗/
5 /∗
D e f i n i t i o n s and m a c r o s u s e d i n t h e AtmelMega16 program
∗/
/∗ Make b o o l e a n more r e a d a b l e ∗/
10 # define t r u e 1
# define f a l s e 0
# define e n a b l e _ r a i s i n g t r u e
/ / Used
# define
# define
# define
# define
20 # define
# define
# define
# define
15
ports
PORT_SERVOS
DDR_SERVOS
PORT_BUTTONS
DDR_BUTTONS
PORT_SWITCHES
DDR_SWITCHES
PORT_LEDS
DDR_LEDS
PORTA
DDRA
PINC
DDRC
PINB
DDRB
PORTC
DDRC
25 # define PIN_DC
PORTA7
/ / N o t i c e t h a t PORTD t a k e s c a r e o f t h e c o m m u n i c a t i o n w i t h t h e c o m p u t e r and s h o u l d n ’ t b e
/ / u s e d i n t h i s program
30 enum s e r v o s { RAISE_SERVO , REJECT_SERVO , DELIVER_SERVO , RESERVE_SERVO } ;
/ / t h e v e l o c i t i e s o f t h e 8 s e r v o s l a r g e v a l u e means f a s t e r
int velocity [4]={1 ,20 ,20 ,20}; / / int v e l o c i t y [4]={20 ,20 ,20 ,20};//{10 ,2 ,5 ,5 ,1 ,2 ,3 ,3};
/ / t h e v e l o c i t i e s o f t h e 8 s e r v o s s m a l l v a l u e means f a s t e r
35 i n t v e l o c i t y 2 [ 4 ] = { 2 , 1 , 1 , 1 } ; / / i n t v e l o c i t y 2 [ 4 ] = { 1 , 1 , 1 , 1 } ; / / { 1 , 2 , 1 , 1 , 2 0 , 2 , 2 0 , 2 0 } ;
/ / macros
# define s e r v o _ s e t ( x )
# define s e r v o _ c l e a r ( x )
40 # define s e r v o _ i n v e r t ( x )
PORT_SERVOS |= _BV ( x )
PORT_SERVOS &= ~_BV ( x )
PORT_SERVOS ^= _BV ( x )
# define l e d _ o f f ( x )
# define led_on ( x )
# define l e d _ i n v e r t ( x )
PORT_LEDS |= _BV ( x )
PORT_LEDS &= ~_BV ( x )
PORT_LEDS ^= _BV ( x )
# define kick_dc_on ( )
# define k i c k _ d c _ o f f ( )
PORT_SERVOS |= _BV ( PIN_DC )
PORT_SERVOS &= ~_BV ( PIN_DC )
45
/ / made s o t h a t t h e macro r e t u r n s t r u e when t h e s w i t c h i s p r e s s e d ( v a l u e =0)
50 # define b u t t o n _ p r e s s e d ( x )
( ( PORT_BUTTONS & _BV ( x ) ) ==0? t r u e : f a l s e )
# define r e a d y _ t o _ r a i s e ( )
( ( PORT_SWITCHES & _BV ( 0 ) ) ==0? f a l s e : t r u e )
/ / D i f f e r e n t a n g l e s u s e d i n t h e s o r t i n g mechanism and p l a c e m e n t box
55
/ / Specific angles
# define SERVO_0
1
# define SERVO_45 0 x31
# define SERVO_90 0x4E
60 # define SERVO_135 0 x69
# define SERVO_180 127
/ / angles
65 # define RAISE_ATTACH_ARM 124
# define RAISE_READY 80
# define RAISE_GRAP 64
# define RAISE_TOP 127
70 # define REJECT_CLOSED 31
# define REJECT_OPEN 65
# define DELIVER_CLOSED 124
# define DELIVER_OPEN 70
130
APPENDIKS C. KILDEKODE
C.7
Communication.h
1 void i n i t _ u s a r t ( void ) ;
C.8
Communication.c
/∗
The c o m m u n i c a t i o n module f o r t h e Atmel mega16 c i r c u i t ,
which i s u s e d t o c o n t r o l t h e s e r v o s , l a m p s and r e c e i v e
d i f f e r e n t i n t e r r u p t s f r o m t h e smr .
4
∗/
9 # include <avr/ i o . h>
# include <avr/ i n t e r r u p t . h>
# include <avr/ s i g n a l . h>
# include " Communication . h "
# include " S e r v o s t y r i n g . h "
14
# define t r u e 1
# define f a l s e 0
# define TRANSMIT_ENABLE 0 x04
19 char
char
char
char
char
24 void
void
input = 0 x00 ;
msg [ 4 ] = { 0 } ;
msg_cnt = 0 ;
msg_len = 0 ;
command = 0 ;
r e c v _ r o u t i n e ( char input ) ;
a n s _ r o u t i n e ( char ∗msg , char nbytes ) ;
char out [ 4 ] = { 0 } ;
char o u t _ c n t = 0 ;
29 char o u t _ l e n = 0 ;
extern
extern
extern
34 e x t e r n
extern
extern
extern
extern
39 e x t e r n
extern
char
char
char
char
char
char
char
char
char
char
start_flag ;
raise_ready_flag ;
raise_grap_flag ;
raise_top_flag ;
reject_closed_flag ;
reject_open_flag ;
deliver_closed_flag ;
deliver_open_flag ;
kick_dc_on_flag ;
kick_dc_off_flag ;
SIGNAL( SIG_UART_TRANS )
44 {
i f ( out_cnt != out_len )
{
o u t _ c n t ++;
UDR = out [ o u t _ c n t ] ;
49
}
else
{
out_cnt = 0 ;
PORTD &= ~TRANSMIT_ENABLE ;
54
}
}
SIGNAL( SIG_UART_RECV )
{
59
input = UDR;
r e c v _ r o u t i n e ( input ) ;
}
64 void i n i t _ u s a r t ( void )
{
/ / S e t s b a u d r a t e t o 115200 ( i f f _ c l k = 1 4 , 7 4 5 6 MHz) :
UBRRH = ( unsigned char ) 0 x00 ;
UBRRL = ( unsigned char ) 0 x07 ;
69
/ / E n a b l e s t r a n s m i t / r e c e i v e and t r a n s m i t / r e c e i v e i n t e r r u p t s :
UCSRB = (1 < <RXCIE ) | (1 < <TXCIE ) | (1 < <RXEN) | (1 < <TXEN) ;
/ / S e t s f r a m e f o r m a t t o 8 d a t a b i t s and 2 s t o p b i t s :
UCSRC = (1 < <URSEL ) | (1 < <USBS ) | (1 < <UCSZ1 ) | (1 < <UCSZ0 ) ;
74
}
C.8. COMMUNICATION.C
131
void r e c v _ r o u t i n e ( char input )
{
79
i f ( msg_cnt < 4 )
msg [ msg_cnt ] = input ;
i f ( msg_cnt == 0 )
msg_len = msg [ 0 ] & 0 x0F ;
84
/ / Store message length
i f ( msg_cnt == msg_len )
{
/ / Act on t h e r e q u e s t i f i t h a s t h e r i g h t a d d r e s s :
i f ( msg_cnt == 1 && ( ( msg [ 1 ] & 0 x0F ) == 0x0A ) ) / / t h e a d r e s s o f t h e Atmel i s A
{
89
command = ( msg [ 1 ] & 0 xF0 ) >> 4 ;
/ / t h i s i s were t h e message i s a n a l y s e d
94
switch ( command ) {
c a s e 0 x01 :
c a s e 0 x02 :
c a s e 0 x03 :
c a s e 0 x04 :
c a s e 0 x05 :
c a s e 0 x06 :
c a s e 0 x07 :
c a s e 0 x08 :
c a s e 0 x09 :
}
99
104
r a i s e _ r e a d y _ f l a g = 1 ; break ;
r a i s e _ g r a p _ f l a g = 1 ; break ;
r a i s e _ t o p _ f l a g = 1 ; break ;
r e j e c t _ c l o s e d _ f l a g = 1 ; break ;
r e j e c t _ o p e n _ f l a g = 1 ; break ;
d e l i v e r _ c l o s e d _ f l a g = 1 ; break ;
d e l i v e r _ o p e n _ f l a g = 1 ; break ;
k i c k _ d c _ o n _ f l a g = 1 ; break ;
k i c k _ d c _ o f f _ f l a g = 1 ; break ;
/∗
o u t [ 0 ] = 0 x01 ;
o u t [ 1 ] = 0x0A | ( ( command +7) << 4 ) ;
a n s _ r o u t i n e ( out , o u t [ 0 ] ) ; ∗/
109
}
/ / Reset buffer counter :
msg_cnt = 0 ;
114
}
else
msg_cnt ++;
119
}
void a n s _ r o u t i n e ( char ∗msg , char nbytes )
{
124
o u t _ l e n = nbytes ;
PORTD |= TRANSMIT_ENABLE ;
UDR = out [ 0 ] ;
}
/ / s e n d command + 7 b a c k
132
APPENDIKS C. KILDEKODE
C.9
Servostyring.h
void r a i s e _ r e a d y ( void ) ;
void r a i s e _ g r a p ( void ) ;
3 void r a i s e _ t o p ( void ) ;
void
void
void
8 void
r e j e c t _ c l o s e d ( void ) ;
r e j e c t _ o p e n ( void ) ;
d e l i v e r _ c l o s e d ( void ) ;
d e l i v e r _ o p e n ( void ) ;
C.10
Servostyring.c
# include <avr/ i o . h>
2 # include <avr/ s i g n a l . h>
/∗ s i g n a l ( i n t e r r u p t ) v e c t o r h a n d l i n g ∗/
# include <avr/ i n t e r r u p t . h> /∗ i n t e r r u p t f l a g s e . g . TIMSK ∗/
# include " D e f i n i t i o n s . h "
# include " Communication . h "
# include " S e r v o s t y r i n g . h "
7
# define debouncing_nr 100
/∗ P r o t o t y p e o f u s e d f u n c t i o n s ∗/
void updateAngle ( i n t servo ) ;
12 void i n i t _ t i m e r 0 ( void ) ;
void s t a r t _ t i m e r 0 ( char countvalue ) ;
void s t o p _ t i m e r 0 ( void ) ;
void i n i t _ t i m e r 1 ( void ) ;
void s t a r t _ t i m e r 1 ( void ) ;
17 void i n i t _ p o r t s ( void ) ;
void s k i t t l e _ r a i s e ( void ) ;
/ / c h a r p r e s e n t A n g l e [ 4 ] = {SORT_HOLD,BOX_M, 0 , 0 } ;
/ / c h a r newAngle [ 4 ] = {SORT_HOLD,BOX_M, 0 , 0 } ;
char presentAngle [ 4 ] = {RAISE_ATTACH_ARM, REJECT_CLOSED , DELIVER_CLOSED , 0 } ;
char newAngle [ 4 ] = {RAISE_ATTACH_ARM, REJECT_CLOSED , DELIVER_CLOSED , 0 } ;
i n t servocount [ 4 ] = { 0 , 0 , 0 , 0 } ;
char s h o u l d F l o a t [ 4 ] = { 0 , 0 , 0 , 0 } ;
27 char p r e s e n t S e r v o ;
i n t timecount = 0 ;
char update_complete = f a l s e ;
char s k i t t l e _ o u t = 1 ;
i n t tmp ;
32
/ / Flags
char r a i s e _ r e a d y _ f l a g = 0 ;
char r a i s e _ g r a p _ f l a g = 0 ;
char r a i s e _ t o p _ f l a g = 0 ;
37
char r e j e c t _ c l o s e d _ f l a g = 0 ;
char r e j e c t _ o p e n _ f l a g = 0 ;
22
char d e l i v e r _ c l o s e d _ f l a g = 0 ;
42 char d e l i v e r _ o p e n _ f l a g = 0 ;
char k i c k _ d c _ o n _ f l a g = 0 ;
char k i c k _ d c _ o f f _ f l a g = 0 ;
47 char s t a r t _ f l a g = 0 ;
char s t a r t _ c n t = 0 ;
i n t main ( i n t argn , char ∗ argv [ ] )
{
52
char b u t t o n s [ 8 ] ;
char i = 0 ;
long debounce_counter ;
char s k i t t l e _ c n t = 0 ;
57
// initialisation
init_ports () ;
init_timer0 () ;
init_timer1 () ;
init_usart () ;
62
/∗ e n a b l e a l l t h e i n t e r r u p t s ∗/
/ / HUSK AT SÆTTE TIL IGEN
sei () ;
67
while ( t r u e )
C.10. SERVOSTYRING.C
133
{
72
/ / Check a l l t h e b u t t o n s t o s e e w h e t h e r t h e y a r e p r e s s e d
f o r ( i = 0 ; i < 7 ; i ++) {
b u t t o n s [ i ]= f a l s e ;
debounce_counter = 0 ;
while ( b u t t o n _ p r e s s e d ( i ) ) {
debounce_counter ++;
i f ( debounce_counter >debouncing_nr ) {
b u t t o n s [ i ]= t r u e ;
break ;
}
}
}
77
82
/ / The g i v e n a c t i o n s h o u l d t a k e p l a c e i f t h e c o r r e s p o n d i n g s w i t c h i s p r e s s e d
/ / o r t h e c o r r e s p o n d i n g f l a g i s s e t by t h e c o m m u n i c a t i o n module
87
if
if
if
if
if
if
if
if
if
92
97
( /∗ b u t t o n s [ 0 ] = = t r u e
( /∗ b u t t o n s [ 1 ] = = t r u e
( /∗ b u t t o n s [ 2 ] = = t r u e
( /∗ b u t t o n s [ 3 ] = = t r u e
( /∗ b u t t o n s [ 4 ] = = t r u e
( /∗ b u t t o n s [ 5 ] = = t r u e
( /∗ b u t t o n s [ 6 ] = = t r u e
( kick_dc_on_flag )
( kick_dc_off_flag )
||
||
||
||
||
||
||
∗/ r a i s e _ r e a d y _ f l a g )
{ raise_ready ( ) ; }
∗/ r a i s e _ g r a p _ f l a g )
{ raise_grap ( ) ; }
∗/ r a i s e _ t o p _ f l a g )
{ raise_top ( ) ; }
∗/ r e j e c t _ c l o s e d _ f l a g )
{ reject_closed () ; }
∗/ r e j e c t _ o p e n _ f l a g )
{ reject_open ( ) ; }
∗/ d e l i v e r _ c l o s e d _ f l a g ) { d e l i v e r _ c l o s e d ( ) ; }
∗/ d e l i v e r _ o p e n _ f l a g )
{ deliver_open ( ) ; }
{ kick_dc_on ( ) ; k i c k _ d c _ o n _ f l a g = 0 ; }
{ kick_dc_off ( ) ; kick_dc_off_flag = 0 ; }
//
when
the
mech
swit
is
pres
}
return 0 ;
102 }
/ / T h i s i n t e r u p t i s c a l l e d e v e r y 20 ms
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
107
int i ;
timecount ++;
i f ( timecount == 3 0 0 0 ) timecount = 0 ;
112
//
/ / r e s e t t h i s c o u n t e r e v e r y 60 s e c .
/ / s e n d t h e new a n g l e s t o t h e d i f f e r e n t s e r v o s
f o r ( i = 0 ; i < 4 ; i ++) {
f o r ( i = 0 ; i < 2 ; i ++) {
update_complete = f a l s e ;
117
updateAngle ( i ) ;
/ / w a i t a w h i l e t o make s u r e t h e u p d a t e A n g l e command h a s b e e n e x e c u t e d
sei () ;
while ( update_complete== f a l s e ) __asm__ ( " nop " ) ;
122
}
}
127
void updateAngle ( i n t servo ) {
char countvalue ;
/ / c h a r tempAngle ;
132
137
servocount [ servo ] + + ;
i f ( servocount [ servo ] = = 2 5 5 ) servocount [ servo ] = 0 ;
//
//
//
//
if
c a l c u l a t e the angle t h a t the servo should uptain using infomation o f
t h e p r e s e n t a n g l e o f t h e s e r v o a s w e l l a s t h e wanted a n g l e ( n e w _ a n g l e )
t o c o n t r o l t h e v e l o c i t y o f t h e s e r v o s movement a n e w a n g l e s h o u l d n ’ t b e s e n t
immediatly but i n s t e a d d i v i d e d i n t o s e p e r a t e a n g l e s
( newAngle [ servo ] > 0 ) {
i f ( servocount [ servo ]% v e l o c i t y 2 [ servo ] = = 0 )
134
142
APPENDIKS C. KILDEKODE
{
147
/ / a new a n g l e s h o u l d b e g i v e n
i f ( ( ( presentAngle [ servo ]+ v e l o c i t y [ servo ] ) >newAngle [ servo ] ) && ( presentAngle [
servo]− v e l o c i t y [ servo ] <newAngle [ servo ] ) )
presentAngle [ servo ] = newAngle [ servo ] ;
else {
i f ( newAngle [ servo ] > presentAngle [ servo ] ) presentAngle [ servo ] +=
v e l o c i t y [ servo ] ;
i f ( newAngle [ servo ] < presentAngle [ servo ] ) presentAngle [ servo ] −=
v e l o c i t y [ servo ] ;
}
/ / p r e s e n t A n g l e [ s e r v o ]= tempAngle ;
}
/ / p r e s e n t A n g l e [ s e r v o ] = newAngle [ s e r v o ] ;
/ / update the angle of the given servo
152
p r e s e n t S e r v o = servo ;
157
s e r v o _ s e t ( servo ) ;
countvalue = presentAngle [ servo ] ;
i f ( countvalue >SERVO_180 ) countvalue = SERVO_180 ;
i f ( countvalue <SERVO_0 ) countvalue = SERVO_0 ;
s t a r t _ t i m e r 0 ( countvalue ) ;
162
}
e l s e { s e r v o _ c l e a r ( servo ) ; update_complete= t r u e ; }
}
SIGNAL (SIG_OUTPUT_COMPARE0) {
/ / this timer controls the length of the pulse
167
servo_clear ( presentServo ) ;
/ / stop this timer
stop_timer0 ( ) ;
update_complete= t r u e ;
}
172
void i n i t _ p o r t s ( void ) {
/∗ S e t t h e d a t a−d i r e c t i o n o f d i f f e r e n t p o r t s .
1 = output
0 = input
177
∗/
DDR_SERVOS
= 0xFF ;
/ / Servos
DDR_SWITCHES = 0 x00 ;
/ / b u t t o n s ( i n t h e r a i s i n g mechanisme )
DDR_BUTTONS = 0 x00 ;
/ / From t h e s t k 5 0 0 b o a r d
DDR_LEDS
= 0xFF ;
/ / LEDS
182
DDRD = 0 x07 ;
PORTB |= 0 x03 ;
/∗ S e t t h e i n i t i a l v a l u e s f o r t h e o u t p u t p o r t s ∗/
PORT_LEDS = 0xFF ;
187
}
void i n i t _ t i m e r 0 ( void ) {
// Possible prescaler settings
192
/ / Timer0 (8− b i t c o u n t e r )
//
/ / CS02 CS01 CS00
//
0
0
0
= Timer0 s t o p p e d
//
0
0
1 = clk
197
//
0
1
0
= clk /8
//
0
1
1
= c l k /64
//
1
0
0
= c l k /256
//
1
0
1
= c l k /1024
//
202
/ / e . g . TCCR0 = _BV ( CS00 ) | _BV ( CS02 ) ; / / c l k / 1 0 2 4
/ / n o t e t h a t _BV ( CS02 ) e q u a l s 0 b00000010
/ / TCCR0 =
_BV ( CS02 ) | _BV ( CS00 ) | _BV (WGM01) ;
/ / Count v a l u e
TCNT0 = 0 x00 ;
207
/ / The s t a r t v a l u e
}
212
void s t a r t _ t i m e r 0 ( char countvalue ) {
OCR0 = countvalue ;
TCNT0 = 0 x00 ;
/ / The s t a r t v a l u e
TCCR0 = _BV ( CS02 ) | _BV (WGM01) ;
TIMSK |= _BV ( OCIE0 ) ;
}
217
void s t o p _ t i m e r 0 ( void ) {
TCCR0 = 0 x00 ;
TIMSK &= ~_BV ( OCIE0 ) ;
}
222
C.10. SERVOSTYRING.C
void i n i t _ t i m e r 1 ( void ) {
TCNT1L = 0 x00 ;
TCNT1H = 0 x00 ;
227
OCR1AH = 0 x90 ;
OCR1AL = 0 x00 ;
/ / TCCR1A = _BV (WGM12) ;
TCCR1B = _BV ( CS11 ) | _BV (WGM12) ;
232
TIMSK |= _BV ( OCIE1A ) ;
}
237
void delay ( i n t time ) {
/ / d e l a y = t i m e ∗ 20ms
timecount = 0 ;
while ( timecount < time ) ;
}
/ / The d i f f e r e n t a c t i o n s
242 void r a i s e _ r e a d y ( void ) {
led_on ( 0 ) ;
newAngle [ RAISE_SERVO]= RAISE_READY ;
velocity [0] = 1;
velocity2 [0] = 2;
247
raise_ready_flag = 0;
led_off (0) ;
}
void r a i s e _ g r a p ( void ) {
led_on ( 1 ) ;
newAngle [ RAISE_SERVO]= RAISE_GRAP ;
velocity [0] = 1;
velocity2 [0] = 2;
raise_grap_flag = 0;
257
led_off (1) ;
}
void r a i s e _ t o p ( void ) {
led_on ( 2 ) ;
velocity [0] = 1;
262
velocity2 [0] = 2;
newAngle [ RAISE_SERVO]= RAISE_TOP ;
raise_top_flag = 0;
led_off (2) ;
}
267
void r e j e c t _ c l o s e d ( void ) {
/ / led_on (0) ;
newAngle [ REJECT_SERVO]= REJECT_CLOSED ;
reject_closed_flag = 0;
272
// led_off (0) ;
}
252
void r e j e c t _ o p e n ( void ) {
/ / led_on (0) ;
277
newAngle [ REJECT_SERVO]= REJECT_OPEN ;
reject_open_flag = 0;
// led_off (0) ;
}
void d e l i v e r _ c l o s e d ( void ) {
282
/ / led_on (0) ;
newAngle [ DELIVER_SERVO]= DELIVER_CLOSED ;
deliver_closed_flag = 0;
// led_off (0) ;
}
287
void d e l i v e r _ o p e n ( void ) {
/ / led_on (0) ;
newAngle [ DELIVER_SERVO]= DELIVER_OPEN ;
deliver_open_flag = 0;
292
// led_off (0) ;
}
135
www.oersted.dtu.dk
Ørsted·DTU
Automation
Danmarks Tekniske Universitet
Elektrovej
Bygning 326
2800 Kgs. Lyngby
Tel: (+45) 45 25 35 50
Fax: (+45) 45 88 12 95
E-mail: [email protected]