Reputation: 875
I need to simulate a warehouse with several autonomous vehicles moving on a given layout with simple priority rules. In my understanding, the problem can easily be tackled with discrete-event simulation (DES) and I would use SimPy for this.
The problem I see is that it seems very hard to me to visualize the actual trajectories and interactions of these vehicles. Of course, I can log all positions of all vehicles in all periods but how can I proceed then to create a visualization?
The dumbest way would be to create a million pictures, but there has to be a better way. Is there any library or tool to visualize movements of objects on a grid by moving symbols before a background?
Another option would be to use an agent-based approach with a software like AnyLogic, but this seems more complicated to me and I would like to apply a DES approach, preferably with open-source software.
Upvotes: 7
Views: 7197
Reputation: 69
A little variation to what you intend to use for the simulation library could be to use salabim instead of simpy. It is very similar to simpy but has an animation engine which simplifies greatly the process.
Upvotes: 1
Reputation: 486
If the animation should be 2D you could use the Pygame Library. I animated a little simpy simulation with it and it worked fine. Just note that you need to use threads otherwise your window will freeze after a few seconds. This simple method draws a red circle for every customer arriving and draws it green when the customer gets served.
def draw(env, timelist):
gameDisplay.fill(white)
start = time.clock()
kdnr = 0
kdaktuell = -1
kdstart = -10
while True:
timer = (time.clock() - startzeit)
if timer > 15: #simulation for 15 sec
break
# incoming customers
if kdnr < len(timelist):
if timelist[kdnr] <= timer:
pygame.draw.circle(gameDisplay,red,(50+30*kdnr,400),10)
print('Customer '+str(kdnr+1)+ ' arrived in minute: ' + str(timelist[kdnr]))
kdnr = kdnr + 1
# served customers
if (kdstart+3) <= timer:
kdaktuell = kdaktuell + 1
kdstart = time
pygame.draw.circle(gameDisplay,green,(50+30*kdaktuell,400),10)
print('Customer '+str(kdaktuell+1)+ ' gets served.')
pygame.display.update()
Upvotes: 3
Reputation: 324
I'd suggest checking out the tkinter library. We do all of our simpy visualization using this.
Here is a very basic example of the kind of animation that can be achieved, pardon the dramatic footage: https://www.youtube.com/watch?v=xnZQ0f--Ink
Here is the source code which roughly describes what you see above: https://github.com/harrymunro/Simulations/blob/master/termini_simulation_animation.py
Here is a copy paste of the animation component:
################ SET UP ANIMATION CANVAS #################
class Train:
def __init__(self, canvas, x1, y1, x2, y2, tag):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.canvas = canvas
self.train = canvas.create_rectangle(self.x1, self.y1, self.x2, self.y2, fill="red", tags = tag)
self.train_number = canvas.create_text(((self.x2 - self.x1)/2 + self.x1), ((self.y2 - self.y1)/2 + self.y1), text = tag)
self.canvas.update()
def move_train(self, deltax, deltay):
self.canvas.move(self.train, deltax, deltay)
self.canvas.move(self.train_number, deltax, deltay)
self.canvas.update()
def remove_train(self):
self.canvas.delete(self.train)
self.canvas.delete(self.train_number)
self.canvas.update()
class Clock:
def __init__(self, canvas, x1, y1, x2, y2, tag):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.canvas = canvas
self.train = canvas.create_rectangle(self.x1, self.y1, self.x2, self.y2, fill="#fff")
self.time = canvas.create_text(((self.x2 - self.x1)/2 + self.x1), ((self.y2 - self.y1)/2 + self.y1), text = "Time = "+str(tag)+"s")
self.canvas.update()
def tick(self, tag):
self.canvas.delete(self.time)
self.time = canvas.create_text(((self.x2 - self.x1)/2 + self.x1), ((self.y2 - self.y1)/2 + self.y1), text = "Time = "+str(tag)+"s")
self.canvas.update()
if show_animation == True:
animation = Tk()
#bitmap = BitmapImage(file="uxbridge.bmp")
im = PhotoImage(file="uxbridge_resized.gif")
canvas = Canvas(animation, width = 800, height = 400)
canvas.create_image(0,0, anchor=NW, image=im)
animation.title("Uxbridge Termini Simulation")
canvas.pack()
#### matplotlib plots
if show_animation == True and hide_plots == False:
f = plt.Figure(figsize=(5,4), dpi=100)
a1 = f.add_subplot(221) # mean headway
a2 = f.add_subplot(222) # TPH meter
a3 = f.add_subplot(223) # headway distribution
a4 = f.add_subplot(224) # train count
a1.plot()
a2.plot()
a3.plot()
a4.plot()
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
dataPlot = FigureCanvasTkAgg(f, master=animation)
dataPlot.show()
dataPlot.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
f.tight_layout()
canvas.pack()
# platforms
if show_animation == True:
canvas.create_rectangle(50, 100, 200, 150, fill = "yellow")
canvas.create_rectangle(50, 200, 200, 250, fill = "yellow")
canvas.create_line(50, 75, 200, 75, fill="green", width=3) # platform 4
canvas.create_line(50, 175, 200, 175, fill="green", width=3) # platform 2/3
canvas.create_line(50, 275, 200, 275, fill="green", width=3) # platform 1
canvas.create_text(125, 110, text = "Platform 4")
canvas.create_text(125, 140, text = "Platform 3")
canvas.create_text(125, 210, text = "Platform 2")
canvas.create_text(125, 240, text = "Platform 1")
# track
canvas.create_line(200, 75, 650, 75, fill="green", width=3) # platform 4 run out
canvas.create_line(200, 175, 650, 175, fill="green", width=3) # platform 2/3 run in
canvas.create_line(300, 175, 400, 75, fill="green", width=3)
canvas.create_line(450, 75, 600, 175, fill="green", width=3)
canvas.create_line(450, 175, 600, 75, fill="green", width=3)
canvas.create_line(200, 275, 300, 275, fill="green", width=3)
canvas.create_line(300, 275, 400, 175, fill="green", width=3)
############ END OF CANVAS #################
Upvotes: 6
Reputation: 875
I found that the R library gganimate does what I want. I have not found an equivalent for Python though (maybe because there is neither an equivalent to ggplot2 nor animate in Python...)
Upvotes: 0
Reputation: 3242
I would just collect all required data and store them somewhere (a file, HDF5, sql, …). Later (or in parallel), you can visualize that data. Either by generating a lot of images with, e.g., matplotlib or by doing something more fancy with D3.js.
Upvotes: 1