TrainSystem.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #!/usr/bin/python3
  2. # This file was automatically generated from drawio2cbd with the command:
  3. # ../../drawio2cbd.py TrainSystem.xml TrainSystem.py -e TrainSystem -T 0.2 -t 360
  4. from ComputerBlock import ComputerBlock
  5. from TrainCostModelBlock import *
  6. from CBD.src.CBD import *
  7. DELTA_T = 0.2
  8. import matplotlib.pyplot as plt
  9. def plot_signals(block, signals, title):
  10. times = []
  11. outputs = []
  12. for signal in signals:
  13. tvpl = block.getSignal(signal)
  14. times = [t for t, _ in tvpl]
  15. outputs.append([v for _, v in tvpl])
  16. # Plot
  17. plt.figure()
  18. plt.title(title)
  19. plt.xlabel('time')
  20. plt.ylabel('N')
  21. for i in range(len(signals)):
  22. plt.plot(times, outputs[i], label=signals[i])
  23. plt.legend()
  24. plt.show()
  25. class Time(CBD):
  26. def __init__(self, block_name, h=(1)):
  27. CBD.__init__(self, block_name, input_ports=[], output_ports=['Out', 'OutDelta'])
  28. # Create the blocks
  29. self.addBlock(ConstantBlock(block_name='zero', value=(0)))
  30. self.addBlock(ConstantBlock(block_name='h', value=(h)))
  31. self.addBlock(AdderBlock(block_name='sum'))
  32. self.addBlock(DelayBlock(block_name='delay'))
  33. # Connect the blocks
  34. self.addConnection('sum', 'delay')
  35. self.addConnection('zero', 'delay', input_port_name='IC')
  36. self.addConnection('h', 'sum')
  37. self.addConnection('delay', 'sum')
  38. self.addConnection('delay', 'Out')
  39. self.addConnection('h', 'OutDelta')
  40. class TrainSystem(CBD):
  41. def __init__(self, block_name, h=(DELTA_T), Kp=(200), Ki=(0), Kd=(0)):
  42. CBD.__init__(self, block_name, input_ports=[], output_ports=['ActualVelocity', 'IdealVelocity', 'PeopleDisplacement', 'Acceleration', 'cost'])
  43. # Create the blocks
  44. self.addBlock(Time(block_name='time', h=(h)))
  45. self.addBlock(ComputerBlock(block_name='LookUp'))
  46. self.addBlock(AdderBlock(block_name='sum'))
  47. self.addBlock(PIDController(block_name='PID', Kp=(Kp), Ki=(Ki), Kd=(Kd)))
  48. self.addBlock(Plant(block_name='plant'))
  49. self.addBlock(NegatorBlock(block_name='neg'))
  50. self.addBlock(CostFunctionBlock(block_name='costBlock'))
  51. self.addBlock(AboveThresholdBlock(block_name='thresh', threshold=(0.4)))
  52. self.addBlock(StopSimulationBlock(block_name='stop'))
  53. # Connect the blocks
  54. self.addConnection('time', 'LookUp', output_port_name='Out')
  55. self.addConnection('sum', 'PID')
  56. self.addConnection('LookUp', 'sum')
  57. self.addConnection('time', 'PID', input_port_name='delta_t', output_port_name='OutDelta')
  58. self.addConnection('PID', 'plant', input_port_name='F')
  59. self.addConnection('time', 'plant', input_port_name='delta_t', output_port_name='OutDelta')
  60. self.addConnection('plant', 'neg', output_port_name='v')
  61. self.addConnection('neg', 'sum')
  62. self.addConnection('plant', 'ActualVelocity', output_port_name='v')
  63. self.addConnection('LookUp', 'IdealVelocity')
  64. self.addConnection('plant', 'PeopleDisplacement', output_port_name='x')
  65. self.addConnection('plant', 'Acceleration', output_port_name='a')
  66. self.addConnection('LookUp', 'costBlock', input_port_name='InVi')
  67. self.addConnection('time', 'costBlock', input_port_name='InDelta', output_port_name='OutDelta')
  68. self.addConnection('plant', 'costBlock', input_port_name='InXPerson', output_port_name='x')
  69. self.addConnection('plant', 'costBlock', input_port_name='InVTrain', output_port_name='v')
  70. self.addConnection('costBlock', 'cost', output_port_name='OutCost')
  71. self.addConnection('thresh', 'stop')
  72. self.addConnection('plant', 'thresh', output_port_name='x')
  73. class PIDController(CBD):
  74. def __init__(self, block_name, Kp=(0), Ki=(0), Kd=(0)):
  75. CBD.__init__(self, block_name, input_ports=['IN1', 'delta_t'], output_ports=['OUT1'])
  76. # Create the blocks
  77. self.addBlock(IntegratorBlock(block_name='int'))
  78. self.addBlock(ProductBlock(block_name='mult1'))
  79. self.addBlock(ConstantBlock(block_name='Kp', value=(Kp)))
  80. self.addBlock(AdderBlock(block_name='sum1'))
  81. self.addBlock(ProductBlock(block_name='mult2'))
  82. self.addBlock(ConstantBlock(block_name='Ki', value=(Ki)))
  83. self.addBlock(AdderBlock(block_name='sum2'))
  84. self.addBlock(DerivatorBlock(block_name='1MvUKixQIvwEmUJ5Sh7E-115'))
  85. self.addBlock(ProductBlock(block_name='1MvUKixQIvwEmUJ5Sh7E-122'))
  86. self.addBlock(ConstantBlock(block_name='Kd', value=(Kd)))
  87. self.addBlock(ConstantBlock(block_name='zero', value=(0)))
  88. # Connect the blocks
  89. self.addConnection('IN1', 'mult1')
  90. self.addConnection('IN1', 'int')
  91. self.addConnection('IN1', '1MvUKixQIvwEmUJ5Sh7E-115')
  92. self.addConnection('delta_t', 'int', input_port_name='delta_t')
  93. self.addConnection('delta_t', '1MvUKixQIvwEmUJ5Sh7E-115', input_port_name='delta_t')
  94. self.addConnection('Kp', 'mult1')
  95. self.addConnection('mult1', 'sum1')
  96. self.addConnection('sum1', 'OUT1')
  97. self.addConnection('int', 'mult2')
  98. self.addConnection('Ki', 'mult2')
  99. self.addConnection('mult2', 'sum2')
  100. self.addConnection('sum2', 'sum1')
  101. self.addConnection('1MvUKixQIvwEmUJ5Sh7E-115', '1MvUKixQIvwEmUJ5Sh7E-122')
  102. self.addConnection('Kd', '1MvUKixQIvwEmUJ5Sh7E-122')
  103. self.addConnection('1MvUKixQIvwEmUJ5Sh7E-122', 'sum2')
  104. self.addConnection('zero', '1MvUKixQIvwEmUJ5Sh7E-115', input_port_name='IC')
  105. self.addConnection('zero', 'int', input_port_name='IC')
  106. class Plant(CBD):
  107. def __init__(self, block_name, k=(300), c=(150), CD=(0.6), p=(1.2), A=(9.12), mp=(73), mt=(5555)):
  108. CBD.__init__(self, block_name, input_ports=['F', 'delta_t'], output_ports=['v', 'x', 'a'])
  109. # Create the blocks
  110. self.addBlock(ConstantBlock(block_name='mt', value=(mt)))
  111. self.addBlock(ConstantBlock(block_name='mp', value=(mp)))
  112. self.addBlock(AdderBlock(block_name='sum_M'))
  113. self.addBlock(InverterBlock(block_name='inv'))
  114. self.addBlock(ProductBlock(block_name='mul_M'))
  115. self.addBlock(ProductBlock(block_name='mul_p'))
  116. self.addBlock(ConstantBlock(block_name='p', value=(p)))
  117. self.addBlock(ConstantBlock(block_name='half', value=(1/2)))
  118. self.addBlock(ProductBlock(block_name='mul_pv'))
  119. self.addBlock(ProductBlock(block_name='square'))
  120. self.addBlock(ConstantBlock(block_name='CD', value=(CD)))
  121. self.addBlock(ProductBlock(block_name='mul_CD'))
  122. self.addBlock(ProductBlock(block_name='mul_above'))
  123. self.addBlock(ConstantBlock(block_name='A', value=(A)))
  124. self.addBlock(NegatorBlock(block_name='neg'))
  125. self.addBlock(AdderBlock(block_name='sum_div'))
  126. self.addBlock(IntegratorBlock(block_name='int'))
  127. self.addBlock(ConstantBlock(block_name='zero', value=(0)))
  128. self.addBlock(ConstantBlock(block_name='k', value=(k)))
  129. self.addBlock(ConstantBlock(block_name='c', value=(c)))
  130. self.addBlock(ProductBlock(block_name='mul_k'))
  131. self.addBlock(ProductBlock(block_name='mul_c'))
  132. self.addBlock(AdderBlock(block_name='sum_kc'))
  133. self.addBlock(ProductBlock(block_name='mul_FTM'))
  134. self.addBlock(ProductBlock(block_name='mul_mMF'))
  135. self.addBlock(AdderBlock(block_name='sum_x'))
  136. self.addBlock(InverterBlock(block_name='inv_mp'))
  137. self.addBlock(ProductBlock(block_name='prod_x'))
  138. self.addBlock(IntegratorBlock(block_name='int_vp'))
  139. self.addBlock(IntegratorBlock(block_name='int_xp'))
  140. self.addBlock(NegatorBlock(block_name='negx'))
  141. # Connect the blocks
  142. self.addConnection('F', 'sum_div')
  143. self.addConnection('F', 'mul_FTM')
  144. self.addConnection('mt', 'sum_M')
  145. self.addConnection('mp', 'sum_M')
  146. self.addConnection('sum_M', 'inv')
  147. self.addConnection('inv', 'mul_M')
  148. self.addConnection('half', 'mul_p')
  149. self.addConnection('mul_p', 'mul_pv')
  150. self.addConnection('square', 'mul_pv')
  151. self.addConnection('CD', 'mul_CD')
  152. self.addConnection('A', 'mul_CD')
  153. self.addConnection('mul_pv', 'mul_above')
  154. self.addConnection('mul_CD', 'mul_above')
  155. self.addConnection('mul_above', 'neg')
  156. self.addConnection('neg', 'sum_div')
  157. self.addConnection('sum_div', 'mul_M')
  158. self.addConnection('mul_M', 'int')
  159. self.addConnection('zero', 'int', input_port_name='IC')
  160. self.addConnection('delta_t', 'int', input_port_name='delta_t')
  161. self.addConnection('delta_t', 'int_vp', input_port_name='delta_t')
  162. self.addConnection('delta_t', 'int_xp', input_port_name='delta_t')
  163. self.addConnection('int', 'square')
  164. self.addConnection('int', 'v')
  165. self.addConnection('k', 'mul_k')
  166. self.addConnection('c', 'mul_c')
  167. self.addConnection('mul_k', 'sum_kc')
  168. self.addConnection('mul_c', 'sum_kc')
  169. self.addConnection('inv', 'mul_FTM')
  170. self.addConnection('mul_FTM', 'mul_mMF')
  171. self.addConnection('mp', 'mul_mMF')
  172. self.addConnection('mul_mMF', 'sum_x')
  173. self.addConnection('sum_kc', 'sum_x')
  174. self.addConnection('inv_mp', 'prod_x')
  175. self.addConnection('prod_x', 'int_vp')
  176. self.addConnection('zero', 'int_vp', input_port_name='IC')
  177. self.addConnection('int_vp', 'mul_c')
  178. self.addConnection('int_vp', 'int_xp')
  179. self.addConnection('zero', 'int_xp', input_port_name='IC')
  180. self.addConnection('int_xp', 'mul_k')
  181. self.addConnection('mul_M', 'a')
  182. self.addConnection('mp', 'inv_mp')
  183. self.addConnection('sum_x', 'negx')
  184. self.addConnection('negx', 'prod_x')
  185. self.addConnection('int_xp', 'x')
  186. self.addConnection('p', 'square')
  187. self.addConnection('int', 'mul_p')
  188. if __name__ == '__main__':
  189. cbd = TrainSystem("TrainSystem")
  190. # Run the simulation
  191. cbd.run(360, delta_t=DELTA_T)
  192. # process simulation results
  193. plot_signals(cbd, ['ActualVelocity', 'IdealVelocity'], 'Velocity of the Train')
  194. plot_signals(cbd, ['PeopleDisplacement', 'Acceleration'], 'People Displacement and Acceleration')