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.
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 #################
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With