mondano
mondano

Reputation: 875

Visualization of a discrete-event simulation on a grid / warehouse layout

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

Answers (5)

David
David

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

AUBSieGUL
AUBSieGUL

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

Harry Munro
Harry Munro

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

mondano
mondano

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

Stefan Scherfke
Stefan Scherfke

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

Related Questions