From 549be0e7da59f69910d4711d991f9a0707d7b86b Mon Sep 17 00:00:00 2001 From: Chris Chow Date: Sat, 7 Mar 2015 21:06:30 -0500 Subject: [PATCH 1/3] faster video rendering --- Main.py | 43 ++++++++++++++++++++++++++++ Simulator.py | 80 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 Main.py diff --git a/Main.py b/Main.py new file mode 100644 index 0000000..6278779 --- /dev/null +++ b/Main.py @@ -0,0 +1,43 @@ +__author__ = 'chris' + +import Simulator +import World +from matplotlib import animation + + +FPS = 30 # hardcoded into simulation assumptions + +world = World.World(100, 100) +sim = Simulator.Simulator(world, 10, FPS, "images") + + +# simulator assumes its physics simulation is running at dt = 1/30 s +# would have to recalculate the true animation framerate (to get physically accurate speeds, etc) +# if you change the raw sample rate of the animator function (which accepts arguments in ms) +simlen = 10 # sec +frames = FPS * simlen + +def tick(i): + return sim.tick() + +ani = animation.FuncAnimation(sim.fig, tick, frames=frames, blit=True, init_func=sim.setup) + +import time + +t = time.time() +ani.save('hello.mp4', fps=FPS, extra_args=['-vcodec', 'libx264']) +print "execution time:", time.time() - t +# execution time: 178.861850023 + +# t = time.time() +# sim.run() +# print "execution time:", time.time() - t +# execution time: 591.768985033 + +# +# os.chdir("images") +# +# callstring = ["ffmpeg", "-f", "image2", "-i", 'img%08d.png', "-r", str(FPS), "output.mp4"] +# +# +# call(callstring) \ No newline at end of file diff --git a/Simulator.py b/Simulator.py index ad28c6d..0c8f614 100644 --- a/Simulator.py +++ b/Simulator.py @@ -5,6 +5,8 @@ ''' import numpy as np +import matplotlib +matplotlib.use("Agg") import matplotlib.pyplot as plt from numpy import * from World import * @@ -17,7 +19,6 @@ from Team import Team - #Called once for initialization ''' Usage guidelines: @@ -33,6 +34,13 @@ def __init__(self, world, simTime, fps, imageDirName): 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 @@ -74,7 +82,6 @@ def setup(self): self.world.agents.append(agent3) self.world.agents.append(agent4) -# #define a bunch of obstacles ob1Pos = array([-50,-50,-50]) ob1 = Obstacle(ob1Pos, 30) @@ -83,7 +90,7 @@ def setup(self): ob2 = Obstacle(ob2Pos, 20) #add obstacles to the world - self.world.obstacles.append(ob1); + self.world.obstacles.append(ob1) self.world.obstacles.append(ob2) #define a ball @@ -93,7 +100,8 @@ def setup(self): #add the ball to the world self.world.balls.append(ball) -#called at a fixed 30fps always + # called at a fixed 30fps always + # physics simulation def fixedLoop(self): for agent in self.world.agents: agent.moveAgent(self.world) @@ -106,55 +114,61 @@ def fixedLoop(self): self.ballWPs.remove(self.ballWPs[0]) -#Called at specifed fps + #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() - - #Setup loop - timeStep = 1/double(30) - frameProb = double(self.fps) / 30 - currTime = double(0) - drawIndex = 0 - physicsIndex = 0 - while(currTime < self.simTime): + + while(self.currTime < self.simTime): self.fixedLoop() - currProb = double(drawIndex)/double(physicsIndex+1) - if currProb < frameProb: - self.drawFrame(drawIndex) - drawIndex+=1 - physicsIndex+=1 - currTime+=double(timeStep) + 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(physicsIndex)+" steps" - print "Drawing ran for "+str(drawIndex)+" steps" + print "Physics ran for "+str(self.physicsIndex)+" steps" + print "Drawing ran for "+str(self.drawIndex)+" steps" def drawFrame(self, loopIndex): - fig = plt.figure(figsize=(16,12)) - ax = fig.add_subplot(111, projection='3d') + 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 + '/' + str(int(100000000+loopIndex)) + '.png' # name the file + 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]) - savefig(fname, format='png', bbox_inches='tight') + self.fig.savefig(fname, format='png', bbox_inches='tight') print 'Written Frame No.'+ str(loopIndex)+' to '+ fname - plt.close() + #Simulation runs here #set the size of the world -world = World(100, 100) -#specify which world to simulate, total simulation time, and frammerate for video -sim = Simulator(world, 60, 30, "images") +# 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() +# sim.run() ''' To create a video using the image sequence, execute the following command in command line. From c8c35ddee1ca79828362b145cbd19ee39d406e54 Mon Sep 17 00:00:00 2001 From: Chris Chow Date: Sat, 7 Mar 2015 23:13:55 -0500 Subject: [PATCH 2/3] remove dead code from simulator --- Main.py | 43 ------------------------------ Simulator.py | 75 ++++++++++++---------------------------------------- 2 files changed, 17 insertions(+), 101 deletions(-) delete mode 100644 Main.py diff --git a/Main.py b/Main.py deleted file mode 100644 index 6278779..0000000 --- a/Main.py +++ /dev/null @@ -1,43 +0,0 @@ -__author__ = 'chris' - -import Simulator -import World -from matplotlib import animation - - -FPS = 30 # hardcoded into simulation assumptions - -world = World.World(100, 100) -sim = Simulator.Simulator(world, 10, FPS, "images") - - -# simulator assumes its physics simulation is running at dt = 1/30 s -# would have to recalculate the true animation framerate (to get physically accurate speeds, etc) -# if you change the raw sample rate of the animator function (which accepts arguments in ms) -simlen = 10 # sec -frames = FPS * simlen - -def tick(i): - return sim.tick() - -ani = animation.FuncAnimation(sim.fig, tick, frames=frames, blit=True, init_func=sim.setup) - -import time - -t = time.time() -ani.save('hello.mp4', fps=FPS, extra_args=['-vcodec', 'libx264']) -print "execution time:", time.time() - t -# execution time: 178.861850023 - -# t = time.time() -# sim.run() -# print "execution time:", time.time() - t -# execution time: 591.768985033 - -# -# os.chdir("images") -# -# callstring = ["ffmpeg", "-f", "image2", "-i", 'img%08d.png', "-r", str(FPS), "output.mp4"] -# -# -# call(callstring) \ No newline at end of file diff --git a/Simulator.py b/Simulator.py index 0c8f614..c4fa9f1 100644 --- a/Simulator.py +++ b/Simulator.py @@ -17,6 +17,7 @@ from LinearAlegebraUtils import distBetween from RunAtBallBrain import RunAtBallBrain from Team import Team +from matplotlib import animation #Called once for initialization @@ -35,23 +36,10 @@ def __init__(self, world, simTime, fps, 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 + + + def setup(self): + #define teams which the agents can be a part of teamA = Team("A", '#ff99ff') teamB = Team("B", '#ffcc99') #Defining a couple of agents @@ -131,49 +119,20 @@ def tick(self): 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 +def tick(i): + return sim.tick() +FPS = 30 # hardcoded into simulation assumptions +world = World(100, 100) +sim = Simulator(world, 10, FPS, "images") -#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() +# simulator assumes its physics simulation is running at dt = 1/30 s +# would have to recalculate the true animation framerate (to get physically accurate speeds, etc) +# if you change the raw sample rate of the animator function (which accepts arguments in ms) +simlen = 10 # sec +frames = FPS * simlen -''' -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. -''' +ani = animation.FuncAnimation(sim.fig, tick, frames=frames, blit=True, init_func=sim.setup) - +ani.save('output.mp4', fps=FPS, extra_args=['-vcodec', 'libx264']) From 316c8d85573dc8fc43105207eda448ec5616df1c Mon Sep 17 00:00:00 2001 From: Chris Chow Date: Sat, 7 Mar 2015 23:18:57 -0500 Subject: [PATCH 3/3] moved simulation length to variable --- Simulator.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Simulator.py b/Simulator.py index c4fa9f1..80bd54e 100644 --- a/Simulator.py +++ b/Simulator.py @@ -122,17 +122,16 @@ def tick(self): def tick(i): return sim.tick() -FPS = 30 # hardcoded into simulation assumptions - -world = World(100, 100) -sim = Simulator(world, 10, FPS, "images") - # simulator assumes its physics simulation is running at dt = 1/30 s # would have to recalculate the true animation framerate (to get physically accurate speeds, etc) # if you change the raw sample rate of the animator function (which accepts arguments in ms) +FPS = 30 # hardcoded into simulation assumptions simlen = 10 # sec frames = FPS * simlen +world = World(100, 100) +sim = Simulator(world, simlen, FPS, "images") + ani = animation.FuncAnimation(sim.fig, tick, frames=frames, blit=True, init_func=sim.setup) ani.save('output.mp4', fps=FPS, extra_args=['-vcodec', 'libx264'])