forked from arindam1993/PyBioSim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Simulator.py
179 lines (142 loc) · 5.54 KB
/
Simulator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
'''
Created on Jan 16, 2015
@author: Arindam
'''
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from numpy import *
from World import *
from Agent import Agent
from Obstacle import *
from pylab import *
from Ball import Ball
from LinearAlegebraUtils import distBetween
from RunAtBallBrain import RunAtBallBrain
from Team import Team
#Called once for initialization
'''
Usage guidelines:
1. Define globals required for the simulation in the __init__ constructor, here we define a bunch of waypoints for the ball
2. Initialize the globals in the setup() method.
'''
class Simulator(object):
def __init__(self, world, simTime, fps, imageDirName):
self.world = world
self.simTime = simTime
self.fps = fps
self.imageDirName = imageDirName
self.currWP = 0
self.ballWPs = [array([50.0, -100.0, 0.0]), array([0.0, 100.0, -70.0]), array([50.0, 20.0, 100.0]),array([-30.0, 50.0, -100.0]), array([80.0, -50.0, 50.0]), array([80.0, -50.0, -50.0]), array([-65.0, 20.0, 50.0]), array([-50.0, 20.0, -60.0])]
self.fig = plt.figure(figsize=(16,12))
self.timeStep = 1/float(30)
self.frameProb = float(self.fps) / 30
self.currTime = float(0)
self.drawIndex = 0
self.physicsIndex = 0
def setup(self):
#setup directory to save the images
self.imageDirName = 'images'
try:
os.mkdir(self.imageDirName)
except:
print self.imageDirName + " subdirectory already exists. OK."
#define teams which the agents can be a part of
teamA = Team("A", '#ff99ff')
teamB = Team("B", '#ffcc99')
#Defining a couple of agents
ag1Pos = array([80, 50, -20])
ag1Rot = array([30, 0, 0])
ag1Brain = RunAtBallBrain()
agent1 = Agent(teamA, ag1Pos, ag1Rot, ag1Brain, 5, 5)
ag2Pos = array([-80, 0, 0])
ag2Rot = array([0, 0, 0])
ag2Brain = RunAtBallBrain()
agent2 = Agent(teamA, ag2Pos, ag2Rot, ag2Brain, 5, 5)
ag3Pos = array([70, 30, 50])
ag3Rot = array([0, 0, 0])
ag3Brain = RunAtBallBrain()
agent3 = Agent(teamB, ag3Pos, ag3Rot, ag3Brain, 5, 5)
ag4Pos = array([-80, 20, 60])
ag4Rot = array([0, 0, 0])
ag4Brain = RunAtBallBrain()
agent4 = Agent(teamB, ag4Pos, ag4Rot, ag4Brain, 5, 5)
#Add the agent to the world
self.world.agents.append(agent1)
self.world.agents.append(agent2)
self.world.agents.append(agent3)
self.world.agents.append(agent4)
#define a bunch of obstacles
ob1Pos = array([-50,-50,-50])
ob1 = Obstacle(ob1Pos, 30)
ob2Pos = array([80,-50,-50])
ob2 = Obstacle(ob2Pos, 20)
#add obstacles to the world
self.world.obstacles.append(ob1)
self.world.obstacles.append(ob2)
#define a ball
ball = Ball(array([0, 0, 0]))
#add the ball to the world
self.world.balls.append(ball)
# called at a fixed 30fps always
# physics simulation
def fixedLoop(self):
for agent in self.world.agents:
agent.moveAgent(self.world)
for ball in self.world.balls:
if len(self.ballWPs) > 0:
ball.moveBall(self.ballWPs[0], 1)
if distBetween(ball.position, self.ballWPs[0]) < 0.5:
if len(self.ballWPs) > 0:
self.ballWPs.remove(self.ballWPs[0])
#Called at specifed fps
def loop(self, ax):
self.world.draw(ax)
# advances simulation 1 tick, returns the current world state plot
def tick(self):
self.fixedLoop()
self.fig.clf()
ax = self.fig.add_subplot(111, projection='3d')
ax.view_init(elev = 30)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
return self.loop(ax), plt.gca().set_ylim(ax.get_ylim()[::-1])
def run(self):
#Run setup once
self.setup()
while(self.currTime < self.simTime):
self.fixedLoop()
currProb = float(self.drawIndex)/float(self.physicsIndex+1)
if currProb < self.frameProb:
self.drawFrame(self.drawIndex)
self.drawIndex+=1
self.physicsIndex+=1
self.currTime+=float(self.timeStep)
print "Physics ran for "+str(self.physicsIndex)+" steps"
print "Drawing ran for "+str(self.drawIndex)+" steps"
def drawFrame(self, loopIndex):
self.fig.clf()
ax = self.fig.add_subplot(111, projection='3d')
ax.view_init(elev = 30)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
fname = self.imageDirName + "/img{:08d}.png".format(int(loopIndex)) # name the file
self.loop(ax)
plt.gca().set_ylim(ax.get_ylim()[::-1])
self.fig.savefig(fname, format='png', bbox_inches='tight')
print 'Written Frame No.'+ str(loopIndex)+' to '+ fname
#Simulation runs here
#set the size of the world
# world = World(100, 100)
#specify which world to simulate, total simulation time, and framerate for video
# sim = Simulator(world, 60, 30, "images")
#run the simulation
# sim.run()
'''
To create a video using the image sequence, execute the following command in command line.
>ffmpeg -f image2 -i "1%08d.png" -r 30 outPut.mp4
Make sure to set your current working directory to /images and have ffmpeg in your path.
'''