LL(1)-sturing van de Lego Mindstorms robotlib.ugent.be/fulltxt/RUG01/000/686/003/RUG01... · (3):...
Transcript of LL(1)-sturing van de Lego Mindstorms robotlib.ugent.be/fulltxt/RUG01/000/686/003/RUG01... · (3):...
Faculteit Toegepaste Wetenschappen
Vakgroep Zuivere Wiskunde en Computeralgebra
Voorzitter: prof. dr. J. A. Thas
LL(1)-sturing van de Lego
Mindstorms robot
door Sam Lerouge
Promotor: prof. dr. A. Hoogewijs
SCRIPTIE ingediend tot het behalen van de academische
graad van licentiaat in de informatica, optie
software-ontwikkeling
Academiejaar 2000-2001
Dankwoord
Graag zou ik iedereen willen bedanken die heeft bijgedragen tot het tot stand komen
van dit eindwerk; in het bijzonder wil ik volgende personen bedanken:
• mijn promotor, prof. Albert Hoogewijs om mij de kans te geven op een nuttige
manier met legoblokken te werken, en om mij van in het begin op het juiste
spoor te zetten;
• mijn ouders, omdat ze mij altijd gesteund hebben tijdens mijn studies;
• Geert Vernaeve, om altijd te antwoorden op mijn vele lastige vragen;
• mijn voorganger Hans Gruyaert, omdat er zonder zijn werk wellicht geen
sprake zou geweest zijn van deze scriptie.
Toelating tot bruikleen
De auteur geeft de toelating deze SCRIPTIE voor consultatie beschikbaar te stellen
en delen van de SCRIPTIE te kopieren voor persoonlijk gebruik.
Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzon-
der met betrekking tot de verplichting de bron uitdrukkelijk te vermelden bij het
aanhalen van resultaten uit deze SCRIPTIE.
Sam Lerouge 30 mei 2001
i
LL(1)-sturing van de Lego Mindstorms robot
door
Sam Lerouge
SCRIPTIE ingediend tot het behalen van de academische graad van licentiaat in de
informatica, optie software-ontwikkeling
Academiejaar 2000–2001
Universiteit Gent
Faculteit Toegepaste Wetenschappen
Vakgroep Zuivere Wiskunde en Computeralgebra
Voorzitter: prof. dr. J. A. Thas
Promotor: prof. dr. A. Hoogewijs
Samenvatting
Drie jaar geleden toonde Hans Gruyaert in zijn thesis “LL(1)-specificaties in robo-
tica” [2] aan dat LL(1)-talen bijzonder geschikt zijn voor het aansturen van robots.
Deze stelling werd eerder al door prof. Hoogewijs naar voor gebracht. In [3] stelde
hij dat LL(1)-beschrijvingen gebruikt kunnen worden voor de automatische ont-
wikkeling van software voor bewegingscontrole, objectherkenners en mens-machine
interfaces.
De ontwikkeling van de Lego Mindstorms robot, die als commercieel pakket op
grote schaal verkocht wordt, gaf de gelegenheid in de praktijk na te gaan hoe LL(1)-
specificaties kunnen gebruikt worden om een robot op een interactieve manier te
besturen.
Trefwoorden: LL(1)-specificaties, syntax-gerichte software-ontwikkeling, ro-
botsturing, Lego Mindstorms.
ii
Inhoudsopgave
1 LL(1) voor robots 1
1.1 LL(1)-talen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Talen en grammatica’s . . . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Reguliere grammatica’s . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 Contextvrije grammatica’s . . . . . . . . . . . . . . . . . . . . 5
1.1.4 LL(1)-grammatica’s . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.5 Betekenis van een taal . . . . . . . . . . . . . . . . . . . . . . 7
1.1.6 Visual MIRA . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 CDL en RCL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.1 Configuration Description Language . . . . . . . . . . . . . . . 10
1.2.2 Robot Control Language . . . . . . . . . . . . . . . . . . . . . 11
1.3 Doel van deze thesis . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4 LL(1)-talen voor robotsturing . . . . . . . . . . . . . . . . . . . . . . 15
2 Lego Mindstorms 18
2.1 Het Mindstorms pakket . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2 Programmeeromgevingen voor de RCX . . . . . . . . . . . . . . . . . 19
2.2.1 RCX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2.2 NQC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.3 LegOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.2.4 TinyVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.2.5 LeJOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
iii
2.2.6 Andere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2.7 De keuze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.3 Lego Mindstorms als educatief hulpmiddel . . . . . . . . . . . . . . . 23
2.4 Bouw van de gebruikte robot . . . . . . . . . . . . . . . . . . . . . . 23
3 Realistatie van de RCL 24
3.1 Bereik van de IR zender . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2 Implementatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2.1 Origineel voorstel . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2.2 Aanpassing van de Robot klasse . . . . . . . . . . . . . . . . . 28
3.2.3 Integratie in de scanner/parser . . . . . . . . . . . . . . . . . 30
3.3 Evaluatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3.1 Eenvoud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3.2 Traagheid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3.3 Vreemde effecten . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3.4 Onzuivere richting . . . . . . . . . . . . . . . . . . . . . . . . 33
4 Verbeteringen 35
4.1 Aanpassing van de taal . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.1 Richtingen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.1.2 Overbodige instructies . . . . . . . . . . . . . . . . . . . . . . 37
4.1.3 Semantische wijziging . . . . . . . . . . . . . . . . . . . . . . . 38
4.2 Bepalen van de positie . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.3 Realisatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.3.1 Bewegen in het rooster . . . . . . . . . . . . . . . . . . . . . . 41
4.3.2 Het gebruik vanuit de parser . . . . . . . . . . . . . . . . . . . 44
5 Conclusie 45
5.1 Suggesties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.1.1 Peer-to-peer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.1.2 De robot als interpreter . . . . . . . . . . . . . . . . . . . . . 48
iv
5.1.3 MIRA als vertaalmechanisme . . . . . . . . . . . . . . . . . . 50
5.2 Besluit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
v
Hoofdstuk 1
LL(1) voor robots
1.1 LL(1)-talen
1.1.1 Talen en grammatica’s
Een taal kunnen we beschouwen als een verzameling van zinnen. Elke zin bestaat uit
een eindig aantal symbolen of bouwstenen. De eindige verzameling van bouwstenen
noemen we het woordenboek of het alfabet. Vermits de meeste talen een oneindig
aantal zinnen bevatten, is er nood aan een formalisme dat toelaat dergelijke talen
op een eindige manier te beschrijven. Een taal zal vastgelegd worden door een
grammatica en een herkenner.
We vertrekken van een eindig woordenboek W en definieren daarmee W +, de
(oneindig aftelbare) verzameling van alle eindige rijen van woorden uit W , d.i. alle
zinnen over W . De lege zin noteren we als & en we noteren W + ∪ {&} als W ∗. Een
taal L over W is een eindige deelverzameling van W ∗.
De kern van een grammatica wordt gevormd door een eindige verzameling P
van herschrijfregels. Een herschrijfregel is een geordend paar (z1, z2) van zinnen met
z1 ∈ W+ en z2 ∈ W ∗. We gebruiken de notatie z1 → z2 wanneer (z1, z2) ∈ P .
Intuıtief kan z1 → z2 gezien worden als “z1 kan vervangen worden door z2” of “z1
kan herschreven worden als z2”. We noemen → de herschrijfrelatie. Ze geeft aan
dat de herschrijving van links naar rechts moet worden toegepast.
1
Definitie 1.1 We zeggen nu dat z′ ∈ W ∗ op directe wijze voortgebracht wordt door
z ∈ W+ wanneer er zinnen u, v, z1, z2 ∈ W ∗ bestaan zodanig dat
z = uz1v, z′ = uz2v, z1 → z2 ∈ P (1.1)
en we noteren dit als z ⇒ z′.
Definitie 1.2 We zeggen dat z′ ∈ W ∗ voortgebracht wordt door z ∈ W + wanneer
er zinnen z0, . . . , zn(n ≥ 0) bestaan zodanig dat
z = z0, z′ = zn, ∀i ∈ [0, n − 1] : zi ⇒ zi+1 (1.2)
en we noteren dit als z ⇒∗ z′.
We zijn nu in staat om een grammatica op een formele manier te definieren. We
spreken van voortbrengende of generatieve grammatica’s aangezien ze een taal op
een generatieve manier beschrijven.
Definitie 1.3 Een generatieve grammatica G is een geordend viertal (N, T, S, P )
waarbij:
N een eindige verzameling van woorden is die we de niet-terminalen zullen
noemen;
T een eindige verzameling is van woorden die we terminalen zullen noemen,
zo dat N ∩ T = ∅; merk op dat W = N ∪ T ;
S ∈ N het startsymbool genoemd wordt;
P een verzameling is van herschrijfregels zodanig dat het linkerlid van de her-
schrijfregels minstens een niet-terminaal bevat, d.w.z. P ∈ W ∗NW ∗ × W ∗.
Definitie 1.4 We zeggen nu dat een zin z voortgebracht wordt door de grammatica
G als z ∈ T ∗ en S ⇒∗ z.
Definitie 1.5 De verzameling van alle zinnen voortgebracht door G noteren we
L(G) = {z ∈ T ∗ : S ⇒∗ z}, en noemen we de taal voortgebracht door G.
2
Chomsky heeft de grammatica’s ingedeeld in een aantal klassen naargelang de
eigenschappen van de herschrijfregels.
Definitie 1.6 Een generatieve grammatica G = (N, T, S, P ) wordt van het type k
of een (type k)-grammatica (k = 0, 1, 2, 3) genoemd als de volgende restrictie voor
de herschrijf-regels vervuld is:
(0): geen restricties;
(1): elke herschrijfregel van P is van de vorm z1 → z2 met z1, z2 ∈ (N ∩ T )+,
zodanig dat |z1| ≤ |z2|, d.w.z. elke herschrijfregel is niet-verkortend (zin z1 bevat
minder of evenveel woorden dan zin z2); ( contextgevoelig)
(2): elke herschrijfregel van P is van de vorm A → z, met A ∈ N en z ∈
(N ∪ T )∗; ( contextvrij)
(3): elke herschrijfregel van P is van de vorm A → aB of A → a met A, B ∈ N
en a ∈ T ; ( regulier)
Gegeven een grammatica G en een zin z, dan kunnen we nagaan of deze zin
kan voortgebracht worden door G, m.a.w. of S ⇒∗ z. Daartoe wordt vertrokken
van S en worden er herschrijvingen toegepast tot de zin z is bekomen. We noemen
dit een afleiding. De afleiding van een zin kunnen we grafisch voorstellen door een
boom, die we de afleidingsboom zullen noemen. In zo een boom is de wortel het
startsymbool, de bladeren zijn terminalen, en de andere knopen zijn niet-terminalen
uit het alfabet.
Een meest-linkse afleiding wordt gedefinieerd als een afleiding waarbij steeds de
meest-linkse niet-terminaal eerst wordt herschreven. Voortaan zullen we met ⇒ en
⇒∗ steeds de meest-linkse afleidingen bedoelen.
1.1.2 Reguliere grammatica’s
Reguliere grammatica’s werden gedefinieerd in de vorige paragraaf. We geven hier
echter een alternatieve definitie die een meer gestructureerde en beknopte beschrij-
ving van de reguliere grammatica’s toelaat.
3
Definitie 1.7 Een reguliere grammatica G wordt gedefinieerd als een koppel (T, e)
waarbij
1. T een eindige verzameling van terminale symbolen is; T = {a1, . . . , an} met
n ≥ 0;
2. e een reguliere expressie is; e kan gezien worden als een regel die aangeeft hoe
strings van terminale symbolen die behoren tot L(G) kunnen afgeleid worden in G.
We geven nu een formele definitie voor reguliere expressies.
Definitie 1.8 Als T een eindige verzameling van terminale symbolen is, dan wordt
een reguliere expressie recursief gedefinieerd door de volgende twee atomaire en drie
samengestelde regels:
(A1) & is de reguliere expressie die de lege string voorstelt;
(A2) ai is een reguliere expressie met ai ∈ T een terminaal symbool;
Stel nu dat e, e1, . . . , en reguliere expressies zijn, dan geldt:
(S1) (e1| . . . |en) is een reguliere expressie (n > 1) waarbij het symbool | de unie-
operator wordt genoemd; intuıtief geeft deze operator aan dat ofwel e1 ofwel e2 ofwel
. . . ofwel en moet gekozen worden;
(S2) e1.e2. . . . .en is een reguliere expressie (n > 1), waarbij het symbool . de
concatenatie- of product-operator wordt genoemd en meestal niet expliciet geschre-
ven wordt;
(S3) (e)∗ is een reguliere expressie waarbij het symbool ∗ de closure-operator
wordt genoemd; intuıtief geeft de closure-operator aan dat e nul of meer keer kan
voorkomen;
Applicaties die als input zinnen uit een bepaalde taal verwachten, krijgen initieel
eigenlijk rijen van karakters aangeboden. Het is de taak van de lexicale analyse om
deze strings te partitioneren in groepjes van karakters die we tokens zullen noemen.
De tokens zijn de elementaire bouwstenen of woorden waarmee de zinnen uit de taal
worden opgebouwd. De tokens hebben dus een betekenis binnen de taal, terwijl
de karakters waaruit de tokens worden opgebouwd, op zich geen betekenis hebben.
4
Voorbeelden van tokens zijn cijfers, operatoren, sleutelwoorden en identifiers. We
kunnen reguliere grammatica’s gebruiken om de lexicale structuur van een taal,
i.e. de manier waarop een rij van karakters moet verdeeld worden in tokens, vast
te leggen. De tokens zullen gebruikt worden in de volgende fase van de compiler,
namelijk de syntax-analyse, die de tokens een hierarchische structuur geeft.
In het zogenaamde Dragon Book [1] worden enkele redenen opgesomd om de
opsplitsing tussen een scanner voor de lexicale analyse en een parser voor de syntax-
analyse te maken:
• het ontwerp van de compiler wordt eenvoudiger en overzichtelijker
• de compiler kan efficienter geschreven worden
• de overdraagbaarheid over verschillende platformen wordt groter omdat pro-
blemen door machine-afhankelijkheden opgevangen kunnen worden in de scan-
ner, zodat enkel daar aanpassingen nodig zullen zijn
1.1.3 Contextvrije grammatica’s
De reguliere grammatica’s zullen meestal gebruikt worden om de lexicale structuur
van een taal vast te leggen. Om de syntactische structuur van een taal te be-
schrijven zijn deze grammatica’s te beperkt. Het is bijvoorbeeld niet mogelijk om
met reguliere grammatica’s geneste structuren te beschrijven, zoals conditionele- en
iteratie-statements, expressies met haken en begin-end blokken. De context-vrije
grammatica’s bieden hiervoor een oplossing.
We vertrekken van een generatieve grammatica G = (N, T, S, P ) waarbij
N = {A0, . . . , An} en T = {a0, . . . , an}. Opnieuw zijn N de niet-terminalen, T de
terminalen, S het startsymbool, en P de verzameling herschrijfregels.
Bij een context-vrije grammatica (CVG) zijn alle herschrijfregels uit P van de
vorm Ai → ei waarbij Ai ∈ N en ei een context-vrije expressie (CVE) is. Er is
precies een herschrijfregel voor elke niet-terminaal uit N . Merk op dat we in de
context van CVG’s zullen spreken van syntax-regels i.p.v. herschrijfregels.
5
De CVE’s worden recursief gedefinieerd door drie atomaire en drie samengestelde
regels. Het verschil met de reguliere grammatica’s zit in de derde atomaire regel: in
een reguliere expressie kunnen enkel niet-terminalen voorkomen.
(A1) & is een CVE;
(A2) ai ∈ T is een CVE;
(A3) Aj ∈ N is een CVE;
Stel nu dat e, e1, . . . , en CVE’s zijn, dan geldt:
(S1) (e1| . . . |en) is een CVE (n > 1);
(S2) e1. . . . .en is een CVE (n > 1);
(S3) (e)∗ is een CVE;
1.1.4 LL(1)-grammatica’s
We beschouwen een CVG G en een zin z = a1 . . . an ∈ L(G), m.a.w. S ⇒∗ z (de
meest-linkse afleiding). We zullen nu nagaan op welke manier de afleiding van z tot
stand komt. Daarvoor gaan we gebruik maken van de top-down methode. Hierbij
wordt vertrokken van de startknoop, en wordt de afleidingsboom van boven naar
beneden opgebouwd zodanig dat de boom uiteindelijk als bladeren a1, . . . , an bevat.
Algemeen gesproken kunnen we parsers schrijven voor om het even welke CVG.
Door onze grammatica goed te schrijven kunnen we er echter voor zorgen dat er
nooit backtracking zal nodig zijn, waardoor de parser een stuk efficienter wordt. We
moeten dan wel op elk ogenblik genoeg informatie uit de configuratie van de parser
kunnen halen om een juiste beslissing te nemen, meer bepaald het volgen van de
juiste productieregel. In dit geval spreken we van predictieve parsers [1].
Uitgaande van een inputzin maken we gebruik van een inputhead, die zich telkens
boven een bepaald inputwoord bevindt. We vertrekken van het startsymbool, en
herschrijven telkens de meest-linkse niet-terminaal. Voor predictieve parsers moet
het inputwoord voldoende informatie geven om de juiste regel te selecteren. Telkens
wanneer we in de afleiding een terminaal bereiken, wordt de inputhead met een
plaats opgeschoven.
6
Een grammatica G wordt een LL(1)-grammatica genoemd wanneer er telkens ten
hoogste 1 woord moet verder gekeken worden vanaf de inputhead om uit te maken
welke herschrijfregel moet toegepast worden. De eerste L staat voor het lezen van
de inputzin van links naar rechts, de tweede L staat voor de meest-linkse afleiding.
Definitie 1.9 Een LL(1)-grammatica is een grammatica waar voor elke zin van de
vorm wAv, w ∈ T ∗, A ∈ N, v ∈ (N∪T )∗, afgeleid door een meest-linkse afleiding, ten
hoogste 1 woord verder moet gekeken worden om op unieke manier te beslissen welke
van de regels met aan de linkerkant de niet-terminaal A, moet toegepast worden.
1.1.5 Betekenis van een taal
Tot nu toe hebben we beschreven hoe de lexicale en de syntactische structuur van
een taal kan vastgelegd worden. De beschrijving van terminalen en syntax-regels uit
een CVG noemen we een syntax-beschrijving of syntax-specificatie. In het bijzonder
kunnen we dus een LL(1)-specificatie opstellen voor een bepaalde LL(1)-grammatica.
Vertrekkend van een dergelijke LL(1)-specificatie kan mechanisch (bv. met Visual
MIRA) een herkenner voor de taal gegenereerd worden. Dit is een programma dat
voor een gegeven inputzin kan uitmaken of de zin al dan niet tot de taal behoort.
We zullen dit programma voortaan de parser noemen.
Met wat we tot nu toe gezien hebben, zijn we in staat om voor een bepaalde
zin na te gaan of deze grammaticaal correct is onder een gegeven grammatica. We
willen echter de gedefinieerde taal ook een betekenis kunnen geven.
De syntax-beschrijving vormt een kader waarop een aantal zaken kunnen gehecht
worden. Die aanvullingen zorgen ervoor dat aan de beschreven taal een betekenis
kan gegeven worden. We geven een kort overzicht:
• Attributen laten toe om zowel aan terminale als aan niet-terminale symbolen
een waarde van een bepaald type te hechten. De terminale en niet-terminale
symbolen met attribuut kunnen dan in semantische acties gebruikt worden als
gewone variabelen.
7
• Een semantische actie kan beschouwd worden als een stukje code met een
naam. De naam wordt gebruikt om de bijhorende code op te roepen en komt
voor binnen de syntax-regels. De code wordt uitgevoerd op het moment dat de
semantische actie geparst wordt. Semantische acties kunnen gebruikt worden
om bepaalde code te hechten aan bepaalde woorden of zinnen uit de taal.
• Lokale en globale variabelen: het is mogelijk om variabelen te declareren die
als scope een bepaalde syntax-regel of alle syntax-regels hebben.
• Op dezelfde manier waarop we een verzameling van inputsymbolen opstellen
kunnen we nu een verzameling van outputsymbolen declareren. De input-
symbolen zijn de symbolen die door de parser kunnen ingelezen worden; de
outputsymbolen zijn de symbolen die door de parser gegenereerd worden. De
outputsymbolen komen ook voor in de syntax-regels. Outputsymbolen worden
vooral gebruikt bij lexicale analyse: de input symbolen zijn dan bv. letters,
de output symbolen de sleutelwoorden uit de taal.
1.1.6 Visual MIRA
Visual MIRA is een CASE-tool (Computer Aided Software Engeneering) dat uit-
gaande van de LL(1)-specificatie voor een softwaresysteem de broncode voor de
parser genereert in een traditionele programmeertaal zoals C++. Het is ontworpen
door de MIRA-Development Group van Expert Software Systems N.V. en toegepast
in de ontwikkeling van industriele systemen.
Naast de beschrijving van de grammatica, weergegeven in Backus-Naur Form
(BNF), kunnen semantische acties opgegeven worden, waarvan de code in C++ is ge-
schreven. BNF is een sterk gestructureerde, hierarchische metataal. Niet-terminalen
in een expressie kunnen opeenvolgend worden vervangen door andere niet-terminalen
alvorens uiteindelijk een terminaal symbool bereikt wordt. Deze boomstructuur van
verschillende niveau’s kan voor mensen moeilijk te volgen zijn omdat tegen de tijd
dat men de terminalen bereikt, men de uitdrukking van het hoogste niveau al lang
8
kan vergeten zijn. Visual MIRA laat toe om de BNF-beschrijvingen te visualiseren
in corresponderende transitiediagrammen. Figuur 1.1 geeft een voorbeeld van zo
een transitiediagram.
Figuur 1.1: Een transitiediagram in Visual MIRA
De MIRA input kunnen we formeel beschrijven als een syntax-regel:
<MIRA Input> = "Comment"*
(<Option Part> | &)
(<Attribute Part> | &)
(<InputPrimitive Part> | &)
(<OutputPrimitive Part> | &)
<Rule Part>*
(<Parser Part> | &)
(<FollowSet Part> | &)
• Option Part: Dit deel laat toe de generatie van de applicatie af te stellen door
bepaalde opties op te geven.
• Attribute Part: Hier worden de types van de attributen gedefinieerd. Attri-
buten kunnen geassocieerd worden aan regels, input- en outputprimitieven.
• InputPrimitive Part: In dit deel worden de symbolen gedefinieerd die de ge-
genereerde applicatie als input zal aanvaarden (de terminalen).
• OutputPrimitive Part: Dit deel bevat de definitie van de symbolen die de
applicatie zal produceren in zijn output.
9
• Rule Part: Dit deel bevat de syntax-regels die de structuur van de input van
de applicatie vastleggen. De syntax-regels kunnen in de context van MIRA
gezien worden als kleine modules die elk hun eigen lokale informatie kunnen
hebben. De attributen worden gebruikt als communicatiemechanisme tussen
regels en ook tussen de stukken C++ code die regels kunnen bevatten (de
semantische acties).
• Parser Part: In dit deel staan de globale code en de data definities. Deze
definities kunnen gebruikt worden in elke regel. Bovendien kunnen de de-
fault routines om inputprimitieven te lezen of outputprimitieven te schrijven
herdefinieerd worden.
1.2 CDL en RCL
Gruyaert [2] ontwikkelde twee domein-afhankelijke specificatie-talen, de ene om de
omgeving van de robot te beschrijven, de andere om de robot aan te sturen.
1.2.1 Configuration Description Language
De omgeving van de robot wordt beschreven door CDL, de Configuration Description
Language. Een CDL-specificatie beschrijft een omgeving. Deze specificatie wordt
omgezet in een configuratie die gebruikt wordt door de controle-eenheid van de
robot. [2]
Zo’n beschrijving geeft minimaal de afmetingen van de werkruimte en de begin-
positie van de robot op. Verder kunnen de posities van obstakels en de doelpositie
van de robot vastgelegd worden.
Wij hebben geen CDL nodig, omdat het niet de bedoeling is dat de gebruiker
de omgeving beschrijft. Het is de robot die zelf door middel van zijn sensoren zijn
omgeving, meer bepaald de plaats van aanwezige obstakels, moet gaan ontdekken.
10
1.2.2 Robot Control Language
Gruyaert haalde zijn inspiratie voor de RCL taal bij Logo, een simpel maar krachtig
interactief systeem voor het uitvoeren van zogenaamde Turtle Graphics. Een turtle
is een kleine driehoekige wijzer die reageert op een aantal eenvoudige commando’s
zoals go, line en left. Logo is net als RCL een geınterpreteerde taal. De commando’s
worden ingelezen aan een prompt en direct uitgevoerd. Een dergelijke omgeving
waarin instructies onmiddellijk een actie van de turtle tot gevolg hebben, leent zich
uitstekend tot het op een speelse en directe manier aanleren van enkele basisprincipes
van het programmeren. [2]
De Robot Control Language is een erg intuıtieve taal voor de besturing van de
robot. Er zijn zogenaamde motion commands of bewegingscommando’s, controle-
statements (if-testen en voorwaardelijke en onvoorwaardelijke lussen), en elemen-
taire operaties op de drie datatypes int (gehele getallen), bool (booleaanse waarden)
en dir (richtingen). Een syntaxbeschrijving moet voldoende zijn om weer te geven
hoe de robot precies bestuurd kon worden.
<RCL input> = (<variable declaration> |
<statement> | <procedure declaration>) ";"
<variable declaration> = ("int" | "bool" | "dir")
(& | "[" "number" "]") "identifier"
<statement> = <simple statement>
| <conditional>
| <iteration>
| <procedure call - assignment>
<simple statement> = "go" (& | <expression>)
| "test" (& | <expression>)
| "turn"
11
| "flip"
<conditional> = "if" <expression> "then" <statement list>
<iteration> = "loop" <expression> "times" <statement list>
| "while" <expression> "repeat" <statement list>
<procedure call - assignment> = "identifier"
(<actual arguments> |
(& | "[" <expression> "]") "=" <expression>)
<statement list> = "[" <statement> (";" <statement>)* "]"
<actual arguments> = & | "("<expression> ("," <expression>)* ")"
<expression> = <comparison> (("and" | "or") <comparison>)*
<comparison> = <integer>
(("<" | "<=" | "==" | ">=" | ">" | "!=") <integer>)*
<integer> = <term> (( "+" | "-") <term>)*
<term> = <factor> (("*" | "/") <factor>)*
<factor> = "not" <factor>
| "-" <factor>
| "abs" <factor>
| "number"
| "true"
12
| "false"
| "left"
| "up"
| "right"
| "down"
| "("<expression>")"
| "identifier" ("[" <expression> "]" | &)
<procedure declaration> = "procedure" "identifier"
<formal arguments> <local variables> <body definition>
<formal arguments> = & | "("<variable declaration>
("," <variable declaration>)* ")"
<local variables> = & | "var" <variable declaration>
("," <variable declaration>)* ";"
<body definition> = "begin"
<statement> (";" <statement>)*
"end"
Bemerk de op het eerste zicht nogal merkwaardige definitie van <statement>:
procedure-calls en assignaties zijn gegroepeerd. Dit is nodig omdat beide soorten
statements met een identifier beginnen. We willen dat onze taal LL(1) is (voor het
gebruik van Visual MIRA), wat betekent dat het volgende inputsymbool voldoende
informatie bevat om te weten welke grammaticaregel(s) we moeten toepassen.
RCL kent drie verschillende datatypes: gehele getallen (int), booleaanse waarden
(bool) en richtingen (dir). Richtingen zijn left, up, right en down, en hebben dezelfde
betekenis als respectievelijk 0, 1, 2, 3 modulo 4. De richtingen worden absoluut
geınterpreteerd, dus niet ten opzichte van de richting van de robot. Om die reden
13
zou het misschien logischer geweest zijn windrichtingen (noord, oost, zuid, west) te
gebruiken om de richtingen aan te duiden, in plaats van de huidige benamingen up,
right, left en down.
De gebruiker kan zelf variabelen van een bepaald type declareren, maar kan ook
gebruik maken van een beperkt aantal systeemvariabelen. Deze geven toegang tot de
informatie omtrent de robot en zijn werkruimte. Ze kunnen niet door de gebruiker
gewijzigd worden en worden bij elke actie van de robot aangepast. In Gruyaert’s
Robot Control Language komen volgende gegevens voor als systeemvariabelen: de
afmetingen van de werkruimte (XW en YW), de positie van de robot (XR en YR),
de coordinaten van het doel (XT en YT), de orientatie van de robot (DIRECTION)
en het resultaat van de test-instructie (CONDITION), indien dit de vorige instructie
was.
Door deze syntaxbeschrijving samen met de gepaste semantische acties als input
aan Visual MIRA te geven, wordt een parser gegenereerd voor RCL. Dit is voor
de auteur van de user interface een C++ functie die als argument een string heeft
die een (al dan niet correcte) RCL instructie voorstelt, een object van de klasse
Robot en de ProgramState, die informatie over de toestand van het programma
bijhoudt. Die twee objecten zijn nodig omdat nogal wat informatie over verschillende
RCL instructies heen bewaard moet worden, zoals gebruikers- en systeemvariabelen.
Figuur 1.2 geeft weer hoe de twee onderdelen in [2] met elkaar samenwerkten in een
geheel.
1.3 Doel van deze thesis
Het is de bedoeling om de Robot Control Language te gebruiken voor de besturing
van een Lego Mindstorms robot in plaats van een virtuele ’turtle’ op het compu-
terscherm. Indien dit nodig blijkt, kan de taal uiteraard ook (in beperkte mate)
aangepast worden aan de nieuwe situatie.
We konden vooraf al voorspellen dat de grootste problemen zouden ontstaan uit
de belangrijkste beperkingen van de Lego robot: infrarood communicatie tussen host
14
Figuur 1.2: De interactie tussen CDL en RCL
en robot vereist visueel contact, de motoren kunnen niet nauwkeurig genoeg afgesteld
worden, en er kunnen slechts drie motoren en drie sensoren gebruikt worden.
1.4 LL(1)-talen voor robotsturing
In Teach your Robot an LL(1)-Jargon [4] wordt beschreven hoe we een domein-
specifieke taal kunnen ontwerpen voor een robot. Met het aanleren van een LL(1)-
Jargon aan een robot bedoelt men het specifieren van een taalprocessor die instruc-
ties voor de robot omzet in machinecode voor die robot. Daarbij kunnen we gebruik
maken van syntaxgestuurde ontwikkeling. Hieronder verstaat men een methode voor
software-ontwikkeling waarbij de syntax van de invoer van de applicatie een centrale
rol speelt: de syntax vormt een kader waaraan semantische acties, attributen en lo-
kale en globale informatie kan opgehangen worden. We kunnen voor de beschrijving
van de taal het ELL(1) formaat gebruiken, in combinatie met Visual MIRA.
Met een jargon bedoelt men een gemakkelijk te ontwikkelen domein-specifieke
15
taal, die kan aangemaakt worden door domein-ingenieurs die zelf geen taalexperten
zijn. De praktijk heeft aangetoond dat voor hen LL(1)-specificaties gemakkelijk te
hanteren zijn. Het jargon dat we willen beschrijven hangt af van de omgeving van
de robot en van de opdrachten die hij zal moeten uitvoeren. We moeten het jargon
definieren alvorens we overgaan tot het schrijven van de taalprocessor, zo stelt [4].
De tekst somt een aantal voordelen op van het syntaxgestuurd ontwikkelen van
een LL(1)-jargon met de hulp van een tool als Visual MIRA:
• De implementatie van het jargon hangt vooral af van de syntaxbeschrijving,
wat aanpassingen aan structurele veranderingen in de omgeving vergemakke-
lijkt.
• Er is een hoog niveau van abstractie, wat zorgt voor een overzichtelijke en
goed leesbare code.
• Het automatisch genereren van de parser verkleint de kans op fouten.
• Het aanbrengen van wijzigingen aan de syntax is erg eenvoudig, en de taal is
gemakkelijk uitbreidbaar.
• Overschakelen naar een ander platform is eenvoudig.
Tijdens mijn realisaties heb ik kunnen vaststellen dat deze voordelen stuk voor
stuk aanwezig zijn. Ik kon inderdaad gemakkelijk reageren op de veranderde omge-
ving, de code die ik overnam uit [2] had ik snel onder de knie, ik had zelden met
bugs te kampen, een kleine toevoeging aan de syntax was in een oogwenk geklaard,
en de overschakeling van een Windows- naar een Linux-platform gaf geen noemens-
waardige problemen. Op elk van deze punten ga ik in de volgende hoofdstukken
dieper in.
De semantische acties die in [4] gebruikt worden bij de syntax-gestuurde ont-
wikkeling van de domein-specifieke RCL taal, zijn objectgeorienteerde C++ functie-
aanroepen, die een parserboom opbouwen. Bij de evaluatie van die boom worden
methodes uit de klasse Robot aangeroepen, waarvan de implementatie specifiek is
16
voor de robot die we ons jargon willen leren. Het gebruik van dit interface-paradigma
vergemakkelijkt de overstap van de ene robot naar de andere: het volstaat de im-
plementatie van de methodes uit die klasse aan te passen aan de nieuwe robot. Dit
paradigma heb ik zelf ook nog eens doorgetrokken op een ander niveau, door in de
eigenlijke code een bestand op te roepen waarin dan precies vastgelegd wordt hoe de
robot zijn bewegingen uitvoert. Het uitgangspunt van mijn werk was een voorstel
in de tekst voor een aanpassing van de RCL omgeving voor de Lego Mindstorms
robot. Binnen de klasse Robot moet hierbij in de eerste plaats een nieuwe methode
moveto(dir) geımplementeerd worden. Deze functie zou dan NQC code genereren,
afhankelijk van de opgegeven richting, en deze dan op de robot laten uitvoeren. De
andere functies in de klasse moeten dan indien nodig ook aangepast worden door
gebruik te maken van deze moveto functie. Voor elke beweging die de robot moet
doen, wordt dus een klein programma naar de robot gestuurd, die dat dan uitvoert.
Om het probleem van visueel contact voor de infrarood verbinding op te lossen,
werd er voor gezorgd dat na elke beweging de robot terug in dezelfde richting keek.
Dit kan door in het begin in de juiste richting te draaien, vooruit te rijden, en tot
slot in de omgekeerde richting te draaien. Figuur 1.3 geeft schematisch weer hoe het
geheel dan zou moeten werken.
inputstring tokenstringScanner Parser
PC Robot
Communicatie
Figuur 1.3: RCL voor Lego Mindstorms
17
Hoofdstuk 2
Lego Mindstorms
2.1 Het Mindstorms pakket
De essentiele onderdelen van de Mindstorms omgeving kunnen we opsplitsen in drie
delen: de zogenaamde RCX programmable brick, een infrarood zender en ontvanger
en een PC.
De kern van de robot is de RCX programmable brick (vanaf nu spreken we van
het RCX blok of kortweg de RCX). Dit is een blok waarop bovenaan en onder-
aan legoblokken kunnen bevestigd worden om zo een robot te kunnen bouwen uit
legoblokken. Binnenin zit de kern van de robot: een Hitachi H8 processor, die
32kB extern RAM-geheugen heeft. Daarnaast bevat de RCX een infrarood zender-
ontvanger, een LCD scherm om informatie te tonen en elektronica voor de invoer-
signalen (3 sensoren) en uitvoersignalen (3 motoren). Verder vinden we nog een
16kB ROM-geheugen dat als driver gebruikt wordt bij het opstarten van de robot.
Samen met de firmware, die zich in het RAM-geheugen bevindt, voert dit geheu-
gen instructies uit die verstuurd worden vanaf de PC. Bij de standaardomgeving die
Lego bij het RIS-pakket (Robot Invention System) levert, is de firmware 16kB groot.
Gebruikersprogramma’s kunnen in een deel van het geheugen dat 6 kB groot is als
bytecode bewaard worden en uitgevoerd worden wanneer daarom wordt gevraagd.
De infrarood zender-ontvanger, ook wel de toren genoemd, heeft twee modes
18
voor het zenden: short range en long range. Het onderscheid is zeer belangrijk,
zoals we later zullen merken. De gebruiker kan kiezen tussen de twee modes met
behulp van een schakelaar op de toren. De infrarood component van de RCX kent
hetzelfde onderscheid, maar daar is geen schakelaar. Wel kan in de meeste program-
meeromgevingen via een instructie bepaald worden in welke mode we werken. De
toren wordt met de PC verbonden via een kabel die op de seriele poort aangesloten
wordt.
In november 1998 slaagde Kekoa Proudfoot [7] erin het seriele protocol tussen de
PC en de RCX te ontcijferen. Daarmee ging een nieuwe wereld open voor de Mind-
storms wereld: verschillende groepen slaagden erin alternatieven te creeren voor de
bestaande firmware die Lego leverde en uiteindelijk toch nogal wat beperkingen had
voor mensen met een minimum aan programmeerervaring.
2.2 Programmeeromgevingen voor de RCX
We kunnen nu een kort overzicht geven van de verschillende mogelijkheden om pro-
gramma’s te schrijven voor de RCX.
2.2.1 RCX
De standaardtaal die Lego zelf levert bij het Mindstorms pakket, en wordt geınter-
preteerd door een door Lego ontwikkelde interpreter die loopt op de RCX processor,
wordt zelf ook RCX genoemd.
Deze taal is vooral gericht naar kinderen van een jaar of twaalf die de wereld
van robots willen leren kennen. Lego levert voor hen een visuele programmeer-
omgeving bij het RIS-pakket. Sterke punten zijn de eenvoud, de mogelijkheid om
visueel te programmeren en de voorzieningen voor multithreading. Zwakheden zijn
het beperkt aantal variabelen en de afwezigheid van procedures.
19
2.2.2 NQC
Dave Baum [8] ontwikkelde een eenvoudige programmeertaal die de mogelijkheden
overhoudt van de vorige taal, maar toch wat meer lijkt op een klassieke program-
meertaal als C, vandaar de naam Not Quite C. Procedures zijn hier wel toegelaten.
De code wordt vertaald naar RCX commando’s, zodat de instellingen van de RCX
niet moeten veranderd worden. Programma’s zijn meestal kort en eenvoudig. NQC
is vrij beschikbaar onder de Mozilla Public License, en wordt gebruikt onder Win32,
Macintosh, Mac OS X en Linux.
De grote zwakte van NQC is dat het slechts een beperkt aantal variabelen toe-
laat (32 om precies te zijn). Daardoor wordt het moeilijker bruikbaar voor grote,
complexere toepassingen. Men kan wel gebruik maken van een veel grotere datalog,
een geheugenruimte waar een NQC-programma gegevens kan naar wegschrijven, en
die later door de host computer kan opgevraagd worden. Jammer genoeg kan de
RCX zelf de datalog niet raadplegen.
Het is nodig om het ook even te hebben over de communicatie van de host compu-
ter met de robot onder NQC. We moeten dit zien als een client-server architectuur,
niet als een peer-to-peer communicatie. We hebben dus niet met twee ’gelijken’ te
maken, die om het even wanneer het initiatief kunnen nemen om een communicatie
op te starten. In het NQC model, opgedrongen door de firmware die Lego levert,
kan enkel de host computer (in dit geval de client) het initiatief nemen om de com-
municatie te beginnen. Dit is bijvoorbeeld het doorsturen van een programma dat
moet uitgevoerd worden, of het opvragen van de datalog. Het is dan aan de RCX,
de server dus, om het verzoek van de client te beantwoorden. Indien de opdracht
een programma was, moet de robot dit uitvoeren maar geen antwoord terugsturen;
indien het het opvragen van de datalog was, wordt er wel een echt antwoord terug-
gestuurd naar de PC. Doordat de infra-rood toren automatisch uitgeschakeld wordt
na enkele seconden inactief zijn, kan de robot niet zelf het initiatief nemen om een
of ander bericht naar de PC te sturen.
20
2.2.3 LegOS
LegOS [9] is een open source besturingssysteem voor de RCX. De kernel vervangt de
oorspronkelijke firmware die Lego zelf voorziet. In LegOS is er wel toegang tot het
beschikbare RAM-geheugen mogelijk en die wordt enkel beperkt door de grootte van
het geheugen. Enkele bibliotheken implementeren de instructies voor de aansturing
van de motoren en het lezen van de gegevens van de sensoren. Programma’s worden
geschreven in C of C++ en gecompileerd met de GNU C compiler, die eerst moet
geconfigureerd worden als cross-compiler1 voor de Hitachi H8 processor. Ook het
besturingssysteem zelf is in C geschreven, en gecompileerd met de GNU C compiler.
De ontwikkeling gebeurde onder Linux, maar legOS zou ook bruikbaar moeten zijn
op alle platformen waarvoor de GNU C compiler beschikbaar is, dus de meeste
Unix-varianten en de Windows-omgeving.
Naast het feit dat de programmeur nu gebruik kan maken van al het beschikbare
geheugen, en in een vertrouwde taal kan programmeren, biedt LegOS nog enkele
voordelen. Zo is multithreading met al zijn aspecten geımplementeerd, en kan de
hardware, bijvoorbeeld het LCD scherm, rechtstreeks aangesproken worden. Er is
het LegOS Network Protocol, dat communicatie mogelijk maakt tussen de RCX en
de host-computer, of zelfs tussen verschillende robots en host-computers. Nadelig
is dat het besturingssysteem ongeveer de helft van het geheugen inneemt, weliswaar
afhankelijk van welke functionaliteiten aanwezig moeten zijn (de voorzieningen voor
geluid kunnen bijvoorbeeld gemakkelijk weggelaten worden bij de installatie). Bo-
vendien is het project op dit ogenblik nog in beta-fase, wat betekent dat het nog
een aantal bugs kan bevatten.
2.2.4 TinyVM
TinyVM [10] is een open source project dat een (beperkte) virtuele Java-machine
bovenop de Hitachi processor implementeert. Het sterke punt is zijn kleine om-
1Een cross-compiler is een compiler die code genereert voor een andere machine dan die waar
de compiler zelf op draait.
21
vang: minder dan 10kB! Bovendien worden de class-files die de programmeur aan-
maakt, nog eens sterk gecomprimeerd. De meeste functionaliteiten van Java worden
geımplementeerd, behalve garbage collection, het gebruik van floating point getallen,
en het gebruik van switch statements. Constante strings worden bovendien gene-
geerd. Ook is slechts een beperkt deel van de standaard Java API geımplementeerd.
Dit alles is natuurlijk een serieuze beperking.
2.2.5 LeJOS
LeJOS [11] is een oplossing voor de beperkingen van TinyVM: het is een meer
volledige virtuele Java-machine, die bijvoorbeeld wel floating point getallen toelaat.
Resultaat is wel dat de grootte onmiddellijk enorm toeneemt. De huidige versie
heeft 17k nodig van de 28k die effectief voor de gebruiker beschikbaar zijn. LeJOS
is op dit ogenblik nog in volle ontwikkeling; zo moet in de nabije toekomst onder
andere nog garbage collection geımplementeerd worden.
2.2.6 Andere
Verder zijn er nog een aantal alternatieve programmeertalen in gebruik of in ontwik-
keling, waaronder pbFORTH en SmallTalk, maar daar ben ik niet diep op ingegaan.
Aangezien er maar weinig over te vinden is, veronderstel ik dat rond deze omge-
vingen niet echt veel gebeurt.
2.2.7 De keuze
Mijn keuze viel uiteindelijk op NQC, in de eerste plaats omwille van zijn eenvoud.
Wie enkele van de talloze voorbeelden op het net bekijkt, zal vaststellen dat op-
drachten die in vele gevallen erg ingewikkeld lijken, dikwijls in bijzonder compacte
en toch nog leesbare code kan gerealiseerd worden. Bovendien was NQC in het be-
gin van het academiejaar het enige platform dat kon gevonden worden dat al een
volledig werkbare, (zo goed als) foutvrije versie kon bieden.
22
2.3 Lego Mindstorms als educatief hulpmiddel
De RCX is al meermaals gebruikt voor educatieve doeleinden, vooral in informatica-
klassen. Zo wordt in [6] beschreven hoe men de robot kan gebruiken om studen-
ten aan te leren meer vooraf te plannen en te ontwerpen, dit in plaats van in het
wilde weg iets uit te proberen en te verbeteren, zoals veel beginnende informatica-
studenten gemakkelijk geneigd zijn te doen.
Indien het lukt de Lego Mindstorms robot op een handige manier te laten be-
sturen via de RCL taal, kan hij ook voor jongere studenten als educatief project
gebruikt worden. Een eenvoudige domein-specifieke taal als RCL is wellicht zeer
goed geschikt om studenten uit het secundair onderwijs te laten kennismaken met
de basisprincipes van programmeren en met de wereld van de robotica.
2.4 Bouw van de gebruikte robot
In de handleiding die bij het Mindstorms pakket zit, wordt een robuuste robot
beschreven, die goed geschikt is om rond te rijden in een omgeving zonder al te
moeilijke hindernissen. Hij wordt aangestuurd door twee motoren, die elk twee wie-
len aandrijven. De robot is zodanig gebouwd dat er makkelijk een of twee bumpers
en een lichtsensor op kunnen aangesloten worden. In de eerste versie was er enkel
een bumper nodig.
23
Hoofdstuk 3
Realistatie van de RCL
3.1 Bereik van de IR zender
Alvorens de methode te volgen die A.Hoogewijs, H.Gruyaert en G.Vernaeve voorstel-
len in het artikel Teach your robot an LL(1)-jargon, dienen we ons er van te gewissen
dat de robot op om het even welke plaats in de te gebruiken ruimte de infra-rood
signalen (meer bepaald mini-programma’s die een atomaire beweging uitvoeren) kan
ontvangen indien de robot voldoende goed gericht staat. Indien dit niet het geval
is, zal een totaal andere aanpak gevolgd moeten worden. Lego zelf beweert in de
Users Guide dat er visueel contact nodig is, en dat de afstand tot zo’n 30 meter mag
oplopen, hoewel de ideale afstand voor het laden van programma’s 10 tot 12 cm is.
Om een beeld te krijgen van de posities waar signalen ontvangen worden, schreef
ik een programma dat zelf zo een beeld uittekent. Het is zodanig geschreven dat
de afmetingen van het rooster gemakkelijk kunnen aangepast worden. Eerst creeert
het programma (geschreven in C) een NQC-programma dat op de robot zal lopen.
De robot gaat op alle plaatsen van het rooster staan, en op elke plaats wacht hij
twee seconden om te zien of hij signalen ontvangt van de IR toren. Als dat zo is,
dan onthoudt hij deze plaats. Op het einde keert hij terug naar de oorspronkelijke
plaats (verondersteld wordt dat dit recht tegenover de toren is) waar hij uiteindelijk
zijn datalog met succesvolle plaatsen doorstuurt naar de host computer. Het C-
24
programma zelf is ondertussen verder gegaan. Het schat de tijd die de robot zal
doen over de hele cyclus, en gedurende die tijd zendt het elke seconde een signaal
naar de robot, die zelf moet kijken of hij dit ontvangt. Wanneer de tijd is afgelopen,
downloadt het programma de daarnet vermelde datalog en gebruikt deze informatie
om de resultaten visueel voor te stellen.
De eerste tests vielen zwaar tegen. Figuur 3.1 toont bijvoorbeeld een situatie
van een 12x10 rooster, met een onderlinge afstand van een tiental centimeter tussen
de meetpunten.
Figuur 3.1: De ontvangst in short range mode
Merk vooral op dat het beeld helemaal niet symmetrisch is. Verder is ook de
afstand teleurstellend, en vooral de hoek waaronder de robot niets meer ontvangt.
Een eerste zware ontgoocheling dus, maar kort nadien las ik in de NQC handlei-
ding dat er een optie -far was die er voor moet zorgen dat er in long range mode
gewerkt wordt. Toen wist ik wel al dat de IR unit van de RCX brick onderscheid
maakte tussen short range en long range, maar blijkbaar gold dit ook voor de to-
ren. Hoopvol probeerde ik hetzelfde, maar dan met de -far optie voor het continu
sturen van boodschappen. De resultaten vielen opnieuw zwaar tegen: bijna identiek
25
hetzelfde resultaat! Figuur 3.2 toont bijvoorbeeld het beeld van een 8x8 rooster met
onderlinge afstand van ongeveer vijftien centimeter.
Figuur 3.2: De ontvangst met de -far optie
Gelukkig had ik de dag voordien op een website [12] gelezen dat er op de IR
toren een schakelaar moest zijn die er voor zorgt dat je kan kiezen tussen short en
long range. Links is short, rechts is long. Deze informatie staat uiteraard ook in de
Users Guide, maar die had ik toen nog niet grondig bekeken. Toen ik de schakelaar
naar rechts had geplaatst en precies hetzelfde programma had uitgevoerd, kreeg ik
de resultaten die weergegeven zijn in figuur 3.3. Ze zijn niet te vergelijken: op elke
plaats is er nu ontvangst! Een uitstekend resultaat, vooral omdat er blijkbaar ook
geen enkel probleem is wat de hoek betreft. Bovenaan in het midden kijkt de robot
naar de toren, maar links en rechts bovenaan kijkt de robot eigenlijk naast de toren;
de hoek tussen de IR transmitters bedraagt net geen 180 graden.
Ik begon mij hierdoor af te vragen wat er zou gebeuren als ik de robot net buiten
het visueel bereik van de toren zou plaatsen (erachter dus). Tot mijn grote verbazing
bleek de robot ook daar alles te ontvangen! Toch ga ik er van uit dat enkel bij visueel
contact de communicatie betrouwbaar genoeg is om te mogen veronderstellen dat
instructies met zekerheid ontvangen zullen worden. Daarom kies ik er voor om de
aanpak uit [4] te blijven volgen. Concreet betekent dit dat elke beweging er voor zal
26
Figuur 3.3: De ontvangst met de zender in long range mode
zorgen dat de robot op het einde toch in de oorspronkelijke richting staat. Een turn
of een flip instructie zal dan geen zichtbaar effect hebben, enkel de ProgramState
wordt aangepast.
3.2 Implementatie
3.2.1 Origineel voorstel
In [4] wordt, zoals eerder al vermeld, voorgesteld om de robot telkens in dezelfde
richting te laten kijken om zo het IR probleem aan te pakken. Wanneer de robot
een vakje naar links wil, zal hij dus niet enkel naar links draaien en vooruit gaan,
maar ook terug naar rechts draaien om de richting te behouden.
Bij dit voorstel worden volgens mij twee belangrijke dingen over het hoofd gezien:
• Het is niet de bedoeling dat de robot achter de IR toren terechtkomt. Daarom
maakt mijn implementatie gebruik van een soort virtuele muur. Bij de initi-
alisatie krijgt de robot de coordinaten (0, 0) mee, wat betekent dat de robot
vlak voor de toren staat (we veronderstellen dus dat de gebruiker de robot
daar gezet heeft). Wanneer de Y-coordinaat positief wordt, kunnen we er dus
27
vanuit gaan dat de robot zich niet meer in het gezichtsveld van de toren zal
bevinden. De oplossing is dus erg eenvoudig: als moveto wordt aangeroepen,
en de robot bevindt zich op een positie met Y-coordinaat 0 en wil vooruit
gaan, dan zullen we dit verhinderen door te doen alsof de robot op een muur
gebotst is.
• Er werd ook geen rekening gehouden met mogelijke obstakels. Kennelijk was
het de bedoeling een tweede functie te implementeren die de testopdrachten
zou realiseren. Toch blijft er dan een probleem: wanneer de robot een obstakel
tegenkomt, blijft hij een zekere tijd verder rijden, waardoor hij gedesorienteerd
kan raken. Een betere oplossing is daarom de twee functies te integreren:
moveto doet de robot naar de opgegeven richting rijden totdat de tijd die
met een vakje overeenkomt overschreden is of tot de bumper een obstakel
detecteert. In dat geval keert hij naar zijn oorspronkelijke plaats terug, en
rapporteert via de datalog de faling aan de PC. De moveto heeft dus altijd
een booleaans resultaat, die in een go opdracht genegeerd wordt, maar waar
in een test opdracht wel rekening mee gehouden wordt. Hierdoor is nog een
aanpassing nodig: bij een go down (achteruit dus), kan de robot niet achteruit
rijden omdat hij daar geen bumper heeft. Hij moet dus 180 graden draaien,
vooruit gaan, en opnieuw 180 graden draaien.
3.2.2 Aanpassing van de Robot klasse
Omdat er niet langer gebruik gemaakt wordt van CDL om de configuratie van de we-
reld van de robot op te geven, maar de robot zelf zijn omgeving gaat aftasten, is het
gebruik van een Workspace, die aanwezig was in de implementatie van [2] overbodig
geworden. Alle verwijzingen ernaar kunnen dus verwijderd worden, waardoor enkele
functies uit de klasse Robot totaal overbodig zijn geworden en dus ook verwijderd
mogen worden.
Om eventuele aanpassingen te vergemakkelijken stopte ik de code die recht-
streeks voor de interactie met de robot zorgt, in een private functie moveto(dir).
28
Die genereert een klein NQC programma dat een atomaire instructie uitvoert: de
robot verplaatst zichzelf hoogstens een coordinaat naar voor, achter, links of rechts,
afhankelijk van de parameter van de functie. Indien de bumper tijdens deze be-
weging ingedrukt raakt, zal de robot naar zijn oorspronkelijke plaats terugkeren.
In de datalog wordt opgeslagen of de beweging al dan niet gelukt is. Aan de kant
van de gebruiker wordt ondertussen voldoende lang gewacht, tot het programma
zeker beeindigd is. Vervolgens wordt de datalog opgevraagd om het resultaat van
de beweging te kennen. De moveto functie wordt aangeroepen vanuit de go en test
functies.
Voor de geınteresseerden geven we nu de inhoud van de moveto functie.
bool Robot::moveto(int dir) {
FILE *program, *datalog;
char line[80];
bool res;
program = fopen("gridmove.nqc", "w");
fprintf(program, "#include \"roverbot.h\"\n\n");
fprintf(program, "task main() {\n int afstand;\n initmotors();\n"
" SetSensor(SENSOR_1,SENSOR_TOUCH);\n afstand = 0;\n");
switch(dir) {
case R: fprintf(program, " right(90);\n"); break;
case D: fprintf(program, " right(180);\n"); break;
case L: fprintf(program, " left(90);\n"); break;
default: break;
}
fprintf(program, " Wait(%d);\n", RELAXTIME);
fprintf(program, " CreateDatalog(1);\n"
29
" if (afstand < %d) AddToDatalog(0);\n"
" else AddToDatalog(1);\n}\n", GRIDTIME);
fclose(program);
system("nqc -d gridmove.nqc -run");
sleep(4);
datalog = popen("nqc -datalog", "r");
if (fgets(line,sizeof(line),datalog)) {
if (strstr(line, "No reply")) res = false;
else
if (atoi(line) == 0) res = false;
else res = true;
}
else res = false;
pclose(datalog);
return res;
}
3.2.3 Integratie in de scanner/parser
Omdat ik mijn pogingen op een Linux-machine uitvoerde, bestond het risico dat
de door Visual MIRA gegenereerde C++ code niet helemaal compatibel zou zijn.
Inderdaad, enkele kleine wijzigingen waren nodig. Eerst en vooral bleek Gruyaerts
implementatie van een geschakelde lijst met templates niet helemaal ANSI C++
compatibel. Een kleine aanpassing volstond om dit euvel weg te werken. Het grote
gevaar zat hem natuurlijk in de code die door Visual MIRA werd gegenereerd.
Groot was mijn opluchting wanneer ik zag dat de fouten die bovenkwamen allemaal
30
afkomstig waren uit de broncode voor Visual MIRA en dus niet uit wat MIRA zelf
genereerde.
Ten eerste gebruikte Gruyaert een functie strupr die een string kon converteren
naar uppercase; dit is echter geen standaard ANSI functie, maar blijkbaar een functie
die door de gebruikte compiler (Borland) aan een van de standaardbibliotheken is
toegevoegd. Dit veranderen was uiteraard heel eenvoudig.
Een tweede probleem was dat Gruyaert een globale veranderlijke _init ge-
bruikte. Dit zorgde voor enkele onduidelijke linker errors. Kort opzoekingswerk
leerde me dat het gebruik van variabelen die beginnen met underscore sterk afge-
raden wordt, omdat veel compilers zelf dit soort variabelen gaan definieren. En
inderdaad, _init vervangen door my_init volstond om dit probleem op te lossen.
Hiermee waren alle errors verdwenen, en de overgebleven warnings gaven ook
geen problemen meer. Het enige wat er nu nog moest gedaan worden was een test-
programma schrijven om te kijken of er inderdaad instructies konden doorgestuurd
worden. Het volstaat hierbij om de functie RCLParser aan te roepen met de gepaste
argumenten. Alles bleek te werken zoals ik het wou, waarmee een eerste belangrijke
stap gezet was. Uiteraard waren er nog flink wat tekortkomingen waar een oplossing
voor moest gezocht worden.
3.3 Evaluatie
3.3.1 Eenvoud
Het sterke punt van deze implementatie is de eenvoud: de aanpassingen die nodig
waren om tot deze implementatie te komen, vertrekkende van het RCL gedeelte van
Gruyaert, waren zeer beperkt. Latere uitbreidingen van de taal zouden ook geen al
te grote veranderingen in de code mogen teweeg brengen.
Merk ook op dat er slechts een functie is in de hele klasse Robot die de ro-
bot rechtsteeks aanstuurt en bovendien nog private is. Ook dit zorgt er voor dat
toekomstige aanpassingen beperkt zullen blijven in omvang.
31
De oorzaak van deze eenvoud ligt in het gebruik van objectgeorienteerd ontwerp,
gecombineerd met de geschiktheid van LL(1)-talen in een CASE-tool als Visual
MIRA.
3.3.2 Traagheid
Een nadeel van deze implementatie, waarbij elke atomaire beweging volledig afzon-
derlijk wordt uitgevoerd, is de traagheid. Elke beweging moet immers doorgestuurd
worden, vervolgens moet het programma wachten tot de beweging beeindigd is, en
tot slot moet het het resultaat opvragen en interpreteren.
3.3.3 Vreemde effecten
Enkele voorbeelden illustreren het bestaan van een tweetal vervelende neveneffecten.
Het eerste kunnen we omschrijven als het ’Echternach-effect’: wanneer we bijvoor-
beeld vooruit willen gaan, zullen we gewoonlijk eerst testen of die plaats wel vrij
is, en pas als dat zo is kunnen we ook effectief naar voor gaan. Stel dat de plaats
inderdaad vrij is. In dat geval zal de robot eerst vooruit bewegen om te kijken of die
plaats vrij is en vervolgens terugkeren naar zijn oorspronkelijke positie. Dan wordt
het resultaat doorgestuurd en op basis daarvan wordt er beslist om terug vooruit te
gaan. Er zijn dus drie bewegingen nodig om op een betrouwbare manier een plaats
vooruit te gaan.
Een tweede neveneffect is het probleem van de richtingen. De klasse Robot houdt
de richting bij naar waar hij gedraaid is. Dit is een overblijfsel van de originele code,
waarin de robot in om het even welke richting gedraaid kan staan. In ons geval staat
de robot echter telkens in dezelfde richting gekeerd. Het resultaat is dat de robot
kan denken dat hij naar rechts gedraaid staat, terwijl de gebruiker hem vooruit ziet
kijken. Het resultaat is natuurlijk een grote verwarring.
Beide fenomenen zijn het gevolg van enkele essentiele verschillen tussen de vir-
tuele robot van Gruyaert en onze Mindstorms robot, die nogal wat beperkingen
heeft.
32
Wat het eerste geval betreft, is het zo dat de virtuele robot zonder te bewegen
langs alle vier de zijden kon detecteren of hij naast een obstakel stond. De omgeving
werd immers gewoon voorgesteld door een matrix, waarvan elk element weergaf of er
al dan niet een obstakel aanwezig was. Het aftasten betekende dus het controleren
van een element binnen die matrix. De Mindstorms robot werkt op een volkomen
andere manier. Ik heb er voor gekozen om zijn leefwereld niet te beperken tot een
statische omgeving, wat wel het geval was bij de virtuele robot. Indien ik dit wel
had gedaan, kon ik de robot laten onthouden op welke plaatsen er een obstakel
aanwezig is. In mijn model daarentegen gaat de robot er van uit dat de omgeving
door externe factoren kan veranderen. Hierdoor is hij verplicht bij elke beweging
te kijken of zijn bumper al dan niet ingedrukt wordt. Daardoor is voor elke test-
instructie ook effectief een beweging nodig.
Zoals ik daarnet al vermeld heb, is het tweede probleem het gevolg van het feit
dat de robot nu omwille van de IR beperking telkens naar dezelfde richting gedraaid
staat bij het beeindigen van een instructie, terwijl de virtuele robot naar om het
even waar gedraaid kon staan.
3.3.4 Onzuivere richting
Na een aantal draaibewegingen zal het duidelijk worden dat de robot ernstige afwij-
kingen begint te vertonen. Een eerste oorzaak is het feit dat ’rechtdoor’ niet altijd
perfect rechtdoor is, omdat de kracht van de twee motoren niet mooi gelijk blijkt te
zijn, en omdat een ondergrond die niet perfect egaal is ook voor afwijkingen zorgt.
Bovendien is het moeilijk om een draaibeweging mooi over 90 graden te doen ver-
lopen. Dit gebeurt gewoon op basis van een experimenteel vastgelegde tijd, terwijl
de hoek in de praktijk niet enkel afhankelijk blijkt te zijn van een tijdsduur, maar
ook van de grip die de wielen ondervinden op het oppervlak en zelfs van de kracht
die de batterijen nog hebben.
Bernd Frassek verwoordt het als volgt in een discussie op LUGnet1: ”Het grote
1www.LUGnet.com is de website van de Lego Users Group, die onder andere tientallen discus-
33
probleem is nauwkeurigheid. Om dit te begrijpen moet men met enkele basisprinci-
pes rekening houden: laat de robot voor ongeveer 2 meter RECHT vooruit rijden;
laat hem terug achteruit rijden tot precies op het startpunt; laat de robot 360 graden
draaien, en als dat lukt, laat hem acht keer 90 graden draaien. Dit lijken triviale
en domme opdrachten, maar probeer ze! Ik heb het geprobeerd, en dit is het re-
sultaat: de bovenstaande opdrachten zijn niet op te lossen, althans niet nauwkeurig
genoeg. Er is te veel speling op de motoren. Ook het contact met de ondergrond is
belangrijk.”
Het is duidelijk dat we op zoek zullen moeten gaan naar een meer intelligente
oplossing om dit moeilijke, maar erg belangrijke probleem op te lossen. Wanneer we
niet kunnen garanderen dat de robot na een vijftal bewegingen staat op de plaats
waar we hem willen, kunnen we moeilijk van een bruikbare robot spreken.
siegroepen bevat over allerlei Lego-onderwerpen, zoals de treinen, piraten, en dus ook de robots
die Lego verkoopt
34
Hoofdstuk 4
Verbeteringen
Het is uiteraard de bedoeling om de vastgestelde problemen aan te pakken en uitein-
delijk tot een goed werkende robot te komen, die ook voor praktische, bijvoorbeeld
educatieve, doeleinden kan gebruikt worden.
Het probleem van de trage bewegingen zou kunnen opgelost worden door niet
elke beweging afzonderlijk door te sturen, maar door een volledige RCL-instructie
in zijn geheel door te sturen. Dit zou kunnen neerkomen op een poging om zo een
instructie te vertalen naar een NQC programma. Hierbij komen echter een aantal
nieuwe problemen kijken. Aangezien de uitvoeringssnelheid niet prioritair is, heb
ik ervoor gekozen hier niet verder op in te gaan. In 5.1 kom ik nog terug op dit
probleem: ik zal er enkele voorstellen doen die voor een aanzienlijke verhoging van
de uitvoeringssnelheid moeten kunnen zorgen.
Het tweede probleem is het verschil tussen de virtuele robot en onze robot. De
enige manier om dit op te lossen, is de RCL taal aan te passen aan de nieuwe
omgeving door een aantal instructies te verwijderen, eventueel enkele andere toe
te voegen, en indien nodig de semantiek van bestaande instructies te wijzigen. Zo
zijn de TURN en FLIP instructies overbodig geworden omdat onze robot altijd in
dezelfde richting zal staan. Een GO instructie moet volgens mij ook de systeemva-
riabele CONDITION kunnen aanpassen zodat de instructie kan gevolgd worden door
een voorwaardelijke instructie. Verder ben ik het niet eens met de keuze van de
35
benaming van de richtingen: waar Gruyaert spreekt van UP, RIGHT, DOWN, LEFT be-
doelt hij eigenlijk NORTH, EAST, SOUTH en WEST. Doordat de robot altijd in dezelfde
richting (NORTH) kijkt, kunnen LEFT en RIGHT behouden blijven, maar UP en DOWN
kunnen volgens mij beter vervangen worden door FORWARD en BACK. Toch lijkt het
mij geen slecht idee om ook de windrichtingen toe te voegen aan de taal.
Het probleem van de onzuiverheid van de richting moet ook aangepakt worden.
Het is duidelijk dat we extra sensoren zullen moeten toevoegen, om zo de robot toe
te laten op een of andere manier een zicht te geven op zijn wereld. Wanneer we een
persoon zouden blinddoeken en er voor zorgen dat hij geen enkel omgevingsgeluid
meer hoort, en hem dan vragen om 2 meter vooruit te stappen en 90 graden naar
links te draaien, en dat vier keer te herhalen, is het twijfelachtig dat hij op zijn
startpunt zal uitkomen. Iemand met zicht op de omgeving heeft meer kans op
slagen omdat hij zijn zintuigen ten volle kan gebruiken. Zo is het ook met onze
robot: hij zal bijkomende zintuigen nodig hebben die hem toelaten zijn omgeving
op een zinnige manier te interpreteren.
4.1 Aanpassing van de taal
Gruyaert merkte in zijn thesis op dat het gebruik van LL(1)-talen met een CASE-tool
als Visual MIRA aanpassingen aan de taal een stuk gemakkelijker maakt. Dit kon ik
aan den lijve ondervinden: het denk- en zoekwerk over welke de juiste syntactische
en semantische wijzigingen waren, was veel moeilijker en duurde veel langer dan de
realisatie van die wijzigingen in de broncode (de code van scanner en parser voor
Visual MIRA en de C++ code die erbij hoort).
4.1.1 Richtingen
De voorgestelde aanpassingen aan de verschillende richtingen (toevoegen van de
windrichtingen en wijziging van UP in FORWARD en DOWN in BACK) was bijzonder
eenvoudig. Het volstaat immers om in de scanner een soort van vertaling in te
36
bouwen, wat in Visual MIRA bijzonder eenvoudig blijkt: de string NORTH in de
broncode wordt vertaald naar het token UP in de parser, waardoor die op geen enkele
plaats meer moet aangepast worden. De enige wijziging zit dus in de MIRA-code
van de scanner.
Deze techniek kan ook gebruikt worden om dezelfde parser te gebruiken voor
een gelijkaardige taal met andere sleutelwoorden. Het zou bijvoorbeeld kunnen dat
we een gelijkaardige RCL willen hebben, maar dan met Nederlandse woorden in
plaats van Engelse, bijvoorbeeld omdat we nederlandstalige kinderen willen laten
kennismaken met de mogelijkheden van de robot. In dat geval kunnen we de string
NOORD bijvoorbeeld in de scanner vertalen naar het token UP en de parser ongewijzigd
laten.
4.1.2 Overbodige instructies
De instructies TURN en FLIP zijn overbodig geworden omdat de robot steeds in
dezelfde richting blijft kijken. Het volstaat in principe om de gepaste stukken code
uit de MIRA-definities van de scanner en de parser te verwijderen.
De wijziging gaat deze keer echter verder: de klasse Robot heeft een attribuut
direction, dat de richting van de robot weergeeft. Aangezien dit niet langer re-
levant is, kan het maar beter verwijderd worden, samen met alle verwijzingen er-
naar in de code van de klasse Robot. Dit is nodig om er voor te zorgen dat pro-
grammeerfouten vermeden worden. Merk op dat dit verwijderen ook in de bron-
code duidelijk maakt waarom TURN en FLIP overbodig zijn geworden: de functies
Robot::Turn() en Robot::Flip() zijn leeg geworden. Daarnaast is ook de sys-
teemvariabele DIRECTION overbodig geworden, zodat ook alle verwijzingen hiernaar
verwijderd moeten worden.
Meteen werden ook enkele andere systeemvariabelen verwijderd, namelijk XW, YW,
XT en YT. Deze systeemvariabelen waren aanwezig voor het opvragen van informatie
over de omgeving, die gedefinieerd werd in de CDL, de Configuration Description
Language, maar zijn niet langer relevant.
37
4.1.3 Semantische wijziging
Het was de bedoeling er voor te zorgen dat een GO instructie ook de systeemvariable
CONDITION aanpast, zodanig dat het al dan niet slagen van een dergelijke instructie
meteen kan beslissen wat de volgende instructie wordt. Het is belangrijk in te zien
dat het verschil met een TEST nu enkel nog het feit is dat bij een TEST de robot altijd
naar zijn oorspronkelijke plaats terugkeert, terwijl een GO op een nieuwe plaats staat
indien die plaats vrij was. Daarom heb ik het stuk code van de TEST gekopieerd, en
de aanpassing van de systeemvariabelen XR en YR toegevoegd.
4.2 Bepalen van de positie
Een van de moeilijkste problemen om op te lossen was dat van de onzuivere rich-
tingen. Het is de bedoeling dat we trachten rekening te houden met een (niet
noodzakelijk zichtbaar) coordinatenstelsel. Tal van voorstellen om de precieze po-
sitie van de robot te bepalen ben ik op discussiegroepen tegengekomen, werden mij
in de late uurtjes op cafe voorgesteld door vrienden, of heb ik zelf bedacht.
Een van de opvallendste ideeen was wellicht het idee van een kleinschalig GPS-
systeem1. Hierbij was het de bedoeling in een kamer drie lichtjes te plaatsen, die elk
aan een andere frequentie flikkerden om zo het onderscheid tussen de verschillende
lichtbronnen te vinden. De robot heeft een soort oog, een lichtsensor dus, waarmee
hij de kamer afspeurt op zoek naar de precieze richting van elk van de drie licht-
bronnen. We kunnen ons echter enkele vragen stellen bij dit idee. Ten eerste lijkt
het mij twijfelachtig of het detecteren van de lichtbronnen wel nauwkeurig genoeg
kan gebeuren. Bovendien is er een groot probleem wanneer we dit in NQC willen
gerealiseerd krijgen: deze taal kent geen floating point getallen, wat we eigenlijk
wel nodig hebben aangezien we aan driehoeksmeetkunde willen doen. Het is ook zo
dat over dit idee al meer dan een jaar op LUGnet gepraat wordt en er ondertussen
1Het Global Positioning System laat toe zeer naukeurig de coordinaten van een plaats op aarde
te bepalen op basis van de positie van minstens drie satellieten.
38
nog niemand iets werkbaar gerealiseerd heeft. Kennelijk is het inderdaad erg moei-
lijk, misschien zelfs onmogelijk om een GPS-achtig systeem te ontwikkelen voor de
Mindstorms robot, tenzij met extra hardware. Het is overigens ook zo dat sommigen
van plan zijn om een echt GPS-systeem te ontwikkelen, dat als sensor op de RCX
moet kunnen aangesloten worden. Dit is voor ons hoe dan ook niet bruikbaar: GPS
is bedoeld voor in open lucht, en de nauwkeurigheid gaat slechts tot een vijftigtal
centimeter, wat in onze situatie veel te weinig is.
Nog een voorstel was gebruik te maken van de afstandsdetectie waar sommigen
al in geslaagd zijn. Het idee achter deze afstandsdetectie is de volgende: de infra-
rood zender/ontvanger op de robot is in staat om licht uit te zenden, dat weliswaar
niet zichtbaar is voor de mens, maar kennelijk wel voor de lichtsensoren. Bovendien
wordt licht weerkaatst door voorwerpen, tenzij ze veel te donker zijn. Deze vast-
stellingen brachten Simen Svale Skogsrud [13] ertoe om de traditionele bumper van
een standaard type robot te vervangen door een lichtsensor die kijkt hoeveel licht
er terugkomt van wat de infra-rood component van de robot elke seconde uitzendt.
Wanneer er erg veel licht ontvangen wordt, kunnen we vermoeden dat we ons vlak
voor een obstakel bevinden, dat we moeten ontwijken. Een andere toepassing is een
soort scanner: een oog tast het blad af dat we willen inscannen, terwijl de RCX
systematisch infra-rood licht op het blad stuurt. Beide projecten behaalden aan-
vaardbare resultaten. Een mogelijk idee was om de afstandsbepaling te gebruiken
om de precieze positie binnen een kamer te bepalen. We moeten ons opnieuw een
aantal vragen stellen. Zo is het twijfelachtig dat de afstand voldoende nauwkeurig
kan bebaald worden. Bovendien moet de RCX precies 90 graden kunnen draaien om
de andere muur te bekijken, en zoals reeds vermeld is dat niet zo vanzelfsprekend.
Tot slot kan nog opgemerkt worden dat dit idee er van uitgaat dat we werken in een
eerder kleine rechthoekige ruimte, waarbij de muren niet al te donker mogen zijn, en
er geen obstakels in het gezichtsveld van de robot mogen staan. Vooral dit laatste
is een probleem aangezien het juist de bedoeling is dat onze robot kan navigeren
in een wereld vol obstakels. De meest eenvoudige oplossing voor het probleem van
39
de positiebepaling werd mij ingefluisterd door Geert Vernaeve, en werd ook al in de
praktijk gerealiseerd met de GridBot van Bernd Frassek [14]. Eerst moet ik opmer-
ken dat het in onze situatie niet nodig is om op elke plaats de precieze coordinaten
te kennen. Het volstaat om voldoende nauwkeurig te kunnen bewegen tussen de
verschillende coordinaten met discrete waarden. Het volgen van een zwarte lijn op
een witte ondergrond is een van de allereenvoudigste oefeningen die Lego aan be-
ginners, in de eerste plaats kinderen dus, vraagt om op te lossen. Het zou dus vrij
goed mogelijk moeten zijn om dit ook in onze robot te gebruiken.
4.3 Realisatie
Het tekenen van een rooster was uiteraard geen groot probleem. De vloer waar wij
gebruik van maakten, is erg licht van kleur, wat noodzakelijk is om genoeg contrast
te hebben. De zwarte lijnen zijn gemaakt van 15 mm brede tape die gebruikt wordt
om elektrische draden te beschermen. De vakjes hebben een breedte van ongeveer
20 cm maar zijn niet altijd even groot. Omdat onze robot hier hoegenaamd geen
rekening mee houdt, kan dit geen enkel probleem opleveren. De lijnen moeten zelfs
niet perfect recht zijn, maar wanneer men ze te dicht bij elkaar zou plaatsen, riskeert
men wel dat de robot onverwachte dingen zal doen. De kans bestaat dan immers
dat hij verschillende lijnen met elkaar gaat verwarren of soms eens een dwarslijn zal
overslaan omdat hij ze nog niet verwacht.
Geert Vernaeve heeft enkele ideeen uitgewerkt om er voor te zorgen dat de robot
maar een lichtsensor zou nodig hebben om door het rooster te navigeren. Naar
mijn mening waren deze voorstellen in de praktijk moeilijk of niet te realiseren. We
moeten immers onderscheid maken tussen drie onafhankelijke problemen die met de
lichtsensoren opgelost dienen te worden:
• Het voorwaarts en achterwaarts volgen van een lijn gedurende onbepaalde tijd.
De lijn dient als een soort rail, die de robot verplicht is te volgen. De robot
moet kunnen detecteren wanneer hij de lijn kwijt is en zo snel mogelijk terug
40
op het goede spoor zien te geraken wanneer dit gebeurt, en dit liefst zodanig
dat hij nog wel even verder kan rijden zonder de lijn opnieuw kwijt te raken.
• Het stoppen bij de eerstvolgende dwarslijn. De robot moet kunnen detecteren
wanneer hij precies moet stoppen, meer bepaald aan het eerstvolgende kruis-
punt, maar hij moet ook opletten dat hij niet te vroeg stopt. Dit kan immers
gebeuren wanneer hij moest manoeuvreren nadat hij zijn rail is kwijtgeraakt.
• Draaien over een hoek van 90 graden, in wijzerzin of tegenwijzerzin. Het is
de bedoeling dat de robot dit zodanig doet, dat hij na deze beweging recht
staat ten opzichte van de dwarslijn, die hij in de volgende beweging wellicht
zal moeten volgen.
Merk op dat de eerste twee problemen tegelijkertijd moeten gebeuren, waardoor het
bijna onmogelijk wordt om hiervoor slechts een lichtsensor te gaan gebruiken. We
hebben dus minimaal twee lichtsensoren nodig om een praktische oplossing uit te
werken. Het derde probleem gebeurt altijd op een ander tijdstip, zodat we daarvoor
geen derde sensor meer nodig hebben, maar een van de eerste twee kunnen gebruiken,
of beide.
Aan de robot die we al hadden werd achteraan een lichtsensor toegevoegd op
de manier die in de handleiding van Lego beschreven wordt. Het was ook niet zo
moeilijk om aan de zijkant van de robot een lichtsensor te hangen.
4.3.1 Bewegen in het rooster
Het volgen van een lijn
• Wanneer de robot zijn lijn kwijt is, draait hij kort om de lijn terug te vinden.
Indien dit niet meteen lukt, zal hij gedurende een iets langere tijd in de andere
richting draaien, enzovoort. Hij onthoudt ook in welke richting hij uiteindelijk
als laatste gedraaid heeft.
41
(a) (c) (d)(b)
Figuur 4.1: Het volgen van een lijn
• Van zodra de robot zijn lijn heeft teruggevonden rijdt hij gedurende een vaste,
experimenteel vastgelegde tijd recht achteruit.
• Vervolgens draait de robot in de tegengestelde richting van die waarin hij moest
draaien om de lijn terug te vinden, en dat tot hij de lijn opnieuw tegenkomt.
• De robot gaat er van uit dat hij nu terug voldoende recht staat en rijdt opnieuw
gewoon vooruit.
In theorie kunnen bij dit algoritme complicaties optreden wanneer de robot zich
in de buurt bevindt van een kruispunt, omdat de dwarslijnen verkeerdelijk zouden
kunnen verward worden met de te volgen lijn. In de praktijk heb ik hier tot nu toe
echter geen problemen mee ondervonden.
Een lijn achterwaarts volgen
Doordat de sensor nu eigenlijk vooraan de robot zit, worden afwijkingen veel sneller
opgemerkt en volstaat het om in dat geval al draaiende de lijn terug te zoeken zoals
in de eerste fase van Figuur 4.1, en dan gewoon de weg verder te zetten zonder nog
verder te manoeuvreren.
42
Stoppen bij de volgende dwarslijn
Omdat deze opdracht in principe onafhankelijk is van het volgen van een lijn, koos
ik er voor om deze twee opdrachten als twee aparte taken te laten lopen, wat in
NQC geen enkel probleem is. De ene taak volgt een lijn op de manier die daarnet
beschreven werd, terwijl de andere de zijdelingse sensor observeert. Het blijkt echter
niet correct te zijn om gewoon te stoppen wanneer een lijn gedetecteerd wordt, en
dit bij twee situaties:
• Tijdens het manoeuvreren kan de zijdelingse sensor de lijn detecteren die de
robot moet volgen; deze geeft uiteraard niet aan dat hij mag stoppen. Tijdens
het manoeuvreren moet de sensor dus genegeerd worden.
• Indien de robot zijn lijn erg snel kwijt is, kan hij tijdens het manoeuvreren
achter de dwarslijn terechtkomen waar hij gestart was. Daarom moet de sensor
dus niet enkel tijdens het manoeuvreren genegeerd worden maar ook gedurende
een korte tijd erna.
Draaien naar links of rechts
(a) (b) (c) (d)
Figuur 4.2: Naar links of naar rechts draaien
De robot rijdt eerst heel even, gedurende een experimenteel vastgelegde tijd
achteruit, en draait dan naar de gevraagde richting tot zijn achterste sensor een lijn
tegenkomt. Vervolgens rijdt hij nog even vooruit tot hij bovenop de dwarslijn staat.
43
4.3.2 Het gebruik vanuit de parser
Nogal wat gegevens die nodig zijn voor de bewegingen die hierboven beschreven
werden, blijken erg afhankelijk te zijn van het ontwerp van de robot. Niet enkel
de experimenteel bepaalde tijden spelen een rol, maar blijkbaar ook de lichtinval;
en wanneer we de lichtsensoren op een andere plaats zouden hangen, zouden de
algoritmes misschien moeten veranderd worden.
Daarom heb ik er voor gekozen om hier een extra niveau van abstractie in te
bouwen. Dit kan door alles wat afhankelijk is van de specifieke bouw van de robot
vast te leggen in een NQC header file. Vanuit de klasse Robot wordt dan dit bestand
geıncludeerd, en er worden enkel nog functies en macro’s aangeroepen die in dat
bestand geımplementeerd zijn. Wanneer we dus om het even welke andere robot
willen gebruiken die ook NQC begrijpt, volstaat het om die functies en macro’s te
herdefinieren. Het is zelfs niet nodig om de parser opnieuw te compileren, aangezien
de header at run-time aangeroepen wordt.
Volgende functies worden verondersteld geımplementeerd te zijn in het bestand
grid.h:
• init() laat de nodige initialisaties toe, bijvoorbeeld om het type van de sen-
soren vast te leggen.
• left() en right() doen de robot 90 graden draaien naar de gepaste richting.
• forward() doet de robot vooruit rijden tot hij ergens op botst of het volgende
punt bereikt; reverse() doet het tegenovergestelde.
• BUMPER is een macro die teruggeeft of de bumper al dan niet is ingedrukt.
44
Hoofdstuk 5
Conclusie
5.1 Suggesties
De aandachtige lezer zal wellicht opgemerkt hebben dat een zwak punt uit de eerste
versie nog niet is aangepakt. De lange wachttijd tussen de instructies is gebleven, en
in de huidige architectuur lijkt het weinig waarschijnlijk dat we daar iets aan gaan
kunnen doen. In de beschrijving van de NQC omgeving in sectie 2.2.2 vermelde ik
al dat de communicatie tussen de PC en de robot het client-server principe volgt.
Bovendien bestaat elke atomaire instructie uit twee fases: in de eerste fase stuurt de
parser een NQC programma door naar de robot, die dit programma uitvoert maar
niets antwoordt, en in de tweede fase vraagt de PC het resultaat van de actie op
via de datalog. Dit zorgt voor een vervelende situatie. Enkel de robot weet immers
wanneer de actie, opgestart vanop de PC, voltooid is. Het is echter het programma
dat op de PC loopt, dat het initiatief moet nemen om naar het resultaat te vragen
van de actie die kort voordien is opgestart. De enige oplossing hiervoor is de PC
voldoende lang te laten wachten, in de hoop dat de actie dan zeker beeindigd is. Het
is dus nodig een voldoende grote marge te nemen. In sommige gevallen, wanneer de
robot slecht geplaatst staat, en dus nogal veel moet manoeuvreren om tot bij zijn
bestemming te geraken, kan een enkele instructie erg lang duren. In onze huidige
architectuur hebben we geen andere keuze dan voor elke instructie zo lang als nodig
45
te wachten, hoewel in de meeste gevallen de beweging snel voltooid is.
inputstring tokenstringScanner Parser
PC RCX
Resultaat?
NQC code
Datalog
Figuur 5.1: De huidige situatie met NQC
Een eerste mogelijke oplossing is om niet op het resultaat van een instructie te
wachten. Dit lijkt mogelijk, omdat we er van kunnen uitgaan dat de systeemvari-
abele CONDITION slechts af en toe door de gebruiker zal opgevraagd worden. We
zouden er dus voor kunnen kiezen om de datalog, die het resultaat van de laatste
beweging bevat, enkel op te vragen wanneer de gebruiker naar die systeemvariabele
vraagt. De klasse Robot houdt echter intern ook de coordinaten van de robot bij,
en als we het principe van de virtuele muur willen blijven gebruiken, kunnen we de
huidige werkwijze niet overboord gooien: we moeten op elk ogenblik de positie van
de robot kennen ten opzichte van de infra-rood toren en daarom moeten we van elke
moveto(dir) weten of de beweging al dan niet gelukt is. Stel dat we er voor zou-
den kiezen dit toch te doen, moeten we met nog enkele andere problemen rekening
houden. Zo kan de gebruiker te vroeg een nieuwe instructie doorgeven. Ook in een
lus of procedure kan de volgende instructie gemakkelijk te vroeg opgestart worden,
voordat de vorige echt voltooid is. En hier zitten we terug met ons oorspronkelijk
probleem: de parser, die op de PC loopt, weet niet wanneer de robot zijn actie heeft
voltooid, terwijl de robot zelf niet het initiatief kan nemen om dit te laten weten.
We moeten ook durven toegeven dat de code een stuk minder elegant wordt. Op
dit ogenblik worden alle systeemvariabelen in een lijst bijgehouden, en tijdens de
uitvoering op de gepaste ogenblikken aangepast. Wanneer de gebruiker er een van
wil opvragen, wordt de lijst doorlopen tot de juiste naam gevonden is, en het bijho-
rende resultaat teruggegeven. In het voorstel dat ik zopas gedaan heb, zou dus een
46
uitzondering moeten gemaakt worden voor een bepaalde systeemvariabele, namelijk
CONDITION, waarbij een totaal ander stuk code moet uitgevoerd worden. Hoewel dit
technisch geen enkel probleem is, gaat de uniformiteit van het gebruik van de sys-
teemvariabelen verloren, waardoor de code toch weer iets moeilijker onderhoudbaar
wordt.
De enige echte oplossing is uiteraard af te stappen van datgene wat de problemen
veroorzaakt: de client-server architectuur die eigen is aan NQC, en eigenlijk afstamt
van de grafische RCX-omgeving. Zelf zie ik drie grote categorieen van oplossingen.
Een eerste behoudt een erg gelijkaardige structuur, maar maakt gebruik van een
architectuur met een peer-to-peer communicatie. De tweede volgt een verschillende
aanpak: we kunnen de parser laten lopen op de RCX zelf. De derde oplossing gaat
het in een nog andere richting zoeken: we zouden Visual MIRA kunnen gebruiken
om RCL commando’s te vertalen naar een andere taal, die we wel rechtstreeks in de
robot kunnen gebruiken.
5.1.1 Peer-to-peer
Zoals reeds vermeld in 2.2.3, gebruikt LegOS een eigen protocol, het LegOS Network
Protocol, om communicatie toe te laten tussen verschillende RCX blokken en PC’s.
Kennelijk is het hier niet nodig dat de communicatie opgestart wordt door de PC,
maar kan om het even welke partij het initiatief nemen. Dit is dus een voorbeeld van
een architectuur die peer-to-peer mogelijkheden heeft. Het moet dus mogelijk zijn
om, wanneer LegOS op de RCX draait, C programma’s te laten genereren, in plaats
van NQC programma’s. Deze moeten dan zelf signaleren wanneer ze beeindigd zijn.
Ondertussen blijft de PC wachten op dit signaal, pas dan kan hij verder gaan. Het
grote voordeel van deze aanpak is dat de huidige code niet al te veel aanpassingen
zal vragen, omdat in de ganse code slechts een functie zal moeten gewijzigd worden.
47
inputstring tokenstringScanner Parser
PC RCX
LNP
Figuur 5.2: Peer-to-peer met LegOS
5.1.2 De robot als interpreter
Wat naar mijn gevoel de boeiendste oplossing is om uit te proberen, is de tweede.
Hierin loopt de interpreter, de scanner en de parser dus, niet langer op een PC, maar
op de robot zelf, die op die manier veel zelfstandiger wordt. Het grote probleem van
deze aanpak is echter de beperking van het geheugen dat op de RCX beschikbaar is.
LegOS is in principe de enige omgeving waarin deze mogelijkheid kan gerealiseerd
worden. Ik heb LegOS nooit geınstalleerd op de RCX, maar ik heb wel de door MIRA
gegenereerde C++ code gecompileerd voor uitvoering op LegOS, en de uitvoerbare
code bleek inderdaad te groot te zijn. Mogelijk wordt deze grootte negatief beınvloed
door het gebruik van de objectgeorienteerde aspecten van C++ en kunnen we dit
wegwerken door de constructie van de parserboom te herschrijven naar C, waardoor
wellicht veel compactere code zal gegenereerd worden. Toch blijft het risico bestaan
dat het opbouwen van parserbomen voor grotere RCL-commando’s te veel geheugen
gaat opslorpen.
tokenstringScanner Parser Instructies
PC RCX
inputstring
Figuur 5.3: De interpreter op de RCX
48
Dit jaar werd bij een andere scriptie op de vakgroep Zuivere Wiskunde en Com-
puteralgebra een nieuwe versie van Visual MIRA ontwikkeld, die het mogelijk moet
maken om Java-code te genereren in plaats van C of C++ [5]. Dit biedt ons de
optie om na te gaan of we de scanner en parser voor RCL niet kunnen herschrijven
naar Java, om dan de zojuist beschreven architectuur met Java te realiseren onder
bijvoorbeeld TinyVM, waarvan we in 2.2.4 al vermeldden dat deze omgeving erg
zuinig is op het geheugengebruik.
Het grote voordeel van deze aanpak is dat de robot veel autonomer wordt: er is
enkel communicatie nodig bij het doorsturen van een RCL instructie en eventueel
bij het beeindigen van een dergelijke instructie. Hierdoor zal de robot wellicht een
stuk efficienter kunnen werken. Doordat de robot op die manier een grote mate
van zelfstandigheid heeft, wordt het wellicht mogelijk om ook andere infra-rood
apparaten te gaan gebruiken om RCL instructies door te sturen. Het enige wat er
immers moet overgedragen worden, is een string van karakters die een commando
vormen. Het enige probleem zou de compatibiliteit van de verschillende infra-rood
apparaten kunnen zijn, maar aangezien men er al is in geslaagd om de RCX te laten
communiceren met een Palm Pilot [15] en met een HP 100lx palmtop computer [16],
lijkt dit me geen onoverkomelijk probleem.
Indien er toch te veel tijd zou nodig zijn voor het doorsturen van de strings,
of er blijft een probleem met de geheugengrootte van de interpreter, kan men nog
altijd een andere mogelijkheid uitproberen. We kunnen in principe de scanner op
de PC en de parser op de robot laten lopen, zodat er enkel nog tokens moeten
overgedragen worden. De tokenstring moet normaal gezien compacter zijn, omdat
de sleutelwoorden van de taal voorgesteld worden door identifiers, gehele getallen
dus. Doordat de scanner niet op de RCX loopt, is er meer geheugen beschikbaar
voor de parser, die wel nog op de RCX loopt. Zoals gezegd werd in 1.1.6, laat Visual
MIRA toe om de zogenaamde read routine en write routine door de gebruiker te
herdefinieren, zodat deze oplossing binnen het kader van Visual MIRA kan blijven.
Een nadeel van deze oplossing is dat de zelfstandigheid van de robot voor een stuk
49
terug verloren gaat en we dus moeilijker andere apparaten kunnen gebruiken voor
de aansturing van de robot.
inputstring Scanner Parser Instructies
PC RCX
tokenstring
Figuur 5.4: Zuiniger zijn op de communicatie
5.1.3 MIRA als vertaalmechanisme
Een compiler wordt in [1] gedefinieerd als een programma dat een programma ge-
schreven in een bepaalde taal vertaalt naar een equivalent programma in een andere
taal. Merk op dat het huidige programma geen echte compiler is, maar een in-
terpreter. Een interpreter produceert geen programma in de doeltaal, maar voert
operaties uit die opgelegd worden door het bronprogramma.
We mogen dus concluderen dat we Visual MIRA ook kunnen gebruiken om een
vertaling te doen van RCL naar bijvoorbeeld NQC. Dit lijkt echter gedoemd om
te mislukken: in RCL kunnen we gebruik maken van variabelen en arrays, denk
maar aan de GOTO2 procedure, terwijl NQC een beperking oplegt aan het aantal
variabelen. Wanneer we RCL vertalen naar C en we laten LegOS op de robot lopen,
moet het wel mogelijk zijn om deze techniek te volgen. Het enige probleem dat ik
op dit ogenblik zie opduiken, is dat procedures op een gegeven moment gedefinieerd
worden en op een later ogenblik worden aangeroepen. In de tussentijd moet de
procedure dus op een of andere manier ergens bewaard worden. En wat er precies
met systeemvariabelen moet gebeuren, is mij ook nog niet helemaal duidelijk.
Stof genoeg dus om in de toekomst nog een of meerdere van deze alternatieven
uit te proberen.
50
inputstring tokenstringScanner Parser
PC RCX
C−programma
Figuur 5.5: Scanner en parser vertalen RCL-instructies naar C-programma’s
5.2 Besluit
Het uitgangspunt voor deze thesis was het eindwerk van Hans Gruyaert [2]. Hierin
wordt onder andere nagegaan of LL(1)-specificaties gebruikt kunnen worden voor de
realisatie van een mens-machine interface voor de bewegingscontrole van een robot.
Om dit in de praktijk aan te tonen ontwikkelde hij een interactietaal: de Robot
Control Language (RCL).
Het was mijn bedoeling te onderzoeken of de Lego Mindstorms robot voldoende
mogelijkheden in zich heeft om een rondzwervende robot te realiseren, die bestuurd
wordt aan de hand van een interactietaal gelijkend op de RCL uit [2].
De Mindstorms robot heeft erg veel beperkingen, hij is immers bedoeld om kin-
deren vanaf 12 jaar spelenderwijs met de wereld van de robots te laten kennismaken,
niet om volwassenen volwaardige robots te laten bouwen. Toch kunnen elk van deze
beperkingen met een beetje creativiteit omzeild worden:
• De communicatie tussen robot en PC gebeurt via infra-rood signalen waardoor
visueel contact nodig is. Door er voor te zorgen dat de robot bij het beeindigen
van elke beweging (min of meer) in de juiste richting kijkt, kunnen we ver-
mijden dat dit problemen geeft. Een gevolg hiervan is dat de robot altijd in
dezelfde richting kijkt waardoor enkele instructies overbodig geworden zijn.
• De robot kan niet zien of er een obstakel is, hij kan het enkel voelen door te
bewegen. Dit is niet echt een groot probleem, maar het gaf wel aanleiding tot
een kleine wijziging in de semantiek van een instructie.
51
• De robot kan zich niet blindelings orienteren in zijn wereld. Om dit probleem
op te lossen kunnen we een rooster tekenen dat de robot moet volgen, gebruik
makend van twee lichtsensoren.
• De robot heeft slechts plaats voor drie sensoren. In mijn ontwerp was dit
voldoende, maar mochten er later toch meer nodig zijn, dan kan men verschil-
lende sensoren op een aansluiting plaatsen. Aan de hand van de zogenaamde
’raw value’, het precieze spanningsverschil aan de aansluiting van de sensoren,
kan men dan toch een vermoeden krijgen van wat de sensoren willen zeggen.
Let wel: niet alle combinaties van sensoren blijken goed te werken.
• De gebrekkige communicatie tussen robot en PC kan op verschillende manieren
aangepakt worden, zoals ik suggereerde in 5.1.
Tijdens de realisatie van het geheel heb ik bovendien kunnen vaststellen dat de
voordelen die in [2] en [4] aangehaald worden over het gebruik van LL(1)-talen met
behulp van een tool als Visual MIRA, in combinatie met objectgeorienteerd ontwerp,
ook in mijn ontwerp blijken te kloppen:
• Het omschakelen tussen verschillende platformen vergt weinig aanpassingen.
Om tot een eerste werkbare versie te komen, bleven de aanpassingen in de
broncode quasi beperkt tot een C++ klasse, waarbinnen ook maar weinig
aanpassingen nodig waren.
• Aanpassingen aan de omgeving kunnen gemakkelijk gebeuren omdat de im-
plementatie sterk gekoppeld is aan de syntaxbeschrijving. In 3.3.3 beschrijf
ik de verschillen tussen de robot uit [2] en onze Lego-robot. Deze verschillen
dwingen ons het jargon van de robot te wijzigen. De nodige aanpassingen
bleken verassend eenvoudig realiseerbaar.
• Het automatisch genereren van scanner en parser vermindert de kans op fou-
ten. De enige bugs die ik gedurende de realisatie van de robotsturing ben
tegengekomen, waren fouten in de NQC programma’s die ik geschreven had.
De fouten lagen dus eigenlijk buiten het domein van de parser.
52
We kunnen dus besluiten dat het mogelijk is om de Lego Mindstorms robot aan
te sturen aan de hand van een LL(1) interactietaal. Wanneer we de robot uiteindelijk
ook voor meer praktische doeleinden willen gaan gebruiken, is het volgens mij wel
aangewezen een andere aanpak te volgen dan mijn methode.
53
Bibliografie
[1] Aho Alfred, Sethi Ravi en Ullman Jeffrey, Compilers, Addison-Wesley
Publishing Company, 1986
[2] Gruyaert Hans, LL(1)-specificaties in robotica, 1998
[3] Hoogewijs Albert, LL(1) descriptions for robots, Robotica volume 15, pp
105-110, Cambridge University Press 1997
[4] Hoogewijs Albert, Gruyaert Hans en Vernaeve Geert, Teach your Robot
an LL(1)-Jargon, 2000
[5] Impens Freya, Visual MIRA voor JAVA, 2001
[6] Wolz Ursula, Teaching Design and Project Management with Lego RCX
Robots, SIGCSE Bulletin, Volume 33, Nr 1, Maart 2001, pp 95-99
[7] RCX, internals, een uitgebreide beschrijving van de in-
terne werking van de RCX, opgesteld door Kekoa Proudfoot:
http://graphics.stanford.edu/ kekoa/rcx/
[8] De homepagina van Dave Baum, de ontwerper van NQC:
http://www.enteract.com/ dbaum/nqc/
[9] De legOS homepagina: http://legos.sourceforge.net/
[10] De TinyVM homepagina: http://tinyvm.sourceforge.net/
[11] De LeJOS homepagina: http://lejos.sourceforge.net/
54
[12] Analysis of the RCX: http://www.rcx.ic24.net/analysis.htm
[13] Proximity detection http://www.mop.no/ simen/legoproxi.htm
[14] De persoonlijke pagina van Bernd Frassek op de Mindstorms
website: http://mindstorms.lego.com/bookmarks/users.asp?
2C41D51DB4D7F2BBA1F71A6F7B0C90A5
[15] RCX and Palm: http://members.rotfl.com/vadim/rcx/
[16] Controlling the LEGO MindStorms robot from a HP100lx palmtop com-
puter: http://www.magicnet.net/ twdow/mindstorms.html
55