Visueel programmeren met Lego Mindstorms Tim Molderez en Quinten David Soetens Wetenschapsweek (22 november 2012)
In deze handleiding1 krijg je een eerste introductie tot het visueel programmeren van een Lego Mindstorms robot. Dit doen we aan de hand van de “Visual Programming Language” die deel uitmaakt van de Microsoft Robotics programmeeromgeving. Het fijne aan deze omgeving is dat je hiermee in principe eender welke robot op een visuele manier kan programmeren. Daarenboven hoeft het niet eens een echte robot te zijn; je kan ook even goed een virtuele robot gebruiken die op je computer wordt gesimuleerd. Het gebruik van een echte Lego Mindstorms robot is dus volledig optioneel; je kan je programma’s ook uitproberen op een simulatie van de Mindstorms robot.
Inhoudsopgave 1 Installatie
2
2 De Lego Mindstorms robot rechtstreeks besturen
3
3 De robot programmeren met de Visual Programming Language
4
3.1
Overzicht van de Visual Programming Language programmeeromgeving . . . . . . . . . . .
4
3.2
Visueel programmeren met blokken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
3.3
Algemene programmeerblokken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
3.4
Lego Mindstorms sensor -en motorblokken . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.4.1
Overzicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4.2
Configuratie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.5
Extra programmeerblokken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.6
Nieuwe types blokken bouwen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.7
Vraag en antwoord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1 Deze
handleiding is ook online beschikbaar op: http://tinyurl.com/ww12robots
1
1
Installatie
Voor we aan de slag kunnen moet je eerst de Microsoft Robotics Developer Studio en de Lego Mindstorms simulatie installeren. Beide zijn gratis; de enige vereiste is dat je Windows 7 (of hoger) gebruikt. Deze installatie doe je als volgt: Microsoft Robotics Developer Studio 2008 R2 1. Download eerst het installatieprogramma voor Microsoft Robotics Developer Studio 2008 R22 . Dit kan je hier terugvinden: http://tinyurl.com/mrds2008. 2. Open het installatieprogramma en volg de instructies. (Blijf op de “Next” knop klikken tot de installatie is voltooid, net zoals je eender welk ander programma installeert.) SimplySim NXT (Lego Mindstorms simulatie) 1. Download nu het installatieprogramma voor SimplySim NXT om ondersteuning voor de Lego Mindstorms robot toe te voegen. Ga naar http://www.simplysim.net/index.php?p=gallery&id=11 en klik onderaan op “Download the package for MSRDS 2008 R2”. 2. Open nu het installatieprogramma dat je net hebt gedownload en volg wederom de instructies. Let op, bij de stap waarin je de installatiefolder kan kiezen moet je één kleine wijziging maken: Verwijder in het “Folder:” tekstvak het woord “Express”, zoals je in figuur 1 kan zien. Er zou nu dus “C:\Users\NAAM\Microsoft Robotics Dev Studio 2008 R2\” moeten staan (waarbij “NAAM” je Windows gebruikersnaam is).
Figuur 1: Installatie SimplySim NXT 2 Microsoft Robotics Developer Studio R2 2008 is ondertussen niet meer de meest recente versie. We gebruiken echter deze specifieke versie omdat de Lego Mindstorms simulatie nog niet is aangepast aan de laatste versie. Mocht je echter enkel geïnteresseerd zijn in het aansturen de echte Lego robot, dan kan je gewoon de laatste versie van Microsoft Robotics Developer Studio downloaden via http://www.microsoft.com/robotics
2
Wetenschapsweek voorbeelden (optioneel) 1. Als je wil kan je tenslotte ook de voorbeelden installeren die tijdens de Wetenschapsweek zijn gebruikt. Allereerst moet je de bestanden met de aangepaste simulatieomgevingen (het parcours en het magazijn) hier downloaden: http://tinyurl.com/mrds2008environments. 2. Ga vervolgens naar je persoonlijke map door op Start te klikken en vervolgens op je naam. Pak het .zip-bestand dat je net hebt gedownload nu uit in je persoonlijke map. Je zal vervolgens een aantal meldingen krijgen dat bepaalde mappen reeds bestaan, en of je ze wil samenvoegen: Klik telkens op Ja. 3. De Wetenschapsweek voorbeelden zelf kan je hier downloaden: http://tinyurl.com/mrds2008examples. 4. Het .zip-bestand dat je nu hebt gedownload kan je eender waar uitpakken (bv. op je bureaublad). Om een voorbeeld te starten: Open eerst de map van het voorbeeld en dubbelklik vervolgens op het bestand met een icoontje met drie kleine rechthoeken. De Visual Programming Language omgeving wordt nu geopend met het voorbeeld. Van zodra alles is geladen kan je het voorbeeld starten door bovenaan op de Start-knop (het groene Play symbool) te klikken.
2
De Lego Mindstorms robot rechtstreeks besturen
De SimplySim NXT installatie bevat een handig programma waarmee je je robot rechtstreeks kan besturen met de muis of een gamepad; je kan er ook de waardes van alle sensors mee uitlezen. Dit programma gebruik je als volgt: 1. Optioneel: Als je een Lego Mindstorms robot hebt moet je eerst het “Tri Bot” basismodel bouwen. (Mocht je de bouwplannen niet hebben, je kan ze steeds downloaden op: http://mindstorms.lego.com/en-us/support/buildinginstructions/8527-/Tribot.aspx) Wanneer je de robot hebt gebouwd mag je hem aanzetten, zodat automatisch een draadloze Bluetooth verbinding met je computer wordt gemaakt. (Ik ga er hierbij vanuit dat je reeds de Lego Mindstorms software op je computer hebt geïnstalleerd.) 2. Optioneel: Als je een gamepad/controller hebt mag je deze nu op je computer aansluiten. (Je gamepad moet wel XBox 360-compatibel zijn, wat meestal wel het geval is.) 3. Open het NXT-MSRDS programma via het icoontje op je bureaublad (ziet eruit als een groene bol met daarin een zwart ventje..). 4. Wacht even tot het programma volledig is gestart. Na verloop van tijd zou er een vinkje moeten staan onder “Simulation”, zoals je kan zien in Figuur 2. (Als je een echte Lego Mindstorms robot gebruikt moet er ook een vinkje staan onder “Real Robot”. Mocht dit niet het geval zijn, druk dan op de “Configure” knop en vul het “Port” tekstvak in met het juiste Bluetooth poortnummer. Dit is een nummer tussen 1 en 9 (meestal 3); je kan het juiste nummer vinden via Start > Configuratiescherm > Apparaten en printers > NXT > Services.) 5. Je kan nu beide de echte robot en de gesimuleerde robot besturen met de linkerjoystick op je gamepad, of met de virtuele joysticks in het linkervenster. De klauw van de robot kan je openen en sluiten
3
Figuur 2: Het SimplySim NXT-MSRDS programma met de sliders in dit linkervenster. Tevens kan je er ook de waardes aflezen van de geluids-,druk,licht- en ultrasoonsensor. Je kan de camera tenslotte ook verplaatsen in het 3D simulatievenster door de linkermuisknop op eender welke plaats in dit venster ingedrukt te houden en tegelijk de pijltjestoetsen te gebruiken. (Dit kan je ook op je gamepad door LB ingedrukt te houden en de joysticks te gebruiken.)
3
De robot programmeren met de Visual Programming Language
In dit hoofdstuk krijg je een inleiding tot het gebruik van de Visual Programming Language, oftewel VPL, om op een visuele manier je eigen programma voor de Lego Mindstorms robot te maken. De VPL programmeeromgeving kan je gewoon via het Startmenu openen: Klik op Start, typ “visual” en normaalgezien verschijnt “Visual Programming Language 2008 R2” al bovenaan de lijst. Klik erop om te beginnen.
3.1
Overzicht van de Visual Programming Language programmeeromgeving
In Figuur 3 kan je de verschillende elementen zien die deel uitmaken van de VPL programmeeromgeving: • Het diagram in het middengedeelte stelt je programma voor, bestaande uit een netwerk van blokken die met elkaar verbonden zijn. Hoe je zo’n diagram moet lezen wordt duidelijker in hoofdstuk 3.2. 4
Figuur 3: De Visual Programming Language programmeeromgeving • Het “Basic Activities” gedeelte linksboven bevat een lijst van algemene programmeerblokken. Deze basisblokken kan je gebruiken om informatie op te slaan, te bewerken, of om keuzes op basis van informatie te maken. Dit klinkt waarschijnlijk nogal abstract, en dat is het ook, maar net omdat die blokken zo abstract en algemeen zijn komen ze van pas in bijna eender welk programma. In hoofdstuk 3.3 krijg je een kort overzicht van wat je allemaal met deze blokken kan doen. • Het “Services” gedeelte linksbeneden toont een lange lijst met allerlei extra programmeerblokken. Gelukkig hebben we maar enkele van deze blokken nodig, voornamelijk die blokken waarmee je met de verschillende sensors en motors van de (gesimuleerde) Lego robot kan communiceren. Deze blokken worden verder uitgelegd in hoofdstuk 3.4 en 3.5. • Het “Properties” gedeelte rechts wordt tenslotte gebruikt om de eigenschappen van het huidig geselecteerde blok (of de huidige verbinding) te wijzigen.
3.2
Visueel programmeren met blokken
Om de diagrammen3 in VPL te begrijpen moet je eerst kijken naar de algemene werking van de blokken waaruit zo’n diagram bestaat. Zo’n blok kan je eigenlijk het makkelijkst vergelijken met een elektrisch toestel waarop allerlei aansluitingen zitten. Neem nu bijvoorbeeld een televisie; aan zo’n toestel zitten verschillende invoer -en uitvoeraansluitingen (.. en vaak ook aansluitingen die beide als invoer en uitvoer gebruikt worden, maar dat is hier niet belangrijk). Je kan bijvoorbeeld een DVD-speler op je televisie aansluiten: Het beeld 3 De
diagrammen die VPL gebruikt zijn een voorbeeld van zogenaamde data flow diagrammen.
5
Figuur 4: Een eenvoudig voorbeeldprogramma dat door de DVD-speler wordt gelezen, wordt via een kabel als invoer naar de televisie gestuurd. Je zou ook extra luidsprekers kunnen aansluiten: Het geluid dat geproduceerd wordt komt als uitvoer uit de televisie, en wordt naar de luidsprekers gestuurd. De blokken in VPL werken net op dezelfde manier; ze hebben ook een aantal invoer -en uitvoeraansluitingen. Je kan de blokken ook op elkaar aansluiten door er een kabel/verbinding tussen te leggen. Het voornaamste verschil is dat je nu geen video of geluid door die kabels gaat sturen, maar je gaat er boodschappen met allerlei informatie door sturen. Hoe ziet zo’n boodschap er dan uit? Meestal is dat vrij eenvoudig; zo’n boodschap bestaat meestal uit één of meerdere getallen of korte stukjes tekst. Je kan dus vanuit één blok een boodschap sturen naar bv. de “SetMotorPower”-invoeraansluiting van een motor-blok. In die boodschap zit dan een getal om aan te duiden hoe snel dat de motor moet draaien. Via zo’n boodschappen kan één blok dus letterlijk aan een ander blok vertellen wat het moet doen. Hoe werkt dit nu allemaal in de praktijk? Laten we het voorbeeld in Figuur 4 nader bekijken: Dit kleine programma laat de robot constant rechtdoor rijden. Als er echter een obstakel (bv. een muur) op minder dan 20 cm afstand voor de robot staat, dan zal de robot naar links blijven draaien tot het obstakel is verdwenen, en zal hij daarna terug rechtdoor rijden. Dit programma kan je als volgt zelf maken: 1. Start Visual Programming Language 2008 R2 vanuit het Start menu. Je zal vanzelf beginnen met een leeg programma. 2. Ga op zoek naar “Simulated Ultrasonic” in de Services lijst linksbeneden. Sleep het naar je lege diagram om een SimulatedUltrasonic blok te maken. Dit blok stelt de ultrasoon sensor van de robot voor, waarmee je afstanden kan meten. Op dit blok zit een zogenaamde “notificatie-aansluiting”4 waarop een boodschap wordt gestuurd telkens als de gemeten afstand verandert. Er zitten momenteel nog geen kabels/verbindingen aangesloten op het blok, dus momenteel zal je programma nog niets doen. 3. We willen een keuze maken op basis van de afstand die de ultrasoon sensor meet: Als de afstand kleiner is dan 20 cm moet de robot draaien; anders moet hij rechtdoor rijden. Om keuzes te kunnen 4 Een notificatie-aansluiting (bolletje) is gelijkaardig aan een uitvoeraansluiting (uitgaande driehoek). Boodschappen op een uitvoeraansluiting zijn meestal een direct gevolg van een boodschap op een invoeraansluiting, wat niet het geval is voor notificatie-aansluitingen. Notificaties gebruik je voornamelijk op blokken die sensors voorstellen. Zie hoofdstuk 3.7 voor meer informatie.
6
(a) In -en uitvoeraansluitingen selecteren
(b) Te versturen boodschap instellen
Figuur 5: Configuratie van een verbinding tussen twee blokken maken heb je een If-blok nodig. Dit vind je linksboven in de “Basic Activities” lijst; sleep het naar je diagram. 4. Trek nu met je muis een verbinding tussen het bolletje aan het SimulatedUltrasonic blok en het invoer-driehoekje aan het If-blok. Telkens als de sensor een nieuwe afstand detecteert zal nu een boodschap met de nieuwe afstand naar het If-blok worden gestuurd. 5. Je moet je If-blok nu nog instellen zodat het weet welke keuze het juist moet maken. Dit kan je doen door te klikken in het tekstvak van het If-blok. Je krijgt nu een lijst te zien met onder andere alle informatie die wordt doorgestuurd vanuit het SimulatedUltrasonic blok. Dubbel-klik op “RawMeasurement”; dit is een variabele die de afstand (in cm) gemeten door de sensor voorstelt. Typ nu nog achteraan “< 20” zodat er staat “RawMeasurement < 20”. Je If-blok is nu volledig ingesteld: Telkens het SimulatedUltrasonic blok een nieuwe afstand ziet zal het een boodschap sturen naar het If-blok. Het If-blok zal vervolgens kijken naar de gemeten afstand: Als deze kleiner is dan 20 cm, dan wordt een boodschap gestuurd naar het eerste uitgaande driehoekje; anders wordt een boodschap gestuurd op het tweede uitgaande driehoekje (waar “Else” naast staat). 6. Nu moeten we enkel aan de wielen van de robot zeggen wat ze juist moeten doen: Zoek naar “Generic Differential Drive” in je Services lijst en sleep het naar je diagram. Met dit blok kan je de wielen van de robot aansturen. Trek nu een verbinding tussen het bovenste uitgaande driehoekje van het If-blok en de GenericDifferentialDrive. Er zal nu een venster getoond worden, net als in Figuur 5a. In dit venster wordt gevraagd op welke uitvoeraansluiting van het If-blok je je verbinding wil aansluiten (linkergedeelte van het venster), en op welke invoeraansluiting van GenericDifferentialDrive (rechtergedeelte van het venster). Kies links voor “TrueChoice” en rechts voor “SetDrivePower”, en klik op OK. Als een boodschap wordt verstuurd naar die SetDrivePower aansluiting, dan kunnen we de snelheid van het linker -en rechterwiel wijzigen. 7. Er verschijnt nu een tweede venster dat eruit ziet als in Figuur 5b. Hierin wordt gevraagd wat je juist wil meesturen in je boodschap naar SetDrivePower. Meer specifiek, er wordt gevraagd op 7
Figuur 6: Overzicht van de algemene programmeerblokken hoeveel kracht de linker-en rechtermotoren van de wielen moeten draaien. Zet onderaan een vinkje naast “Edit values directly”, zodat je zelf concrete waardes kan invullen. In de twee tekstvakken (“LeftWheelPower” en “RightWheelPower”) vul je respectievelijk -0.3 en 0.3 in. Dit wil zeggen dat je linkermotor op 30% kracht achteruit draait, en de rechtermotor op 30% vooruit draait. (Als je dus 0.0 zou invullen staat de motor stil; bij 1.0 draait hij op volle kracht vooruit en bij -1.0 draait hij op volle kracht achteruit.) Klik op OK en je verbinding is nu volledig ingesteld. Als de sensor nu dus een afstand kleiner dan 20 cm ziet, dan zal de robot constant naar links draaien aan 30% kracht. 8. Om de robot nu rechtdoor te laten rijden als de afstand 20 cm of groter is moeten we terug een verbinding leggen naar de GenericDifferentialDrive. Je kan echter geen meerdere verbindingen maken naar hetzelfde invoerdriehoekje van een blok, simpelweg omdat dit snel onduidelijk zou worden. Daarom moet je een kopie maken van je GenericDifferentialDrive blok, door het te selecteren en het te kopiëren en plakken (Ctrl+C, gevold door Ctrl+V). Hoewel je nu twee GenericDifferentialDrive blokken hebt gemaakt verwijzen ze beide naar hetzelfde, zijnde de wielen van de robot. 9. Gelijkaardig aan stap 6 en 7, trek nu een verbinding van de “Else” uitgaande driehoek, naar de GenericDifferentialDrive kopie. Selecteer wederom SetDrivePower en klik op OK. Vul deze keer 0.5 in voor LeftWheelPower, en 0.5 voor RightWheelPower. Op deze manier zal je robot rechtdoor rijden op halve kracht. Klik tenslotte op OK. 10. Alvorens je je programma kan uitproberen moet je de SimulatedUltrasonic en GenericDifferentialDrive blokken configureren, zodat ze weten welke simulatierobot ze juist moeten aansturen5 . Dit wordt uitgelegd in deel 3.4.2. 11. Zodra je de blokken hebt geconfigureerd is je programma is klaar om uitgetest te worden! Klik op de Start-knop (het groene Play symbool) bovenaan en de simulatierobot zal je programma gaan uitvoeren. Wanneer je klaar bent klik je op de “Stop” knop in het “Run” venster.
3.3
Algemene programmeerblokken
In dit hoofdstuk geven we je een kort overzicht van de voornaamste algemene programmeerblokken, ook getoond in Figuur 6, die in eender welk programma van pas kunnen komen: • Activity Creëer je eigen types blokken met het Activity blok. Meer hierover in deel 3.6. • Variable Dit blok heb je nodig als je programma iets (een getal, een stukje tekst, ..) moet onthouden zodat je het later terug kan gebruiken. Hetgene dat je wil onthouden kan je dus opslaan in een zogenaamde variabele. Dit blok gebruik je als volgt: 5 De blokken die we gebruiken zijn namelijk niet specifiek aan Lego robots en kunnen voor eender welke (gesimuleerde) robot gebruikt worden. Je programma kan dus heel eenvoudig aangepast worden om op een andere robot te draaien.
8
Figuur 7: Variabelen definiëren 1. Om allereerst een nieuwe variabele aan te maken moet je eerst op de “...” knop klikken op het Variabele blok zelf. Vervolgens krijg je een venster te zien net als in Figuur 7. Dit venster toont een lijst met alle variabelen die je momenteel zelf hebt gemaakt. 2. Klik op de Add knop om een nieuwe variabele toe te voegen. In het tekstvak kan je vervolgens een gepaste naam kiezen voor je nieuwe variabele (in plaats van de standaard “Field” naam). 3. Tevens zeer belangrijk is het type van je variabele. Met andere woorden, wat voor soort informatie wil je opslaan in je variabele? Een getal, een stuk tekst? Het type van je variabele kan je kiezen in de “Type:” lijst. De types die je meestal gaat gebruiken zijn de volgende: int Een geheel getal. Sommige sensors van de robot geven een geheel getal terug. (Bijvoorbeeld, de microfoon geeft een geheel getal tussen 0 en 100 om aan te geven hoe luid het geluid is dat de microfoon opvangt.) double Een reëel getal. Als je bijvoorbeeld wil instellen aan hoeveel kracht de wielen van de robot moeten draaien, dan wordt een reëel getal tussen -1.0 en 1.0 verwacht. Let op als je ergens een reëel getal wil meegeven; in de meeste programmeertalen typ je kommagetallen met een punt in plaats van een komma! (gezien dat in Amerika de gewoonte is..) string Een stukje tekst. Let op; als je een stuk tekst wil meegeven moet je er dubbele aanhalingstekens rond zetten! (Zo kan er geen verwarring ontstaan als je bijvoorbeeld 35 wil meegeven als tekst. “35” is duidelijk tekst omdat er aanhalingstekens rond staan. Anders zal je programma het interpreteren als een geheel getal.) De enige uitzondering op deze regel is in een Data blok; daar hoef je geen aanhalingstekens te zetten. bool Een “booleaanse” variabele heeft maar twee waardes: waar of vals. (in het Engels: true or false) Dit type gebruik je om aan te duiden of iets waar is of niet. (Je kan bijvoorbeeld het rode lampje van de lichtsensor aan of uit zetten door een booleaanse waarde mee te geven aan de SpotlightUpdate invoeraansluiting. Geef de waarde true mee om de lamp aan te zetten; false om ze uit te zetten.) 9
4. Wanneer je een type hebt gekozen voor je variabele, dan mag je op OK klikken. Normaal gezien krijg je nu de naam van je variabele in het Variable blok te zien. Het blok is nu klaar voor gebruik. 5. Als je nu iets in je variabele wil opslaan, gebruik dan de SetValue invoeraansluiting. Je kan bijvoorbeeld een verbinding maken tussen de uitvoeraansluiting van een Data blok en de SetValue invoeraansluiting van een Variable blok. De waarde van het Data blok wordt vervolgens opgeslagen in de variabele. 6. Tenslotte wil je de waarde in je variabele natuurlijk ook kunnen gebruiken. Stel dat je de variabele “MijnVariabele” hebt gemaakt, dan kan je de waarde op bijna eender welke plaats gebruiken door “state.MijnVariabele” te typen. Dat kan je bijvoorbeeld doen in het tekstvak van een If-blok, of een Calculate-blok. Je kan het ook gebruiken wanneer je een verbinding tussen twee blokken maakt en er wordt gevraagd wat er in de boodschappen voor die verbinding moet staan. • Calculate Dit blok kan je gebruiken om eenvoudige berekeningen te doen (met gehele of reële getallen). Zodra je in het tekstvak klikt van het blok zal je zien welke informatie beschikbaar is in het blok. Als je het Calculate blok bijvoorbeeld hebt aangesloten op de lichtsensor, dan zal tussen dit lijstje RawMeasurement staan, wat de gemeten waarde van je sensor voorstelt. Dubbelklik op een item in het lijstje om het in je berekening te zetten. Je kan dan met deze waarde rekenen door een rekenoperatie in te typen, dus simpelweg +, -, * of /. Het lijstje zal dan opnieuw verschijnen als je een andere waarde wil gebruiken. Je kan ook zelf simpelweg een getal intypen. Op deze manier kan je dus berekeningen schrijven in je Calculate blok. Zo’n berekening kan je zo lang maken als je zelf wil, bijvoorbeeld “(RawMeasurement / 100) + 2.0 - state.MijnVariabele”. Het resultaat van de berekening wordt vervolgens in een boodschap op de uitvoeraansluiting verstuurd. • Data Dit blok bevat een constante waarde (een getal, een stukje tekst, ..) dat je in een boodschap kan doorsturen naar een ander blok. Om het te gebruiken typ je dus bijvoorbeeld een getal of een stuk tekst (zonder aanhalingstekens!) in het blok. Vervolgens kies je aan de onderkant van het blok welk type je waarde heeft (int voor een geheel getal; double voor een reëel getal; string voor een stuk tekst). Tenslotte kan je je waarde doorsturen naar een ander blok door een verbinding te trekken vanuit de uitvoeraansluiting van het Data blok naar een invoeraansluiting van een ander blok. Indien je de invoeraansluiting van het Data-blok niet gebruikt, dan zal éénmalig de boodschap op de uitvoeraansluiting worden verstuurd zodra het programma is gestart. Als je ze wél gebruikt, dan zal de boodschap op de uitvoeraansluiting enkel verstuurd worden telkens je een boodschap ontvangt op de invoeraansluiting. • Join Dit blok wacht tot er een boodschap binnenkomt op al z’n invoeraansluitingen, en zal vervolgens al deze boodschappen combineren en als één grote boodschap langs de uitvoeraansluiting naar buiten sturen. Je kan elk van de deelboodschappen een eigen naam geven met de tekstvakken in het Join blok. • Merge Dit blok zal eender welke boodschap die binnenkomt op eender welke invoeraansluiting onmiddellijk doorsturen op de uitvoeraansluiting. (.. dus zonder te wachten op andere invoeraansluitingen, in tegenstelling tot een Join blok) • If Met dit blok kan je je programma keuzes laten maken. Naargelang hetgene dat je invult in het tekstvak van het If blok (de “conditie”) zal een binnenkomende boodschap doorgestuurd worden op één van de twee (of meerdere) uitvoeraansluitingen. Om specifiek te zijn, als de conditie waar is, dan wordt de boodschap doorgestuurd op de bovenste uitvoeraansluiting; anders op de onderste. 10
(a) Blokken van de gesimuleerde robot
(b) Blokken van de echte robot
Figuur 8: Overzicht van alle blokken om de robot aan te sturen Het invullen van het tekstvak van je If blok gebeurt vrij gelijkaardig aan het Calculate blok. Alleen gebruik je nu geen rekenoperaties, maar vergelijkingsoperaties. Er zijn verschillende vergelijkingsoperaties beschikbaar: <, >, <=, >=, =, !=. (respectievelijk: kleiner dan, groter dan, kleiner of gelijk aan, groter of gelijk aan, gelijk aan, niet gelijk aan) Als je bijvoorbeeld de lichtsensor aansluit op een If-blok zou je iets kunnen invullen als “RawMeasurement > 50”, om aan te geven dat de waarde van de lichtsensor groter moet zijn dan 50. Als dat het geval is, dan wordt een boodschap verstuurd op de bovenste uitvoeraansluiting; zo niet wordt een boodschap op de onderste uitvoeraansluiting verstuurd. Je kan ook meerdere vergelijkingen aan elkaar schakelen met && en ||. (respectievelijk: en, of) Typ bijvoorbeeld “RawMeasurement > 50 && RawMeasurement > 80” om aan te geven dat de waarde groter moet zijn als 50 én kleiner als 80. • Comment Dit blok doet op zich niets; het is niets meer dan een tekstvak dat je kan gebruiken om extra uitleg over je programma in te typen voor jezelf, of iemand anders die wil begrijpen wat je programma juist doet.
3.4
Lego Mindstorms sensor -en motorblokken
Om de Lego robot te kunnen aansturen zijn er in VPL een aantal blokken voorzien waarmee je met de verschillende sensors en motoren van de robot kan communiceren. 3.4.1
Overzicht
De blokken om de gesimuleerde robot te besturen zie je in Figuur 8a; de blokken voor de echte robot zie je in Figuur 8b. Zoals je ziet zijn sommige blokken hetzelfde voor de gesimuleerde robot en de echte robot, maar anderen zijn verschillend. We zullen in onderstaande lijst alle onderdelen van de robot overlopen en telkens aangeven welke blok benodigd is voor de gesimuleerde en de echte robot. Voor elk blok geven we ook een korte beschrijving van de belangrijkste invoer-en uitvoeraansluitingen: • Wielen van de robot: Gebruik het GenericDifferentialDrive blok, beide voor de gesimuleerde en de echte robot 11
– DriveDistance (invoer ) Laat de robot een bepaalde afstand rijden (in m) aan een bepaalde kracht (tussen -1.0 en 1.0) – RotateDegrees (invoer ) Laat de linker-en rechterwielen een bepaald aantal graden draaien aan een bepaalde kracht (tussen -1.0 en 1.0) – SetDrivePower (invoer ) Stel de kracht in van de linker-en rechtermotor zodat ze continu aan die kracht blijven draaien (tot je een andere boodschap naar dit blok stuurt). – X - Success (uitvoer ) Als je naar invoeraansluiting X een boodschap stuurde, zal (als die boodschap succesvol is verwerkt) onmiddellijk op deze uitvoeraansluiting een boodschap verstuurd worden. • Klauw van de robot: Het GenericMotor blok, beide voor de gesimuleerde en de echte robot – SetMotorPower (invoer ) Stel de kracht van de motor in (tussen -1.0 en 1.0) en de motor van de klauw blijft continu aan deze kracht draaien – SetMotorPower - Success (uitvoer ) Er wordt over deze aansluiting een boodschap verstuurd zodra de kracht van de motor succesvol is ingesteld. • Licht sensor van de robot: Het SimulatedLightSensor blok voor de gesimuleerde robot; LegoNXTLightSensorv2 voor de echte robot – AnalogSensorUpdate (notificatie) Om de zoveel milliseconden zal de sensor via deze notificatieaansluiting een boodschap uitsturen met de huidige waarde van de sensor (tussen 0 en 100, waar 0 puur zwart is en 100 puur wit). Deze waarde is beschikbaar in de RawMeasurement variabele. – SpotlightUpdate (invoer, enkel op het LegoNXTLightSensorv2 blok) Zet het rode lampje van de lichtsensor aan of uit. (De lamp moet aan zijn opdat de sensor goed kan werken.) • De ultrasoon afstandsmeter: Het SimulatedUltrasonic blok voor de gesimuleerde robot; LegoNXTUltrasonicSensorv2 voor de echte robot – AnalogSensorUpdate (notificatie) Om de zoveel milliseconden zal de sensor via deze notificatieaansluiting een boodschap uitsturen met de huidige afstand (in cm) gemeten door de sensor. Deze afstand is beschikbaar in de RawMeasurement variabele. • Drukknop van de robot: Het GenericContactSensors blok, beide voor de gesimuleerde en de echte robot – ContactSensorUpdate (notificatie) Een boodschap wordt verstuurd telkens de knop wordt ingedrukt of losgelaten. De Pressed variabele duidt aan of de knop momenteel is ingedrukt of niet. • Geluidssensor van de robot: Het LegoNXTSoundSensorv2 blok voor de echte robot; niet beschikbaar op de gesimuleerde robot – SoundSensorUpdate (notificatie) Om de zoveel milliseconden zal de sensor via deze notificatieaansluiting een boodschap uitsturen met het huidige volume (tussen 0 en 100) gemeten door de microfoon. Dit geluidsvolume is beschikbaar in de Intensity variabele.
12
Figuur 9: Overzicht van de extra programmeerblokken 3.4.2
Configuratie
Wanneer je deze sensor -en motorblokken gebruikt moet je ook een configuratiebestand instellen6 . In zo’n bestand staat bijvoorbeeld op welke poort van de NXT computer een bepaald onderdeel is aangesloten, of welke simulatieomgeving gebruikt moet worden. Je kan een sensor -of motorblok als volgt configureren: 1. Sleep het blok eerst naar je diagram indien je dit nog niet hebt gedaan. 2. Selecteer het blok door erop te klikken. 3. In het Properties gedeelte rechts, selecteer “Use a manifest” in de “Configuration:” lijst. 4. Klik vervolgens op de “Import ...” knop om een configuratiebestand te kiezen. 5. Selecteer nu één van de volgende bestanden: • Real.manifest.xml Gebruik dit configuratiebestand voor de echte robot. • SimulationStandalone.manifest.xml Kies dit bestand voor de simulatierobot in een omgeving met de standaard Lego Mindstorms mat. • Simulation-Track.manifest.xml De simulatierobot in een omgeving met een parcours (gebruikt in de Wetenschapsweek voorbeelden). • Simulation-Warehouse.manifest.xml De simulatierobot in een magazijnomgeving (gebruikt in de Wetenschapsweek voorbeelden). 6. Klik op OK en je blok is nu geconfigureerd.
3.5
Extra programmeerblokken
Naast de standaard algemene programmeerblokken en de sensor -en motorblokken zijn er ook nog allerlei extra programmeerblokken die van pas kunnen komen. Hier zijn er enkele van: • Desktop Joystick Als je dit blok in je diagram zet zal een extra venster getoond worden terwijl je programma wordt uitgevoerd. Dit venster bevat allerlei knoppen en een virtuele joystick die je zelf kan programmeren. 6 Als je werkt met de voorbeelden van de Wetenschapsweek hoef je geen configuratie te doen; de blokken in de voorbeelden zijn reeds ingesteld.
13
– UpdateButtons (notificatie) Er wordt hierop een boodschap verstuurd telkens wanneer je op één van de knoppen klikt. (Voor de meer gevorderde gebruikers: Als je wil bepalen welke knop juist is ingedrukt kan je de Pressed variabele gebruiken. Hierin zit een lijst van waar/valswaardes; voor elke knop is er één waarde in de lijst. Maak bijvoorbeeld een verbinding met een If-knop en typ daarin dan bv. “Pressed[1]”. Als je dan op de knop met het getal 1 klikt, dan zal een boodschap verstuurd worden op de eerste uitvoeraansluiting van je If-blok.) • Log Hiermee kan je tekstboodschappen tonen in het “Run” venster dat verschijnt zodra je je programma opstart. – LogError (invoer ) Toon een foutboodschap (rood gekleurd). – LogInfo (invoer ) Toon een informatieve boodschap (groen gekleurd). – LogWarning (invoer ) Toon een waarschuwing (geel gekleurd). • Simple Dialog Met dit blok kan je eenvoudige pop-up vensters tonen. – AlertDialog (invoer ) Toon een venster met een bepaalde tekstboodschap en een OK knop. – ConfirmDialog (invoer ) Toon een venster waarin je een vraag aan de gebruiker kan stellen, met een OK en een Annuleren knop. – PromptDialog (invoer ) Toon een venster waarin een tekstvak wordt getoond dat door de gebruiker ingevuld moet worden. – ConfirmDialog - Success (uitvoer ) Als je de ConfirmDialog invoeraansluiting gebruikte zal op deze uitvoeraansluiting een boodschap verstuurd worden zodra op OK of annuleren is gedrukt. De booleaanse variabele Confirmed zal true zijn als op OK is geklikt. – PromptDialog - Success (uitvoer ) Als je de PromptDialog invoeraansluiting gebruikte zal op deze uitvoeraansluiting een boodschap verstuurd worden zodra op OK of annuleren is gedrukt. De booleaanse variabele Confirmed zal true zijn als op OK is geklikt. De variabele TextData bevat de tekst die door de gebruiker is ingevuld. • Text to Speech (TTS) Laat je computer een stuk tekst uitspreken. – SayText (invoer ) Geef een stukje tekst mee aan deze invoeraansluiting en een Engelse stem zal de tekst op je computer uitspreken. • Timer Een alarmklok; handig als je een aantal (milli)seconden wil wachten. – Wait (invoer ) Aan deze invoeraansluiting kan je meegeven hoeveel milliseconden je wil wachten. Zodra deze tijd is verlopen zal op de Wait - Success uitvoeraansluiting een boodschap worden verstuurd. – SetTimer (invoer ) Aan deze invoeraansluiting kan je meegeven hoeveel milliseconden je wil wachten. Zodra deze tijd is verlopen zal op de TimerComplete notificatie een boodschap worden verstuurd. – Tick (notificatie) Elke seconde wordt op deze aansluiting een boodschap verstuurd. – TimerComplete (notificatie) Als je SetTimer hebt gebruikt om een aantal milliseconden te wachten zal op deze aansluiting een boodschap worden verstuurd zodra de klok afloopt.
14
– Wait - Success (uitvoer ) Als je Wait hebt gebruikt om een aantal milliseconden te wachten zal op deze aansluiting een boodschap worden verstuurd zodra de klok afloopt. • WaitForDriveCompletion Sommige operaties van de GenericDifferentialDrive (de wielen van de robot) duren een onbepaalde duur, bv. een aantal graden draaien of een bepaalde afstand rijden. Met dit blok kan je wachten tot zo’n operaties voltooid zijn. – Wait (invoer ) Als je deze invoeraansluiting gebruikt, dan moet het begin van de verbinding een X - Success uitvoeraansluiting zijn van een GenericDifferentialDrive blok. Stel dat je je robot een bepaald aantal graden laten draaien, en dat je vervolgens een verbinding maakt tussen de RotateDegrees - Success uitvoeraansluiting en deze Wait invoeraansluiting, dan zal dit WaitForDriveCompletion blok wachten tot de robot klaar is met draaien, en vervolgens een boodschap uitsturen via de Wait - Success uitvoeraansluiting. – Wait - Success (uitvoer ) Van zodra de robot klaar is met de operatie waarmee dit blok is verbonden, dan zal op deze uitvoeraansluiting een boodschap worden verstuurd.
3.6
Nieuwe types blokken bouwen
Om te voorkomen dat je een gigantisch groot diagram gaat tekenen als je een iets complexer programma wil bouwen kan je ook zelf nieuwe types blokken aanmaken. Deze nieuwe blokken kunnen je diagram heel wat kleiner en duidelijker maken doordat je een gedeelte van het programma in zo’n blok kan herbergen. Je kan een nieuw type blok als volgt aanmaken: 1. Sleep een Activity blok naar je diagram. Van dit blok gaan we nu ons eigen type blok maken. 2. Kies je eigen naam voor het nieuwe soort blok door het “Name:” tekstvak in te vullen in het Properties gedeelte rechts. Deze naam mag wel geen spatie-tekens bevatten! Vul vervolgens “Friendly Name:” in met dezelfde naam (Nu mag je wel spaties gebruiken) en “Description:” met een korte beschrijving van wat je blok zal doen. 3. Klik ergens op een lege plaats in je diagram en het Activity blok zal nu hernoemd zijn naar de naam die je net hebt gekozen. 4. Dubbelklik nu op het blok om het te bewerken. 5. Klik bovenaan op het knopje rechts naast de “Action” lijst. Nu krijg je het “Actions and Notifications” venster te zien, net als in Figuur 6. In dit venster kan je vastleggen welke invoeraansluitingen (ook “actions” genoemd) en notificaties beschikbaar zullen zijn op je nieuwe blok. 6. Klik op de meeste linkse Add-knop om een nieuwe invoeraansluiting te maken. In het tekstvak onder “Actions:” kan je vervolgens de naam intypen van de invoeraansluiting. 7. Met de lijst “Input values:” kan je vastleggen welke informatie verwacht wordt van boodschappen die naar je invoeraansluiting gestuurd worden. (Deze lijst werkt op dezelfde manier als de lijst waarmee je variabelen aanmaakt.) De variabelen in deze lijst zullen enkel beschikbaar zijn in het diagram voor deze invoeraansluiting. 8. Hetzelfde kan je doen voor de lijst “Output values:”. Dit is de informatie die je moet meesturen als je een boodschap verstuurd naar de uitvoeraansluiting. (Er is maar één uitvoeraansluiting beschikbaar als je zelf blokken maakt.) 15
Figuur 10: Overzicht van de extra programmeerblokken 9. Als je naast invoer -en uitvoeraansluitingen ook notificatie-aansluitingen wil maken, dan kan je dit nu doen door op het Notifications tabblad te klikken. Dit tabblad werkt op een gelijkaardige manier, maar nu moet je enkel de lijst “Notification values:” aanvullen om aan te geven welke informatie verstuurd wordt op een notificatie-aansluiting. 10. Wanneer je klaar bent, klik op OK. (Je kan de aansluitingen van je blok nog steeds achteraf aanpassen.) 11. In de “Action:” lijst bovenaan kan je nu wisselen tussen je verschillende invoeraansluitingen. (Momenteel zal je telkens een leeg diagram te zien krijgen.) De enige uitzondering is “Start”. Dit is geen invoeraansluiting, maar een diagram dat sowieso éénmalig wordt uitgevoerd aan het begin van je hele programma. (Dit kan handig zijn om variabelen een beginwaarde te geven.) 12. Nu kan je een diagram tekenen voor de invoeraansluiting die je momenteel hebt gekozen. Dit werkt op min of meer dezelfde manier die je reeds kent om programma’s te bouwen. Het grote verschil is dat je nu helemaal links een grotere invoerdriehoek ziet, en helemaal recht een grotere uitvoerdriehoek (en eventueel meerdere notificatiebollen). De boodschappen die naar je blok (dat je nu aan het programmeren bent) verstuurd worden zullen aankomen op deze grote invoerpijl. De boodschappen die uit de uitvoeraansluiting moeten komen moet je aansluiten op de grote uitvoerdriehoek. Als je een bepaalde notificatieboodschap wil sturen moet je een verbinding maken met één van de bollen rechts. 13. Op deze manier kan je een diagram tekenen voor al je invoeraansluitingen.
16
14. Wanneer je klaar bent kan je terug naar je hoofdprogramma gaan door bovenaan op het “Diagram” tabblad te klikken. Nu kan je je nieuwe blok ook eens uitproberen door het aan te sluiten op andere blokken.
3.7
Vraag en antwoord
• Waarom doet mijn programma niet wat ik verwacht? Allereerst kan je nakijken of al de sensoren motorblokken die je hebt gebruikt correct zijn geconfigureerd. Daarnaast kan het zijn dat er een waarschuwingsteken wordt getoond in sommige blokken. Dit kan erop duiden dat je ergens het verkeerde type van informatie hebt ingevuld. (Je geeft bijvoorbeeld ergens een reëel getal mee waar een geheel getal is verwacht.) Het kan ook gebeuren dat je per ongeluk de verkeerde invoer-of uitvoeraansluiting hebt gekozen, of dat je een uitvoeraansluiting gebruikt zonder eerst iets met de overeenkomstige invoeraansluiting te verbinden. Mocht het nog steeds onduidelijk zijn waarom je programma niet juist werkt, probeer dan gedeeltes van je programma te verwijderen tot je terug een verwacht resultaat krijgt, om op die manier de bron van de fout te kunnen opsporen. Wat tenslotte ook zinvol kan zijn (in grotere programma’s) is om een apart klein testprogramma te maken waarin je enkel het gedeelte uittest dat niet lijkt te werken. • Wat is het verschil tussen een uitvoeraansluiting en een notificatie? Visueel wordt een uitvoeraansluiting voorgesteld als het uitgaand driehoekje naast een blok; een notificatie-aansluiting ziet eruit als een bolletje. Als een blok een boodschap verstuurd naar één van z’n uitvoeraansluitingen, dan is dit altijd een rechtstreeks gevolg van een boodschap die het blok via één van de invoeraansluitingen heeft aangekregen. (Sommige blokken vormen een uitzondering op deze regel, bv. het Data blok. Als er niets op de invoeraansluitingen van een Data blok is aangesloten, dan zal het éénmalig in het begin van het programma een boodschap sturen op z’n uitvoeraansluiting.) Aan de andere kant, als je een notificatie-aansluiting gebruikt, dan lijkt het alsof er “uit het niets” boodschappen op verstuurd kunnen worden. Bij een gewone uitvoeraansluiting verwacht je dat er een boodschap op verstuurd wordt als reactie op iets dat naar een invoeraansluiting is verstuurd. Zo’n notificatie-aansluiting gebruik je vooral voor blokken die sensors aansturen. Stel je gebruikt een drukknop sensor: Als je op de knop drukt zal het overeenkomstige blok een notificatieboodschap versturen. Omdat je programma echter geen weet heeft van de buitenwereld lijkt het dus alsof die boodschap uit het niets komt. Om die reden is het overigens niet mogelijk dat je een invoeraansluiting van een blok gebruikt, én een notificatie-aansluiting van hetzelfde blok. Anders lijkt het alsof boodschappen op de notificatie-aansluiting een reactie zijn op de invoeraansluiting, wat er verwarrend uitziet. Je kan dus enkel een notificatie-aansluiting gebruiken als er niets op de invoeraansluitingen is aangesloten. • Hoe kan ik wijzigen welke boodschappen verstuurd moeten worden door een verbinding? Klik eender waar op de verbinding en je krijgt de details te zien in het Properties gedeelte rechts, waar je ze ook kan aanpassen. • Kan ik mijn blokken geen andere naam geven? Zeker: Klik simpelweg op het blok en wijzig de naam in het “Name:” tekstveld in het Properties gedeelte rechts. Klik ergens op een lege plaats in je programma en je blok (en alle kopies ervan) krijgen de nieuwe naam. • Kan ik een andere robot gebruiken als het “Tri bot” model? Wat betreft de echte robot mag je gerust eender welk model bouwen. De programmeerblokken blijven zoals verwacht werken. (Behalve enkele invoeraansluitingen op de GenericDifferentialDrive, met name RotateDegrees en DriveDistance. 17
Deze operaties gaan ervan uit dat de wielen een bepaalde diameter hebben en op een bepaalde afstand van elkaar staan.) Wat betreft de simulatie is voorlopig enkel het “Tri bot” model beschikbaar. • Wat als ik meerdere verschillende Timer blokken (alarmklokken) wil maken? Soms wil je meerdere Timer blokken aanmaken die niet allemaal een kopie van elkaar zijn. Op die manier kan je meerdere verschillende klokken tegelijk instellen, of kan je iets verschillend doen naargelang welke klok afloopt. Om meerdere verschillende klokken te maken moet je een Timer blok uit de Services lijst links naar je diagram slepen. Als je reeds een Timer blok hebt gebruikt zal nu een venster “Add activity” verschijnen. Kies “Add a new activity” en klik op OK. Je nieuwe Timer blok is nu verschillend van de Timer die al bestond. De naam zal ook lichtjes anders zijn, bijvoorbeeld Timer0. • Waar kan ik meer informatie rond de Visual Programming Language vinden? Je kan de officiële handleiding (in het Engels) vinden op: http://msdn.microsoft.com/en-us/library/bb964572.aspx. Daarnaast vind je op dit adres ook de nodige informatie voor de gehele Microsoft Robotics omgeving (, waarvan de Visual Programming Language een onderdeel is).
18