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.
- examples/advanced/hardware/block_diagram.py +162 -0
- examples/advanced/hardware/camera.py +93 -0
- examples/advanced/hardware/gui_emio.py +231 -0
- examples/advanced/hardware/lmi.py +69 -0
- examples/advanced/hardware/main.py +57 -0
- examples/advanced/hardware/parameters.py +54 -0
- examples/advanced/qp_problem/params.py +10 -0
- examples/advanced/qp_problem/run.py +14 -0
- examples/advanced/sofa/gui/finger/Finger.py +108 -0
- examples/advanced/sofa/gui/finger/FingerController.py +53 -0
- examples/advanced/sofa/gui/finger/parameters_auto.py +22 -0
- examples/advanced/sofa/gui/sofa_plant/run.py +14 -0
- examples/advanced/sofa/python/Finger.py +107 -0
- examples/advanced/sofa/python/FingerController.py +48 -0
- examples/advanced/sofa/python/closedloop.py +64 -0
- examples/advanced/sofa/python/openloop.py +58 -0
- examples/basics/algebraic_function/g.py +7 -0
- examples/basics/algebraic_function/run.py +14 -0
- examples/basics/dc_motor/gui/run.py +14 -0
- examples/basics/dc_motor/multiple_order.py +91 -0
- examples/basics/dc_motor/openloop.py +62 -0
- examples/basics/dc_motor/pi.py +99 -0
- examples/basics/dc_motor/pid.py +118 -0
- examples/basics/dc_motor/pid_block.py +82 -0
- examples/basics/dc_motor/pid_block_vs_manual.py +143 -0
- examples/basics/external/parameters.py +4 -0
- examples/basics/external/run.py +14 -0
- examples/basics/file_sources/temp.py +16 -0
- examples/basics/observer.py +76 -0
- examples/basics/state_feedback/gui/parameters.py +9 -0
- examples/basics/state_feedback/gui/run.py +14 -0
- examples/basics/state_feedback/state_feedback.py +102 -0
- examples/basics/state_space/linear/gui/run.py +14 -0
- examples/basics/state_space/linear/ss_block.py +89 -0
- examples/basics/state_space/linear/ss_manual.py +105 -0
- examples/basics/state_space/non_linear/nlss.py +47 -0
- examples/basics/state_space/non_linear/run.py +14 -0
- examples/basics/state_space/polytope/params.py +39 -0
- examples/basics/state_space/polytope/weights.py +12 -0
- examples/comparison/simulink/convert.py +29 -0
- examples/comparison/simulink/openloop.py +127 -0
- examples/comparison/simulink/pi.py +148 -0
- examples/comparison/simulink/pid.py +154 -0
- examples/comparison/simulink/pid_backward.py +155 -0
- examples/quick_start/filter.py +35 -0
- examples/quick_start/gui/run.py +14 -0
- examples/tutorials/tutorial_1_python/main.py +99 -0
- examples/tutorials/tutorial_3_sofa/finger/Finger.py +120 -0
- examples/tutorials/tutorial_3_sofa/finger/FingerController.py +37 -0
- pySimBlocks/__init__.py +35 -0
- pySimBlocks/blocks/__init__.py +68 -0
- pySimBlocks/blocks/controllers/__init__.py +27 -0
- pySimBlocks/blocks/controllers/pid.py +250 -0
- pySimBlocks/blocks/controllers/state_feedback.py +141 -0
- pySimBlocks/blocks/interfaces/__init__.py +27 -0
- pySimBlocks/blocks/interfaces/external_input.py +107 -0
- pySimBlocks/blocks/interfaces/external_output.py +113 -0
- pySimBlocks/blocks/observers/__init__.py +23 -0
- pySimBlocks/blocks/observers/luenberger.py +175 -0
- pySimBlocks/blocks/operators/__init__.py +47 -0
- pySimBlocks/blocks/operators/algebraic_function.py +258 -0
- pySimBlocks/blocks/operators/dead_zone.py +186 -0
- pySimBlocks/blocks/operators/delay.py +254 -0
- pySimBlocks/blocks/operators/demux.py +123 -0
- pySimBlocks/blocks/operators/discrete_derivator.py +237 -0
- pySimBlocks/blocks/operators/discrete_integrator.py +265 -0
- pySimBlocks/blocks/operators/gain.py +294 -0
- pySimBlocks/blocks/operators/mux.py +131 -0
- pySimBlocks/blocks/operators/product.py +194 -0
- pySimBlocks/blocks/operators/rate_limiter.py +214 -0
- pySimBlocks/blocks/operators/saturation.py +178 -0
- pySimBlocks/blocks/operators/sum.py +188 -0
- pySimBlocks/blocks/operators/zero_order_hold.py +141 -0
- pySimBlocks/blocks/optimizers/__init__.py +23 -0
- pySimBlocks/blocks/optimizers/quadratic_program.py +326 -0
- pySimBlocks/blocks/sources/__init__.py +37 -0
- pySimBlocks/blocks/sources/chirp.py +168 -0
- pySimBlocks/blocks/sources/constant.py +82 -0
- pySimBlocks/blocks/sources/file_source.py +294 -0
- pySimBlocks/blocks/sources/function_source.py +197 -0
- pySimBlocks/blocks/sources/ramp.py +99 -0
- pySimBlocks/blocks/sources/sinusoidal.py +113 -0
- pySimBlocks/blocks/sources/step.py +138 -0
- pySimBlocks/blocks/sources/white_noise.py +107 -0
- pySimBlocks/blocks/systems/__init__.py +27 -0
- pySimBlocks/blocks/systems/linear_state_space.py +180 -0
- pySimBlocks/blocks/systems/non_linear_state_space.py +309 -0
- pySimBlocks/blocks/systems/polytopic_state_space.py +193 -0
- pySimBlocks/blocks/systems/sofa/__init__.py +30 -0
- pySimBlocks/blocks/systems/sofa/sofa_controller.py +472 -0
- pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +120 -0
- pySimBlocks/blocks/systems/sofa/sofa_plant.py +306 -0
- pySimBlocks/cli.py +127 -0
- pySimBlocks/core/__init__.py +32 -0
- pySimBlocks/core/block.py +167 -0
- pySimBlocks/core/block_source.py +94 -0
- pySimBlocks/core/config.py +90 -0
- pySimBlocks/core/fixed_time_manager.py +46 -0
- pySimBlocks/core/model.py +250 -0
- pySimBlocks/core/scheduler.py +30 -0
- pySimBlocks/core/simulator.py +329 -0
- pySimBlocks/core/task.py +73 -0
- pySimBlocks/docs/blocks/controllers/pid.md +78 -0
- pySimBlocks/docs/blocks/controllers/state_feedback.md +60 -0
- pySimBlocks/docs/blocks/interfaces/external_input.md +39 -0
- pySimBlocks/docs/blocks/interfaces/external_output.md +39 -0
- pySimBlocks/docs/blocks/observers/luenberger.md +70 -0
- pySimBlocks/docs/blocks/operators/algebraic_function.md +76 -0
- pySimBlocks/docs/blocks/operators/dead_zone.md +67 -0
- pySimBlocks/docs/blocks/operators/delay.md +76 -0
- pySimBlocks/docs/blocks/operators/demux.md +64 -0
- pySimBlocks/docs/blocks/operators/discrete_derivator.md +61 -0
- pySimBlocks/docs/blocks/operators/discrete_integrator.md +87 -0
- pySimBlocks/docs/blocks/operators/gain.md +97 -0
- pySimBlocks/docs/blocks/operators/mux.md +64 -0
- pySimBlocks/docs/blocks/operators/product.md +51 -0
- pySimBlocks/docs/blocks/operators/rate_limiter.md +70 -0
- pySimBlocks/docs/blocks/operators/saturation.md +62 -0
- pySimBlocks/docs/blocks/operators/sum.md +49 -0
- pySimBlocks/docs/blocks/operators/zero_order_hold.md +61 -0
- pySimBlocks/docs/blocks/optimizers/quadratic_program.md +98 -0
- pySimBlocks/docs/blocks/sources/chirp.md +102 -0
- pySimBlocks/docs/blocks/sources/constant.md +53 -0
- pySimBlocks/docs/blocks/sources/file_source.md +51 -0
- pySimBlocks/docs/blocks/sources/function_source.md +52 -0
- pySimBlocks/docs/blocks/sources/ramp.md +58 -0
- pySimBlocks/docs/blocks/sources/sinusoidal.md +60 -0
- pySimBlocks/docs/blocks/sources/step.md +63 -0
- pySimBlocks/docs/blocks/sources/white_noise.md +58 -0
- pySimBlocks/docs/blocks/systems/linear_state_space.md +66 -0
- pySimBlocks/docs/blocks/systems/non_linear_state_space.md +90 -0
- pySimBlocks/docs/blocks/systems/polytopic_state_space.md +72 -0
- pySimBlocks/docs/blocks/systems/sofa/sofa_exchange_i_o.md +63 -0
- pySimBlocks/docs/blocks/systems/sofa/sofa_plant.md +62 -0
- pySimBlocks/gui/__init__.py +20 -0
- pySimBlocks/gui/addons/__init__.py +19 -0
- pySimBlocks/gui/addons/sofa/__init__.py +19 -0
- pySimBlocks/gui/addons/sofa/sofa_dialog.py +190 -0
- pySimBlocks/gui/addons/sofa/sofa_service.py +209 -0
- pySimBlocks/gui/blocks/block_dialog_session.py +47 -0
- pySimBlocks/gui/blocks/block_meta.py +408 -0
- pySimBlocks/gui/blocks/controllers/pid.py +116 -0
- pySimBlocks/gui/blocks/controllers/state_feedback.py +80 -0
- pySimBlocks/gui/blocks/interfaces/external_input.py +64 -0
- pySimBlocks/gui/blocks/interfaces/external_output.py +63 -0
- pySimBlocks/gui/blocks/observers/luenberger.py +108 -0
- pySimBlocks/gui/blocks/operators/algebraic_function.py +232 -0
- pySimBlocks/gui/blocks/operators/dead_zone.py +79 -0
- pySimBlocks/gui/blocks/operators/delay.py +79 -0
- pySimBlocks/gui/blocks/operators/demux.py +98 -0
- pySimBlocks/gui/blocks/operators/discrete_derivator.py +67 -0
- pySimBlocks/gui/blocks/operators/discrete_integrator.py +80 -0
- pySimBlocks/gui/blocks/operators/gain.py +79 -0
- pySimBlocks/gui/blocks/operators/mux.py +100 -0
- pySimBlocks/gui/blocks/operators/product.py +109 -0
- pySimBlocks/gui/blocks/operators/rate_limiter.py +79 -0
- pySimBlocks/gui/blocks/operators/saturation.py +72 -0
- pySimBlocks/gui/blocks/operators/sum.py +91 -0
- pySimBlocks/gui/blocks/operators/zero_order_hold.py +64 -0
- pySimBlocks/gui/blocks/optimizers/quadratic_program.py +128 -0
- pySimBlocks/gui/blocks/parameter_meta.py +34 -0
- pySimBlocks/gui/blocks/port_meta.py +31 -0
- pySimBlocks/gui/blocks/sources/chirp.py +146 -0
- pySimBlocks/gui/blocks/sources/constant.py +63 -0
- pySimBlocks/gui/blocks/sources/file_source.py +196 -0
- pySimBlocks/gui/blocks/sources/function_source.py +202 -0
- pySimBlocks/gui/blocks/sources/ramp.py +73 -0
- pySimBlocks/gui/blocks/sources/sinusoidal.py +81 -0
- pySimBlocks/gui/blocks/sources/step.py +83 -0
- pySimBlocks/gui/blocks/sources/white_noise.py +70 -0
- pySimBlocks/gui/blocks/systems/linear_state_space.py +102 -0
- pySimBlocks/gui/blocks/systems/non_linear_state_space.py +233 -0
- pySimBlocks/gui/blocks/systems/polytopic_state_space.py +109 -0
- pySimBlocks/gui/blocks/systems/sofa/sofa_exchange_i_o.py +221 -0
- pySimBlocks/gui/blocks/systems/sofa/sofa_plant.py +220 -0
- pySimBlocks/gui/dialogs/__init__.py +19 -0
- pySimBlocks/gui/dialogs/block_dialog.py +125 -0
- pySimBlocks/gui/dialogs/display_yaml_dialog.py +89 -0
- pySimBlocks/gui/dialogs/help_dialog.py +39 -0
- pySimBlocks/gui/dialogs/plot_dialog.py +230 -0
- pySimBlocks/gui/dialogs/settings/plots.py +187 -0
- pySimBlocks/gui/dialogs/settings/project.py +146 -0
- pySimBlocks/gui/dialogs/settings/simulation.py +137 -0
- pySimBlocks/gui/dialogs/settings_dialog.py +88 -0
- pySimBlocks/gui/dialogs/unsaved_dialog.py +92 -0
- pySimBlocks/gui/editor.py +49 -0
- pySimBlocks/gui/graphics/__init__.py +29 -0
- pySimBlocks/gui/graphics/block_item.py +289 -0
- pySimBlocks/gui/graphics/connection_item.py +266 -0
- pySimBlocks/gui/graphics/port_item.py +153 -0
- pySimBlocks/gui/graphics/theme.py +119 -0
- pySimBlocks/gui/main_window.py +162 -0
- pySimBlocks/gui/models/__init__.py +31 -0
- pySimBlocks/gui/models/block_instance.py +114 -0
- pySimBlocks/gui/models/connection_instance.py +43 -0
- pySimBlocks/gui/models/port_instance.py +52 -0
- pySimBlocks/gui/models/project_simulation_params.py +50 -0
- pySimBlocks/gui/models/project_state.py +114 -0
- pySimBlocks/gui/project_controller.py +302 -0
- pySimBlocks/gui/services/__init__.py +20 -0
- pySimBlocks/gui/services/project_loader.py +381 -0
- pySimBlocks/gui/services/project_saver.py +68 -0
- pySimBlocks/gui/services/simulation_runner.py +66 -0
- pySimBlocks/gui/services/yaml_tools.py +261 -0
- pySimBlocks/gui/widgets/__init__.py +19 -0
- pySimBlocks/gui/widgets/block_list.py +131 -0
- pySimBlocks/gui/widgets/diagram_view.py +312 -0
- pySimBlocks/gui/widgets/toolbar_view.py +161 -0
- pySimBlocks/project/__init__.py +35 -0
- pySimBlocks/project/build_model.py +92 -0
- pySimBlocks/project/generate_run_script.py +109 -0
- pySimBlocks/project/generate_sofa_controller.py +215 -0
- pySimBlocks/project/load_project_config.py +197 -0
- pySimBlocks/project/load_simulation_config.py +166 -0
- pySimBlocks/project/load_simulator.py +45 -0
- pySimBlocks/project/plot_from_config.py +174 -0
- pySimBlocks/project/pySimBlocks_blocks_index.yaml +106 -0
- pySimBlocks/real_time/__init__.py +23 -0
- pySimBlocks/real_time/real_time_runner.py +148 -0
- pySimBlocks/tools/__init__.py +19 -0
- pySimBlocks/tools/blocks_registry.py +141 -0
- pySimBlocks/tools/generate_blocks_index.py +124 -0
- pysimblocks-0.1.0.dist-info/METADATA +180 -0
- pysimblocks-0.1.0.dist-info/RECORD +262 -0
- pysimblocks-0.1.0.dist-info/WHEEL +5 -0
- pysimblocks-0.1.0.dist-info/entry_points.txt +2 -0
- pysimblocks-0.1.0.dist-info/licenses/LICENSE.md +165 -0
- pysimblocks-0.1.0.dist-info/top_level.txt +3 -0
- tests/blocks/controllers/test_pid.py +143 -0
- tests/blocks/controllers/test_state_feedback.py +193 -0
- tests/blocks/observers/test_luenberger.py +225 -0
- tests/blocks/operators/test_algebraic_function.py +230 -0
- tests/blocks/operators/test_dead_zone.py +106 -0
- tests/blocks/operators/test_delay.py +167 -0
- tests/blocks/operators/test_demux.py +111 -0
- tests/blocks/operators/test_discrete_derivator.py +160 -0
- tests/blocks/operators/test_discrete_integrator.py +149 -0
- tests/blocks/operators/test_gain.py +182 -0
- tests/blocks/operators/test_mux.py +101 -0
- tests/blocks/operators/test_product.py +171 -0
- tests/blocks/operators/test_rate_limiter.py +166 -0
- tests/blocks/operators/test_saturation.py +157 -0
- tests/blocks/operators/test_sum.py +183 -0
- tests/blocks/operators/test_zero_order_hold.py +106 -0
- tests/blocks/sources/test_chirp.py +157 -0
- tests/blocks/sources/test_constant.py +55 -0
- tests/blocks/sources/test_file_source.py +185 -0
- tests/blocks/sources/test_function_source.py +135 -0
- tests/blocks/sources/test_ramp.py +110 -0
- tests/blocks/sources/test_sinusoidal.py +113 -0
- tests/blocks/sources/test_step.py +76 -0
- tests/blocks/sources/test_white_noise.py +108 -0
- tests/blocks/systems/test_linear_state_space.py +135 -0
- tests/blocks/systems/test_polytopic_state_space.py +133 -0
- tests/core/test_core_errors_and_determinism.py +82 -0
- tests/core/test_core_multirate_tasks.py +88 -0
- tests/core/test_core_two_phase_and_propagation.py +132 -0
- tests/gui/main_window_open_test.py +162 -0
- tests/gui/test_block_meta_param_cache.py +16 -0
- tests/gui/test_file_source_meta.py +17 -0
- tests/gui/test_function_source_meta.py +28 -0
- tests/regression/test_simulink_dc_motor.py +217 -0
|
@@ -0,0 +1,31 @@
|
|
|
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.models.block_instance import BlockInstance
|
|
22
|
+
from pySimBlocks.gui.models.connection_instance import ConnectionInstance
|
|
23
|
+
from pySimBlocks.gui.models.port_instance import PortInstance
|
|
24
|
+
from pySimBlocks.gui.models.project_state import ProjectState
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"BlockInstance",
|
|
28
|
+
"ConnectionInstance",
|
|
29
|
+
"PortInstance",
|
|
30
|
+
"ProjectState"
|
|
31
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
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 uuid
|
|
22
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
23
|
+
|
|
24
|
+
from pySimBlocks.gui.models.port_instance import PortInstance
|
|
25
|
+
|
|
26
|
+
try: # Python 3.11+
|
|
27
|
+
from typing import Self
|
|
28
|
+
except ImportError: # Python <3.11
|
|
29
|
+
from typing_extensions import Self
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from pySimBlocks.gui.blocks.block_meta import BlockMeta
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class BlockInstance:
|
|
37
|
+
"""
|
|
38
|
+
GUI-side mutable instance of a block.
|
|
39
|
+
|
|
40
|
+
- References an immutable BlockMeta
|
|
41
|
+
- Stores instance-level data (name, parameters)
|
|
42
|
+
- Used by BlockItem and BlockDialog
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def copy(cls, block: Self) -> Self:
|
|
47
|
+
cpy = BlockInstance(block.meta)
|
|
48
|
+
cpy.name = block.name
|
|
49
|
+
cpy.parameters = block.parameters.copy()
|
|
50
|
+
return cpy
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def __init__(self, meta: 'BlockMeta'):
|
|
54
|
+
self.uid: str = uuid.uuid4().hex
|
|
55
|
+
self.meta = meta
|
|
56
|
+
self.name: str = meta.name
|
|
57
|
+
self.parameters: Dict[str, Any] = self._init_parameters()
|
|
58
|
+
self.ports: List[PortInstance] = []
|
|
59
|
+
|
|
60
|
+
def _init_parameters(self) -> dict[str, Any]:
|
|
61
|
+
"""
|
|
62
|
+
Initialize instance parameters from metadata.
|
|
63
|
+
"""
|
|
64
|
+
params = {}
|
|
65
|
+
|
|
66
|
+
for p in self.meta.parameters:
|
|
67
|
+
params[p.name] = p.default if p.autofill else None
|
|
68
|
+
|
|
69
|
+
return params
|
|
70
|
+
|
|
71
|
+
def update_params(self, params: dict[str, Any]):
|
|
72
|
+
for k, v in params.items():
|
|
73
|
+
if k in self.parameters:
|
|
74
|
+
self.parameters[k] = v
|
|
75
|
+
|
|
76
|
+
def resolve_ports(self) -> None:
|
|
77
|
+
|
|
78
|
+
new_ports = self.meta.build_ports(self)
|
|
79
|
+
|
|
80
|
+
if not self.ports:
|
|
81
|
+
self.ports = new_ports
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
old_inputs = [p for p in self.ports if p.direction == "input"]
|
|
85
|
+
old_outputs = [p for p in self.ports if p.direction == "output"]
|
|
86
|
+
|
|
87
|
+
updated_ports = []
|
|
88
|
+
|
|
89
|
+
for np in new_ports:
|
|
90
|
+
if np.direction == "input":
|
|
91
|
+
if old_inputs:
|
|
92
|
+
p = old_inputs.pop(0)
|
|
93
|
+
p.name = np.name
|
|
94
|
+
p.display_as = np.display_as
|
|
95
|
+
updated_ports.append(p)
|
|
96
|
+
else:
|
|
97
|
+
updated_ports.append(np)
|
|
98
|
+
else:
|
|
99
|
+
if old_outputs:
|
|
100
|
+
p = old_outputs.pop(0)
|
|
101
|
+
p.name = np.name
|
|
102
|
+
p.display_as = np.display_as
|
|
103
|
+
updated_ports.append(p)
|
|
104
|
+
else:
|
|
105
|
+
updated_ports.append(np)
|
|
106
|
+
|
|
107
|
+
self.ports = updated_ports
|
|
108
|
+
|
|
109
|
+
def active_parameters(self) -> dict[str, Any]:
|
|
110
|
+
return {
|
|
111
|
+
k: v
|
|
112
|
+
for k, v in self.parameters.items()
|
|
113
|
+
if self.meta.is_parameter_active(k, self.parameters)
|
|
114
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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 typing import TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from pySimBlocks.gui.graphics.port_item import PortInstance
|
|
25
|
+
from pySimBlocks.gui.project_controller import BlockInstance
|
|
26
|
+
|
|
27
|
+
class ConnectionInstance:
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
src_port: "PortInstance",
|
|
31
|
+
dst_port: "PortInstance",
|
|
32
|
+
):
|
|
33
|
+
self.src_port = src_port
|
|
34
|
+
self.dst_port = dst_port
|
|
35
|
+
|
|
36
|
+
def src_block(self) -> "BlockInstance":
|
|
37
|
+
return self.src_port.block
|
|
38
|
+
|
|
39
|
+
def dst_block(self) -> "BlockInstance":
|
|
40
|
+
return self.dst_port.block
|
|
41
|
+
|
|
42
|
+
def is_block_involved(self, block: "BlockInstance") -> bool:
|
|
43
|
+
return block in (self.src_port.block, self.dst_port.block)
|
|
@@ -0,0 +1,52 @@
|
|
|
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 typing import Literal, TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
from pySimBlocks.gui.blocks.port_meta import PortMeta
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from pySimBlocks.gui.models.connection_instance import ConnectionInstance
|
|
27
|
+
from pySimBlocks.gui.project_controller import BlockInstance
|
|
28
|
+
|
|
29
|
+
class PortInstance:
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
name: str,
|
|
33
|
+
display_as: str,
|
|
34
|
+
direction: Literal['input', 'output'],
|
|
35
|
+
block: "BlockInstance"
|
|
36
|
+
):
|
|
37
|
+
self.name = name
|
|
38
|
+
self.display_as = display_as
|
|
39
|
+
self.direction = direction
|
|
40
|
+
self.block = block
|
|
41
|
+
|
|
42
|
+
def is_compatible(self, other: "PortInstance"):
|
|
43
|
+
return self.direction != other.direction
|
|
44
|
+
|
|
45
|
+
def can_accept_connection(self, connections: list["ConnectionInstance"]) -> bool:
|
|
46
|
+
"""
|
|
47
|
+
Check whether this port can accept a new connection.
|
|
48
|
+
|
|
49
|
+
The `connections` list is expected to contain all and only the connections
|
|
50
|
+
already linked to this PortInstance.
|
|
51
|
+
"""
|
|
52
|
+
return self.direction == "output" or not connections
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
class ProjectSimulationParams:
|
|
22
|
+
|
|
23
|
+
DEFAULT_DT = 0.1
|
|
24
|
+
DEFAULT_T = 10.
|
|
25
|
+
DEFAULT_SOLVER = "fixed"
|
|
26
|
+
DEFAULT_CLOCK = "internal"
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
dt: float = DEFAULT_DT,
|
|
31
|
+
T: float = DEFAULT_T,
|
|
32
|
+
solver: str = DEFAULT_SOLVER,
|
|
33
|
+
clock: str = DEFAULT_CLOCK
|
|
34
|
+
):
|
|
35
|
+
self.dt = dt
|
|
36
|
+
self.T = T
|
|
37
|
+
self.solver = solver
|
|
38
|
+
self.clock = clock
|
|
39
|
+
|
|
40
|
+
def load_from_dict(self, params: dict) -> None:
|
|
41
|
+
self.dt = params.get("dt", self.dt)
|
|
42
|
+
self.T = params.get("T", self.T)
|
|
43
|
+
self.solver = params.get("solver", self.solver)
|
|
44
|
+
self.clock = params.get("clock", self.clock)
|
|
45
|
+
|
|
46
|
+
def clear(self) -> None:
|
|
47
|
+
self.dt = self.DEFAULT_DT
|
|
48
|
+
self.T = self.DEFAULT_T
|
|
49
|
+
self.solver = self.DEFAULT_SOLVER
|
|
50
|
+
self.clock = self.DEFAULT_CLOCK
|
|
@@ -0,0 +1,114 @@
|
|
|
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 pathlib import Path
|
|
22
|
+
|
|
23
|
+
from pySimBlocks.gui.models.block_instance import BlockInstance, PortInstance
|
|
24
|
+
from pySimBlocks.gui.models.connection_instance import ConnectionInstance
|
|
25
|
+
from pySimBlocks.gui.models.project_simulation_params import ProjectSimulationParams
|
|
26
|
+
|
|
27
|
+
class ProjectState:
|
|
28
|
+
def __init__(self, directory_path: Path):
|
|
29
|
+
self.blocks: list[BlockInstance] = []
|
|
30
|
+
self.connections: list[ConnectionInstance] = []
|
|
31
|
+
self.simulation = ProjectSimulationParams()
|
|
32
|
+
self.external: str | None = None
|
|
33
|
+
self.directory_path = directory_path
|
|
34
|
+
self.logging: list[str] = []
|
|
35
|
+
self.logs: dict = {}
|
|
36
|
+
self.plots: list[dict[str, str | list[str]]] = []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def clear(self):
|
|
40
|
+
self.blocks.clear()
|
|
41
|
+
self.connections.clear()
|
|
42
|
+
|
|
43
|
+
self.logs.clear()
|
|
44
|
+
self.logging.clear()
|
|
45
|
+
self.plots.clear()
|
|
46
|
+
|
|
47
|
+
self.simulation.clear()
|
|
48
|
+
|
|
49
|
+
self.external = None
|
|
50
|
+
|
|
51
|
+
def load_simulation(self, sim_data: dict, external = None):
|
|
52
|
+
self.simulation.load_from_dict(sim_data)
|
|
53
|
+
|
|
54
|
+
if external:
|
|
55
|
+
self.external = external
|
|
56
|
+
|
|
57
|
+
# --------------------------------------------------------------------------
|
|
58
|
+
# Block management
|
|
59
|
+
# --------------------------------------------------------------------------
|
|
60
|
+
def get_block(self, name:str):
|
|
61
|
+
for block in self.blocks:
|
|
62
|
+
if name == block.name:
|
|
63
|
+
return block
|
|
64
|
+
|
|
65
|
+
def add_block(self, block_instance: BlockInstance):
|
|
66
|
+
self.blocks.append(block_instance)
|
|
67
|
+
|
|
68
|
+
def remove_block(self, block_instance: BlockInstance):
|
|
69
|
+
if block_instance in self.blocks:
|
|
70
|
+
self.blocks.remove(block_instance)
|
|
71
|
+
|
|
72
|
+
# --------------------------------------------------------------------------
|
|
73
|
+
# Connection management
|
|
74
|
+
# --------------------------------------------------------------------------
|
|
75
|
+
def add_connection(self, conn: ConnectionInstance):
|
|
76
|
+
self.connections.append(conn)
|
|
77
|
+
|
|
78
|
+
def remove_connection(self, conn: ConnectionInstance):
|
|
79
|
+
if conn in self.connections:
|
|
80
|
+
self.connections.remove(conn)
|
|
81
|
+
|
|
82
|
+
def get_connections_of_block(self, block_instance: BlockInstance) -> list[ConnectionInstance]:
|
|
83
|
+
return [
|
|
84
|
+
c for c in self.connections
|
|
85
|
+
if block_instance is c.src_block() or block_instance is c.dst_block()
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
def get_connections_of_port(self, port_instance: PortInstance) -> list[ConnectionInstance]:
|
|
89
|
+
return [
|
|
90
|
+
c for c in self.connections
|
|
91
|
+
if port_instance is c.src_port or port_instance is c.dst_port
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
# --------------------------------------------------------------------------
|
|
95
|
+
# Signals
|
|
96
|
+
# --------------------------------------------------------------------------
|
|
97
|
+
def get_output_signals(self) -> list[str]:
|
|
98
|
+
signals = []
|
|
99
|
+
|
|
100
|
+
for block in self.blocks:
|
|
101
|
+
for port in block.ports:
|
|
102
|
+
if port.direction == "output":
|
|
103
|
+
signals.append(f"{block.name}.outputs.{port.name}")
|
|
104
|
+
|
|
105
|
+
return signals
|
|
106
|
+
|
|
107
|
+
def can_plot(self) -> tuple[bool, str]:
|
|
108
|
+
if not bool(self.logs):
|
|
109
|
+
return False, "Simulation has not been done.\nPlease run fist."
|
|
110
|
+
|
|
111
|
+
if not ("time" in self.logs):
|
|
112
|
+
return False, "Time is not in logs."
|
|
113
|
+
|
|
114
|
+
return True, "Plotting is available."
|