2017-04-24 94 views
1

我需要模擬一個倉庫,其中有幾個自動車輛按照簡單的優先級規則在給定的佈局上移動。根據我的理解,這個問題可以通過離散事件仿真(DES)輕鬆解決,我會使用SimPy來解決這個問題。網格/倉庫佈局上的離散事件模擬的可視化

我看到的問題是,我很難想象這些車輛的實際軌跡和相互作用。當然,我可以在所有時段記錄所有車輛的所有位置,但是如何繼續創建可視化?

最愚蠢的做法是製作一百萬張照片,但必須有更好的方法。是否有任何庫或工具通過在背景之前移動符號來可視化網格上對象的移動?

另一種選擇是使用基於代理的方法和AnyLogic這樣的軟件,但是這對我來說似乎更加複雜,我希望應用DES方法,最好使用開源軟件。

+1

請注意,要求對圖書館或工具的建議明確聲明爲使您的問題關閉的標準。也就是說,諸如Simio,Arena或ExtendSim等商用DES產品都提供動畫/可視化功能。壞消息是它們很昂貴。可能的一線希望是其中一些可用於學術用途。 – pjs

+0

感謝您的澄清。如果不在SO上,我不確定如何以及在哪裏獲得有關我的問題的幫助。你會問什麼,或者我需要如何改寫我的問題? – mondano

回答

0

我發現R庫gganimate做我想要的。我還沒有找到Python的等價物(可能是因爲在Python中沒有相當於ggplot2和animate ...)

0

我只會收集所有需要的數據並將它們存儲在某個地方(一個文件,HDF5,sql,...)。稍後(或平行),您可以可視化該數據。或者通過使用例如matplotlib生成大量圖像,或者通過使用D3.js更特別的方式來生成一些圖像。

+0

我的問題是*我會如何做這個可視化部分。如果我對8小時的掛鐘時間進行模擬並每秒鐘拍攝一張「圖片」,則我可以通過8h * 60分鐘/小時* 60秒/分鐘* 1 MB = 28.8 GB來模擬一次模擬運行。這似乎有點太過分了。我正在尋找更有效的解決方案。對於這個動態問題,我還沒有找到相應的D3.js圖表​​選項。你能直接告訴我一個嗎? – mondano

2

我建議檢出tkinter庫。我們用這個來完成我們所有的簡單可視化。

這裏是那種動畫的可以實現的一個非常簡單的例子,原諒了戲劇性的鏡頭:https://www.youtube.com/watch?v=xnZQ0f--Ink

這裏是源代碼,大致描述你看到的上面:https://github.com/harrymunro/Simulations/blob/master/termini_simulation_animation.py

這裏動畫元件的複製粘貼:

################ 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 ################# 
+1

謝謝,這是一個非常有趣的解決方案! – mondano

1

如果動畫應該是2D您可以使用Pygame庫。我用它動畫了一個簡單的模擬,它工作得很好。請注意,您需要使用線程,否則您的窗口會在幾秒鐘後凍結。這種簡單的方法爲每個到達的客戶繪製一個紅圈,並在客戶獲得服務時將其繪製爲綠色。

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()