Logistieke Robots/les 4
Les 4
In de vorige les heb je de basis geleerd om een controller te ontwikkelen met behulp van Python. We hebben ook de omgeving geïntroduceerd waar we de rest van het project mee blijven werken: een magazijn. De robots krijgen bestellingen binnen die uit verschillende artikelen bestaan. Ze moeten deze artikelen gaan verzamelen om de bestelling compleet te maken. Dit kan natuurlijk op meerdere manieren: een robot kan de artikelen 1 voor 1 ophalen, allemaal in 1 keer of misschien kan deze robot maar een maximaal aantal artikelen tillen, of een maximaal gewicht. Als de bestelling compleet is, krijgt een robot een nieuwe bestelling.
In deze les leren we hoe we een controller kunnen maken voor 1 robot die de artikelen 1 voor 1 ophaalt. Open de file “warehouse_one_order.blend”. Wat je in deze les ontwikkelt, gebruik je in de volgende lessen als basis om op door werken.
Sturen van de bestelling door centrale systeem
Een robot moet een bestelling doorkrijgen van een computer die het overzicht heeft over alle bestellingen. Deze controller moeten we aan een centraal object in Blender toegevoegen. We kiezen hiervoor de vloer (Ground object).
Net als in de vorige les ontwikkelen we de controller via de logic bricks en via Python scripting.
Stap 1: Python script aanmaken voor Ground object
- Selecteer het Ground object;
- Maak een nieuw Python script aan door op het ‘+ New’ teken te drukken in de header van de tekst editor. Geef het script de naam “central_controller.py”;
- Voeg een Python controller aan met dit script.
Stap 2: Logic bricks voor Ground object
- Voeg een keyboard “Start” sensor toe met de ENTER key. Druk op Tap. Dit betekent dat de sensor eenmalig een positieve puls geeft aan de controller in plaats van zolang de sensor waar is.
- Verbind deze sensor met de Python-controller van de vorige stap.
Stap 3: Programmeren script “central_controller.py”
In deze stap programmeren we de centrale controller die de bestellingen verstuurt aan de robot. Hier zullen we voor het eerst ingewikkeldere Python kennis gebruiken. Het script bouwen we op de volgende manier op:
- Importeren van de nodige packages, ophalen van de controller en het object en declareren van de sensor. Dit hebben we ook gezien in de vorige les.
import bge
import GameLogic
import random
cont = bge.logic.getCurrentController() # controller of this script
central = cont.owner # game object owning this controller
# get sensors
sens = cont.sensors["Start"]
- Definiëren van variabelen. We hebben al gezien dat je variabelen kunt definiëren door “Game Properties” aan te maken voor een game-object zoals een robot. De vloer is ook een dergelijk game-object waar we een controller en variabelen aan kunnen koppelen. Deze variabelen kun je aanmaken en een waarde geven via het script met behulp van de volgende code:
game_object[“naam_variabele”] = waarde
Belangrijke variabelen in het pakhuis zijn hoeveel boxen er gevuld moeten worden, hoe groot de bestellingen zijn en welke artikelen in deze box kunnen zitten. Dit coderen we dus als volgt:
# define game properties
central["boxes_tot"] = 5
central["box_size"] = 3
box_articles = ["Shelf_1", "Shelf_2", "Shelf_3", "Shelf_4", "Shelf_5", "Shelf_6", "Shelf_7", "Shelf_8"]
“boxes_tot” en “box_size” zijn game properties verbonden aan het Ground object.
“box_articles” is een lokale variabele in het script - en geen game-property. Dit is een array van strings: deze declareren we op de manier van Python. Shelf_1 tot en met Shelf_8 corresponderen met de kasten die te zien zijn in het pakhuis en iedere kast heeft één soort artikel. Shelf_1 heeft dus een kast vol met artikelen nummer 1.
- We willen dat het systeem pas begint wanneer we op ENTER drukken. Wanneer deze sensor, “sens”, een positieve puls krijgt, wil je Robot_11 een bestelling (order) meegeven. Dit kan op de volgende manier:
if sens.positive:
robot = "11"
Send_order(robot)
waarin Send_order
als volgt gedefinieerd is:
def Send_order(robot):
order = ""
for j in range(central["box_size"]):
order += " " + random.choice(box_articles)
GameLogic.sendMessage("Start", order , "Robot_"+robot , "Ground")
GameLogic.sendMessage("Start", robot , "Robot_"+robot , "Ground")
Zoals je kunt zien krijgt de functie Send_order een getal mee van de robot waar de bestelling naar toe moet. Dit doen we omdat we straks meer robots aan gaan sturen met deze functie. Vervolgens maken we een order aan. Dit moet in de vorm van een String variabelen omdat we deze anders niet mee kunnen sturen naar de robot. We plakken steeds een willekeurig artikel (tussen 1 en 8) aan de order. Wanneer we de lengte van de order bereikt hebben, in ons geval 3, sturen we de order naar de robot en ook de variabele “robot”. Dit laatste doen we zodat we de robot.py controller kunnen hergebruiken voor alle robots. We hoeven dan niet een aparte python controller te maken voor iedere robot. De sendMessage functie is een functie die Blender al voor ons heeft gemaakt. Aan deze functie moet je de titel geven van de message (let op: de robot moet dus een message “Start” sensor hebben), wat er in de message staat, naar wie de message toe moet en wie deze message stuurt.
Inpakken van de bestelling
De centrale controller kan nu een order sturen naar de Robot_11. Robot_11 moet wel in staat zijn de message op te kunnen vangen en vervolgens aan de slag te gaan. Dit doen we weer aan de hand van de zelfde stappen als in de vorige paragraaf.
Stap 1: Python script aanmaken voor Robot_11
Creëer een python script door op het ‘+’ teken te drukken in de header van de tekst editor. Geef het script de naam “robot.py”.
Stap 2: Logic bricks voor Robot_11
- Voeg een message “Start” sensor toe
- Voeg een collission “Shelf” sensor toe met de Tap functie aan
- Voeg de python controller toe
- Voeg een steering “TrackTo” actuator toe, facing de –X as.
- Voeg een Integer Game Property “article_number” toe en vink je blauwe “i” aan. We hebben gezien dat je deze ook aan kunt maken via Python scripting maar alleen op deze manier kun je ervoor zorgen dat de variabele in de 3D window te zien is.
Stap 3: Programmeren script “robot.py”
- Importeer de nodige packages, haal de controller op en definieer de sensoren/actuatoren.
# import necessary packages
import bge
import GameLogic
import re
# get the current controller
cont = bge.logic.getCurrentController()
robot = cont.owner
# get sensors and actuators
start_sens = cont.sensors["Start"]
shelf_sens = cont.sensors["Shelf"]
track_act = cont.actuators["TrackTo"]
- Bij een positieve puls door het ontvangen van de “Start” message vang je de bestelling als volgt op:
if start_sens.positive:
priint("Start new order:")
get_order
Nieuwe bestelling
Als er meerdere bestellingen ingepakt moeten worden, kan de robot aan de centrale controller doorgeven dat hij klaar is voor een nieuwe bestelling. Deze nieuwe bestelling is er omdat we in de central_controller aangegeven hebben dat we 5 boxen willen vullen.
Logic bricks uitbreiding voor Ground object
- voeg een message “Done” sensor toe
- voeg een integer game property toe met de naam “boxes_done”, zodat we deze in de 3D view kunnen zien
Script uitbreiding voor Ground object
- De zojuist aangemaakt sensor moet in het script opgehaald worden:
- Wanneer de message een positieve puls geeft moet de centrale controller hierop reageren door nog een order te sturen. Dit kan op de volgende manier:
Script uitbereiding voor Robot object In de controller van de robot hoeft maar 1 regel toegevoegd te worden. Denk zelf over deze regel na. Als dit niet lukt zoek dan het verschil in onderstaande code:
Kijk of je programma werkt door naar de spelmodus te gaan. De output in de Terminal moet er als volgt uit zien (waarbij de inhoud van de orders kan verschillen):
Plusopdracht
- Visualiseer dat artikelen vastgehouden worden door de robot en op de tafel geplaats worden. Wanneer alle artikelen compleet zijn, mogen ze verdwijnen in de box.
- De robot haalt de artikelen nu 1 voor 1 op. Implementeer het scenario dat de robot alle artikelen in 1 keer op kan halen. De robot loopt dus eerst langs meerdere kasten voordat