Logistieke Robots/les 3

Uit Lab
Naar navigatie springen Naar zoeken springen
Logistieke Robots

Lessen

  1. Les 1
  2. Les 2
  3. Les 3
  4. Les 4
  5. Les 5
  6. Les 6
  7. Les 7
  8. Les 8

Software

Zie ook Regels en richtlijnen
Zie ook Artikelen bewerken

Morsy besturen met Python

In de vorige les hebben we gezien dat de controller van Morsy veel complexer wordt als we hem autonoom aan willen sturen. Wanneer we Morsy nog meer taken willen geven, en wanneer we Morsy in een groep willen laten werken, zijn de logic bricks niet meer toereikend. Daarom gaan we Blender combineren met de programmeertaal Python.

Controleer eerst of de juiste versie van Python op je systeem geïnstalleerd is, op de juiste plaats. (Zie: Python installeren voor verdere aanwijzingen.) In sommige gevallen is Python geïnstalleerd als onderdeel van Blender.

Blender combineren met programmeertaal Python

In deze les gebruiken we warehouse.blend. Deze omgeving zullen we gedurende de rest van het project gebruiken. Het openen van het bestand gaat nu anders omdat we de Python output willen zien.

OS X: Blender opstarten met Terminal

Ga naar de Blender applicatie en open de Package Contents van Blender.

Show Package contents

Open vervolgens het blender executable bestand via het openen van de volgende folders:

Blender starten met terminal

Als Blender opstart, kun je via File>Open het bestand “warehouse.blend” openen.

Windows:

Open Blender op de gebruikelijke manier. Ga naar de Info Window en klik op Window >Toggle System Console. Er is nu een extra scherm in beeld.

Wanneer je de file “warehouse.blend” geopend hebt, zie je in het window linksonder een Tekst Editor. Hier kun je een Python controller ontwikkelen.

Controleren of Python werkt in Blender

Om te testen of de link tussen Blender en Python werkt, voeren we de volgende stappen uit:

  1. Voeg aan Robot_11 (de voorste) een Always sensor toe.
  2. Maak een nieuw Python script aan:
    1. klik op de "+" onderin het Text Editor venster (naast de naam van het bestand).
    2. verander de naam van het bestand in "Text.py"
    3. typ in de Text Editor: print(“Hello”)
  3. Voeg aan Robot_11 een Python controller:
    Voeg Python controller toe
  4. Selecteer als script voor deze Python-controller: "Text.py"
  5. Link de controller met de sensor:
    Link sensor en controller
  6. Ga na de spel modus (of, voor OS X, naar de Terminal) en kijk naar de console. Dit moet er nu in de console te zien zijn:
Blender Game Engine Started
Hello
Blender Game Engine Finished

Ontwikkelen van een controller in Python

Nu je weet hoe je Python aan Blender moet koppelen, kunnen we een Python controller maken. We gaan Morsy, nu genaamd Robot_11, naar een kast laten lopen om een artikel op te halen en in de box te zetten op tafel. Voordat we hieraan kunnen beginnen moeten we begrijpen hoe je sensoren kunt opvangen en actuatoren kunt aansturen via een Python controller.

Morsy laten lopen door een Python controller

Wat je in deze paragraaf gaat leren lijkt op wat je geleerd hebt in les 2, het autonoom laten ophalen van objecten en naar een bepaald doel brengen, maar nu doen we dat via een Python controller.

Stap 1: Onderdelen van een script

Blender heeft al een opzet voor hoe je een robot moet aansturen. Ga in de Tekst editor window naar Templates > Python> GameLogic Simple. Je ziet nu de volgende code verschijnen:

import bge


def main():

    cont = bge.logic.getCurrentController()
    own = cont.owner

    sens = cont.sensors['mySensor']
    actu = cont.actuators['myActuator']

    if sens.positive:
        cont.activate(actu)
    else:
        cont.deactivate(actu)

main()

Dit heet een script. Dit script bestaat uit verschillende onderdelen.

  • (r. 1) import bge importeert de Blender Game Engine module voor Python. In deze module is onder andere de functie logic.getCurrentController() gedefinieerd.
  • (r. 4-15) De definitie van de functie main();
  • (r. 17) Een aanroep van de functie main(): de opdrachten in de definitie daarvan worden uitgevoerd.

Het is belangrijk om te begrijpen hoe een script werkt. Wanneer deze controller geactiveerd wordt (bijvoorbeeld door een sensor), wordt het script uitgevoerd, en gebeurt er het volgende:

  1. import bge - Het script importeert de module ‘bge’ en beschikt zo over alle gedefinieerde functies in de bge module.
  2. def main(): - definieert de functie main met de daarop volgende opdrachten.
  3. main() - aanroep van de functie main. De opdrachten in de definitie (“body”) van de functie main worden uitgevoerd.

Stap 2: Sensors en actuators toevoegen

Als we op ENTER (ofwel Return) drukken willen we dat Morsy naar de voorste kast gaat lopen. Ga door de volgende stappen heen om de juiste sensors en actuators toe te voegen:

  1. Verander de Always sensor in een Keyboard sensor met als Key de ENTER knop. Geef deze sensor de naam ‘Start’
  2. Voeg een Steering actuator toe. Laat deze de naam ‘Steering’ houden en over de –X as bewegen.
  3. Voeg een Collission sensor genaamd ‘AtTarget’ toe link deze aan de Python controller.

Dit zijn alle actuators en sensors die we nodig hebben om de genoemde taak uit te voeren.

Stap 3: Triggers ontvangen en versturen door de Python controller

In de vorige lessen hadden we een sensor, bijvoorbeeld een Keyboard sensor, aan een And controller gekoppeld. Wanneer je de juiste toets aanraakt op je toetsenbord gaat er een positieve ‘trigger’ naar de And controller die de bijbehorende actuator activeert.

Nu moeten we de Start trigger op zien te vangen in de Python controller. Doe dit als volgt:

  • Het script moet de controller kunnen aanroepen waar de sensoren en actuatoren aan gekoppeld zijn. Dit kan door de functie bge.logic.getCurrentController()
  • Vervolgens moet de controller kunnen herkennen welke van de inkomende sensoren een trigger geeft om een juiste actuator aan te roepen. Je kunt deze sensoren vinden via cont.sensors[“Start”] en cont.sensors[“AtTarget”]

Om de code overzichtelijk te houden kun je verwijzingen maken naar de sensoren en actuatoren. Je mag deze namen zelf verzinnen of de volgende gebruiken:

import bge
cont = bge.logic.getCurrentController()
start = cont.sensors[Start]
collision = cont.sensors[AtTarget]

def main():
  # define function main…

main()
  • Bij het indrukken van de ENTER key, willen we dat Morsy zijn taak uit gaat voeren. Zowel het indrukken als het loslaten van de ENTER key geeft een trigger aan de controller. Het indrukken is een positive pulse en loslaten een negative pulse. Via een boolean (met waarde TRUE of FALSE) wordt aangegeven of er een pulse gegeven wordt. We willen dat de main() alleen aangeroepen wordt als start.positive TRUE is. Omdat start.positive een boolean is kun je dit als volgt opschrijven:
if start.positive
    main()

(Let op: een Tab in Python staat gelijk aan 4 spaties en is nodig om aan te geven wat er moet gebeuren als de conditie van de if TRUE is)

  • Zorg ervoor dat in de definitie van de functie main() de Steering actuator geactiveerd wordt en naar Shelf_8 toe gaat (de voorste kast). De code ziet er nu als volgt uit:
import bge

cont = bge.logic.getCurrentController()
start = cont.sensors[Start]
collision = cont.sensors[AtTarget]
steering - cont.actuators[Steering]

def main():
    steering.target = Shelf_8
    cont.activate(steering)

if start.positive:
    main()

Stap 4: Script afmaken

Wanneer je nu in de play modus gaat en op ENTER drukt zie je dat Morsy naar Shelf_8 gaat lopen.

In deze stap ga je zelf uitzoeken hoe Morsy heen en weer loopt naar de kast. Het is geen vereiste meer dat de ENTER key voor de start zorgt. Morsy mag gelijk van start gaan in de play modus. Denk zelf na hoe je dit moet doen.

Tips: je moet een Game Property aanmaken voor Desk_11, Shelf_8 en een voor Robot_11 om aan te geven waar hij heen moet lopen. Deze kun je aanroepen en veranderen via de variabele cont.owner[“naam van game propery”] . Ook moet je in de Collision sensor de Tap button aanklikken om maar 1 trigger te geven bij aanraking van de tafel of kast.

De Start sensor kun je veranderen in een Always sensors zodat Morsy gelijk begint met lopen.

Het is niet erg als je er zelf nog niet helemaal uit bent gekomen. Juist als het niet werkt zoals je wilt leer je hier meer van doordat je de verkeerde code moet herstellen. Wanneer je er niet uit komt kun je naar onderstaande uitwerking kijken:

import bge

def main():
    print("main called")
    cont = bge.logic.getCurrentController()
    own = cont.owner

    collision1 = cont.sensors['AtTarget']
    steering = cont.actuators['Steering']
   
    if collision1.positive:
        print("Collision   target=" + steering.target.name)
        if steering.target.name == "Shelf_8":
            steering.target = "Desk_11"
            collision1.propName = "Desk"
        else:
            steering.target = "Shelf_8"
            collision1.propName = "Shelf"
    else:
        print("no Collision")        

    cont.activate(steering)

main()