minimal_rtdevs.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from pypdevs.DEVS import AtomicDEVS, CoupledDEVS
  2. from pypdevs.simulator import Simulator
  3. from pypdevs.infinity import INFINITY
  4. import random, math, sys, getopt
  5. import Tkinter as tk
  6. class Canvas:
  7. def __init__(self, resolution):
  8. self.width = resolution[0]
  9. self.height = resolution[1]
  10. class ParticleState:
  11. def __init__(self):
  12. self.remaining = 0.0
  13. self.curr_frames = 0.0
  14. class Particle(AtomicDEVS):
  15. def __init__(self, canvas):
  16. AtomicDEVS.__init__(self, "Particle")
  17. self.r = random.uniform(5.0, 30.0)
  18. x = random.uniform(self.r, canvas.width - self.r)
  19. y = random.uniform(self.r, canvas.height - self.r)
  20. self.pos = (x, y)
  21. self.POS_OUT = self.addOutPort("POS_OUT")
  22. self.INTERRUPT = self.addInPort("INTERRUPT")
  23. self.state = ParticleState()
  24. def timeAdvance(self):
  25. return self.state.remaining
  26. def outputFnc(self):
  27. return {self.POS_OUT: [self.pos, self.r]}
  28. def intTransition(self):
  29. self.state.curr_frames += self.timeAdvance()
  30. self.state.remaining = 1
  31. return self.state
  32. def extTransition(self, inputs):
  33. self.state.remaining -= self.elapsed
  34. print 'extTransition'
  35. return self.state
  36. class Field(CoupledDEVS):
  37. def __init__(self, canvas):
  38. CoupledDEVS.__init__(self, "Field")
  39. self.INTERRUPT = self.addInPort("INTERRUPT")
  40. self.POS_OUT = self.addOutPort("POS_OUT")
  41. self.particle = self.addSubModel(Particle(canvas))
  42. self.connectPorts(self.INTERRUPT, self.particle.INTERRUPT)
  43. self.connectPorts(self.particle.POS_OUT, self.POS_OUT)
  44. class ParticleVisualization:
  45. def __init__(self, circle_id, canvas, sim):
  46. self.circle_id = circle_id
  47. self.canvas = canvas
  48. self.sim = sim
  49. self.canvas.tag_bind(self.circle_id, "<Button-1>", self.on_click)
  50. def on_click(self, event):
  51. self.sim.realtime_interrupt("INTERRUPT myValue")
  52. class Visualizer(tk.Toplevel):
  53. def __init__(self, root, resolution, sim):
  54. tk.Toplevel.__init__(self)
  55. self.sim = sim
  56. self.root = root
  57. self.particle = None
  58. self.geometry('{}x{}'.format(resolution[0], resolution[1]))
  59. CANVAS_SIZE_TUPLE = (0, 0, self.winfo_screenwidth(), self.winfo_screenheight())
  60. self.canvas = tk.Canvas(self, relief=tk.RIDGE, scrollregion=CANVAS_SIZE_TUPLE)
  61. self.canvas.pack(expand = True, fill=tk.BOTH)
  62. self.protocol("WM_DELETE_WINDOW", lambda: self.root.destroy())
  63. def handle_output(self, msgs):
  64. for msg_contents in msgs:
  65. if self.particle == None:
  66. (x, y), r = msg_contents
  67. circle_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, fill="red")
  68. self.particle = ParticleVisualization(circle_id, self.canvas, self.sim)
  69. else:
  70. (x, y), r = msg_contents
  71. curr_x, curr_y = self.canvas.coords(self.particle.circle_id)[0:2]
  72. self.canvas.move(self.particle.circle_id, x - r - curr_x, y - r - curr_y)
  73. if __name__ == '__main__':
  74. root = tk.Tk()
  75. root.withdraw()
  76. model = Field(Canvas((800, 600)))
  77. sim = Simulator(model)
  78. sim.setRealTime(True, 1.0 / 30)
  79. sim.setRealTimeInputFile(None)
  80. sim.setRealTimePorts({'INTERRUPT': model.INTERRUPT})
  81. sim.setRealTimePlatformTk(root)
  82. sim.setDSDEVS(True)
  83. sim.setClassicDEVS(True)
  84. sim.setTerminationTime(60 * 30)
  85. sim.setVerbose("minimalOutputFile")
  86. visualizer = Visualizer(root, (800, 600), sim)
  87. visualizer.title('ParticleInteraction')
  88. sim.setListenPorts(model.POS_OUT, visualizer.handle_output)
  89. sim.simulate()
  90. root.mainloop()