pySimBlocks 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. examples/advanced/hardware/block_diagram.py +162 -0
  2. examples/advanced/hardware/camera.py +93 -0
  3. examples/advanced/hardware/gui_emio.py +231 -0
  4. examples/advanced/hardware/lmi.py +69 -0
  5. examples/advanced/hardware/main.py +57 -0
  6. examples/advanced/hardware/parameters.py +54 -0
  7. examples/advanced/qp_problem/params.py +10 -0
  8. examples/advanced/qp_problem/run.py +14 -0
  9. examples/advanced/sofa/gui/finger/Finger.py +108 -0
  10. examples/advanced/sofa/gui/finger/FingerController.py +53 -0
  11. examples/advanced/sofa/gui/finger/parameters_auto.py +22 -0
  12. examples/advanced/sofa/gui/sofa_plant/run.py +14 -0
  13. examples/advanced/sofa/python/Finger.py +107 -0
  14. examples/advanced/sofa/python/FingerController.py +48 -0
  15. examples/advanced/sofa/python/closedloop.py +64 -0
  16. examples/advanced/sofa/python/openloop.py +58 -0
  17. examples/basics/algebraic_function/g.py +7 -0
  18. examples/basics/algebraic_function/run.py +14 -0
  19. examples/basics/dc_motor/gui/run.py +14 -0
  20. examples/basics/dc_motor/multiple_order.py +91 -0
  21. examples/basics/dc_motor/openloop.py +62 -0
  22. examples/basics/dc_motor/pi.py +99 -0
  23. examples/basics/dc_motor/pid.py +118 -0
  24. examples/basics/dc_motor/pid_block.py +82 -0
  25. examples/basics/dc_motor/pid_block_vs_manual.py +143 -0
  26. examples/basics/external/parameters.py +4 -0
  27. examples/basics/external/run.py +14 -0
  28. examples/basics/file_sources/temp.py +16 -0
  29. examples/basics/observer.py +76 -0
  30. examples/basics/state_feedback/gui/parameters.py +9 -0
  31. examples/basics/state_feedback/gui/run.py +14 -0
  32. examples/basics/state_feedback/state_feedback.py +102 -0
  33. examples/basics/state_space/linear/gui/run.py +14 -0
  34. examples/basics/state_space/linear/ss_block.py +89 -0
  35. examples/basics/state_space/linear/ss_manual.py +105 -0
  36. examples/basics/state_space/non_linear/nlss.py +47 -0
  37. examples/basics/state_space/non_linear/run.py +14 -0
  38. examples/basics/state_space/polytope/params.py +39 -0
  39. examples/basics/state_space/polytope/weights.py +12 -0
  40. examples/comparison/simulink/convert.py +29 -0
  41. examples/comparison/simulink/openloop.py +127 -0
  42. examples/comparison/simulink/pi.py +148 -0
  43. examples/comparison/simulink/pid.py +154 -0
  44. examples/comparison/simulink/pid_backward.py +155 -0
  45. examples/quick_start/filter.py +35 -0
  46. examples/quick_start/gui/run.py +14 -0
  47. examples/tutorials/tutorial_1_python/main.py +99 -0
  48. examples/tutorials/tutorial_3_sofa/finger/Finger.py +120 -0
  49. examples/tutorials/tutorial_3_sofa/finger/FingerController.py +37 -0
  50. pySimBlocks/__init__.py +35 -0
  51. pySimBlocks/blocks/__init__.py +68 -0
  52. pySimBlocks/blocks/controllers/__init__.py +27 -0
  53. pySimBlocks/blocks/controllers/pid.py +250 -0
  54. pySimBlocks/blocks/controllers/state_feedback.py +141 -0
  55. pySimBlocks/blocks/interfaces/__init__.py +27 -0
  56. pySimBlocks/blocks/interfaces/external_input.py +107 -0
  57. pySimBlocks/blocks/interfaces/external_output.py +113 -0
  58. pySimBlocks/blocks/observers/__init__.py +23 -0
  59. pySimBlocks/blocks/observers/luenberger.py +175 -0
  60. pySimBlocks/blocks/operators/__init__.py +47 -0
  61. pySimBlocks/blocks/operators/algebraic_function.py +258 -0
  62. pySimBlocks/blocks/operators/dead_zone.py +186 -0
  63. pySimBlocks/blocks/operators/delay.py +254 -0
  64. pySimBlocks/blocks/operators/demux.py +123 -0
  65. pySimBlocks/blocks/operators/discrete_derivator.py +237 -0
  66. pySimBlocks/blocks/operators/discrete_integrator.py +265 -0
  67. pySimBlocks/blocks/operators/gain.py +294 -0
  68. pySimBlocks/blocks/operators/mux.py +131 -0
  69. pySimBlocks/blocks/operators/product.py +194 -0
  70. pySimBlocks/blocks/operators/rate_limiter.py +214 -0
  71. pySimBlocks/blocks/operators/saturation.py +178 -0
  72. pySimBlocks/blocks/operators/sum.py +188 -0
  73. pySimBlocks/blocks/operators/zero_order_hold.py +141 -0
  74. pySimBlocks/blocks/optimizers/__init__.py +23 -0
  75. pySimBlocks/blocks/optimizers/quadratic_program.py +326 -0
  76. pySimBlocks/blocks/sources/__init__.py +37 -0
  77. pySimBlocks/blocks/sources/chirp.py +168 -0
  78. pySimBlocks/blocks/sources/constant.py +82 -0
  79. pySimBlocks/blocks/sources/file_source.py +294 -0
  80. pySimBlocks/blocks/sources/function_source.py +197 -0
  81. pySimBlocks/blocks/sources/ramp.py +99 -0
  82. pySimBlocks/blocks/sources/sinusoidal.py +113 -0
  83. pySimBlocks/blocks/sources/step.py +138 -0
  84. pySimBlocks/blocks/sources/white_noise.py +107 -0
  85. pySimBlocks/blocks/systems/__init__.py +27 -0
  86. pySimBlocks/blocks/systems/linear_state_space.py +180 -0
  87. pySimBlocks/blocks/systems/non_linear_state_space.py +309 -0
  88. pySimBlocks/blocks/systems/polytopic_state_space.py +193 -0
  89. pySimBlocks/blocks/systems/sofa/__init__.py +30 -0
  90. pySimBlocks/blocks/systems/sofa/sofa_controller.py +472 -0
  91. pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +120 -0
  92. pySimBlocks/blocks/systems/sofa/sofa_plant.py +306 -0
  93. pySimBlocks/cli.py +127 -0
  94. pySimBlocks/core/__init__.py +32 -0
  95. pySimBlocks/core/block.py +167 -0
  96. pySimBlocks/core/block_source.py +94 -0
  97. pySimBlocks/core/config.py +90 -0
  98. pySimBlocks/core/fixed_time_manager.py +46 -0
  99. pySimBlocks/core/model.py +250 -0
  100. pySimBlocks/core/scheduler.py +30 -0
  101. pySimBlocks/core/simulator.py +329 -0
  102. pySimBlocks/core/task.py +73 -0
  103. pySimBlocks/docs/blocks/controllers/pid.md +78 -0
  104. pySimBlocks/docs/blocks/controllers/state_feedback.md +60 -0
  105. pySimBlocks/docs/blocks/interfaces/external_input.md +39 -0
  106. pySimBlocks/docs/blocks/interfaces/external_output.md +39 -0
  107. pySimBlocks/docs/blocks/observers/luenberger.md +70 -0
  108. pySimBlocks/docs/blocks/operators/algebraic_function.md +76 -0
  109. pySimBlocks/docs/blocks/operators/dead_zone.md +67 -0
  110. pySimBlocks/docs/blocks/operators/delay.md +76 -0
  111. pySimBlocks/docs/blocks/operators/demux.md +64 -0
  112. pySimBlocks/docs/blocks/operators/discrete_derivator.md +61 -0
  113. pySimBlocks/docs/blocks/operators/discrete_integrator.md +87 -0
  114. pySimBlocks/docs/blocks/operators/gain.md +97 -0
  115. pySimBlocks/docs/blocks/operators/mux.md +64 -0
  116. pySimBlocks/docs/blocks/operators/product.md +51 -0
  117. pySimBlocks/docs/blocks/operators/rate_limiter.md +70 -0
  118. pySimBlocks/docs/blocks/operators/saturation.md +62 -0
  119. pySimBlocks/docs/blocks/operators/sum.md +49 -0
  120. pySimBlocks/docs/blocks/operators/zero_order_hold.md +61 -0
  121. pySimBlocks/docs/blocks/optimizers/quadratic_program.md +98 -0
  122. pySimBlocks/docs/blocks/sources/chirp.md +102 -0
  123. pySimBlocks/docs/blocks/sources/constant.md +53 -0
  124. pySimBlocks/docs/blocks/sources/file_source.md +51 -0
  125. pySimBlocks/docs/blocks/sources/function_source.md +52 -0
  126. pySimBlocks/docs/blocks/sources/ramp.md +58 -0
  127. pySimBlocks/docs/blocks/sources/sinusoidal.md +60 -0
  128. pySimBlocks/docs/blocks/sources/step.md +63 -0
  129. pySimBlocks/docs/blocks/sources/white_noise.md +58 -0
  130. pySimBlocks/docs/blocks/systems/linear_state_space.md +66 -0
  131. pySimBlocks/docs/blocks/systems/non_linear_state_space.md +90 -0
  132. pySimBlocks/docs/blocks/systems/polytopic_state_space.md +72 -0
  133. pySimBlocks/docs/blocks/systems/sofa/sofa_exchange_i_o.md +63 -0
  134. pySimBlocks/docs/blocks/systems/sofa/sofa_plant.md +62 -0
  135. pySimBlocks/gui/__init__.py +20 -0
  136. pySimBlocks/gui/addons/__init__.py +19 -0
  137. pySimBlocks/gui/addons/sofa/__init__.py +19 -0
  138. pySimBlocks/gui/addons/sofa/sofa_dialog.py +190 -0
  139. pySimBlocks/gui/addons/sofa/sofa_service.py +209 -0
  140. pySimBlocks/gui/blocks/block_dialog_session.py +47 -0
  141. pySimBlocks/gui/blocks/block_meta.py +408 -0
  142. pySimBlocks/gui/blocks/controllers/pid.py +116 -0
  143. pySimBlocks/gui/blocks/controllers/state_feedback.py +80 -0
  144. pySimBlocks/gui/blocks/interfaces/external_input.py +64 -0
  145. pySimBlocks/gui/blocks/interfaces/external_output.py +63 -0
  146. pySimBlocks/gui/blocks/observers/luenberger.py +108 -0
  147. pySimBlocks/gui/blocks/operators/algebraic_function.py +232 -0
  148. pySimBlocks/gui/blocks/operators/dead_zone.py +79 -0
  149. pySimBlocks/gui/blocks/operators/delay.py +79 -0
  150. pySimBlocks/gui/blocks/operators/demux.py +98 -0
  151. pySimBlocks/gui/blocks/operators/discrete_derivator.py +67 -0
  152. pySimBlocks/gui/blocks/operators/discrete_integrator.py +80 -0
  153. pySimBlocks/gui/blocks/operators/gain.py +79 -0
  154. pySimBlocks/gui/blocks/operators/mux.py +100 -0
  155. pySimBlocks/gui/blocks/operators/product.py +109 -0
  156. pySimBlocks/gui/blocks/operators/rate_limiter.py +79 -0
  157. pySimBlocks/gui/blocks/operators/saturation.py +72 -0
  158. pySimBlocks/gui/blocks/operators/sum.py +91 -0
  159. pySimBlocks/gui/blocks/operators/zero_order_hold.py +64 -0
  160. pySimBlocks/gui/blocks/optimizers/quadratic_program.py +128 -0
  161. pySimBlocks/gui/blocks/parameter_meta.py +34 -0
  162. pySimBlocks/gui/blocks/port_meta.py +31 -0
  163. pySimBlocks/gui/blocks/sources/chirp.py +146 -0
  164. pySimBlocks/gui/blocks/sources/constant.py +63 -0
  165. pySimBlocks/gui/blocks/sources/file_source.py +196 -0
  166. pySimBlocks/gui/blocks/sources/function_source.py +202 -0
  167. pySimBlocks/gui/blocks/sources/ramp.py +73 -0
  168. pySimBlocks/gui/blocks/sources/sinusoidal.py +81 -0
  169. pySimBlocks/gui/blocks/sources/step.py +83 -0
  170. pySimBlocks/gui/blocks/sources/white_noise.py +70 -0
  171. pySimBlocks/gui/blocks/systems/linear_state_space.py +102 -0
  172. pySimBlocks/gui/blocks/systems/non_linear_state_space.py +233 -0
  173. pySimBlocks/gui/blocks/systems/polytopic_state_space.py +109 -0
  174. pySimBlocks/gui/blocks/systems/sofa/sofa_exchange_i_o.py +221 -0
  175. pySimBlocks/gui/blocks/systems/sofa/sofa_plant.py +220 -0
  176. pySimBlocks/gui/dialogs/__init__.py +19 -0
  177. pySimBlocks/gui/dialogs/block_dialog.py +125 -0
  178. pySimBlocks/gui/dialogs/display_yaml_dialog.py +89 -0
  179. pySimBlocks/gui/dialogs/help_dialog.py +39 -0
  180. pySimBlocks/gui/dialogs/plot_dialog.py +230 -0
  181. pySimBlocks/gui/dialogs/settings/plots.py +187 -0
  182. pySimBlocks/gui/dialogs/settings/project.py +146 -0
  183. pySimBlocks/gui/dialogs/settings/simulation.py +137 -0
  184. pySimBlocks/gui/dialogs/settings_dialog.py +88 -0
  185. pySimBlocks/gui/dialogs/unsaved_dialog.py +92 -0
  186. pySimBlocks/gui/editor.py +49 -0
  187. pySimBlocks/gui/graphics/__init__.py +29 -0
  188. pySimBlocks/gui/graphics/block_item.py +289 -0
  189. pySimBlocks/gui/graphics/connection_item.py +266 -0
  190. pySimBlocks/gui/graphics/port_item.py +153 -0
  191. pySimBlocks/gui/graphics/theme.py +119 -0
  192. pySimBlocks/gui/main_window.py +162 -0
  193. pySimBlocks/gui/models/__init__.py +31 -0
  194. pySimBlocks/gui/models/block_instance.py +114 -0
  195. pySimBlocks/gui/models/connection_instance.py +43 -0
  196. pySimBlocks/gui/models/port_instance.py +52 -0
  197. pySimBlocks/gui/models/project_simulation_params.py +50 -0
  198. pySimBlocks/gui/models/project_state.py +114 -0
  199. pySimBlocks/gui/project_controller.py +302 -0
  200. pySimBlocks/gui/services/__init__.py +20 -0
  201. pySimBlocks/gui/services/project_loader.py +381 -0
  202. pySimBlocks/gui/services/project_saver.py +68 -0
  203. pySimBlocks/gui/services/simulation_runner.py +66 -0
  204. pySimBlocks/gui/services/yaml_tools.py +261 -0
  205. pySimBlocks/gui/widgets/__init__.py +19 -0
  206. pySimBlocks/gui/widgets/block_list.py +131 -0
  207. pySimBlocks/gui/widgets/diagram_view.py +312 -0
  208. pySimBlocks/gui/widgets/toolbar_view.py +161 -0
  209. pySimBlocks/project/__init__.py +35 -0
  210. pySimBlocks/project/build_model.py +92 -0
  211. pySimBlocks/project/generate_run_script.py +109 -0
  212. pySimBlocks/project/generate_sofa_controller.py +215 -0
  213. pySimBlocks/project/load_project_config.py +197 -0
  214. pySimBlocks/project/load_simulation_config.py +166 -0
  215. pySimBlocks/project/load_simulator.py +45 -0
  216. pySimBlocks/project/plot_from_config.py +174 -0
  217. pySimBlocks/project/pySimBlocks_blocks_index.yaml +106 -0
  218. pySimBlocks/real_time/__init__.py +23 -0
  219. pySimBlocks/real_time/real_time_runner.py +148 -0
  220. pySimBlocks/tools/__init__.py +19 -0
  221. pySimBlocks/tools/blocks_registry.py +141 -0
  222. pySimBlocks/tools/generate_blocks_index.py +124 -0
  223. pysimblocks-0.1.0.dist-info/METADATA +180 -0
  224. pysimblocks-0.1.0.dist-info/RECORD +262 -0
  225. pysimblocks-0.1.0.dist-info/WHEEL +5 -0
  226. pysimblocks-0.1.0.dist-info/entry_points.txt +2 -0
  227. pysimblocks-0.1.0.dist-info/licenses/LICENSE.md +165 -0
  228. pysimblocks-0.1.0.dist-info/top_level.txt +3 -0
  229. tests/blocks/controllers/test_pid.py +143 -0
  230. tests/blocks/controllers/test_state_feedback.py +193 -0
  231. tests/blocks/observers/test_luenberger.py +225 -0
  232. tests/blocks/operators/test_algebraic_function.py +230 -0
  233. tests/blocks/operators/test_dead_zone.py +106 -0
  234. tests/blocks/operators/test_delay.py +167 -0
  235. tests/blocks/operators/test_demux.py +111 -0
  236. tests/blocks/operators/test_discrete_derivator.py +160 -0
  237. tests/blocks/operators/test_discrete_integrator.py +149 -0
  238. tests/blocks/operators/test_gain.py +182 -0
  239. tests/blocks/operators/test_mux.py +101 -0
  240. tests/blocks/operators/test_product.py +171 -0
  241. tests/blocks/operators/test_rate_limiter.py +166 -0
  242. tests/blocks/operators/test_saturation.py +157 -0
  243. tests/blocks/operators/test_sum.py +183 -0
  244. tests/blocks/operators/test_zero_order_hold.py +106 -0
  245. tests/blocks/sources/test_chirp.py +157 -0
  246. tests/blocks/sources/test_constant.py +55 -0
  247. tests/blocks/sources/test_file_source.py +185 -0
  248. tests/blocks/sources/test_function_source.py +135 -0
  249. tests/blocks/sources/test_ramp.py +110 -0
  250. tests/blocks/sources/test_sinusoidal.py +113 -0
  251. tests/blocks/sources/test_step.py +76 -0
  252. tests/blocks/sources/test_white_noise.py +108 -0
  253. tests/blocks/systems/test_linear_state_space.py +135 -0
  254. tests/blocks/systems/test_polytopic_state_space.py +133 -0
  255. tests/core/test_core_errors_and_determinism.py +82 -0
  256. tests/core/test_core_multirate_tasks.py +88 -0
  257. tests/core/test_core_two_phase_and_propagation.py +132 -0
  258. tests/gui/main_window_open_test.py +162 -0
  259. tests/gui/test_block_meta_param_cache.py +16 -0
  260. tests/gui/test_file_source_meta.py +17 -0
  261. tests/gui/test_function_source_meta.py +28 -0
  262. tests/regression/test_simulink_dc_motor.py +217 -0
@@ -0,0 +1,99 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from pySimBlocks import Model, Simulator, SimulationConfig
4
+ from pySimBlocks.blocks.sources import Step
5
+ from pySimBlocks.blocks.systems import LinearStateSpace
6
+ from pySimBlocks.blocks.operators import Sum, Gain, DiscreteIntegrator
7
+
8
+
9
+ def manual(A, B, C, Kp, Ki, dt, T):
10
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
11
+ motor = LinearStateSpace("motor", A, B, C)
12
+ error = Sum("error", signs="+-")
13
+ kp = Gain("Kp", Kp)
14
+ ki = Gain("Ki", Ki)
15
+ integrator = DiscreteIntegrator("integrator")
16
+ sum = Sum("sum", "++")
17
+
18
+ blocks = [ref, error, kp, integrator, ki, sum, motor]
19
+
20
+ model = Model("DC Motor Control")
21
+ for block in blocks:
22
+ model.add_block(block)
23
+ model.connect("ref", "out", "error", "in1")
24
+ model.connect("motor", "y", "error", "in2")
25
+ model.connect("error", "out", "Kp", "in")
26
+ model.connect("error", "out", "Ki", "in")
27
+ model.connect("Kp", "out", "sum", "in1")
28
+ model.connect("Ki", "out", "integrator", "in")
29
+ model.connect("integrator", "out", "sum", "in2")
30
+ model.connect("sum", "out", "motor", "u")
31
+
32
+ # Simulator
33
+ sim_cfg = SimulationConfig(dt, T)
34
+ sim = Simulator(model, sim_cfg, verbose=False)
35
+ logs = sim.run(logging=[
36
+ "ref.outputs.out",
37
+ "motor.outputs.y",
38
+ "sum.outputs.out",
39
+ "integrator.outputs.out",
40
+ "Kp.outputs.out"
41
+ ])
42
+
43
+
44
+ time = sim.get_data("time")
45
+ r = sim.get_data("ref.outputs.out").squeeze()
46
+ w = sim.get_data("motor.outputs.y").squeeze()
47
+ u = sim.get_data("sum.outputs.out").squeeze()
48
+ p_term = sim.get_data("Kp.outputs.out").squeeze()
49
+ i_term = sim.get_data("integrator.outputs.out").squeeze()
50
+
51
+ return time, r, w, u, p_term, i_term
52
+
53
+ def main():
54
+ # DC Motor parameters
55
+ R = 0.1
56
+ L = 0.5
57
+ J = 0.01
58
+ K = 0.1
59
+ a = 0.001
60
+
61
+ Kp = np.array([[0.001]])
62
+ Ki = np.array([[0.02]])
63
+
64
+ # Simulation parameters
65
+ dt = 0.01
66
+ T = 100.
67
+
68
+ # State-space matrices
69
+ A = np.array([[1-dt*R/L, -dt*K/L], [dt*K/J, 1-dt*a/J]])
70
+ B = np.array([[dt/L], [0]])
71
+ C = np.array([[0, 1]])
72
+
73
+
74
+ time_man, r_man, w_man, u_man, p_term, i_term = manual(A, B, C, Kp, Ki, dt, T)
75
+
76
+
77
+ plt.figure()
78
+ plt.step(time_man, r_man, ':r', label="Reference (Manual)", where='post')
79
+ plt.step(time_man, w_man, ':b', label="Motor Speed (Manual)", where='post')
80
+ plt.step(time_man, u_man, ':g', label="Control Input (Manual)", where='post')
81
+ plt.xlabel("Time (s)")
82
+ plt.ylabel("Speed (rad/s)")
83
+ plt.title("DC Motor PI Speed Response")
84
+ plt.legend()
85
+ plt.grid()
86
+
87
+ plt.figure()
88
+ plt.step(time_man, p_term, '-r', label="P Term", where='post')
89
+ plt.step(time_man, i_term, '-g', label="I Term", where='post')
90
+ plt.xlabel("Time (s)")
91
+ plt.ylabel("Term Value")
92
+ plt.title("PID Controller Terms (Manual Implementation)")
93
+ plt.legend()
94
+ plt.grid()
95
+
96
+ plt.show()
97
+
98
+ if __name__ == "__main__":
99
+ main()
@@ -0,0 +1,118 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from pySimBlocks import Model, Simulator, SimulationConfig
4
+ from pySimBlocks.blocks.sources import Step
5
+ from pySimBlocks.blocks.systems import LinearStateSpace
6
+ from pySimBlocks.blocks.operators import (
7
+ Sum,
8
+ Gain,
9
+ DiscreteIntegrator,
10
+ DiscreteDerivator,
11
+ )
12
+
13
+
14
+ def manual(A, B, C, Kp, Ki, Kd, dt, T):
15
+ ref = Step("ref", start_time=1.0, value_before=0.0, value_after=1.0)
16
+ motor = LinearStateSpace("motor", A, B, C)
17
+ error = Sum("error", signs="+-")
18
+ kp = Gain("Kp", Kp)
19
+ ki = Gain("Ki", Ki)
20
+ integrator = DiscreteIntegrator("integrator")
21
+ kd = Gain("Kd", Kd)
22
+ derivator = DiscreteDerivator("derivator")
23
+ sum = Sum("sum", "+++")
24
+
25
+ blocks = [ref, error, kp, integrator, ki, sum, motor, kd, derivator]
26
+
27
+ model = Model("DC Motor Control")
28
+ for block in blocks:
29
+ model.add_block(block)
30
+ model.connect("ref", "out", "error", "in1")
31
+ model.connect("motor", "y", "error", "in2")
32
+ model.connect("error", "out", "Kp", "in")
33
+ model.connect("error", "out", "Ki", "in")
34
+ model.connect("error", "out", "Kd", "in")
35
+ model.connect("Kp", "out", "sum", "in1")
36
+ model.connect("Ki", "out", "integrator", "in")
37
+ model.connect("integrator", "out", "sum", "in3")
38
+ model.connect("Kd", "out", "derivator", "in")
39
+ model.connect("derivator", "out", "sum", "in2")
40
+ model.connect("sum", "out", "motor", "u")
41
+
42
+ # Simulator
43
+ sim_cfg = SimulationConfig(dt, T)
44
+ sim = Simulator(model, sim_cfg, verbose=False)
45
+
46
+ logs = sim.run(
47
+ logging=[
48
+ "ref.outputs.out",
49
+ "motor.outputs.y",
50
+ "sum.outputs.out",
51
+ "derivator.outputs.out",
52
+ "integrator.outputs.out",
53
+ "Kp.outputs.out",
54
+ ]
55
+ )
56
+
57
+ time = sim.get_data("time")
58
+ r = sim.get_data("ref.outputs.out").squeeze()
59
+ w = sim.get_data("motor.outputs.y").squeeze()
60
+ u = sim.get_data("sum.outputs.out").squeeze()
61
+
62
+ p_term = sim.get_data("Kp.outputs.out").squeeze()
63
+ i_term = sim.get_data("integrator.outputs.out").squeeze()
64
+ d_term = sim.get_data("derivator.outputs.out").squeeze()
65
+
66
+ return time, r, w, u, p_term, i_term, d_term
67
+
68
+
69
+ def main():
70
+ # DC Motor parameters
71
+ R = 0.1
72
+ L = 0.5
73
+ J = 0.01
74
+ K = 0.1
75
+ a = 0.001
76
+
77
+ Kp = np.array([[0.001]])
78
+ Ki = np.array([[0.02]])
79
+ Kd = np.array([[0.01]])
80
+
81
+ # Simulation parameters
82
+ dt = 0.01
83
+ T = 100.0
84
+
85
+ # State-space matrices
86
+ A = np.array([[1 - dt * R / L, -dt * K / L], [dt * K / J, 1 - dt * a / J]])
87
+ B = np.array([[dt / L], [0]])
88
+ C = np.array([[0, 1]])
89
+
90
+ time_man, r_man, w_man, u_man, p_term, i_term, d_term = manual(
91
+ A, B, C, Kp, Ki, Kd, dt, T
92
+ )
93
+
94
+ plt.figure()
95
+ plt.step(time_man, r_man, ":r", label="Reference (Manual)", where="post")
96
+ plt.step(time_man, w_man, ":b", label="Motor Speed (Manual)", where="post")
97
+ plt.step(time_man, u_man, ":g", label="Control Input (Manual)", where="post")
98
+ plt.xlabel("Time (s)")
99
+ plt.ylabel("Speed (rad/s)")
100
+ plt.title("DC Motor PID Speed Response")
101
+ plt.legend()
102
+ plt.grid()
103
+
104
+ plt.figure()
105
+ plt.step(time_man, p_term, "-r", label="P Term", where="post")
106
+ plt.step(time_man, i_term, "-g", label="I Term", where="post")
107
+ plt.step(time_man, d_term, "-b", label="D Term", where="post")
108
+ plt.xlabel("Time (s)")
109
+ plt.ylabel("Term Value")
110
+ plt.title("PID Controller Terms (Manual Implementation)")
111
+ plt.legend()
112
+ plt.grid()
113
+
114
+ plt.show()
115
+
116
+
117
+ if __name__ == "__main__":
118
+ main()
@@ -0,0 +1,82 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from pySimBlocks import Model, Simulator, SimulationConfig
4
+ from pySimBlocks.blocks.sources import Step
5
+ from pySimBlocks.blocks.systems import LinearStateSpace
6
+ from pySimBlocks.blocks.operators import Sum
7
+ from pySimBlocks.blocks.controllers import Pid
8
+
9
+
10
+ def pid(A, B, C, Kp, Ki, Kd, dt, T):
11
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
12
+ motor = LinearStateSpace("motor", A, B, C)
13
+ error = Sum("error", signs="+-")
14
+ pid = Pid("pid", Kp=Kp, Ki=Ki, Kd=Kd)
15
+
16
+ blocks = [ref, error, pid, motor]
17
+
18
+ # Model
19
+ model = Model("DC Motor Control")
20
+ for block in blocks:
21
+ model.add_block(block)
22
+ model.connect("ref", "out", "error", "in1")
23
+ model.connect("motor", "y", "error", "in2")
24
+ model.connect("error", "out", "pid", "e")
25
+ model.connect("pid", "u", "motor", "u")
26
+
27
+ # Simulator
28
+ sim_cfg = SimulationConfig(dt, T)
29
+ sim = Simulator(model, sim_cfg, verbose=False)
30
+
31
+ logs = sim.run(logging=[
32
+ "ref.outputs.out",
33
+ "motor.outputs.y",
34
+ "pid.outputs.u"
35
+ ])
36
+
37
+ time = sim.get_data("time")
38
+ r = sim.get_data("ref.outputs.out").squeeze()
39
+ w = sim.get_data("motor.outputs.y").squeeze()
40
+ u = sim.get_data("pid.outputs.u").squeeze()
41
+
42
+ return time, r, w, u
43
+
44
+
45
+ def main():
46
+ # DC Motor parameters
47
+ R = 0.1
48
+ L = 0.5
49
+ J = 0.01
50
+ K = 0.1
51
+ a = 0.001
52
+
53
+ Kp = 0.001
54
+ Ki = 0.02
55
+ Kd = 0.01
56
+
57
+ # Simulation parameters
58
+ dt = 0.01
59
+ T = 100.
60
+
61
+ # State-space matrices
62
+ A = np.array([[1-dt*R/L, -dt*K/L], [dt*K/J, 1-dt*a/J]])
63
+ B = np.array([[dt/L], [0]])
64
+ C = np.array([[0, 1]])
65
+
66
+
67
+ time_pid, r_pid, w_pid, u_pid = pid(A, B, C, Kp, Ki, Kd, dt, T)
68
+
69
+
70
+ plt.figure()
71
+ plt.step(time_pid, r_pid, '--r', label="Reference (PID)", where='post')
72
+ plt.step(time_pid, w_pid, '--b', label="Motor Speed (PID)", where='post')
73
+ plt.step(time_pid, u_pid, '--g', label="Control Input (PID)", where='post')
74
+ plt.xlabel("Time (s)")
75
+ plt.ylabel("Speed (rad/s)")
76
+ plt.title("DC Motor Speed Response")
77
+ plt.legend()
78
+ plt.grid()
79
+ plt.show()
80
+
81
+ if __name__ == "__main__":
82
+ main()
@@ -0,0 +1,143 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from pySimBlocks import Model, Simulator, SimulationConfig
4
+ from pySimBlocks.blocks.sources import Step
5
+ from pySimBlocks.blocks.systems import LinearStateSpace
6
+ from pySimBlocks.blocks.operators import Sum, Gain, DiscreteIntegrator, DiscreteDerivator
7
+ from pySimBlocks.blocks.controllers import Pid
8
+
9
+
10
+ def pid(A, B, C, Kp, Ki, Kd, dt, T):
11
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
12
+ motor = LinearStateSpace("motor", A, B, C)
13
+ error = Sum("error", signs="+-")
14
+ pid = Pid("pid", Kp=Kp, Ki=Ki, Kd=Kd)
15
+
16
+ blocks = [ref, error, pid, motor]
17
+
18
+ # Model
19
+ model = Model("DC Motor Control")
20
+ for block in blocks:
21
+ model.add_block(block)
22
+ model.connect("ref", "out", "error", "in1")
23
+ model.connect("motor", "y", "error", "in2")
24
+ model.connect("error", "out", "pid", "e")
25
+ model.connect("pid", "u", "motor", "u")
26
+
27
+ # Simulator
28
+ sim_cfg = SimulationConfig(dt, T)
29
+ sim = Simulator(model, sim_cfg, verbose=False)
30
+ logs = sim.run(logging=[
31
+ "ref.outputs.out",
32
+ "motor.outputs.y",
33
+ "pid.outputs.u"
34
+ ])
35
+
36
+ time = sim.get_data("time")
37
+ r = sim.get_data("ref.outputs.out").squeeze()
38
+ w = sim.get_data("motor.outputs.y").squeeze()
39
+ u = sim.get_data("pid.outputs.u").squeeze()
40
+
41
+ return time, r, w, u
42
+
43
+ def manual(A, B, C, Kp, Ki, Kd, dt, T):
44
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
45
+ motor = LinearStateSpace("motor", A, B, C)
46
+ error = Sum("error", signs="+-")
47
+ kp = Gain("Kp", Kp)
48
+ ki = Gain("Ki", Ki)
49
+ integrator = DiscreteIntegrator("integrator")
50
+ kd = Gain("Kd", Kd)
51
+ derivator = DiscreteDerivator("derivator")
52
+ sum = Sum("sum", "+++")
53
+
54
+ blocks = [ref, error, kp, integrator, ki, sum, motor, kd, derivator]
55
+
56
+ model = Model("DC Motor Control")
57
+ for block in blocks:
58
+ model.add_block(block)
59
+ model.connect("ref", "out", "error", "in1")
60
+ model.connect("motor", "y", "error", "in2")
61
+ model.connect("error", "out", "Kp", "in")
62
+ model.connect("error", "out", "Ki", "in")
63
+ model.connect("error", "out", "Kd", "in")
64
+ model.connect("Kp", "out", "sum", "in1")
65
+ model.connect("Ki", "out", "integrator", "in")
66
+ model.connect("integrator", "out", "sum", "in3")
67
+ model.connect("Kd", "out", "derivator", "in")
68
+ model.connect("derivator", "out", "sum", "in2")
69
+ model.connect("sum", "out", "motor", "u")
70
+
71
+ # Simulator
72
+ sim_cfg = SimulationConfig(dt, T)
73
+ sim = Simulator(model, sim_cfg, verbose=False)
74
+ logs = sim.run(logging=[
75
+ "ref.outputs.out",
76
+ "motor.outputs.y",
77
+ "sum.outputs.out",
78
+ "derivator.outputs.out",
79
+ "integrator.outputs.out",
80
+ "Kp.outputs.out"
81
+ ])
82
+
83
+ time = sim.get_data("time")
84
+ r = sim.get_data("ref.outputs.out").squeeze()
85
+ w = sim.get_data("motor.outputs.y").squeeze()
86
+ u = sim.get_data("sum.outputs.out").squeeze()
87
+
88
+ return time, r, w, u
89
+
90
+ def main():
91
+ # DC Motor parameters
92
+ R = 0.1
93
+ L = 0.5
94
+ J = 0.01
95
+ K = 0.1
96
+ a = 0.001
97
+
98
+ Kp = np.array([[0.001]])
99
+ Ki = np.array([[0.02]])
100
+ Kd = np.array([[0.01]])
101
+
102
+ # Simulation parameters
103
+ dt = 0.01
104
+ T = 30.
105
+
106
+ # State-space matrices
107
+ A = np.array([[1-dt*R/L, -dt*K/L], [dt*K/J, 1-dt*a/J]])
108
+ B = np.array([[dt/L], [0]])
109
+ C = np.array([[0, 1]])
110
+
111
+
112
+ time_pid, r_pid, w_pid, u_pid = pid(A, B, C, Kp, Ki, Kd, dt, T)
113
+ time_man, r_man, w_man, u_man = manual(A, B, C, Kp, Ki, Kd, dt, T)
114
+
115
+ error = np.linalg.norm(w_pid - w_man)
116
+ print(f"Error between PID block and manual implementation: {error:.6f}")
117
+ print("Mean Error: ", np.mean(np.abs(w_pid - w_man)))
118
+
119
+ print("Time: ", time_pid[98:105].flatten())
120
+ print("PID w: ", w_pid[98:105].flatten())
121
+ print("Man w: ", w_man[98:105].flatten())
122
+ print("PID u: ", u_pid[98:105].flatten())
123
+ print("Man u: ", u_man[98:105].flatten())
124
+
125
+ plt.figure()
126
+ plt.step(time_pid, r_pid, '--r', label="Reference (PID)", where='post')
127
+ plt.step(time_pid, w_pid, '--b', label="Motor Speed (PID)", where='post')
128
+ plt.step(time_man, r_man, ':r', label="Reference (Manual)", where='post')
129
+ plt.step(time_man, w_man, ':b', label="Motor Speed (Manual)", where='post')
130
+ plt.xlabel("Time (s)")
131
+ plt.ylabel("Speed (rad/s)")
132
+ plt.title("DC Motor Speed Response")
133
+ plt.legend()
134
+ plt.grid()
135
+
136
+
137
+ plt.figure()
138
+ plt.step(time_pid, u_pid, '--g', label="Control Input (PID)", where='post')
139
+ plt.step(time_man, u_man, ':g', label="Control Input (Manual)", where='post')
140
+ plt.show()
141
+
142
+ if __name__ == "__main__":
143
+ main()
@@ -0,0 +1,4 @@
1
+ import numpy as np
2
+
3
+ Kp = np.array([[2.]])
4
+ Ki = np.array([[1.]])
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+ from pySimBlocks.project import load_simulator_from_project
3
+ from pySimBlocks.project.plot_from_config import plot_from_config
4
+
5
+ try:
6
+ BASE_DIR = Path(__file__).parent.resolve()
7
+ except Exception:
8
+ BASE_DIR = Path("")
9
+
10
+ sim, plot_cfg = load_simulator_from_project(BASE_DIR / "project.yaml")
11
+
12
+ logs = sim.run()
13
+ if True and plot_cfg is not None:
14
+ plot_from_config(logs, plot_cfg)
@@ -0,0 +1,16 @@
1
+ import csv
2
+ import numpy as np
3
+
4
+ t = np.arange(0, 10, 0.1)
5
+ y = np.sin(t)
6
+ y = y.reshape(-1, 1)
7
+
8
+ np.savez('data.npz', time=t, y=y)
9
+
10
+ np.save('data.npy', y)
11
+
12
+ with open('data.csv', 'w', newline='') as csvfile:
13
+ writer = csv.writer(csvfile)
14
+ writer.writerow(['time', 'y']) # Write header
15
+ for t_val, y_val in zip(t, y):
16
+ writer.writerow([t_val, y_val[0]]) # Write each row of data
@@ -0,0 +1,76 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+
4
+ from pySimBlocks import Model, Simulator, SimulationConfig
5
+ from pySimBlocks.blocks.sources import Constant
6
+ from pySimBlocks.blocks.systems import LinearStateSpace
7
+ from pySimBlocks.blocks.observers import Luenberger
8
+
9
+
10
+ def main():
11
+ # System
12
+ A = np.array([[0.9]])
13
+ B = np.array([[1.0]])
14
+ C = np.array([[1.0]])
15
+
16
+ # Observer gain L
17
+ L = np.array([[0.5]])
18
+
19
+ # True plant
20
+ plant = LinearStateSpace("plant", A=A, B=B, C=C, x0=np.array([[0.0]]))
21
+
22
+ # Command (constant)
23
+ u_val = np.array([[1.0]])
24
+ u_src = Constant("u", value=u_val)
25
+
26
+ # Observer
27
+ obs = Luenberger(
28
+ name="observer",
29
+ A=A, B=B, C=C, L=L,
30
+ x0=np.array([[-2.0]])
31
+ )
32
+
33
+ # Build model
34
+ model = Model("observer_test")
35
+ model.add_block(u_src)
36
+ model.add_block(plant)
37
+ model.add_block(obs)
38
+
39
+ model.connect("u", "out", "plant", "u")
40
+ model.connect("u", "out", "observer", "u")
41
+ model.connect("plant", "y", "observer", "y")
42
+
43
+ dt = 0.1
44
+ T = 10.
45
+ sim_cfg = SimulationConfig(dt, T)
46
+ sim = Simulator(model, sim_cfg)
47
+
48
+ logs = sim.run(logging=[
49
+ "plant.outputs.x",
50
+ "observer.outputs.x_hat",
51
+ ]
52
+ )
53
+
54
+ # Extract logs
55
+ t = sim.get_data("time")
56
+ x_true = sim.get_data("plant.outputs.x").squeeze()
57
+ x_hat = sim.get_data("observer.outputs.x_hat").squeeze()
58
+
59
+ # The observer should track the state with low error after a few steps
60
+ error = np.linalg.norm(x_true[-1] - x_hat[-1])
61
+ print(f"Final estimation error: {error}")
62
+
63
+
64
+ plt.figure()
65
+ plt.step(t, x_true, "--r", label="True State x", where="post")
66
+ plt.step(t, x_hat, '--b', label="Estimated State x_hat", where="post")
67
+ plt.xlabel("Time [s]")
68
+ plt.ylabel("State Value")
69
+ plt.title("Luenberger Observer State Estimation")
70
+ plt.legend()
71
+ plt.grid()
72
+ plt.show()
73
+
74
+
75
+ if __name__ == "__main__":
76
+ main()
@@ -0,0 +1,9 @@
1
+ import numpy as np
2
+ import control as ct
3
+
4
+ A = np.array([[0.95, 0.1], [0, 0.98]])
5
+ B = np.array([[1], [1]])
6
+ C = np.array([[1., 0.]])
7
+
8
+ K = ct.place(A, B, [0.9, 0.91])
9
+ G = np.linalg.inv(C @ np.linalg.inv(np.eye(2) - A + B @ K) @ B)
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+ from pySimBlocks.project import load_simulator_from_project
3
+ from pySimBlocks.project.plot_from_config import plot_from_config
4
+
5
+ try:
6
+ BASE_DIR = Path(__file__).parent.resolve()
7
+ except Exception:
8
+ BASE_DIR = Path("")
9
+
10
+ sim, plot_cfg = load_simulator_from_project(BASE_DIR / 'project.yaml')
11
+
12
+ logs = sim.run()
13
+ if True and plot_cfg is not None:
14
+ plot_from_config(logs, plot_cfg)
@@ -0,0 +1,102 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import control as ct
4
+
5
+ from pySimBlocks import Model, Simulator, SimulationConfig
6
+ from pySimBlocks.blocks.sources import Step
7
+ from pySimBlocks.blocks.controllers import StateFeedback
8
+ from pySimBlocks.blocks.systems import LinearStateSpace
9
+
10
+
11
+ def main():
12
+ # --- 1. Define system matrices (SISO example) ---
13
+ A = np.array([[0.95, 0.1], [0, 0.98]])
14
+ B = np.array([[1], [1]])
15
+ C = np.array([[1., 0.]])
16
+
17
+ K = ct.place(A, B, [0.9, 0.91])
18
+ G = np.linalg.inv(C @ np.linalg.inv(np.eye(2) - A + B @ K) @ B)
19
+
20
+ # --- 2. Create blocks ---
21
+ # Step : 0 -> 1 at start_time = 0.5 s
22
+ ref = Step(
23
+ name="ref",
24
+ value_before=np.array([[0.0]]),
25
+ value_after=np.array([[1.0]]),
26
+ start_time=0.5,
27
+ )
28
+
29
+ # State feedback controller
30
+ controller = StateFeedback(name="controller", K=K, G=G)
31
+
32
+ # Linear state-space system
33
+ plant = LinearStateSpace(
34
+ name="plant",
35
+ A=A, B=B, C=C,
36
+ x0=np.array([[0.], [0.]]),
37
+ )
38
+
39
+ # --- 3. Build the model ---
40
+ model = Model(name="state_feedback_control")
41
+ model.add_block(ref)
42
+ model.add_block(controller)
43
+ model.add_block(plant)
44
+
45
+ # Connect:
46
+ model.connect("ref", "out", "controller", "r")
47
+ model.connect("controller", "u", "plant", "u")
48
+ model.connect("plant", "x", "controller", "x")
49
+
50
+ # --- 4. Create the simulator ---
51
+ dt = 0.01 # 10 ms
52
+ T = 2.0 # 2 seconds
53
+ sim_cfg = SimulationConfig(dt, T)
54
+ sim = Simulator(model, sim_cfg)
55
+
56
+ # --- 5. Run simulation ---
57
+ logs = sim.run(logging=[
58
+ "ref.outputs.out",
59
+ "controller.outputs.u",
60
+ "plant.outputs.x",
61
+ "plant.outputs.y",
62
+ ],
63
+ )
64
+
65
+ # --- 6. Inspect / print some results ---
66
+ length = len(logs["plant.outputs.y"])
67
+
68
+ t = sim.get_data("time")
69
+ r = sim.get_data("ref.outputs.out").squeeze()
70
+ y = sim.get_data("plant.outputs.y").squeeze()
71
+ x = sim.get_data("plant.outputs.x").squeeze()
72
+ u = sim.get_data("controller.outputs.u").squeeze()
73
+
74
+ plt.figure()
75
+ plt.step(t, r, label="ref (step)", where="post")
76
+ plt.step(t, y, label="y (plant output)", where="post")
77
+ plt.legend()
78
+ plt.grid(True)
79
+ plt.xlabel("Time [s]")
80
+ plt.title("Reference tracking")
81
+
82
+
83
+ plt.figure()
84
+ plt.step(t, u, label="u = gain(ref)", where="post")
85
+ plt.legend()
86
+ plt.grid(True)
87
+ plt.xlabel("Time [s]")
88
+ plt.title("Control input")
89
+
90
+ plt.figure()
91
+ plt.step(t, x[:, 0], label="x1 (state 1)", where="post")
92
+ plt.step(t, x[:, 1], label="x2 (state 2)", where="post")
93
+ plt.legend()
94
+ plt.grid(True)
95
+ plt.xlabel("Time [s]")
96
+ plt.title("States evolution")
97
+
98
+ plt.show()
99
+
100
+
101
+ if __name__ == "__main__":
102
+ main()