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,202 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ import os
22
+ import subprocess
23
+ import sys
24
+ from pathlib import Path
25
+ from typing import Literal
26
+
27
+ from PySide6.QtWidgets import QFormLayout, QLabel, QLineEdit, QPushButton
28
+
29
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta, ParameterMeta
30
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
31
+ from pySimBlocks.gui.models import BlockInstance, PortInstance
32
+
33
+
34
+ class FunctionSourceMeta(BlockMeta):
35
+
36
+ def __init__(self):
37
+ self.name = "FunctionSource"
38
+ self.category = "sources"
39
+ self.type = "function_source"
40
+ self.summary = "User-defined source block y = f(t, dt)."
41
+ self.description = (
42
+ "This block evaluates a user-provided Python function with no inputs:\n\n"
43
+ " y = f(t, dt)\n\n"
44
+ "The function is loaded from an external Python file and executed at each\n"
45
+ "activation. The function must return a dict whose keys match\n"
46
+ "`output_keys`. One output port is created for each key."
47
+ )
48
+
49
+ self.parameters = [
50
+ ParameterMeta(
51
+ name="file_path",
52
+ type="string",
53
+ required=True,
54
+ description=(
55
+ "Path to the Python file containing the function, relative to "
56
+ "the project.yaml file."
57
+ ),
58
+ ),
59
+ ParameterMeta(
60
+ name="function_name",
61
+ type="string",
62
+ required=True,
63
+ description="Name of the function to call inside the Python file.",
64
+ ),
65
+ ParameterMeta(
66
+ name="output_keys",
67
+ type="list[string]",
68
+ required=True,
69
+ autofill=True,
70
+ default=["out"],
71
+ description="List of output port names. The function must return a dict with exactly these keys.",
72
+ ),
73
+ ParameterMeta(
74
+ name="sample_time",
75
+ type="float",
76
+ description="Optional execution period of the block.",
77
+ ),
78
+ ]
79
+
80
+ self.outputs = [
81
+ PortMeta(
82
+ name="out",
83
+ display_as="",
84
+ shape=[],
85
+ description="Function output signals defined by output_keys.",
86
+ )
87
+ ]
88
+
89
+ # --------------------------------------------------------------------------
90
+ # Port resolution
91
+ # --------------------------------------------------------------------------
92
+ def resolve_port_group(
93
+ self,
94
+ port_meta: PortMeta,
95
+ direction: Literal["input", "output"],
96
+ instance: "BlockInstance",
97
+ ) -> list["PortInstance"]:
98
+ if direction == "output":
99
+ keys = instance.parameters.get("output_keys", [])
100
+ if keys is None:
101
+ return []
102
+ return [
103
+ PortInstance(
104
+ name=f"{key}",
105
+ display_as=key,
106
+ direction="output",
107
+ block=instance,
108
+ )
109
+ for key in keys
110
+ ]
111
+
112
+ return super().resolve_port_group(port_meta, direction, instance)
113
+
114
+ # --------------------------------------------------------------------------
115
+ # Dialog methods
116
+ # --------------------------------------------------------------------------
117
+ def build_param(
118
+ self,
119
+ session,
120
+ form: QFormLayout,
121
+ readonly: bool = False,
122
+ ):
123
+ name_edit = QLineEdit(session.instance.name)
124
+ name_edit.textChanged.connect(
125
+ lambda val: self._on_param_changed(val, "name", session, readonly)
126
+ )
127
+ form.addRow(QLabel("Block name:"), name_edit)
128
+ if readonly:
129
+ name_edit.setReadOnly(True)
130
+ session.name_edit = name_edit
131
+
132
+ for pmeta in self.parameters:
133
+ if pmeta.name == "file_path":
134
+ self.build_file_param_row(
135
+ session,
136
+ form,
137
+ pmeta,
138
+ readonly=readonly,
139
+ file_filter="Python files (*.py);;All files (*)",
140
+ )
141
+ continue
142
+
143
+ label, widget = self._create_param_row(session, pmeta, readonly)
144
+ if widget is None:
145
+ continue
146
+ if readonly:
147
+ self._set_readonly_style(widget)
148
+
149
+ form.addRow(label, widget)
150
+ session.param_widgets[pmeta.name] = widget
151
+ session.param_labels[pmeta.name] = label
152
+
153
+ # ------------------------------------------------------
154
+ def build_post_param(self, session, form: QFormLayout, readonly: bool = False):
155
+ open_btn = QPushButton("Open file")
156
+ open_btn.clicked.connect(lambda: self._open_file_from_session(session))
157
+ form.addRow(QLabel(""), open_btn)
158
+ session.open_file_btn = open_btn
159
+ self._refresh_open_button_state(session)
160
+
161
+ # ------------------------------------------------------
162
+ def refresh_form(self, session):
163
+ super().refresh_form(session)
164
+ self._refresh_open_button_state(session)
165
+
166
+ # ------------------------------------------------------
167
+ def _resolve_file_path(self, session) -> Path | None:
168
+ raw = session.local_params.get("file_path")
169
+ if not raw:
170
+ return None
171
+
172
+ path = Path(str(raw)).expanduser()
173
+ if not path.is_absolute() and session.project_dir is not None:
174
+ path = (session.project_dir / path).resolve()
175
+ return path
176
+
177
+ # ------------------------------------------------------
178
+ def _refresh_open_button_state(self, session) -> None:
179
+ btn = getattr(session, "open_file_btn", None)
180
+ if btn is None:
181
+ return
182
+
183
+ target = self._resolve_file_path(session)
184
+ exists = target is not None and target.is_file()
185
+ btn.setEnabled(exists)
186
+ if exists:
187
+ btn.setToolTip(str(target))
188
+ else:
189
+ btn.setToolTip("Set a valid existing file_path to open the file.")
190
+
191
+ # ------------------------------------------------------
192
+ def _open_file_from_session(self, session) -> None:
193
+ target = self._resolve_file_path(session)
194
+ if target is None or not target.is_file():
195
+ return
196
+
197
+ if sys.platform.startswith("darwin"):
198
+ subprocess.Popen(["open", str(target)])
199
+ elif os.name == "nt":
200
+ os.startfile(str(target))
201
+ else:
202
+ subprocess.Popen(["xdg-open", str(target)])
@@ -0,0 +1,73 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta
22
+ from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
23
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
24
+
25
+
26
+ class RampMeta(BlockMeta):
27
+
28
+ def __init__(self):
29
+ self.name = "Ramp"
30
+ self.category = "sources"
31
+ self.type = "ramp"
32
+ self.summary = "Multi-dimensional ramp signal source."
33
+ self.description = (
34
+ "Generates a ramp signal defined by:\n"
35
+ "$$\n"
36
+ "y_i(t) = o_i + s_i \\max(0, t - t_{0,i})\n"
37
+ "$$\n"
38
+ )
39
+
40
+ self.parameters = [
41
+ ParameterMeta(
42
+ name="slope",
43
+ type="scalar | vector | matrix",
44
+ required=True,
45
+ autofill=True,
46
+ default=[[1.0]],
47
+ description="Ramp slope for each output dimension."
48
+ ),
49
+ ParameterMeta(
50
+ name="start_time",
51
+ type="scalar | vector | matrix",
52
+ description="Time at which the ramp starts."
53
+ ),
54
+ ParameterMeta(
55
+ name="offset",
56
+ type="scalar | vector | matrix",
57
+ description="Output value before the ramp starts."
58
+ ),
59
+ ParameterMeta(
60
+ name="sample_time",
61
+ type="float",
62
+ description="Block execution period."
63
+ )
64
+ ]
65
+
66
+ self.outputs = [
67
+ PortMeta(
68
+ name="out",
69
+ display_as="out",
70
+ shape=["n", "m"],
71
+ description="Ramp output signal."
72
+ )
73
+ ]
@@ -0,0 +1,81 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta
22
+ from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
23
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
24
+
25
+
26
+ class SinusoidalMeta(BlockMeta):
27
+
28
+ def __init__(self):
29
+ self.name = "Sinusoidal"
30
+ self.category = "sources"
31
+ self.type = "sinusoidal"
32
+ self.summary = "Multi-dimensional sinusoidal signal source."
33
+ self.description = (
34
+ "Generates a sinusoidal signal defined by:\n"
35
+ "$$\n"
36
+ "y_i(t) = A_i \\sin(2\\pi f_i t + \\varphi_i) + o_i\n"
37
+ "$$\n"
38
+ )
39
+
40
+ self.parameters = [
41
+ ParameterMeta(
42
+ name="amplitude",
43
+ type="scalar | vector | matrix",
44
+ required=True,
45
+ autofill=True,
46
+ default=[[1.0]],
47
+ description="Sinusoidal amplitude."
48
+ ),
49
+ ParameterMeta(
50
+ name="frequency",
51
+ type="scalar | vector | matrix",
52
+ required=True,
53
+ autofill=True,
54
+ default=[[1.0]],
55
+ description="Sinusoidal frequency in Hertz."
56
+ ),
57
+ ParameterMeta(
58
+ name="phase",
59
+ type="scalar | vector | matrix",
60
+ description="Phase shift in radians."
61
+ ),
62
+ ParameterMeta(
63
+ name="offset",
64
+ type="scalar | vector | matrix",
65
+ description="Constant offset added to the signal."
66
+ ),
67
+ ParameterMeta(
68
+ name="sample_time",
69
+ type="float",
70
+ description="Block execution period."
71
+ )
72
+ ]
73
+
74
+ self.outputs = [
75
+ PortMeta(
76
+ name="out",
77
+ display_as="out",
78
+ shape=["n", "m"],
79
+ description="Sinusoidal output signal."
80
+ )
81
+ ]
@@ -0,0 +1,83 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta
22
+ from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
23
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
24
+
25
+
26
+ class StepMeta(BlockMeta):
27
+
28
+ def __init__(self):
29
+ self.name = "Step"
30
+ self.category = "sources"
31
+ self.type = "step"
32
+ self.summary = "Step signal source."
33
+ self.description = (
34
+ "Generates a step signal defined by:\n"
35
+ "$$\n"
36
+ "y(t) =\n"
37
+ "\\begin{cases}\n"
38
+ "y_{\\text{before}}, & t < t_0 \\\\\n"
39
+ "y_{\\text{after}}, & t \\geq t_0\n"
40
+ "\\end{cases}\n"
41
+ "$$\n"
42
+ )
43
+
44
+ self.parameters = [
45
+ ParameterMeta(
46
+ name="value_before",
47
+ type="scalar | vector | matrix",
48
+ required=True,
49
+ autofill=True,
50
+ default=[[0.0]],
51
+ description="Output value before the step time."
52
+ ),
53
+ ParameterMeta(
54
+ name="value_after",
55
+ type="scalar | vector | matrix",
56
+ required=True,
57
+ autofill=True,
58
+ default=[[1.0]],
59
+ description="Output value after the step time."
60
+ ),
61
+ ParameterMeta(
62
+ name="start_time",
63
+ type="float",
64
+ required=True,
65
+ autofill=True,
66
+ default=1.0,
67
+ description="Time at which the step occurs."
68
+ ),
69
+ ParameterMeta(
70
+ name="sample_time",
71
+ type="float",
72
+ description="Block execution period."
73
+ )
74
+ ]
75
+
76
+ self.outputs = [
77
+ PortMeta(
78
+ name="out",
79
+ display_as="out",
80
+ shape=["n", "m"],
81
+ description="Step output signal."
82
+ )
83
+ ]
@@ -0,0 +1,70 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta
22
+ from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
23
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
24
+
25
+
26
+ class WhiteNoiseMeta(BlockMeta):
27
+
28
+ def __init__(self):
29
+ self.name = "WhiteNoise"
30
+ self.category = "sources"
31
+ self.type = "white_noise"
32
+ self.summary = "Multi-dimensional Gaussian white noise source."
33
+ self.description = (
34
+ "Generates independent Gaussian noise samples at each simulation step:\n"
35
+ "$$\n"
36
+ "y_i(t) \\sim \\mathcal{N}(\\mu_i, \\sigma_i^2)\n"
37
+ "$$\n"
38
+ )
39
+
40
+ self.parameters = [
41
+ ParameterMeta(
42
+ name="mean",
43
+ type="scalar | vector | matrix",
44
+ description="Mean value of the noise."
45
+ ),
46
+ ParameterMeta(
47
+ name="std",
48
+ type="scalar | vector | matrix",
49
+ description="Standard deviation of the noise."
50
+ ),
51
+ ParameterMeta(
52
+ name="seed",
53
+ type="int",
54
+ description="Random seed for reproducibility."
55
+ ),
56
+ ParameterMeta(
57
+ name="sample_time",
58
+ type="float",
59
+ description="Block execution period."
60
+ )
61
+ ]
62
+
63
+ self.outputs = [
64
+ PortMeta(
65
+ name="out",
66
+ display_as="out",
67
+ shape=["n", "m"],
68
+ description="Gaussian noise output signal."
69
+ )
70
+ ]
@@ -0,0 +1,102 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.gui.blocks.block_meta import BlockMeta
22
+ from pySimBlocks.gui.blocks.parameter_meta import ParameterMeta
23
+ from pySimBlocks.gui.blocks.port_meta import PortMeta
24
+
25
+
26
+ class LinearStateSpaceMeta(BlockMeta):
27
+
28
+ def __init__(self):
29
+ self.name = "LinearStateSpace"
30
+ self.category = "systems"
31
+ self.type = "linear_state_space"
32
+ self.summary = "Discrete-time linear state-space system."
33
+ self.description = (
34
+ "Implements the discrete-time state-space equations:\n"
35
+ "$$\n"
36
+ "x[k+1] = A x[k] + B u[k]\n"
37
+ "$$\n"
38
+ "$$\n"
39
+ "y[k] = C x[k]\n"
40
+ "$$\n"
41
+ )
42
+
43
+ self.parameters = [
44
+ ParameterMeta(
45
+ name="A",
46
+ type="matrix",
47
+ required=True,
48
+ autofill=True,
49
+ default=[[0.99]],
50
+ description="State transition matrix."
51
+ ),
52
+ ParameterMeta(
53
+ name="B",
54
+ type="matrix",
55
+ required=True,
56
+ autofill=True,
57
+ default=[[1.0]],
58
+ description="Input matrix."
59
+ ),
60
+ ParameterMeta(
61
+ name="C",
62
+ type="matrix",
63
+ required=True,
64
+ autofill=True,
65
+ default=[[1.0]],
66
+ description="Output matrix."
67
+ ),
68
+ ParameterMeta(
69
+ name="x0",
70
+ type="vector",
71
+ description="Initial state vector."
72
+ ),
73
+ ParameterMeta(
74
+ name="sample_time",
75
+ type="float",
76
+ description="Block execution period."
77
+ )
78
+ ]
79
+
80
+ self.inputs = [
81
+ PortMeta(
82
+ name="u",
83
+ display_as="u",
84
+ shape=["m", 1],
85
+ description="Input vector."
86
+ )
87
+ ]
88
+
89
+ self.outputs = [
90
+ PortMeta(
91
+ name="x",
92
+ display_as="x",
93
+ shape=["n", 1],
94
+ description="State vector."
95
+ ),
96
+ PortMeta(
97
+ name="y",
98
+ display_as="y",
99
+ shape=["p", 1],
100
+ description="Output vector."
101
+ )
102
+ ]