pySimBlocks 0.1.1__tar.gz → 0.2.0__tar.gz
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.
- {pysimblocks-0.1.1/pySimBlocks.egg-info → pysimblocks-0.2.0}/PKG-INFO +3 -2
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/README.md +1 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/__init__.py +5 -1
- pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/bus_from.py +88 -0
- pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/goto.py +78 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/file_source.py +30 -5
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/__init__.py +2 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/linear_state_space.py +40 -5
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/non_linear_state_space.py +2 -4
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_controller.py +151 -16
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_plant.py +2 -1
- pysimblocks-0.2.0/pySimBlocks/blocks/systems/transfer_function.py +380 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/cli.py +45 -19
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/config.py +27 -3
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/model.py +42 -0
- pysimblocks-0.2.0/pySimBlocks/core/signal_bus.py +37 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/simulator.py +3 -0
- pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/bus_from.md +63 -0
- pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/goto.md +59 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/file_source.md +4 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/linear_state_space.md +22 -5
- pysimblocks-0.2.0/pySimBlocks/docs/blocks/systems/transfer_function.md +89 -0
- pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/slider_params_dialog.py +513 -0
- pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_dialog.py +324 -0
- pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_service.py +397 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_dialog_session.py +13 -6
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_meta.py +4 -1
- pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/bus_from.py +228 -0
- pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/goto.py +74 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/file_source.py +16 -2
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/linear_state_space.py +9 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_exchange_i_o.py +5 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_plant.py +5 -1
- pysimblocks-0.2.0/pySimBlocks/gui/blocks/systems/transfer_function.py +122 -0
- pysimblocks-0.2.0/pySimBlocks/gui/diagram_clipboard.py +694 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/block_dialog.py +6 -2
- pysimblocks-0.2.0/pySimBlocks/gui/dialogs/export_npz_dialog.py +171 -0
- pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_dialog.py +1564 -0
- pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_series_style_dialog.py +268 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/plots.py +53 -3
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/project.py +24 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/editor.py +6 -2
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/__init__.py +7 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/block_item.py +58 -7
- pysimblocks-0.2.0/pySimBlocks/gui/graphics/connection_item.py +497 -0
- pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_item.py +490 -0
- pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_proxy_item.py +245 -0
- pysimblocks-0.2.0/pySimBlocks/gui/graphics/manual_boundary_wire_item.py +53 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/theme.py +8 -0
- pysimblocks-0.2.0/pySimBlocks/gui/group_boundary_labels.py +38 -0
- pysimblocks-0.2.0/pySimBlocks/gui/group_ports.py +10 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/main_window.py +74 -32
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/__init__.py +4 -1
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/project_state.py +61 -5
- pysimblocks-0.2.0/pySimBlocks/gui/models/visual_group.py +130 -0
- pysimblocks-0.2.0/pySimBlocks/gui/project_controller.py +2611 -0
- pysimblocks-0.2.0/pySimBlocks/gui/services/group_boundary_service.py +168 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_loader.py +105 -7
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/simulation_runner.py +3 -9
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/yaml_tools.py +72 -37
- pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/commands.py +775 -0
- pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/undo_redo_manager.py +60 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/block_list.py +19 -2
- pysimblocks-0.2.0/pySimBlocks/gui/widgets/diagram_view.py +1366 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/toolbar_view.py +135 -15
- pysimblocks-0.2.0/pySimBlocks/gui/widgets/view_navigation_bar.py +86 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/generate_run_script.py +54 -19
- pysimblocks-0.2.0/pySimBlocks/project/generate_sofa_scaffold.py +191 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_project_config.py +42 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_simulation_config.py +67 -0
- pysimblocks-0.2.0/pySimBlocks/project/plot_from_config.py +272 -0
- pysimblocks-0.2.0/pySimBlocks/project/plot_series.py +337 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/pySimBlocks_blocks_index.yaml +9 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0/pySimBlocks.egg-info}/PKG-INFO +3 -2
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/SOURCES.txt +27 -91
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/requires.txt +1 -0
- pysimblocks-0.2.0/pySimBlocks.egg-info/top_level.txt +1 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pyproject.toml +3 -1
- pysimblocks-0.1.1/docs/_build/html/_downloads/005a2fbb3c705d1ad26b3514425388ea/filter.py +0 -35
- pysimblocks-0.1.1/docs/_build/html/_downloads/55a3b8989a3f25f02b02155793932456/run.py +0 -14
- pysimblocks-0.1.1/docs/_build/html/_downloads/6f0602c197379a812604b0c5d14a0785/main.py +0 -99
- pysimblocks-0.1.1/docs/source/_ext/api_generator.py +0 -295
- pysimblocks-0.1.1/docs/source/conf.py +0 -116
- pysimblocks-0.1.1/examples/advanced/hardware/block_diagram.py +0 -162
- pysimblocks-0.1.1/examples/advanced/hardware/camera.py +0 -93
- pysimblocks-0.1.1/examples/advanced/hardware/gui_emio.py +0 -231
- pysimblocks-0.1.1/examples/advanced/hardware/lmi.py +0 -69
- pysimblocks-0.1.1/examples/advanced/hardware/main.py +0 -57
- pysimblocks-0.1.1/examples/advanced/hardware/parameters.py +0 -54
- pysimblocks-0.1.1/examples/advanced/qp_problem/params.py +0 -10
- pysimblocks-0.1.1/examples/advanced/qp_problem/run.py +0 -14
- pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/Finger.py +0 -108
- pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/FingerController.py +0 -53
- pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/parameters_auto.py +0 -22
- pysimblocks-0.1.1/examples/advanced/sofa/gui/sofa_plant/run.py +0 -14
- pysimblocks-0.1.1/examples/advanced/sofa/python/Finger.py +0 -107
- pysimblocks-0.1.1/examples/advanced/sofa/python/FingerController.py +0 -48
- pysimblocks-0.1.1/examples/advanced/sofa/python/closedloop.py +0 -64
- pysimblocks-0.1.1/examples/advanced/sofa/python/openloop.py +0 -58
- pysimblocks-0.1.1/examples/basics/algebraic_function/g.py +0 -7
- pysimblocks-0.1.1/examples/basics/algebraic_function/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/dc_motor/gui/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/dc_motor/multiple_order.py +0 -91
- pysimblocks-0.1.1/examples/basics/dc_motor/openloop.py +0 -62
- pysimblocks-0.1.1/examples/basics/dc_motor/pi.py +0 -99
- pysimblocks-0.1.1/examples/basics/dc_motor/pid.py +0 -118
- pysimblocks-0.1.1/examples/basics/dc_motor/pid_block.py +0 -82
- pysimblocks-0.1.1/examples/basics/dc_motor/pid_block_vs_manual.py +0 -143
- pysimblocks-0.1.1/examples/basics/external/parameters.py +0 -4
- pysimblocks-0.1.1/examples/basics/external/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/file_sources/temp.py +0 -16
- pysimblocks-0.1.1/examples/basics/observer.py +0 -76
- pysimblocks-0.1.1/examples/basics/state_feedback/gui/parameters.py +0 -9
- pysimblocks-0.1.1/examples/basics/state_feedback/gui/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/state_feedback/state_feedback.py +0 -102
- pysimblocks-0.1.1/examples/basics/state_space/linear/gui/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/state_space/linear/ss_block.py +0 -89
- pysimblocks-0.1.1/examples/basics/state_space/linear/ss_manual.py +0 -105
- pysimblocks-0.1.1/examples/basics/state_space/non_linear/nlss.py +0 -47
- pysimblocks-0.1.1/examples/basics/state_space/non_linear/run.py +0 -14
- pysimblocks-0.1.1/examples/basics/state_space/polytope/params.py +0 -39
- pysimblocks-0.1.1/examples/basics/state_space/polytope/weights.py +0 -12
- pysimblocks-0.1.1/examples/comparison/simulink/convert.py +0 -29
- pysimblocks-0.1.1/examples/comparison/simulink/openloop.py +0 -127
- pysimblocks-0.1.1/examples/comparison/simulink/pi.py +0 -148
- pysimblocks-0.1.1/examples/comparison/simulink/pid.py +0 -154
- pysimblocks-0.1.1/examples/comparison/simulink/pid_backward.py +0 -155
- pysimblocks-0.1.1/examples/quick_start/filter.py +0 -35
- pysimblocks-0.1.1/examples/quick_start/gui/run.py +0 -14
- pysimblocks-0.1.1/examples/tutorials/tutorial_1_python/main.py +0 -99
- pysimblocks-0.1.1/examples/tutorials/tutorial_2_gui/run.py +0 -14
- pysimblocks-0.1.1/examples/tutorials/tutorial_3_sofa/finger/Finger.py +0 -120
- pysimblocks-0.1.1/examples/tutorials/tutorial_3_sofa/finger/FingerController.py +0 -35
- pysimblocks-0.1.1/pySimBlocks/gui/addons/sofa/sofa_dialog.py +0 -238
- pysimblocks-0.1.1/pySimBlocks/gui/addons/sofa/sofa_service.py +0 -250
- pysimblocks-0.1.1/pySimBlocks/gui/dialogs/plot_dialog.py +0 -245
- pysimblocks-0.1.1/pySimBlocks/gui/graphics/connection_item.py +0 -325
- pysimblocks-0.1.1/pySimBlocks/gui/project_controller.py +0 -437
- pysimblocks-0.1.1/pySimBlocks/gui/widgets/diagram_view.py +0 -420
- pysimblocks-0.1.1/pySimBlocks/project/generate_sofa_controller.py +0 -259
- pysimblocks-0.1.1/pySimBlocks/project/plot_from_config.py +0 -158
- pysimblocks-0.1.1/pySimBlocks.egg-info/top_level.txt +0 -7
- pysimblocks-0.1.1/tests/blocks/controllers/test_pid.py +0 -143
- pysimblocks-0.1.1/tests/blocks/controllers/test_state_feedback.py +0 -193
- pysimblocks-0.1.1/tests/blocks/observers/test_luenberger.py +0 -225
- pysimblocks-0.1.1/tests/blocks/operators/test_algebraic_function.py +0 -230
- pysimblocks-0.1.1/tests/blocks/operators/test_dead_zone.py +0 -106
- pysimblocks-0.1.1/tests/blocks/operators/test_delay.py +0 -167
- pysimblocks-0.1.1/tests/blocks/operators/test_demux.py +0 -111
- pysimblocks-0.1.1/tests/blocks/operators/test_discrete_derivator.py +0 -160
- pysimblocks-0.1.1/tests/blocks/operators/test_discrete_integrator.py +0 -149
- pysimblocks-0.1.1/tests/blocks/operators/test_gain.py +0 -182
- pysimblocks-0.1.1/tests/blocks/operators/test_mux.py +0 -101
- pysimblocks-0.1.1/tests/blocks/operators/test_product.py +0 -171
- pysimblocks-0.1.1/tests/blocks/operators/test_rate_limiter.py +0 -166
- pysimblocks-0.1.1/tests/blocks/operators/test_saturation.py +0 -157
- pysimblocks-0.1.1/tests/blocks/operators/test_sum.py +0 -183
- pysimblocks-0.1.1/tests/blocks/operators/test_zero_order_hold.py +0 -106
- pysimblocks-0.1.1/tests/blocks/sources/test_chirp.py +0 -157
- pysimblocks-0.1.1/tests/blocks/sources/test_constant.py +0 -55
- pysimblocks-0.1.1/tests/blocks/sources/test_file_source.py +0 -185
- pysimblocks-0.1.1/tests/blocks/sources/test_function_source.py +0 -135
- pysimblocks-0.1.1/tests/blocks/sources/test_ramp.py +0 -110
- pysimblocks-0.1.1/tests/blocks/sources/test_sinusoidal.py +0 -113
- pysimblocks-0.1.1/tests/blocks/sources/test_step.py +0 -76
- pysimblocks-0.1.1/tests/blocks/sources/test_white_noise.py +0 -108
- pysimblocks-0.1.1/tests/blocks/systems/test_linear_state_space.py +0 -135
- pysimblocks-0.1.1/tests/blocks/systems/test_polytopic_state_space.py +0 -133
- pysimblocks-0.1.1/tests/core/test_core_errors_and_determinism.py +0 -82
- pysimblocks-0.1.1/tests/core/test_core_multirate_tasks.py +0 -97
- pysimblocks-0.1.1/tests/core/test_core_two_phase_and_propagation.py +0 -132
- pysimblocks-0.1.1/tests/gui/main_window_open_test.py +0 -162
- pysimblocks-0.1.1/tests/gui/test_block_meta_param_cache.py +0 -16
- pysimblocks-0.1.1/tests/gui/test_file_source_meta.py +0 -17
- pysimblocks-0.1.1/tests/gui/test_function_source_meta.py +0 -28
- pysimblocks-0.1.1/tests/regression/test_simulink_dc_motor.py +0 -217
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/LICENSE.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/pid.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/state_feedback.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_input.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_output.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/luenberger.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/algebraic_function.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/dead_zone.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/delay.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/demux.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_derivator.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_integrator.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/gain.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/mux.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/product.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/rate_limiter.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/saturation.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/sum.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/zero_order_hold.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/quadratic_program.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/chirp.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/constant.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/function_source.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/ramp.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/sinusoidal.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/step.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/white_noise.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/polytopic_state_space.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/block.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/block_source.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/fixed_time_manager.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/scheduler.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/task.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/pid.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/state_feedback.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_input.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_output.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/observers/luenberger.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/algebraic_function.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/dead_zone.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/delay.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/demux.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_derivator.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_integrator.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/gain.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/mux.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/product.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/rate_limiter.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/saturation.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/sum.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/zero_order_hold.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/optimizers/quadratic_program.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/chirp.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/constant.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/function_source.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/ramp.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/sinusoidal.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/step.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/white_noise.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/non_linear_state_space.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/polytopic_state_space.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_exchange_i_o.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_plant.md +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/sofa/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/pid.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/state_feedback.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_input.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_output.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/observers/luenberger.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/algebraic_function.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/dead_zone.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/delay.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/demux.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_derivator.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_integrator.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/gain.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/mux.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/product.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/rate_limiter.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/saturation.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/sum.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/zero_order_hold.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/optimizers/quadratic_program.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/parameter_meta.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/port_meta.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/chirp.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/constant.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/function_source.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/ramp.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/sinusoidal.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/step.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/white_noise.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/non_linear_state_space.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/polytopic_state_space.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/display_yaml_dialog.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/help_dialog.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/simulation.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings_dialog.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/unsaved_dialog.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/port_item.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/block_instance.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/connection_instance.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/port_instance.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/project_simulation_params.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_saver.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/build_model.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_simulator.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/real_time/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/real_time/real_time_runner.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/__init__.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/blocks_registry.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/generate_blocks_index.py +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/dependency_links.txt +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/entry_points.txt +0 -0
- {pysimblocks-0.1.1 → pysimblocks-0.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySimBlocks
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A block-diagram simulation environment with PySide6 editor
|
|
5
5
|
Author-email: Antoine Alessandrini <antoine.alessandrini@univ-lille.fr>
|
|
6
6
|
License-Expression: LGPL-3.0-or-later
|
|
@@ -28,6 +28,7 @@ Provides-Extra: docs
|
|
|
28
28
|
Requires-Dist: sphinx; extra == "docs"
|
|
29
29
|
Requires-Dist: myst-parser; extra == "docs"
|
|
30
30
|
Requires-Dist: furo; extra == "docs"
|
|
31
|
+
Requires-Dist: sphinxcontrib-video; extra == "docs"
|
|
31
32
|
Provides-Extra: tests
|
|
32
33
|
Requires-Dist: pytest; extra == "tests"
|
|
33
34
|
Requires-Dist: pytest-qt; extra == "tests"
|
|
@@ -153,7 +154,7 @@ A collection of basic and advanced examples is available in the
|
|
|
153
154
|
[examples](./examples) directory, including:
|
|
154
155
|
|
|
155
156
|
- Control system demonstrations
|
|
156
|
-
- SOFA-based simulations (tested with SOFA
|
|
157
|
+
- SOFA-based simulations (tested with SOFA v26.06 and later.)
|
|
157
158
|
- Hardware and real-time use cases
|
|
158
159
|
- Comparisons with external tools
|
|
159
160
|
|
|
@@ -118,7 +118,7 @@ A collection of basic and advanced examples is available in the
|
|
|
118
118
|
[examples](./examples) directory, including:
|
|
119
119
|
|
|
120
120
|
- Control system demonstrations
|
|
121
|
-
- SOFA-based simulations (tested with SOFA
|
|
121
|
+
- SOFA-based simulations (tested with SOFA v26.06 and later.)
|
|
122
122
|
- Hardware and real-time use cases
|
|
123
123
|
- Comparisons with external tools
|
|
124
124
|
|
|
@@ -20,8 +20,12 @@
|
|
|
20
20
|
|
|
21
21
|
from pySimBlocks.blocks.interfaces.external_input import ExternalInput
|
|
22
22
|
from pySimBlocks.blocks.interfaces.external_output import ExternalOutput
|
|
23
|
+
from pySimBlocks.blocks.interfaces.goto import Goto
|
|
24
|
+
from pySimBlocks.blocks.interfaces.bus_from import BusFrom
|
|
23
25
|
|
|
24
26
|
__all__ = [
|
|
25
27
|
"ExternalInput",
|
|
26
|
-
"ExternalOutput"
|
|
28
|
+
"ExternalOutput",
|
|
29
|
+
"Goto",
|
|
30
|
+
"BusFrom",
|
|
27
31
|
]
|
|
@@ -0,0 +1,88 @@
|
|
|
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.core.block import Block
|
|
22
|
+
from pySimBlocks.core import signal_bus
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class BusFrom(Block):
|
|
26
|
+
"""Read a signal from the global signal bus by tag.
|
|
27
|
+
|
|
28
|
+
BusFrom and Goto blocks implement a virtual wiring mechanism: a Goto writes
|
|
29
|
+
its input to ``signal_bus._signal_bus[tag]`` each tick, and this block
|
|
30
|
+
reads that value without requiring an explicit connection in the model
|
|
31
|
+
graph.
|
|
32
|
+
|
|
33
|
+
The model's topological sort injects a virtual edge from each Goto to every
|
|
34
|
+
BusFrom sharing the same tag, ensuring the Goto executes before this block
|
|
35
|
+
within the same tick.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
direct_feedthrough = True
|
|
39
|
+
|
|
40
|
+
def __init__(self, name: str, tag: str, sample_time: float | None = None):
|
|
41
|
+
"""Initialize a BusFrom block.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
name: Unique identifier for this block instance.
|
|
45
|
+
tag: Signal bus tag to read from. Must match the tag of the
|
|
46
|
+
corresponding Goto block.
|
|
47
|
+
sample_time: Sampling period in seconds, or None to use the
|
|
48
|
+
global simulation dt.
|
|
49
|
+
"""
|
|
50
|
+
super().__init__(name, sample_time)
|
|
51
|
+
self.tag = tag
|
|
52
|
+
self.outputs["out"] = None
|
|
53
|
+
|
|
54
|
+
# --------------------------------------------------------------------------
|
|
55
|
+
# Public methods
|
|
56
|
+
# --------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
def initialize(self, t0: float) -> None:
|
|
59
|
+
"""Read the initial value from the signal bus if available.
|
|
60
|
+
|
|
61
|
+
If the tag is not yet in the bus (Goto not yet initialized), the
|
|
62
|
+
output is set to None.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
t0: Initial simulation time in seconds.
|
|
66
|
+
"""
|
|
67
|
+
self.outputs["out"] = signal_bus._signal_bus.get(self.tag)
|
|
68
|
+
|
|
69
|
+
def output_update(self, t: float, dt: float) -> None:
|
|
70
|
+
"""Read the current value from the signal bus.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
t: Current simulation time in seconds.
|
|
74
|
+
dt: Current time step in seconds.
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
KeyError: If no Goto with the matching tag has written to the bus
|
|
78
|
+
in this run.
|
|
79
|
+
"""
|
|
80
|
+
if self.tag not in signal_bus._signal_bus:
|
|
81
|
+
raise KeyError(
|
|
82
|
+
f"[{self.name}] Tag '{self.tag}' not found in signal bus. "
|
|
83
|
+
"Ensure a Goto block with the same tag exists in the model."
|
|
84
|
+
)
|
|
85
|
+
self.outputs["out"] = signal_bus._signal_bus[self.tag]
|
|
86
|
+
|
|
87
|
+
def state_update(self, t: float, dt: float) -> None:
|
|
88
|
+
"""No-op: BusFrom carries no internal state."""
|
|
@@ -0,0 +1,78 @@
|
|
|
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.core.block import Block
|
|
22
|
+
from pySimBlocks.core import signal_bus
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Goto(Block):
|
|
26
|
+
"""Publish a signal to the global signal bus under a named tag.
|
|
27
|
+
|
|
28
|
+
Goto and From blocks implement a virtual wiring mechanism: a Goto writes
|
|
29
|
+
its input to ``signal_bus._signal_bus[tag]`` each tick, and any From block
|
|
30
|
+
with the same tag reads that value without requiring an explicit connection
|
|
31
|
+
in the model graph.
|
|
32
|
+
|
|
33
|
+
The model's topological sort injects a virtual edge from each Goto to every
|
|
34
|
+
From sharing the same tag, ensuring the Goto executes before its consumers
|
|
35
|
+
within the same tick.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
direct_feedthrough = True
|
|
39
|
+
|
|
40
|
+
def __init__(self, name: str, tag: str, sample_time: float | None = None):
|
|
41
|
+
"""Initialize a Goto block.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
name: Unique identifier for this block instance.
|
|
45
|
+
tag: Signal bus tag under which the input value is published.
|
|
46
|
+
Must match the tag of the corresponding From block(s).
|
|
47
|
+
sample_time: Sampling period in seconds, or None to use the
|
|
48
|
+
global simulation dt.
|
|
49
|
+
"""
|
|
50
|
+
super().__init__(name, sample_time)
|
|
51
|
+
self.tag = tag
|
|
52
|
+
self.inputs["in"] = None
|
|
53
|
+
|
|
54
|
+
# --------------------------------------------------------------------------
|
|
55
|
+
# Public methods
|
|
56
|
+
# --------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
def initialize(self, t0: float) -> None:
|
|
59
|
+
"""Publish the current input to the signal bus.
|
|
60
|
+
|
|
61
|
+
If no input has been connected yet (None), the bus entry is set to None.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
t0: Initial simulation time in seconds.
|
|
65
|
+
"""
|
|
66
|
+
signal_bus._signal_bus[self.tag] = self.inputs["in"]
|
|
67
|
+
|
|
68
|
+
def output_update(self, t: float, dt: float) -> None:
|
|
69
|
+
"""Write the input value to the signal bus under this block's tag.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
t: Current simulation time in seconds.
|
|
73
|
+
dt: Current time step in seconds.
|
|
74
|
+
"""
|
|
75
|
+
signal_bus._signal_bus[self.tag] = self.inputs["in"]
|
|
76
|
+
|
|
77
|
+
def state_update(self, t: float, dt: float) -> None:
|
|
78
|
+
"""No-op: Goto carries no internal state."""
|
|
@@ -38,9 +38,12 @@ class FileSource(BlockSource):
|
|
|
38
38
|
|
|
39
39
|
- ``.npz`` / ``.npy``: 1D ``(N,)`` treated as ``(N, 1)``, or 2D ``(N, n)``
|
|
40
40
|
where N is the number of samples and n the signal dimension. Each step
|
|
41
|
-
outputs a ``(n, 1)`` column vector.
|
|
41
|
+
outputs a ``(n, 1)`` column vector. If the stored array is instead
|
|
42
|
+
``(n, N)`` (signals in rows, samples in columns), set ``transpose=True``
|
|
43
|
+
to have it transposed to ``(N, n)`` before use.
|
|
42
44
|
- ``.csv``: a single column is selected by ``key``, always producing shape
|
|
43
|
-
``(N, 1)``. Output per step is ``(1, 1)``.
|
|
45
|
+
``(N, 1)``. Output per step is ``(1, 1)``. ``transpose`` is not
|
|
46
|
+
applicable to CSV input.
|
|
44
47
|
|
|
45
48
|
Alternatively, when ``use_time=True``, the output is selected by
|
|
46
49
|
looking up the closest past timestamp in a time column bundled with
|
|
@@ -52,6 +55,8 @@ class FileSource(BlockSource):
|
|
|
52
55
|
key: Array key (NPZ) or column name (CSV) to load. None for NPY files.
|
|
53
56
|
repeat: If True, restart from the first sample after the last one.
|
|
54
57
|
use_time: If True, select samples by time lookup instead of index.
|
|
58
|
+
transpose: If True (NPZ/NPY only), transpose the loaded 2D array
|
|
59
|
+
before use, i.e. treat it as ``(n, N)`` instead of ``(N, n)``.
|
|
55
60
|
"""
|
|
56
61
|
|
|
57
62
|
VALID_FILE_TYPES = {"npz", "npy", "csv"}
|
|
@@ -63,6 +68,7 @@ class FileSource(BlockSource):
|
|
|
63
68
|
key: str | None = None,
|
|
64
69
|
repeat: bool = False,
|
|
65
70
|
use_time: bool = False,
|
|
71
|
+
transpose: bool = False,
|
|
66
72
|
sample_time: float | None = None,
|
|
67
73
|
):
|
|
68
74
|
"""Initialize a FileSource block.
|
|
@@ -77,13 +83,18 @@ class FileSource(BlockSource):
|
|
|
77
83
|
use_time: If True, select samples by nearest past timestamp
|
|
78
84
|
instead of advancing by step index. Requires a ``"time"``
|
|
79
85
|
key or column in the file.
|
|
86
|
+
transpose: If True, transpose the loaded 2D array before use.
|
|
87
|
+
Only supported for NPZ and NPY inputs, where it allows
|
|
88
|
+
loading data stored as ``(n, N)`` (signals in rows) instead
|
|
89
|
+
of the expected ``(N, n)`` (samples in rows).
|
|
80
90
|
sample_time: Sampling period in seconds, or None to use the
|
|
81
91
|
global simulation dt.
|
|
82
92
|
|
|
83
93
|
Raises:
|
|
84
94
|
ValueError: If the file extension is unsupported, if ``use_time``
|
|
85
|
-
is combined with an NPY file or with ``repeat=True``,
|
|
86
|
-
|
|
95
|
+
is combined with an NPY file or with ``repeat=True``, if
|
|
96
|
+
``transpose`` is combined with a CSV file, or if the loaded
|
|
97
|
+
data is invalid.
|
|
87
98
|
FileNotFoundError: If the file does not exist.
|
|
88
99
|
"""
|
|
89
100
|
super().__init__(name, sample_time)
|
|
@@ -93,6 +104,7 @@ class FileSource(BlockSource):
|
|
|
93
104
|
self.key = key
|
|
94
105
|
self.repeat = self._to_bool(repeat, "repeat")
|
|
95
106
|
self.use_time = self._to_bool(use_time, "use_time")
|
|
107
|
+
self.transpose = self._to_bool(transpose, "transpose")
|
|
96
108
|
|
|
97
109
|
if self.use_time and self.file_type == "npy":
|
|
98
110
|
raise ValueError(
|
|
@@ -102,6 +114,10 @@ class FileSource(BlockSource):
|
|
|
102
114
|
raise ValueError(
|
|
103
115
|
f"[{self.name}] repeat cannot be used when use_time=True."
|
|
104
116
|
)
|
|
117
|
+
if self.transpose and self.file_type == "csv":
|
|
118
|
+
raise ValueError(
|
|
119
|
+
f"[{self.name}] transpose is supported only for NPZ and NPY inputs."
|
|
120
|
+
)
|
|
105
121
|
|
|
106
122
|
self._time: np.ndarray | None = None
|
|
107
123
|
self._samples = self._load_samples()
|
|
@@ -198,7 +214,10 @@ class FileSource(BlockSource):
|
|
|
198
214
|
|
|
199
215
|
if arr.ndim == 1:
|
|
200
216
|
arr = arr.reshape(-1, 1)
|
|
201
|
-
elif arr.ndim
|
|
217
|
+
elif arr.ndim == 2:
|
|
218
|
+
if self.transpose:
|
|
219
|
+
arr = arr.T
|
|
220
|
+
else:
|
|
202
221
|
raise ValueError(
|
|
203
222
|
f"[{self.name}] Loaded data must be 1D or 2D. Got shape {arr.shape}."
|
|
204
223
|
)
|
|
@@ -206,6 +225,12 @@ class FileSource(BlockSource):
|
|
|
206
225
|
if arr.shape[0] == 0:
|
|
207
226
|
raise ValueError(f"[{self.name}] Loaded file contains no samples.")
|
|
208
227
|
|
|
228
|
+
if time is not None and time.shape[0] != arr.shape[0]:
|
|
229
|
+
raise ValueError(
|
|
230
|
+
f"[{self.name}] time length ({time.shape[0]}) must match number "
|
|
231
|
+
f"of samples ({arr.shape[0]}) after applying transpose."
|
|
232
|
+
)
|
|
233
|
+
|
|
209
234
|
self._time = time
|
|
210
235
|
|
|
211
236
|
return arr.astype(float, copy=False)
|
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
|
|
21
21
|
from pySimBlocks.blocks.systems.linear_state_space import LinearStateSpace
|
|
22
22
|
from pySimBlocks.blocks.systems.polytopic_state_space import PolytopicStateSpace
|
|
23
|
+
from pySimBlocks.blocks.systems.transfer_function import TransferFunction
|
|
23
24
|
|
|
24
25
|
__all__ = [
|
|
25
26
|
"LinearStateSpace",
|
|
26
27
|
"PolytopicStateSpace",
|
|
28
|
+
"TransferFunction"
|
|
27
29
|
]
|
|
@@ -29,20 +29,25 @@ from pySimBlocks.core.block import Block
|
|
|
29
29
|
class LinearStateSpace(Block):
|
|
30
30
|
"""Discrete-time linear state-space system block.
|
|
31
31
|
|
|
32
|
-
Implements a
|
|
32
|
+
Implements a discrete-time linear system:
|
|
33
33
|
|
|
34
34
|
x[k+1] = A x[k] + B u[k]
|
|
35
|
-
|
|
36
|
-
y[k] = C x[k]
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
y[k] = C x[k] (if D is None)
|
|
37
|
+
y[k] = C x[k] + D u[k] (if D is provided)
|
|
38
|
+
|
|
39
|
+
When D is None the block is strictly proper (no direct feedthrough).
|
|
40
|
+
When D is provided the block has direct feedthrough and algebraic loops
|
|
41
|
+
involving this block will be detected and rejected at compile time.
|
|
39
42
|
|
|
40
43
|
Attributes:
|
|
41
44
|
A: State transition matrix of shape (n, n).
|
|
42
45
|
B: Input matrix of shape (n, m).
|
|
43
46
|
C: Output matrix of shape (p, n).
|
|
47
|
+
D: Feedthrough matrix of shape (p, m), or None.
|
|
44
48
|
"""
|
|
45
49
|
|
|
50
|
+
# Default at class level; overridden per-instance when D is provided.
|
|
46
51
|
direct_feedthrough = False
|
|
47
52
|
|
|
48
53
|
def __init__(
|
|
@@ -51,6 +56,7 @@ class LinearStateSpace(Block):
|
|
|
51
56
|
A: ArrayLike,
|
|
52
57
|
B: ArrayLike,
|
|
53
58
|
C: ArrayLike,
|
|
59
|
+
D: ArrayLike | None = None,
|
|
54
60
|
x0: ArrayLike | None = None,
|
|
55
61
|
sample_time: float | None = None,
|
|
56
62
|
):
|
|
@@ -61,6 +67,9 @@ class LinearStateSpace(Block):
|
|
|
61
67
|
A: State transition matrix, array-like of shape (n, n).
|
|
62
68
|
B: Input matrix, array-like of shape (n, m).
|
|
63
69
|
C: Output matrix, array-like of shape (p, n).
|
|
70
|
+
D: Feedthrough matrix, array-like of shape (p, m), or None.
|
|
71
|
+
When provided, the block gains direct feedthrough and
|
|
72
|
+
y[k] = C x[k] + D u[k].
|
|
64
73
|
x0: Initial state vector, array-like of shape (n, 1) or (n,).
|
|
65
74
|
Defaults to zeros.
|
|
66
75
|
sample_time: Sampling period in seconds, or None to use the
|
|
@@ -101,6 +110,23 @@ class LinearStateSpace(Block):
|
|
|
101
110
|
self._m = self.B.shape[1]
|
|
102
111
|
self._p = self.C.shape[0]
|
|
103
112
|
|
|
113
|
+
# --- D matrix (optional) ---
|
|
114
|
+
if D is not None:
|
|
115
|
+
self.D = np.asarray(D, dtype=float)
|
|
116
|
+
if self.D.ndim != 2:
|
|
117
|
+
raise ValueError(f"[{self.name}] D must be 2D. Got shape {self.D.shape}.")
|
|
118
|
+
if self.D.shape != (self._p, self._m):
|
|
119
|
+
raise ValueError(
|
|
120
|
+
f"[{self.name}] D must have shape ({self._p}, {self._m}). "
|
|
121
|
+
f"Got {self.D.shape}."
|
|
122
|
+
)
|
|
123
|
+
# Override direct_feedthrough at the instance level so the
|
|
124
|
+
# scheduler sees this block as having direct feedthrough.
|
|
125
|
+
self.direct_feedthrough = True
|
|
126
|
+
else:
|
|
127
|
+
self.D = None
|
|
128
|
+
|
|
129
|
+
# --- Initial state ---
|
|
104
130
|
if x0 is None:
|
|
105
131
|
x0_arr = np.zeros((n, 1), dtype=float)
|
|
106
132
|
else:
|
|
@@ -143,12 +169,21 @@ class LinearStateSpace(Block):
|
|
|
143
169
|
def output_update(self, t: float, dt: float) -> None:
|
|
144
170
|
"""Compute y and x outputs from the committed state.
|
|
145
171
|
|
|
172
|
+
When D is provided, u[k] is read at this step (direct feedthrough).
|
|
173
|
+
|
|
146
174
|
Args:
|
|
147
175
|
t: Current simulation time in seconds.
|
|
148
176
|
dt: Current time step in seconds.
|
|
149
177
|
"""
|
|
150
178
|
x = self.state["x"]
|
|
151
|
-
self.
|
|
179
|
+
if self.D is not None:
|
|
180
|
+
u = self.inputs["u"]
|
|
181
|
+
if u is None:
|
|
182
|
+
raise RuntimeError(f"[{self.name}] Input 'u' is not connected or not set.")
|
|
183
|
+
u_vec = self._to_col_vec("u", u, self._m)
|
|
184
|
+
self.outputs["y"] = self.C @ x + self.D @ u_vec
|
|
185
|
+
else:
|
|
186
|
+
self.outputs["y"] = self.C @ x
|
|
152
187
|
self.outputs["x"] = x.copy()
|
|
153
188
|
|
|
154
189
|
def state_update(self, t: float, dt: float) -> None:
|
{pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/non_linear_state_space.py
RENAMED
|
@@ -22,6 +22,7 @@ import importlib.util
|
|
|
22
22
|
import inspect
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any, Callable, Dict, List
|
|
25
|
+
from numpy.typing import ArrayLike
|
|
25
26
|
|
|
26
27
|
import numpy as np
|
|
27
28
|
|
|
@@ -87,10 +88,7 @@ class NonLinearStateSpace(Block):
|
|
|
87
88
|
self.input_keys = list(input_keys)
|
|
88
89
|
self.output_keys = list(output_keys)
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
raise TypeError(
|
|
92
|
-
f"{self.name}: x0 must be a numpy array"
|
|
93
|
-
)
|
|
91
|
+
x0 = np.asarray(x0, dtype=float) # <-- conversion, comme dans les autres blocs
|
|
94
92
|
if x0.ndim == 1:
|
|
95
93
|
x0 = x0.reshape(-1, 1)
|
|
96
94
|
elif x0.ndim != 2 or x0.shape[1] != 1:
|