Custom Simulations - snowpuppy/augreality GitHub Wiki
This tutorial will explain the process of creating a simulation for the augmented reality hardware in detail.
To create your own custom simulation, you will need to create a number of files. A pacman and a tree example have been created and may be referenced when writing a simulation. This tutorial will use the tree simulation as an example of the least amount of work required to create a simulation. The files needed are:
- ascii art config file
- 3d models for your simulation in a models/ directory
- A python program that includes the necessary interfaces to integrate with the framework.
There are three main sections of the config file:
- Global Settings
- Letter Mapping
- Ascii Map
[GlobalSettings] WIDTH 37 HEIGHT 31 SCALE 1 ORIGINX 11 ORIGINY 14
The Global Settings section must begin with "[GlobalSettings]". There cannot be any non whitespace before this identifier in the config file. Every item following this identifier must follow on consecutive lines. The last entry must have one empty line after it before the "[LetterMapping]" identifier. The WIDTH parameter specifies how many characters are on one line for the map. The map must be rectangular. The HEIGHT parameter specifies how many lines there are in the map. The SCALE specifies what the map coordinates should be multiplied by if you would like to make the map bigger by an integer scale. The ORIGINX and ORIGINY numbers specify the the location where the user will start in the map. The X increases going down and the Y increases going right on your map.
[LetterMapping] t tree scale=1 is3d=1 p pikachu scale=1 is3d=1
The Letter Mapping section allows you to specify any number of mappings from characters to objects. Each line must have a visible character (not whitespace), followed by a space, followed by the name of the object which will be used when referencing the object in the dictionary in the python simulation, followed by a space, followed by the word scale, followed by '=', followed by a floating point number, followed by a space, followed by the word is3d, followed by '=', followed by an integer (either 1 or 0). The scale parameter allows one to request that the rendering code scale an object to make it bigger or smaller. The is3d should always be 1 for now, but will specify whether this is a flat 2d image or a 3d object. The name following the character must also be the name of the 3d model! See the "models/" dir in the tree simulation for an example. There must be a blank line after the list of character mappings.
[AsciiMap] t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t ppppppppppppppp t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t
The ascii map must start with the "[AsciiMap]" identifier. The next line must start the map. White spaces indicate that the coordinate is not used. A character indicates that an object from the character mapping should be placed at this coordinate.
All 3D models need to go into the "models/" directory for your Sim. The Sims are stored in the "augreality/headset/src/simulation_src/simulations/" directory. You will need to create your own directory there with the name of your simulation.
The python simulation must be end in ".py" and have the letters "Sim" in it somewhere. I recommend following the convention of "nameSim.py" where "name" is the name of your simulation (e.x. pacmanSim.py or treesSim.py). The required portions of the python simulation and what they do are explained below using treesSim.py as an example.
#!/usr/bin/python # # Filename: treeSim.py # Author: Thor Smith # Purpose: Create a sample python application to run the tree simulation. # from __future__ import division import sys import os import socket import time import copy import subprocess from math import sqrt
From the imports above the os, sys, and subprocess are required. The Time module is required to call the sleep function and add delays. Copy, division, socket, and sqrt are all optional and should probably be removed from this file eventually...
os.chdir(sys.path[0]) sys.path.append(os.path.realpath('../gui_src/')) from guiNetInterface import * from gpuPyInterface import *
The code above is necessary. It sets the working directory so that the guiNetInterface and the gpuPyInterface can be included. These interfaces provide the API for communicating with the rendering software and the networking/sensor software. The guiNetInterface is in the gui_src/ directory.
# hardcoded id of headset. subprocess.Popen(["../gpu_src/render/render", "simulations/trees/trees", "simulations/trees/models/"]) time.sleep(1.0) output = getRunning(); #print "Running", output
The code above is necessary. It starts the 3d rendering code that the simulation will be communicating with. The rendering code takes two arguments as can be seen from the Popen call. The first argument is the ascii art map file and the second argument is the path to the models for your simulation. Both of these arguments will need to be updated should you write your own simulation. Just follow the pattern.
# reset origin on game start. resetGPSOrigin()
This code above was added for redundancy and should be removed from this simulation. It is NOT necessary, but demonstrates that it is possible to reset the origin after starting the simulation.
# Read in the information for each # object from the config file. configFile = open("tmp.cfg"); myObjs = readObjsFromConfig(configFile) time.sleep(3.0)
The code above does a neat trick. It reads in the temporary config file generated by the rendering code and makes a list of all 3d objects for you that have position information and fills in their starting attributes. The starting attributes can be changed and a subset of this list of objects may be passed to the appropriate updateObjs() function to tell the rendering code to apply your change. The information is passed through sockets to the rendering code. The function can be found in the gpuPyInterface.py file. While the "open" call and the "readObjsFromConfig" call should be left in your simulation, the "time.sleep" is arbitrary and you may leave it out.
# def __init__(self, instId, typeShow, x2, y2, x3, y3, z3, roll, pitch, yaw, scale, name): gameEnd = False while (not gameEnd): if gameEnd: break try: output = getRunning(); except: print "Rendering exited... Quitting simulation." exit() time.sleep(.1)
The main loop is above. The comment shows the constructor for the objects read in by the readObjsFromConfig function. The gameEnd variable determines the end of game condition, which isn't actually used for much in this simulation. This simulation keeps running until the user tells the rendering software to quit by pressing "-" on the numpad. The call to "getRunning()" will cause an exception if the rendering code is not running. By catching this exception, we can gracefully exit the simulation when the user quits. Every simulation should have this bit of code to allow the user to manually quit the rendering code. When this process ends, control will return to the user interface.
time.sleep(3.0) gpuQuit()
While this code is never run (the delay isn't necessary), it shows that it is possible to quit the rendering software on demand. Calling gpuQuit tells the rendering software to exit. This will primarily be used when you have reached and end of simulation condition and wish to stop the simulation automatically for the user.