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,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,89 @@
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 Step
6
+ from pySimBlocks.blocks.systems import LinearStateSpace
7
+
8
+ def main():
9
+ # --- 1. Define system matrices (SISO example) ---
10
+ A = np.array([[0., 0.25], [0.3, 0.91]])
11
+ B = np.array([[0.5], [0.3]])
12
+ C = np.array([[0., 1.0]])
13
+ x0 = np.zeros((A.shape[0], 1))
14
+
15
+
16
+ # --- 2. Create blocks ---
17
+ command = Step(
18
+ name="command",
19
+ value_before=np.array([[0.0]]),
20
+ value_after=np.array([[1.0]]),
21
+ start_time=0.5,
22
+ )
23
+
24
+ # Linear state-space system
25
+ plant = LinearStateSpace(
26
+ name="plant",
27
+ A=A, B=B, C=C,
28
+ x0=x0,
29
+ )
30
+
31
+ # --- 3. Build the model ---
32
+ model = Model(name="siso")
33
+ model.add_block(command)
34
+ model.add_block(plant)
35
+
36
+ model.connect("command", "out", "plant", "u")
37
+
38
+
39
+ # --- 4. Create the simulator ---
40
+ dt = 0.01
41
+ T = 5.
42
+ sim_cfg = SimulationConfig(dt, T)
43
+ sim = Simulator(model, sim_cfg)
44
+
45
+ # --- 5. Run simulation ---
46
+ logs = sim.run(logging=[
47
+ "command.outputs.out",
48
+ "plant.outputs.x",
49
+ "plant.outputs.y",
50
+ ],
51
+ )
52
+
53
+
54
+ # --- 6. Inspect / print some results ---
55
+ t = sim.get_data("time")
56
+ u = sim.get_data("command.outputs.out").squeeze()
57
+ x = sim.get_data("plant.outputs.x").squeeze()
58
+ y = sim.get_data("plant.outputs.y").squeeze()
59
+
60
+
61
+ # --- 6. Plot the result ---
62
+ plt.figure()
63
+ plt.step(t, x[:, 0], "--r", label="x[0]", where="post")
64
+ plt.step(t, x[:, 1], "--b", label="x[1]", where="post")
65
+ plt.xlabel("Time [s]")
66
+ plt.ylabel("State")
67
+ plt.grid(True)
68
+ plt.legend()
69
+ plt.title("State evolution")
70
+
71
+ plt.figure()
72
+ plt.step(t, y, "--g", label="y (output)", where="post")
73
+ plt.xlabel("Time [s]")
74
+ plt.ylabel("Output")
75
+ plt.grid(True)
76
+ plt.legend()
77
+ plt.title("Output evolution")
78
+
79
+ plt.figure()
80
+ plt.step(t, u, "--k", label="u (input)", where="post")
81
+ plt.xlabel("Time [s]")
82
+ plt.ylabel("Input")
83
+ plt.grid(True)
84
+ plt.legend()
85
+ plt.title("Input signal")
86
+ plt.show()
87
+
88
+ if __name__ == "__main__":
89
+ main()
@@ -0,0 +1,105 @@
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 Step
6
+ from pySimBlocks.blocks.operators import Gain, Sum, Delay
7
+
8
+
9
+ def main():
10
+ """Closed chain block digram test.
11
+ x[k+1] = A*x[k] + B*u[k]
12
+ """
13
+
14
+ A = np.array([[0., 0.25], [0.3, 0.91]])
15
+ B = np.array([[0.5], [0.3]])
16
+ C = np.array([[0., 1.0]])
17
+ x0 = np.zeros((A.shape[0], 1))
18
+
19
+ # -------------------------------------------------------
20
+ # 1. Create the blocks
21
+ # -------------------------------------------------------
22
+ step = Step(
23
+ name="u",
24
+ value_before=np.array([[0.0]]),
25
+ value_after=np.array([[1.0]]),
26
+ start_time=0.5
27
+ )
28
+ state_matrix = Gain(name="A", gain=A, multiplication="Matrix (K @ u)")
29
+ input_matrix = Gain(name="B", gain=B, multiplication="Matrix (K @ u)")
30
+ output_matrix = Gain(name="C", gain=C, multiplication="Matrix (K @ u)")
31
+ sum = Sum(name="sum", signs="++")
32
+ delay = Delay(name="delay", initial_output=x0)
33
+
34
+ # -------------------------------------------------------
35
+ # 2. Build the model
36
+ # -------------------------------------------------------
37
+ model = Model("test")
38
+ for block in [step, input_matrix, state_matrix, sum, delay, output_matrix]:
39
+ model.add_block(block)
40
+
41
+ model.connect("u", "out", "B", "in")
42
+ model.connect("B", "out", "sum", "in1")
43
+ model.connect("A", "out", "sum", "in2")
44
+ model.connect("sum", "out", "delay", "in")
45
+ model.connect("delay", "out", "A", "in")
46
+ model.connect("delay", "out", "C", "in")
47
+
48
+ # -------------------------------------------------------
49
+ # 3. Create the simulator
50
+ # -------------------------------------------------------
51
+ dt = 0.01
52
+ T = 5.
53
+ sim_cfg = SimulationConfig(dt, T)
54
+ sim = Simulator(model, sim_cfg, verbose=True)
55
+
56
+ # -------------------------------------------------------
57
+ # 4. Run the simulation for 2 seconds
58
+ # -------------------------------------------------------
59
+ logs = sim.run(logging=[
60
+ "u.outputs.out",
61
+ "delay.outputs.out",
62
+ "C.outputs.out",
63
+ ]
64
+ )
65
+
66
+ # -------------------------------------------------------
67
+ # 5. Extract logged data
68
+ # -------------------------------------------------------
69
+ t = sim.get_data("time")
70
+ u = sim.get_data("u.outputs.out").squeeze()
71
+ x = sim.get_data("delay.outputs.out").squeeze()
72
+ y = sim.get_data("C.outputs.out").squeeze()
73
+
74
+ # -------------------------------------------------------
75
+ # 6. Plot the result
76
+ # -------------------------------------------------------
77
+ plt.figure()
78
+ plt.step(t, x[:, 0], "--r", label="x[0]", where="post")
79
+ plt.step(t, x[:, 1], "--b", label="x[1]", where="post")
80
+ plt.xlabel("Time [s]")
81
+ plt.ylabel("State")
82
+ plt.grid(True)
83
+ plt.legend()
84
+ plt.title("State evolution")
85
+
86
+ plt.figure()
87
+ plt.step(t, y, "--g", label="y (output)", where="post")
88
+ plt.xlabel("Time [s]")
89
+ plt.ylabel("Output")
90
+ plt.grid(True)
91
+ plt.legend()
92
+ plt.title("Output evolution")
93
+
94
+ plt.figure()
95
+ plt.step(t, u, "--k", label="u (input)", where="post")
96
+ plt.xlabel("Time [s]")
97
+ plt.ylabel("Input")
98
+ plt.grid(True)
99
+ plt.legend()
100
+ plt.title("Input signal")
101
+ plt.show()
102
+
103
+
104
+ if __name__ == "__main__":
105
+ main()
@@ -0,0 +1,47 @@
1
+ import numpy as np
2
+
3
+ def f(t, dt, x, u):
4
+ """
5
+ Non-linear state-space function for a discrete-time system.
6
+
7
+ Parameters:
8
+ t : float
9
+ Current time.
10
+ dt : float
11
+ Time step.
12
+ x : ndarray
13
+ Current state vector.
14
+ u : ndarray
15
+ Current input vector.
16
+
17
+ Returns:
18
+ x_next : ndarray
19
+ Next state vector after applying the non-linear dynamics.
20
+ """
21
+ x_next = np.zeros_like(x)
22
+ x_next[0] = x[0] + dt * (x[1] + np.sin(x[0]) + u[0]**2)
23
+ x_next[1] = x[1] + dt * (-x[0]**3 - 0.5 * x[1])
24
+
25
+ return x_next
26
+
27
+
28
+ def g(t, dt, x):
29
+ """
30
+ Non-linear output function for a discrete-time system.
31
+
32
+ Parameters:
33
+ t : float
34
+ Current time.
35
+ dt : float
36
+ Time step.
37
+ x : ndarray
38
+ Current state vector.
39
+
40
+ Returns:
41
+ y : ndarray
42
+ Output vector after applying the non-linear output function.
43
+ """
44
+ y = np.zeros((1, 1))
45
+ y[0] = x[0]**2 + np.cos(x[1])
46
+
47
+ return {"y": y}
@@ -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,39 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+
4
+ # Dimensions
5
+ r = 3 # number of vertices
6
+ nx = 4 # state dimension
7
+ nu = 1 # input dimension
8
+ ny = 2 # output dimension
9
+
10
+
11
+ # Create A_i matrices
12
+ A1 = np.array([
13
+ [0.8, 0.1, 0.0, 0.0],
14
+ [0.0, 0.7, 0.1, 0.0],
15
+ [0.0, 0.0, 0.6, 0.1],
16
+ [0.0, 0.0, 0.0, 0.5],
17
+ ])
18
+
19
+ A2 = A1 + 0.05 * np.eye(nx)
20
+ A3 = A1 - 0.05 * np.eye(nx)
21
+
22
+ A = np.hstack([A1, A2, A3])
23
+
24
+
25
+ # Create B_i matrices
26
+ B1 = np.array([[1.0], [0.0], [0.0], [0.0]])
27
+ B2 = np.array([[0.5], [0.5], [0.0], [0.0]])
28
+ B3 = np.array([[0.2], [0.3], [0.3], [0.2]])
29
+
30
+ B = np.hstack([B1, B2, B3])
31
+
32
+
33
+ # Output matrix
34
+ C = np.array([
35
+ [1.0, 0.0, 0.0, 0.0],
36
+ [0.0, 0.0, 1.0, 0.0],
37
+ ])
38
+
39
+
@@ -0,0 +1,12 @@
1
+ import numpy as np
2
+
3
+
4
+ def get_weights(t, dt, c):
5
+ w1 = np.clip(0.4 + 0.2 * np.sin(0.5 * t) + c, 0.0, 1.0)
6
+ w2 = np.clip(0.3 + 0.1 * np.cos(0.3 * t), 0.0, 1-w1)
7
+ w3 = 1.0 - w1 - w2
8
+ w3 = np.clip(w3, 0.0, 1.0)
9
+
10
+ val = np.array([w1, w2, w3]).reshape(-1, 1)
11
+ return {"w": val}
12
+
@@ -0,0 +1,29 @@
1
+ import csv
2
+ import numpy as np
3
+
4
+ filename = "simulation.csv"
5
+
6
+ # Lecture du CSV
7
+ with open(filename, "r") as f:
8
+ reader = csv.reader(f)
9
+ rows = list(reader)
10
+
11
+ # Titres
12
+ titles = rows[0]
13
+
14
+ # Données converties en float
15
+ data = np.array(rows[1:], dtype=float)
16
+
17
+ # Construction dynamique du dictionnaire pour savez
18
+ save_dict = {"titles": np.array(titles)}
19
+
20
+ for i, name in enumerate(titles):
21
+ key = name.strip()
22
+
23
+ # Optionnel : sécuriser le nom si nécessaire
24
+ # key = key.replace(" ", "_").replace("-", "_")
25
+
26
+ save_dict[key] = data[:, i]
27
+
28
+ # Sauvegarde
29
+ np.savez("simulation.npz", **save_dict)
@@ -0,0 +1,127 @@
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 Gain, Sum, Delay
7
+
8
+
9
+ def manual_sim(A, B, C, T, dt):
10
+
11
+ # Blocks
12
+ ref = Step("u", start_time=1., value_before=0., value_after=1.)
13
+ delay_x = Delay("x", num_delays=1, initial_output=np.zeros((A.shape[0], 1)))
14
+ gain_A = Gain("A", A, multiplication="Matrix (K @ u)")
15
+ gain_B = Gain("B", B, multiplication="Matrix (K @ u)")
16
+ gain_C = Gain("C", C, multiplication="Matrix (K @ u)")
17
+ sum_x = Sum("sum_x", "++")
18
+
19
+ # model
20
+ model = Model("manual_ss")
21
+ for blk in [ref, delay_x, gain_A, gain_B, gain_C, sum_x]:
22
+ model.add_block(blk)
23
+
24
+ # connection
25
+ model.connect("u", "out", "B", "in") # u -> B
26
+ model.connect("B", "out", "sum_x", "in1") # B u -> sum
27
+ model.connect("x", "out", "A", "in") # x -> A
28
+ model.connect("A", "out", "sum_x", "in2") # A x -> sum
29
+ model.connect("sum_x", "out", "x", "in") # x_next -> Delay
30
+ model.connect("x", "out", "C", "in") # x -> C
31
+
32
+ # Simulator
33
+ sim_cfg = SimulationConfig(dt, T, logging=[
34
+ "u.outputs.out",
35
+ "C.outputs.out",
36
+ "x.outputs.out"
37
+ ])
38
+ sim = Simulator(model, sim_cfg, verbose=True)
39
+ logs = sim.run( )
40
+
41
+ time = sim.get_data("time")
42
+ u = sim.get_data("u.outputs.out").squeeze()
43
+ w = sim.get_data("C.outputs.out").squeeze()
44
+
45
+ return time, u, w
46
+
47
+
48
+
49
+ def block_sim(A, B, C, T, dt):
50
+ # Blocks
51
+ ref = Step("command", start_time=1., value_before=0., value_after=1.)
52
+ motor = LinearStateSpace("motor", A, B, C)
53
+
54
+ # Model
55
+ model = Model("DC Motor Control")
56
+ for block in [ref, motor]:
57
+ model.add_block(block)
58
+ model.connect("command", "out", "motor", "u")
59
+
60
+ # Simulator
61
+ sim_cfg = SimulationConfig(dt, T, logging=[
62
+ "command.outputs.out",
63
+ "motor.outputs.y"
64
+ ])
65
+ sim = Simulator(model, sim_cfg, verbose=False)
66
+ logs = sim.run()
67
+
68
+ time = sim.get_data("time")
69
+ u = sim.get_data("command.outputs.out").squeeze()
70
+ w = sim.get_data("motor.outputs.y").squeeze()
71
+
72
+ return time, u, w
73
+
74
+
75
+ def main():
76
+ # DC Motor parameters
77
+ R = 0.1
78
+ L = 0.5
79
+ J = 0.01
80
+ K = 0.1
81
+ a = 0.001
82
+
83
+ # Simulation parameters
84
+ dt = 0.1
85
+ T = 30.
86
+
87
+ # State-space matrices
88
+ A = np.array([[1-dt*R/L, -dt*K/L], [dt*K/J, 1-dt*a/J]])
89
+ B = np.array([[dt/L], [0]])
90
+ C = np.array([[0, 1]])
91
+
92
+ time, uol, wol = manual_sim(A, B, C, T, dt)
93
+ time_block, uol_block, wol_block = block_sim(A, B, C, T, dt)
94
+
95
+ # data from simulink
96
+ data = np.load("simulation.npz")
97
+ t_sim = data["time"]
98
+ uol_sim, wol_sim = data["uol"], data["wol"]
99
+
100
+ print("Error simulink - manual: ", np.linalg.norm(wol_sim - wol))
101
+ print("Error simulink - block: ", np.linalg.norm(wol_sim - wol_block))
102
+
103
+ # Plot
104
+ plt.figure()
105
+ plt.step(t_sim, wol_sim, '-r', label="w ((simulink)", where="post")
106
+ plt.step(time, wol, '--b', label="w (manual)", where="post")
107
+ plt.step(time_block, wol_block, ':g', label="w (block)", where="post")
108
+ plt.xlabel("Time (s)")
109
+ plt.ylabel("Speed (rad/s)")
110
+ plt.legend()
111
+ plt.grid()
112
+ plt.title("Open-Loop DC Motor Response")
113
+
114
+ plt.figure()
115
+ plt.step(t_sim, uol_sim, '-r', label="u (simulink)", where="post")
116
+ plt.step(time, uol, '--b', label="u (Manual)", where="post")
117
+ plt.step(time_block, uol_block, ':g', label="u (block)", where="post")
118
+ plt.xlabel("Time (s)")
119
+ plt.ylabel("motor (V)")
120
+ plt.legend()
121
+ plt.grid()
122
+ plt.title("Command")
123
+
124
+ plt.show()
125
+
126
+ if __name__ == "__main__":
127
+ main()
@@ -0,0 +1,148 @@
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
+ from pySimBlocks.blocks.controllers import Pid
8
+
9
+
10
+ def manual_sim(A, B, C, Kp, Ki, T, dt):
11
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
12
+ motor = LinearStateSpace("motor", A, B, C)
13
+ error = Sum("error", "+-")
14
+ kp = Gain("Kp", Kp, multiplication="Matrix (K @ u)")
15
+ ki = Gain("Ki", Ki, multiplication="Matrix (K @ u)")
16
+ integrator = DiscreteIntegrator("integrator")
17
+ sum = Sum("sum", "++")
18
+
19
+ blocks = [ref, error, kp, integrator, ki, sum, motor]
20
+
21
+ model = Model("DC Motor Control")
22
+ for block in blocks:
23
+ model.add_block(block)
24
+ model.connect("ref", "out", "error", "in1")
25
+ model.connect("motor", "y", "error", "in2")
26
+ model.connect("error", "out", "Kp", "in")
27
+ model.connect("Kp", "out", "sum", "in1")
28
+ model.connect("error", "out", "Ki", "in")
29
+ model.connect("Ki", "out", "integrator", "in")
30
+ model.connect("integrator", "out", "sum", "in2")
31
+ model.connect("sum", "out", "motor", "u")
32
+
33
+ # Simulator
34
+ sim_cfg = SimulationConfig(dt, T, logging=[
35
+ "ref.outputs.out",
36
+ "motor.outputs.y",
37
+ "sum.outputs.out"])
38
+ sim = Simulator(model, sim_cfg, verbose=True)
39
+ logs = sim.run()
40
+
41
+ time = sim.get_data("time")
42
+ u = sim.get_data("sum.outputs.out").squeeze()
43
+ w = sim.get_data("motor.outputs.y").squeeze()
44
+ r = sim.get_data("ref.outputs.out").squeeze()
45
+
46
+ return time, u, w, r
47
+
48
+
49
+ def block_sim(A, B, C, Kp, Ki, T, dt):
50
+ ref = Step("ref", start_time=1., value_before=0., value_after=1.)
51
+ motor = LinearStateSpace("motor", A, B, C)
52
+ error = Sum("error", "+-")
53
+ pid = Pid("pid", Kp=Kp, Ki=Ki, controller="PI")
54
+
55
+ blocks = [ref, error, pid, motor]
56
+
57
+ # Model
58
+ model = Model("DC Motor Control")
59
+ for block in blocks:
60
+ model.add_block(block)
61
+ model.connect("ref", "out", "error", "in1")
62
+ model.connect("motor", "y", "error", "in2")
63
+ model.connect("error", "out", "pid", "e")
64
+ model.connect("pid", "u", "motor", "u")
65
+
66
+ # Simulator
67
+ sim_cfg = SimulationConfig(dt, T, logging=[
68
+ "ref.outputs.out",
69
+ "motor.outputs.y",
70
+ "pid.outputs.u"
71
+ ])
72
+ sim = Simulator(model, sim_cfg, verbose=True)
73
+ logs = sim.run()
74
+
75
+ time = sim.get_data("time")
76
+ u = sim.get_data("pid.outputs.u").squeeze()
77
+ w = sim.get_data("motor.outputs.y").squeeze()
78
+ r = sim.get_data("ref.outputs.out").squeeze()
79
+
80
+ return time, u, w, r
81
+
82
+
83
+ def main():
84
+ # DC Motor parameters
85
+ R = 0.1
86
+ L = 0.5
87
+ J = 0.01
88
+ K = 0.1
89
+ a = 0.001
90
+
91
+ Kp = np.array([[.001]])
92
+ Ki = np.array([[.02]])
93
+
94
+ # Simulation parameters
95
+ data = np.load("simulation.npz")
96
+ dt = 0.1
97
+ T = 30.
98
+
99
+ # State-space matrices
100
+ A = np.array([[1-dt*R/L, -dt*K/L], [dt*K/J, 1-dt*a/J]])
101
+ B = np.array([[dt/L], [0]])
102
+ C = np.array([[0, 1]])
103
+
104
+ time, upi, wpi, rpi = manual_sim(A, B, C, Kp, Ki, T, dt)
105
+ time_block, upi_block, wpi_block, rpi_block = block_sim(A, B, C, Kp, Ki, T, dt)
106
+
107
+ # data from simulink
108
+ t_sim = data["time"]
109
+ upi_sim, wpi_sim, rpi_sim = data["upi"], data["wpi"], data['r']
110
+
111
+
112
+ print("Error simulink - manual: ", np.linalg.norm(wpi_sim - wpi))
113
+ print("Error simulink - block: ", np.linalg.norm(wpi_sim - wpi_block))
114
+
115
+ # Plot
116
+ plt.figure()
117
+ plt.step(t_sim, wpi_sim, '-r', label="w (simulink)", where="post")
118
+ plt.step(time, wpi, '--b', label="w (manual)", where="post")
119
+ plt.step(time_block, wpi_block, ':g', label="w (block)", where="post")
120
+ plt.xlabel("Time (s)")
121
+ plt.ylabel("Speed (rad/s)")
122
+ plt.legend()
123
+ plt.grid()
124
+ plt.title("PI DC Motor Response")
125
+
126
+ plt.figure()
127
+ plt.step(t_sim, upi_sim, '-r', label="u (simulink)", where="post")
128
+ plt.step(time, upi, '--b', label="u (Manual)", where="post")
129
+ plt.step(time_block, upi_block, ':g', label="u (block)", where="post")
130
+ plt.xlabel("Time (s)")
131
+ plt.ylabel("motor (V)")
132
+ plt.legend()
133
+ plt.grid()
134
+ plt.title("Command")
135
+
136
+ plt.figure()
137
+ plt.step(t_sim, rpi_sim, '-r', label="r (simulink)", where="post")
138
+ plt.step(time, rpi, '--b', label="r (Manual)", where="post")
139
+ plt.step(time_block, rpi_block, ':g', label="r (block)", where="post")
140
+ plt.xlabel("Time (s)")
141
+ plt.legend()
142
+ plt.grid()
143
+ plt.title("Reference")
144
+
145
+ plt.show()
146
+
147
+ if __name__ == "__main__":
148
+ main()