run_train.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. from Tkinter import *
  2. import random
  3. import math
  4. import train
  5. from python_runtime.statecharts_core import Event
  6. from python_runtime.tkinter_eventloop import *
  7. width_railway = 20
  8. marked = {}
  9. kind_of_object = {}
  10. class SimulationGUI(Tk):
  11. def __init__(self):
  12. def update_scale(value):
  13. if hasattr(self, "controller"):
  14. self.controller.addInput(Event("accel", "tkinter_input", [float(value)]))
  15. def press_continue():
  16. self.controller.addInput(Event("continue", "tkinter_input", []))
  17. def press_pause():
  18. self.controller.addInput(Event("pause", "tkinter_input", []))
  19. def press_open():
  20. self.controller.addInput(Event("open", "tkinter_input", []))
  21. def press_close():
  22. self.controller.addInput(Event("close", "tkinter_input", []))
  23. def press_awake():
  24. self.controller.addInput(Event("awake", "tkinter_input", []))
  25. Tk.__init__(self)
  26. self.travelled_x = 0.0
  27. self.travelled_x_int = 0
  28. self.next_light = 0.0
  29. self.frame = Frame(self)
  30. self.frame.focus_set()
  31. self.resizable(0, 0)
  32. self.canvas = Canvas(self.frame, height=150, width=1000, bg="white")
  33. self.img_train = PhotoImage(file="imgs/train.gif")
  34. self.img_red = PhotoImage(file="imgs/red.gif")
  35. self.img_yellow = PhotoImage(file="imgs/yellow.gif")
  36. self.img_green = PhotoImage(file="imgs/green.gif")
  37. self.img_station = PhotoImage(file="imgs/station.gif")
  38. self.img_railway = PhotoImage(file="imgs/rail.gif")
  39. self.label_error = Label(self.frame, text="")
  40. self.slider_acceleration = Scale(self.frame, command=update_scale, orient=HORIZONTAL, resolution=0.01, from_=-1, to=1)
  41. self.button_continue = Button(self.frame, text="continue", command=press_continue)
  42. self.button_pause = Button(self.frame, text="pause", command=press_pause)
  43. self.button_open = Button(self.frame, text="open", command=press_open)
  44. self.button_close = Button(self.frame, text="close", command=press_close)
  45. self.button_poll = Button(self.frame, text="poll", command=press_awake)
  46. self.label_speed = Label(self.frame, text="")
  47. self.label_doors = Label(self.frame, text="Doors are CLOSED")
  48. self.items = []
  49. self.rails = []
  50. x = 0
  51. while x <= 1000 + width_railway:
  52. self.rails.append(self.canvas.create_image(x, 80, image=self.img_railway, anchor=NW))
  53. x += width_railway
  54. self.item_train = self.canvas.create_image(0, 75, image=self.img_train, anchor=NW)
  55. self.label_speed.grid(row=0, column=0, columnspan=2)
  56. self.label_doors.grid(row=1, column=0, columnspan=2)
  57. self.canvas.grid(row=2, column=0, columnspan=2, sticky=W)
  58. self.label_error.grid(row=3, column=0, columnspan=2)
  59. self.slider_acceleration.grid(row=4, column=0, columnspan=2, sticky=W+E)
  60. self.button_continue.grid(row=5, column=0, sticky=W+E)
  61. self.button_pause.grid(row=5, column=1, sticky=W+E)
  62. self.button_open.grid(row=6, column=0, sticky=W+E)
  63. self.button_close.grid(row=6, column=1, sticky=W+E)
  64. self.button_poll.grid(row=7, column=0, columnspan=2, sticky=W+E)
  65. self.frame.grid()
  66. self.remainder = 0.0
  67. self.next_station = 1000
  68. self.counter = 0
  69. self.train = None
  70. self.light_change_events = []
  71. self.updateState()
  72. self.after(20, self.throwEvents)
  73. def openDoors(self):
  74. self.label_doors.config(text="Doors are OPEN")
  75. def closeDoors(self):
  76. self.label_doors.config(text="Doors are CLOSED")
  77. def trainIs(self, train):
  78. self.train = train
  79. def throwEvents(self):
  80. # Check if we passed anything
  81. if hasattr(self, "controller"):
  82. for item in self.items:
  83. coords = self.canvas.coords(item)
  84. if coords[0] < 30 and item not in marked:
  85. # Passed light or entered station
  86. t = kind_of_object[item]
  87. if t == "STATION":
  88. marked[item] = False
  89. self.controller.addInput(Event("enter", "tkinter_input", []))
  90. elif t == "RED":
  91. marked[item] = True
  92. self.controller.addInput(Event("red_light", "tkinter_input", []))
  93. elif t == "YELLOW":
  94. marked[item] = True
  95. self.controller.addInput(Event("yellow_light", "tkinter_input", []))
  96. elif t == "GREEN":
  97. marked[item] = True
  98. self.controller.addInput(Event("green_light", "tkinter_input", []))
  99. elif coords[0] < -170 and not marked[item]:
  100. self.controller.addInput(Event("leave", "tkinter_input", []))
  101. marked[item] = True
  102. self.after(20, self.throwEvents)
  103. def notify(self, msg, color):
  104. self.label_error.config(text=msg, bg=color)
  105. def updateState(self):
  106. def turn_green(item):
  107. kind_of_object[item] = "GREEN"
  108. self.canvas.itemconfigure(item, image=self.img_green)
  109. def turn_yellow(item):
  110. self.canvas.itemconfigure(item, image=self.img_yellow)
  111. kind_of_object[item] = "YELLOW"
  112. self.light_change_events.append((self.counter + random.random() * 500 + 300, item, turn_green))
  113. if self.train is not None:
  114. self.train.velocity += self.train.acceleration / 2
  115. self.label_speed.config(text="Velocity: %.2f" % self.train.velocity)
  116. self.travelled_x += float(self.train.velocity) / 20
  117. delta_x = -int(self.travelled_x - self.travelled_x_int)
  118. self.travelled_x_int = int(self.travelled_x)
  119. # Move rails
  120. for item in self.rails:
  121. self.canvas.move(item, delta_x, 0)
  122. # Move items and remove if necessary
  123. for item in self.items:
  124. self.canvas.move(item, delta_x, 0)
  125. if self.canvas.coords(item) < -100:
  126. self.canvas.delete(item)
  127. self.items.remove(item)
  128. # Update rails
  129. while 1:
  130. coords = self.canvas.coords(self.rails[0])
  131. if coords[0] < -width_railway:
  132. self.canvas.delete(self.rails[0])
  133. self.rails.pop(0)
  134. self.rails.append(self.canvas.create_image(self.canvas.coords(self.rails[-1])[0]+width_railway, 80, image=self.img_railway, anchor=NW))
  135. self.canvas.tag_lower(self.rails[-1])
  136. else:
  137. break
  138. # Add in an element only if there is space
  139. if self.next_station < self.travelled_x:
  140. # Generate a station
  141. self.items.append(self.canvas.create_image(1000, 120, image=self.img_station, anchor=NW))
  142. kind_of_object[self.items[-1]] = "STATION"
  143. self.next_station += random.random() * 3000 + 2000
  144. if self.next_light < self.travelled_x:
  145. self.next_light += 500
  146. self.items.append(self.canvas.create_image(1000, 40, image=self.img_red, anchor=NW))
  147. kind_of_object[self.items[-1]] = "RED"
  148. self.light_change_events.append((self.counter + random.random() * 500, self.items[-1], turn_yellow))
  149. self.counter += 1
  150. for light_change in self.light_change_events:
  151. if light_change[0] <= self.counter:
  152. light_change[2](light_change[1])
  153. self.light_change_events.remove(light_change)
  154. root = SimulationGUI()
  155. if __name__ == "__main__":
  156. random.seed(1)
  157. controller = train.Controller(root, TkEventLoop(root))
  158. root.controller = controller
  159. controller.start()
  160. try:
  161. root.mainloop()
  162. finally:
  163. controller.stop()