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,76 @@
1
+ # Algebraic Function
2
+
3
+ ## Summary
4
+
5
+ The **Algebraic Function** block evaluates a user-defined, stateless Python
6
+ function at each simulation step.
7
+
8
+ It implements an algebraic mapping between input and output signals, possibly
9
+ depending on the current simulation time.
10
+
11
+ The python function that defines the algebraic relation must always return:
12
+ - A dictionary containing the output signals, with keys matching the `output_keys` parameter.
13
+ - It should always work and return outputs of the correct shape when called with any inputs.
14
+
15
+ ---
16
+
17
+ ## Mathematical definition
18
+
19
+ The block implements a general algebraic relation of the form:
20
+
21
+ $$
22
+ y[k] = g(t_k, \Delta t_k, u_1[k], u_2[k], \dots)
23
+ $$
24
+
25
+ where:
26
+ - $ u_i[k] $ are the input signals at step $k$,
27
+ - $ y[k] $ is the output signal,
28
+ - $ t_k $ is the current simulation time,
29
+ - $ \Delta t_k $ is the time step since the previous activation.
30
+
31
+ The function $ g $ is provided by the user as a Python function.
32
+
33
+ ---
34
+
35
+ ## Parameters
36
+
37
+ | Name | Type | Description | Required |
38
+ |------|------|-------------|----------|
39
+ | `file_path` | string | Path to the Python file containing the user-defined function. | Yes |
40
+ | `function_name` | string | Name of the function $ g $ to call inside the block. | Yes |
41
+ | `input_keys` | list[string] | Names of the input ports $ u_1, \dots, u_m $. | Yes |
42
+ | `output_keys` | list[string] | Names of the output ports returned by the output function. | Yes |
43
+ | `sample_time` | float | Execution period of the block. If omitted, the global simulation time step is used. | No |
44
+
45
+ ---
46
+
47
+ ## Inputs
48
+
49
+ Inputs are dynamically defined by `input_keys`.
50
+
51
+ - Each input must be connected.
52
+ - Each input is a NumPy array of shape $ (n,1) $.
53
+
54
+ ---
55
+
56
+ ## Outputs
57
+
58
+ Outputs are dynamically defined by `output_keys`.
59
+
60
+ - Each output is a NumPy array of shape $ (n,1) $.
61
+
62
+ ---
63
+
64
+ ## Execution semantics
65
+
66
+ - The block is stateless.
67
+ - The block has direct feedthrough.
68
+ - At each activation, the function is evaluated as:
69
+
70
+ ```python
71
+ g(t, dt, **inputs)
72
+ ```
73
+
74
+
75
+ ---
76
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,67 @@
1
+ # DeadZone
2
+
3
+ ## Summary
4
+
5
+ The **DeadZone** block applies a dead-zone nonlinearity to its input signal.
6
+ Values within a specified interval around zero are suppressed, while values
7
+ outside the interval are shifted accordingly.
8
+
9
+ ---
10
+
11
+ ## Mathematical definition
12
+
13
+ For each output component $i$, the signal is defined as:
14
+
15
+ $$
16
+ y_i =
17
+ \begin{cases}
18
+ 0 & \text{if } u_{\min,i} \le u_i \le u_{\max,i} \\
19
+ u_i - u_{\max,i} & \text{if } u_i > u_{\max,i} \\
20
+ u_i - u_{\min,i} & \text{if } u_i < u_{\min,i}
21
+ \end{cases}
22
+ $$
23
+
24
+ where:
25
+ - $u_{\min,i}$ is the lower bound of the dead zone,
26
+ - $u_{\max,i}$ is the upper bound of the dead zone.
27
+
28
+
29
+ ---
30
+
31
+ ## Parameters
32
+
33
+ | Name | Type | Description | Optional |
34
+ |------------|-------------|-------------|-------------|
35
+ | `lower_bound` | scalar or vector or matrix | Lower bound of the dead zone. Must be less than or equal to zero. Default is zero. | True |
36
+ | `upper_bound` | scalar or vector or matrix | Upper bound of the dead zone. Must be greater than or equal to zero. Default is zero. | True |
37
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
38
+
39
+ ---
40
+
41
+ ## Inputs
42
+
43
+ | Port | Description |
44
+ |------|------------|
45
+ | `in` | Input signal to be processed. |
46
+
47
+ ---
48
+
49
+ ## Outputs
50
+
51
+ | Port | Description |
52
+ |------|------------|
53
+ | `out` | Output signal after dead-zone transformation. |
54
+
55
+ ---
56
+
57
+ ## Notes
58
+
59
+ - The block has no internal state.
60
+ - The block has direct feedthrough.
61
+ - Bounds are broadcast to match the input dimension when needed.
62
+ - The dead zone must always include zero.
63
+ - This block is equivalent to the Simulink **Dead Zone** block.
64
+
65
+
66
+ ---
67
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,76 @@
1
+ # Delay
2
+
3
+ ## Summary
4
+
5
+ The **Delay** block outputs a delayed version of its input signal by a fixed
6
+ number of discrete simulation steps.
7
+
8
+ The block can be reset to an initial output value via an optional reset input.
9
+ This reset is a level-triggered signal: when the reset input is true (non-zero), the delay buffer is reset to the initial output value.
10
+ It is not a rising-edge or falling-edge trigger.
11
+
12
+ ---
13
+
14
+ ## Mathematical definition
15
+
16
+ For a delay of $N$ steps, the block implements:
17
+
18
+ $$
19
+ y[k] = u[k - N]
20
+ $$
21
+
22
+ where:
23
+ - $u[k]$ is the input signal,
24
+ - $y[k]$ is the delayed output signal.
25
+
26
+ ---
27
+
28
+ ## Parameters
29
+
30
+ | Name | Type | Description | Optional |
31
+ |------------|-------------|-------------|-------------|
32
+ | `num_delays` | integer | Number of discrete delay steps. Default is 1. | True |
33
+ | `initial_output` | scalar or vector or matrix | Initial value to fill the delay buffer. If not provided, the buffer is initialized as zero. | True |
34
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
35
+
36
+ ---
37
+
38
+ ## Inputs
39
+
40
+ | Port | Description |
41
+ |------|------------|
42
+ | `in` | Input signal to be delayed. |
43
+ | `reset` | Optional reset signal. When true (non-zero), the delay buffer is reset to the initial output value. |
44
+
45
+ ---
46
+
47
+ ## Outputs
48
+
49
+
50
+ | Port | Description |
51
+ |------|------------|
52
+ | `out` | Delayed output signal. |
53
+
54
+ ---
55
+
56
+ ## Notes
57
+
58
+ - The block has internal state.
59
+ - The block has no direct feedthrough.
60
+ - The delay buffer stores the last $N$ input samples.
61
+ - Output dimensions are inferred from the first valid input if not explicitly
62
+ initialized.
63
+ - This block is equivalent to the Simulink **Delay** / **Unit Delay** block.
64
+ - Policy:
65
+ + Signals are 2D arrays.
66
+ + Buffer always exists (never None).
67
+ + Shape is fixed either:
68
+ * immediately if initial_output is non-scalar 2D (shape != (1,1))
69
+ * otherwise at the first non-None input seen by the block
70
+ + If buffer is still "unfixed" and currently scalar (1,1), it can be
71
+ broadcast ONCE to match the first input shape.
72
+ + After shape is fixed, any shape mismatch raises.
73
+
74
+
75
+ ---
76
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,64 @@
1
+ # Demux
2
+
3
+ ## Summary
4
+
5
+ The **Demux** block splits one input column vector into multiple output
6
+ column vectors.
7
+
8
+ ---
9
+
10
+ ## Mathematical definition
11
+
12
+ Given an input vector $\mathrm{in} \in \mathbb{R}^{n \times 1}$ and
13
+ $p$ outputs:
14
+
15
+ $$
16
+ q = \left\lfloor \frac{n}{p} \right\rfloor, \quad
17
+ m = n \bmod p
18
+ $$
19
+
20
+ The output segments are:
21
+ - the first $m$ outputs have size $(q+1, 1)$,
22
+ - the remaining $(p-m)$ outputs have size $(q, 1)$.
23
+
24
+ This corresponds to an even split with the remainder distributed on the
25
+ first outputs.
26
+
27
+ ---
28
+
29
+ ## Parameters
30
+
31
+ | Name | Type | Description | Optional |
32
+ |------------|-------------|-------------|-------------|
33
+ | `num_outputs` | integer | Number of output ports to create. | True |
34
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
35
+
36
+ ---
37
+
38
+ ## Inputs
39
+
40
+ | Port | Description |
41
+ |------|------------|
42
+ | `in` | Input column vector of shape $(n,1)$. |
43
+
44
+ ---
45
+
46
+ ## Outputs
47
+
48
+ | Port | Description |
49
+ |------|------------|
50
+ | `out1 … outP` | Output vector segments according to the split rule above. |
51
+
52
+ ---
53
+
54
+ ## Notes
55
+
56
+ - The block has no internal state.
57
+ - The block has direct feedthrough.
58
+ - Input must be a column vector of shape $(n,1)$.
59
+ - The parameter `num_outputs` must satisfy $1 \le p \le n$.
60
+ - This block is equivalent to the Simulink **Demux** concept for vector splitting.
61
+
62
+
63
+ ---
64
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,61 @@
1
+ # DiscreteDerivator
2
+
3
+ ## Summary
4
+
5
+ The **DiscreteDerivator** block estimates the discrete-time derivative of an
6
+ input signal using a backward finite-difference scheme.
7
+
8
+ ---
9
+
10
+ ## Mathematical definition
11
+
12
+ The derivative is approximated as:
13
+
14
+ $$
15
+ y[k] = \frac{u[k] - u[k-1]}{dt}
16
+ $$
17
+
18
+ where:
19
+ - $u[k]$ is the current input sample,
20
+ - $u[k-1]$ is the previous input sample,
21
+ - $dt$ is the simulation time step.
22
+
23
+ ---
24
+
25
+ ## Parameters
26
+
27
+ | Name | Type | Description | Optional |
28
+ |------------|-------------|-------------|-------------|
29
+ | `initial_output` | scalar or vector or matrix | Initial value to fill the delay buffer. If not provided, the buffer is initialized as zero. | True |
30
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
31
+
32
+ ---
33
+
34
+ ## Inputs
35
+
36
+ | Port | Description |
37
+ |------|------------|
38
+ | `in` | Input signal for derivative estimation. |
39
+
40
+ ---
41
+
42
+ ## Outputs
43
+
44
+ | Port | Description |
45
+ |------|------------|
46
+ | `out` | Estimated discrete-time derivative of the input signal. |
47
+
48
+ ---
49
+
50
+ ## Notes
51
+
52
+ - The block has internal state.
53
+ - The block has direct feedthrough.
54
+ - A backward difference scheme is used because future input values are not
55
+ accessible.
56
+ - Input dimension changes between steps are not allowed.
57
+ - This block matches Simulink **Derivative** behavior in discrete-time mode.
58
+
59
+
60
+ ---
61
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,87 @@
1
+ # DiscreteIntegrator
2
+
3
+ ## Summary
4
+
5
+ The **DiscreteIntegrator** block integrates an input signal over time using
6
+ a discrete-time numerical integration scheme.
7
+
8
+ ---
9
+
10
+ ## Mathematical definition
11
+
12
+ The integrator state evolves according to:
13
+
14
+ $$
15
+ x[k+1] = x[k] + dt * u[k]
16
+ $$
17
+
18
+ The output depends on the selected integration method.
19
+
20
+ ### Euler forward
21
+
22
+ $$
23
+ y[k] = x[k]
24
+ $$
25
+
26
+ ### Euler backward
27
+
28
+ $$
29
+ y[k] = x[k] + dt * u[k]
30
+ $$
31
+
32
+ where:
33
+ - $u[k]$ is the input signal,
34
+ - $x[k]$ is the internal integrated state,
35
+ - $dt$ is the simulation time step.
36
+
37
+ ---
38
+
39
+ ## Parameters
40
+
41
+ | Name | Type | Description | Optional |
42
+ |------------|-------------|-------------|-------------|
43
+ | `initial_state` | scalar or vector or matrix | Initial value of the integrated state. If omitted, the state is initialized as a zero vector. | True |
44
+ | `method` | string | Numerical integration method: `euler forward` or `euler backward`. | True |
45
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
46
+
47
+ ---
48
+
49
+ ## Inputs
50
+
51
+ | Port | Description |
52
+ |------|------------|
53
+ | `in` | Input signal to be integrated. |
54
+
55
+ ---
56
+
57
+ ## Outputs
58
+
59
+ | Port | Description |
60
+ |------|------------|
61
+ | `out` | Integrated output signal. |
62
+
63
+ ---
64
+
65
+ ## Notes
66
+
67
+ - The block has internal state.
68
+ - Direct feedthrough depends on the integration method:
69
+ - no direct feedthrough for forward Euler,
70
+ - direct feedthrough for backward Euler.
71
+ - The integrator uses a fixed-step discrete formulation.
72
+ - Input dimension changes between steps are not allowed.
73
+ - This block is equivalent to the Simulink **Discrete-Time Integrator** block.
74
+ - Policy:
75
+ + Never propagate None: output is always a 2D array (at least (1,1)).
76
+ + Shape is NOT frozen while we are in placeholder shape (1,1) and no explicit
77
+ non-scalar initial_state was given.
78
+ + As soon as a non-scalar input appears (shape != (1,1)), the shape becomes frozen.
79
+ + If initial_state is provided and non-scalar, it freezes the shape immediately.
80
+ If initial_state is scalar (1,1), it is treated as a placeholder: can be upgraded
81
+ once a non-scalar input appears.
82
+ + After shape is frozen, any non-scalar input shape mismatch raises ValueError.
83
+ + If shape is frozen to (m,n), scalar input (1,1) is broadcast to (m,n).
84
+
85
+
86
+ ---
87
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,97 @@
1
+ # Gain Block
2
+
3
+ ## Description
4
+
5
+ The **Gain** block applies a static transformation to its input signal using a gain **K**.
6
+
7
+ Depending on the selected multiplication mode, it computes one of:
8
+
9
+ - **Element-wise**:
10
+ $$ y = K \odot u $$
11
+ - **Left matrix product**:
12
+ $$ y = K \cdot u $$
13
+ - **Right matrix product**:
14
+ $$ y = u \cdot K $$
15
+
16
+ Where:
17
+ - $u$ is the input signal (2D array),
18
+ - $K$ is the gain,
19
+ - $y$ is the output signal.
20
+
21
+ ---
22
+
23
+ ## Multiplication modes
24
+
25
+ ### 1) Element wise (K * u)
26
+
27
+ Element-wise multiplication with strict shape rules (no implicit matrix product):
28
+
29
+ - **K scalar**: `y = K * u`
30
+ Works for any 2D `u` shape `(m,n)`.
31
+
32
+ - **K vector (m,)**: `y = K[:,None] * u`
33
+ Requires `u.shape[0] == m`. Output shape is `(m,n)`.
34
+
35
+ - **K matrix (m,n)**: `y = K * u`
36
+ Requires `u.shape == (m,n)`.
37
+
38
+ Any other mismatch raises an error.
39
+
40
+ ---
41
+
42
+ ### 2) Matrix (K @ u)
43
+
44
+ Left matrix product:
45
+
46
+ - Requires **K is a 2D matrix** with shape `(p,m)`
47
+ - Requires input `u` is 2D with shape `(m,ncols)`
48
+ - Output `y` has shape `(p,ncols)`
49
+
50
+ ---
51
+
52
+ ### 3) Matrix (u @ K)
53
+
54
+ Right matrix product:
55
+
56
+ - Requires **K is a 2D matrix** with shape `(m,q)`
57
+ - Requires input `u` is 2D with shape `(nrows,m)`
58
+ - Output `y` has shape `(nrows,q)`
59
+
60
+ ---
61
+
62
+ ## Parameters
63
+
64
+ | Name | Type | Description | Optional |
65
+ |------|------|-------------|----------|
66
+ | `gain` | scalar, vector (m,), or matrix (p,m) / (m,q) | Gain coefficient(s). | False |
67
+ | `multiplication` | string enum | `"Element wise (K * u)"` \| `"Matrix (K @ u)"` \| `"Matrix (u @ K)"` | True (default: element-wise) |
68
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
69
+
70
+ ---
71
+
72
+ ## Inputs
73
+
74
+ | Port | Description |
75
+ |------|------------|
76
+ | `in` | Input signal $u$ (**must be a 2D NumPy array**). |
77
+
78
+ ---
79
+
80
+ ## Outputs
81
+
82
+ | Port | Description |
83
+ |------|------------|
84
+ | `out` | Output signal $y$ (2D array). |
85
+
86
+ ---
87
+
88
+ ## Notes
89
+
90
+ - The Gain block is **stateless** and **direct feedthrough**.
91
+ - Inputs must be **2D** (`ndim == 2`). No implicit reshape/flatten is applied.
92
+ - Dimension mismatches raise an error.
93
+ - This block is conceptually similar to Simulink **Gain**, but the multiplication behavior is made explicit via `multiplication`.
94
+
95
+
96
+ ---
97
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,64 @@
1
+ # Mux
2
+
3
+ ## Summary
4
+
5
+ The **Mux** block concatenates multiple input column vectors vertically
6
+ into a single output column vector.
7
+
8
+ ---
9
+
10
+ ## Mathematical definition
11
+
12
+ Given $N$ input vectors $\mathrm{in}_i \in \mathbb{R}^{n_i \times 1}$,
13
+ the output is defined as:
14
+
15
+ $$
16
+ \mathrm{out} =
17
+ \begin{bmatrix}
18
+ \mathrm{in}_1 \\
19
+ \mathrm{in}_2 \\
20
+ \vdots \\
21
+ \mathrm{in}_N
22
+ \end{bmatrix}
23
+ $$
24
+
25
+ The resulting output dimension is $(\sum_i n_i, 1)$.
26
+
27
+ ---
28
+
29
+ ## Parameters
30
+
31
+ | Name | Type | Description | Optional |
32
+ |------------|-------------|-------------|-------------|
33
+ | `num_inputs` | integer | Number of input ports to create. | True |
34
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
35
+
36
+ ---
37
+
38
+ ## Inputs
39
+
40
+ | Port | Description |
41
+ |------|------------|
42
+ | `in1 … inN` | Input column vectors to be concatenated. |
43
+
44
+ ---
45
+
46
+ ## Outputs
47
+
48
+ | Port | Description |
49
+ |------|------------|
50
+ | `out` | Vertically concatenated output vector. |
51
+
52
+ ---
53
+
54
+ ## Notes
55
+
56
+ - The block has no internal state.
57
+ - The block has direct feedthrough.
58
+ - Input vectors are not required to have the same dimension.
59
+ - All input ports must be connected for the block to produce an output.
60
+ - This block is equivalent to the Simulink **Mux** block.
61
+
62
+
63
+ ---
64
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later
@@ -0,0 +1,51 @@
1
+ # Product Block
2
+
3
+ ## Description
4
+
5
+ The **Product** block computes a multiplication or division of multiple input signals.
6
+
7
+ If multiplication is "Element-wise (*)", it performs element-wise multiplication or division:
8
+ $$ y = u_1 oper_1 u_2 oper_2 \dots oper_{N-1} u_N $$
9
+ where each coefficient \( oper_i \) is either * or /.
10
+
11
+ If multiplication is "Matrix (@)", it performs matrix multiplication or division:
12
+ $$ y = u_1 oper_1 u_2 oper_2 \dots oper_{N-1} u_N $$
13
+ where each coefficient \( oper_i \) is either * (matrix product @) or / (matrix inverse).
14
+
15
+ ---
16
+
17
+ ## Parameters
18
+
19
+ | Name | Type | Description | Optional |
20
+ |------|------------|
21
+ | `operations` | string | Specify the operations between inputs as a string of "*" and "/" characters. For example, for three inputs and operations "*", "/", the string would be "* /". The length of this string must be one less than the number of inputs. | False |
22
+ | `multiplication` | string | Type of multiplication: "Element-wise (*)" or "Matrix (@)". | False |
23
+ | `sample_time` | float | Block sample time. If omitted, the global simulation time step is used. | True |
24
+
25
+ ---
26
+
27
+ ## Inputs
28
+
29
+ | Port | Description |
30
+ |------|------------|
31
+ | `in1 … inN` | Input signals to be multiplied or divided. All inputs must have identical dimensions or scalar |
32
+
33
+ ---
34
+
35
+ ## Outputs
36
+
37
+ | Port | Description |
38
+ |------|------------|
39
+ | `out` | Result of the multiplication/division of all input signals. |
40
+
41
+ ---
42
+
43
+ ## Notes
44
+
45
+ - The Sum block has no internal state.
46
+ - The Sum block is direct-feedthrough.
47
+ - The number of input ports is determined by the length of `operations` + 1 .
48
+
49
+
50
+ ---
51
+ © 2026 Université de Lille & INRIA – Licensed under LGPL-3.0-or-later