pySimBlocks 0.1.0__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.
Files changed (309) hide show
  1. {pysimblocks-0.1.0/pySimBlocks.egg-info → pysimblocks-0.2.0}/PKG-INFO +27 -37
  2. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/README.md +21 -32
  3. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/pid.py +74 -56
  4. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/state_feedback.py +65 -39
  5. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/__init__.py +5 -1
  6. pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/bus_from.py +88 -0
  7. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_input.py +32 -26
  8. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_output.py +33 -33
  9. pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/goto.py +78 -0
  10. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/luenberger.py +79 -42
  11. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/algebraic_function.py +95 -53
  12. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/dead_zone.py +72 -44
  13. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/delay.py +63 -62
  14. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/demux.py +49 -27
  15. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_derivator.py +48 -76
  16. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_integrator.py +63 -88
  17. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/gain.py +65 -67
  18. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/mux.py +48 -35
  19. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/product.py +66 -47
  20. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/rate_limiter.py +70 -53
  21. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/saturation.py +63 -50
  22. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/sum.py +53 -54
  23. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/zero_order_hold.py +50 -27
  24. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/quadratic_program.py +67 -91
  25. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/chirp.py +75 -22
  26. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/constant.py +34 -27
  27. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/file_source.py +109 -29
  28. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/function_source.py +67 -17
  29. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/ramp.py +44 -36
  30. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/sinusoidal.py +46 -35
  31. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/step.py +47 -71
  32. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/white_noise.py +46 -35
  33. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/__init__.py +2 -0
  34. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/linear_state_space.py +93 -38
  35. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/non_linear_state_space.py +90 -75
  36. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/polytopic_state_space.py +65 -33
  37. pysimblocks-0.2.0/pySimBlocks/blocks/systems/sofa/sofa_controller.py +564 -0
  38. pysimblocks-0.2.0/pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +126 -0
  39. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_plant.py +148 -85
  40. pysimblocks-0.2.0/pySimBlocks/blocks/systems/transfer_function.py +380 -0
  41. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/cli.py +45 -19
  42. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/block.py +84 -63
  43. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/block_source.py +45 -21
  44. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/config.py +57 -15
  45. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/fixed_time_manager.py +39 -8
  46. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/model.py +146 -43
  47. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/scheduler.py +32 -4
  48. pysimblocks-0.2.0/pySimBlocks/core/signal_bus.py +37 -0
  49. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/simulator.py +124 -76
  50. pysimblocks-0.2.0/pySimBlocks/core/task.py +103 -0
  51. pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/bus_from.md +63 -0
  52. pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/goto.md +59 -0
  53. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/file_source.md +5 -3
  54. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/linear_state_space.md +22 -5
  55. pysimblocks-0.2.0/pySimBlocks/docs/blocks/systems/transfer_function.md +89 -0
  56. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/slider_params_dialog.py +513 -0
  57. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_dialog.py +324 -0
  58. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_service.py +397 -0
  59. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_dialog_session.py +35 -6
  60. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_meta.py +107 -82
  61. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/pid.py +22 -0
  62. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/state_feedback.py +10 -0
  63. pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/bus_from.py +228 -0
  64. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_input.py +9 -9
  65. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_output.py +9 -8
  66. pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/goto.py +74 -0
  67. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/observers/luenberger.py +9 -0
  68. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/algebraic_function.py +45 -9
  69. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/dead_zone.py +9 -0
  70. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/delay.py +9 -0
  71. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/demux.py +23 -0
  72. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_derivator.py +9 -0
  73. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_integrator.py +9 -0
  74. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/gain.py +9 -0
  75. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/mux.py +23 -0
  76. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/product.py +23 -0
  77. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/rate_limiter.py +9 -0
  78. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/saturation.py +9 -0
  79. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/sum.py +25 -2
  80. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/zero_order_hold.py +9 -0
  81. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/optimizers/quadratic_program.py +9 -0
  82. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/parameter_meta.py +15 -0
  83. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/port_meta.py +9 -0
  84. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/chirp.py +9 -0
  85. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/constant.py +9 -0
  86. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/file_source.py +62 -11
  87. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/function_source.py +45 -9
  88. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/ramp.py +9 -0
  89. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/sinusoidal.py +9 -0
  90. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/step.py +9 -0
  91. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/white_noise.py +9 -0
  92. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/linear_state_space.py +18 -1
  93. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/non_linear_state_space.py +45 -9
  94. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/polytopic_state_space.py +9 -0
  95. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_exchange_i_o.py +50 -10
  96. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_plant.py +50 -10
  97. pysimblocks-0.2.0/pySimBlocks/gui/blocks/systems/transfer_function.py +122 -0
  98. pysimblocks-0.2.0/pySimBlocks/gui/diagram_clipboard.py +694 -0
  99. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/block_dialog.py +39 -9
  100. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/display_yaml_dialog.py +21 -3
  101. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/export_npz_dialog.py +171 -0
  102. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/help_dialog.py +11 -0
  103. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_dialog.py +1564 -0
  104. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_series_style_dialog.py +268 -0
  105. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/plots.py +94 -15
  106. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/project.py +53 -0
  107. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/simulation.py +28 -4
  108. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings_dialog.py +31 -1
  109. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/unsaved_dialog.py +21 -2
  110. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/editor.py +22 -7
  111. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/__init__.py +7 -1
  112. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/block_item.py +139 -24
  113. pysimblocks-0.2.0/pySimBlocks/gui/graphics/connection_item.py +497 -0
  114. pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_item.py +490 -0
  115. pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_proxy_item.py +245 -0
  116. pysimblocks-0.2.0/pySimBlocks/gui/graphics/manual_boundary_wire_item.py +53 -0
  117. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/port_item.py +67 -17
  118. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/theme.py +25 -0
  119. pysimblocks-0.2.0/pySimBlocks/gui/group_boundary_labels.py +38 -0
  120. pysimblocks-0.2.0/pySimBlocks/gui/group_ports.py +10 -0
  121. pysimblocks-0.2.0/pySimBlocks/gui/main_window.py +280 -0
  122. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/models/__init__.py +4 -1
  123. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/models/block_instance.py +53 -15
  124. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/models/connection_instance.py +37 -0
  125. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/models/port_instance.py +37 -4
  126. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/models/project_simulation_params.py +28 -0
  127. pysimblocks-0.2.0/pySimBlocks/gui/models/project_state.py +245 -0
  128. pysimblocks-0.2.0/pySimBlocks/gui/models/visual_group.py +130 -0
  129. pysimblocks-0.2.0/pySimBlocks/gui/project_controller.py +2611 -0
  130. pysimblocks-0.2.0/pySimBlocks/gui/services/group_boundary_service.py +168 -0
  131. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_loader.py +148 -12
  132. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_saver.py +40 -1
  133. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/services/simulation_runner.py +18 -9
  134. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/services/yaml_tools.py +124 -32
  135. pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/commands.py +775 -0
  136. pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/undo_redo_manager.py +60 -0
  137. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/block_list.py +65 -2
  138. pysimblocks-0.2.0/pySimBlocks/gui/widgets/diagram_view.py +1366 -0
  139. pysimblocks-0.2.0/pySimBlocks/gui/widgets/toolbar_view.py +319 -0
  140. pysimblocks-0.2.0/pySimBlocks/gui/widgets/view_navigation_bar.py +86 -0
  141. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/project/build_model.py +18 -25
  142. pysimblocks-0.2.0/pySimBlocks/project/generate_run_script.py +152 -0
  143. pysimblocks-0.2.0/pySimBlocks/project/generate_sofa_scaffold.py +191 -0
  144. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/project/load_project_config.py +70 -3
  145. pysimblocks-0.2.0/pySimBlocks/project/load_simulation_config.py +252 -0
  146. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/project/load_simulator.py +19 -2
  147. pysimblocks-0.2.0/pySimBlocks/project/plot_from_config.py +272 -0
  148. pysimblocks-0.2.0/pySimBlocks/project/plot_series.py +337 -0
  149. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/project/pySimBlocks_blocks_index.yaml +9 -0
  150. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/real_time/real_time_runner.py +43 -43
  151. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/tools/blocks_registry.py +55 -34
  152. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/tools/generate_blocks_index.py +45 -22
  153. {pysimblocks-0.1.0 → pysimblocks-0.2.0/pySimBlocks.egg-info}/PKG-INFO +27 -37
  154. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks.egg-info/SOURCES.txt +27 -85
  155. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks.egg-info/requires.txt +6 -0
  156. pysimblocks-0.2.0/pySimBlocks.egg-info/top_level.txt +1 -0
  157. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pyproject.toml +9 -5
  158. pysimblocks-0.1.0/examples/advanced/hardware/block_diagram.py +0 -162
  159. pysimblocks-0.1.0/examples/advanced/hardware/camera.py +0 -93
  160. pysimblocks-0.1.0/examples/advanced/hardware/gui_emio.py +0 -231
  161. pysimblocks-0.1.0/examples/advanced/hardware/lmi.py +0 -69
  162. pysimblocks-0.1.0/examples/advanced/hardware/main.py +0 -57
  163. pysimblocks-0.1.0/examples/advanced/hardware/parameters.py +0 -54
  164. pysimblocks-0.1.0/examples/advanced/qp_problem/params.py +0 -10
  165. pysimblocks-0.1.0/examples/advanced/qp_problem/run.py +0 -14
  166. pysimblocks-0.1.0/examples/advanced/sofa/gui/finger/Finger.py +0 -108
  167. pysimblocks-0.1.0/examples/advanced/sofa/gui/finger/FingerController.py +0 -53
  168. pysimblocks-0.1.0/examples/advanced/sofa/gui/finger/parameters_auto.py +0 -22
  169. pysimblocks-0.1.0/examples/advanced/sofa/gui/sofa_plant/run.py +0 -14
  170. pysimblocks-0.1.0/examples/advanced/sofa/python/Finger.py +0 -107
  171. pysimblocks-0.1.0/examples/advanced/sofa/python/FingerController.py +0 -48
  172. pysimblocks-0.1.0/examples/advanced/sofa/python/closedloop.py +0 -64
  173. pysimblocks-0.1.0/examples/advanced/sofa/python/openloop.py +0 -58
  174. pysimblocks-0.1.0/examples/basics/algebraic_function/g.py +0 -7
  175. pysimblocks-0.1.0/examples/basics/algebraic_function/run.py +0 -14
  176. pysimblocks-0.1.0/examples/basics/dc_motor/gui/run.py +0 -14
  177. pysimblocks-0.1.0/examples/basics/dc_motor/multiple_order.py +0 -91
  178. pysimblocks-0.1.0/examples/basics/dc_motor/openloop.py +0 -62
  179. pysimblocks-0.1.0/examples/basics/dc_motor/pi.py +0 -99
  180. pysimblocks-0.1.0/examples/basics/dc_motor/pid.py +0 -118
  181. pysimblocks-0.1.0/examples/basics/dc_motor/pid_block.py +0 -82
  182. pysimblocks-0.1.0/examples/basics/dc_motor/pid_block_vs_manual.py +0 -143
  183. pysimblocks-0.1.0/examples/basics/external/parameters.py +0 -4
  184. pysimblocks-0.1.0/examples/basics/external/run.py +0 -14
  185. pysimblocks-0.1.0/examples/basics/file_sources/temp.py +0 -16
  186. pysimblocks-0.1.0/examples/basics/observer.py +0 -76
  187. pysimblocks-0.1.0/examples/basics/state_feedback/gui/parameters.py +0 -9
  188. pysimblocks-0.1.0/examples/basics/state_feedback/gui/run.py +0 -14
  189. pysimblocks-0.1.0/examples/basics/state_feedback/state_feedback.py +0 -102
  190. pysimblocks-0.1.0/examples/basics/state_space/linear/gui/run.py +0 -14
  191. pysimblocks-0.1.0/examples/basics/state_space/linear/ss_block.py +0 -89
  192. pysimblocks-0.1.0/examples/basics/state_space/linear/ss_manual.py +0 -105
  193. pysimblocks-0.1.0/examples/basics/state_space/non_linear/nlss.py +0 -47
  194. pysimblocks-0.1.0/examples/basics/state_space/non_linear/run.py +0 -14
  195. pysimblocks-0.1.0/examples/basics/state_space/polytope/params.py +0 -39
  196. pysimblocks-0.1.0/examples/basics/state_space/polytope/weights.py +0 -12
  197. pysimblocks-0.1.0/examples/comparison/simulink/convert.py +0 -29
  198. pysimblocks-0.1.0/examples/comparison/simulink/openloop.py +0 -127
  199. pysimblocks-0.1.0/examples/comparison/simulink/pi.py +0 -148
  200. pysimblocks-0.1.0/examples/comparison/simulink/pid.py +0 -154
  201. pysimblocks-0.1.0/examples/comparison/simulink/pid_backward.py +0 -155
  202. pysimblocks-0.1.0/examples/quick_start/filter.py +0 -35
  203. pysimblocks-0.1.0/examples/quick_start/gui/run.py +0 -14
  204. pysimblocks-0.1.0/examples/tutorials/tutorial_1_python/main.py +0 -99
  205. pysimblocks-0.1.0/examples/tutorials/tutorial_3_sofa/finger/Finger.py +0 -120
  206. pysimblocks-0.1.0/examples/tutorials/tutorial_3_sofa/finger/FingerController.py +0 -37
  207. pysimblocks-0.1.0/pySimBlocks/blocks/systems/sofa/sofa_controller.py +0 -472
  208. pysimblocks-0.1.0/pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +0 -120
  209. pysimblocks-0.1.0/pySimBlocks/core/task.py +0 -73
  210. pysimblocks-0.1.0/pySimBlocks/gui/addons/sofa/sofa_dialog.py +0 -190
  211. pysimblocks-0.1.0/pySimBlocks/gui/addons/sofa/sofa_service.py +0 -209
  212. pysimblocks-0.1.0/pySimBlocks/gui/dialogs/plot_dialog.py +0 -230
  213. pysimblocks-0.1.0/pySimBlocks/gui/graphics/connection_item.py +0 -266
  214. pysimblocks-0.1.0/pySimBlocks/gui/main_window.py +0 -162
  215. pysimblocks-0.1.0/pySimBlocks/gui/models/project_state.py +0 -114
  216. pysimblocks-0.1.0/pySimBlocks/gui/project_controller.py +0 -302
  217. pysimblocks-0.1.0/pySimBlocks/gui/widgets/diagram_view.py +0 -312
  218. pysimblocks-0.1.0/pySimBlocks/gui/widgets/toolbar_view.py +0 -161
  219. pysimblocks-0.1.0/pySimBlocks/project/generate_run_script.py +0 -109
  220. pysimblocks-0.1.0/pySimBlocks/project/generate_sofa_controller.py +0 -215
  221. pysimblocks-0.1.0/pySimBlocks/project/load_simulation_config.py +0 -166
  222. pysimblocks-0.1.0/pySimBlocks/project/plot_from_config.py +0 -174
  223. pysimblocks-0.1.0/pySimBlocks.egg-info/top_level.txt +0 -7
  224. pysimblocks-0.1.0/tests/blocks/controllers/test_pid.py +0 -143
  225. pysimblocks-0.1.0/tests/blocks/controllers/test_state_feedback.py +0 -193
  226. pysimblocks-0.1.0/tests/blocks/observers/test_luenberger.py +0 -225
  227. pysimblocks-0.1.0/tests/blocks/operators/test_algebraic_function.py +0 -230
  228. pysimblocks-0.1.0/tests/blocks/operators/test_dead_zone.py +0 -106
  229. pysimblocks-0.1.0/tests/blocks/operators/test_delay.py +0 -167
  230. pysimblocks-0.1.0/tests/blocks/operators/test_demux.py +0 -111
  231. pysimblocks-0.1.0/tests/blocks/operators/test_discrete_derivator.py +0 -160
  232. pysimblocks-0.1.0/tests/blocks/operators/test_discrete_integrator.py +0 -149
  233. pysimblocks-0.1.0/tests/blocks/operators/test_gain.py +0 -182
  234. pysimblocks-0.1.0/tests/blocks/operators/test_mux.py +0 -101
  235. pysimblocks-0.1.0/tests/blocks/operators/test_product.py +0 -171
  236. pysimblocks-0.1.0/tests/blocks/operators/test_rate_limiter.py +0 -166
  237. pysimblocks-0.1.0/tests/blocks/operators/test_saturation.py +0 -157
  238. pysimblocks-0.1.0/tests/blocks/operators/test_sum.py +0 -183
  239. pysimblocks-0.1.0/tests/blocks/operators/test_zero_order_hold.py +0 -106
  240. pysimblocks-0.1.0/tests/blocks/sources/test_chirp.py +0 -157
  241. pysimblocks-0.1.0/tests/blocks/sources/test_constant.py +0 -55
  242. pysimblocks-0.1.0/tests/blocks/sources/test_file_source.py +0 -185
  243. pysimblocks-0.1.0/tests/blocks/sources/test_function_source.py +0 -135
  244. pysimblocks-0.1.0/tests/blocks/sources/test_ramp.py +0 -110
  245. pysimblocks-0.1.0/tests/blocks/sources/test_sinusoidal.py +0 -113
  246. pysimblocks-0.1.0/tests/blocks/sources/test_step.py +0 -76
  247. pysimblocks-0.1.0/tests/blocks/sources/test_white_noise.py +0 -108
  248. pysimblocks-0.1.0/tests/blocks/systems/test_linear_state_space.py +0 -135
  249. pysimblocks-0.1.0/tests/blocks/systems/test_polytopic_state_space.py +0 -133
  250. pysimblocks-0.1.0/tests/core/test_core_errors_and_determinism.py +0 -82
  251. pysimblocks-0.1.0/tests/core/test_core_multirate_tasks.py +0 -88
  252. pysimblocks-0.1.0/tests/core/test_core_two_phase_and_propagation.py +0 -132
  253. pysimblocks-0.1.0/tests/gui/main_window_open_test.py +0 -162
  254. pysimblocks-0.1.0/tests/gui/test_block_meta_param_cache.py +0 -16
  255. pysimblocks-0.1.0/tests/gui/test_file_source_meta.py +0 -17
  256. pysimblocks-0.1.0/tests/gui/test_function_source_meta.py +0 -28
  257. pysimblocks-0.1.0/tests/regression/test_simulink_dc_motor.py +0 -217
  258. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/LICENSE.md +0 -0
  259. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/__init__.py +0 -0
  260. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/__init__.py +0 -0
  261. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/__init__.py +0 -0
  262. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/__init__.py +0 -0
  263. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/__init__.py +0 -0
  264. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/__init__.py +0 -0
  265. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/__init__.py +0 -0
  266. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/__init__.py +0 -0
  267. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/core/__init__.py +0 -0
  268. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/pid.md +0 -0
  269. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/state_feedback.md +0 -0
  270. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_input.md +0 -0
  271. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_output.md +0 -0
  272. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/observers/luenberger.md +0 -0
  273. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/algebraic_function.md +0 -0
  274. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/dead_zone.md +0 -0
  275. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/delay.md +0 -0
  276. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/demux.md +0 -0
  277. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_derivator.md +0 -0
  278. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_integrator.md +0 -0
  279. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/gain.md +0 -0
  280. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/mux.md +0 -0
  281. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/product.md +0 -0
  282. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/rate_limiter.md +0 -0
  283. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/saturation.md +0 -0
  284. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/sum.md +0 -0
  285. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/zero_order_hold.md +0 -0
  286. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/optimizers/quadratic_program.md +0 -0
  287. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/chirp.md +0 -0
  288. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/constant.md +0 -0
  289. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/function_source.md +0 -0
  290. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/ramp.md +0 -0
  291. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/sinusoidal.md +0 -0
  292. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/step.md +0 -0
  293. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/white_noise.md +0 -0
  294. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/non_linear_state_space.md +0 -0
  295. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/polytopic_state_space.md +0 -0
  296. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_exchange_i_o.md +0 -0
  297. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_plant.md +0 -0
  298. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/__init__.py +0 -0
  299. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/__init__.py +0 -0
  300. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/sofa/__init__.py +0 -0
  301. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/__init__.py +0 -0
  302. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/services/__init__.py +0 -0
  303. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/__init__.py +0 -0
  304. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/project/__init__.py +0 -0
  305. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/real_time/__init__.py +0 -0
  306. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks/tools/__init__.py +0 -0
  307. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks.egg-info/dependency_links.txt +0 -0
  308. {pysimblocks-0.1.0 → pysimblocks-0.2.0}/pySimBlocks.egg-info/entry_points.txt +0 -0
  309. {pysimblocks-0.1.0 → 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.1.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
@@ -11,10 +11,6 @@ Keywords: simulation,block-diagram,control,discrete-time,pyside6
11
11
  Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: Intended Audience :: Education
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Programming Language :: Python :: 3.11
17
- Classifier: Programming Language :: Python :: 3.12
18
14
  Classifier: Topic :: Scientific/Engineering
19
15
  Classifier: Topic :: Scientific/Engineering :: Visualization
20
16
  Requires-Python: >=3.10
@@ -28,6 +24,11 @@ Requires-Dist: typing_extensions; python_version < "3.11"
28
24
  Provides-Extra: examples
29
25
  Requires-Dist: control; extra == "examples"
30
26
  Requires-Dist: qpsolvers[clarabel,osqp]; extra == "examples"
27
+ Provides-Extra: docs
28
+ Requires-Dist: sphinx; extra == "docs"
29
+ Requires-Dist: myst-parser; extra == "docs"
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"
@@ -35,45 +36,34 @@ Dynamic: license-file
35
36
 
36
37
  # pySimBlocks
37
38
 
39
+ [![PyPI version](https://img.shields.io/pypi/v/pySimBlocks.svg)](https://pypi.org/project/pySimBlocks/)
40
+ [![Python](https://img.shields.io/pypi/pyversions/pySimBlocks.svg)](https://pypi.org/project/pySimBlocks/)
41
+ [![License](https://img.shields.io/github/license/AlessandriniAntoine/pySimBlocks)](./LICENSE.md)
42
+ [![Documentation](https://readthedocs.org/projects/pysimblocks/badge/?version=latest)](https://pysimblocks.readthedocs.io)
43
+
44
+ ---
45
+
38
46
  A deterministic block-diagram simulation framework for discrete-time modeling,
39
47
  co-simulation and research prototyping in Python.
40
48
 
41
- pySimBlocks allows you to build, configure, and execute discrete-time systems
49
+ pySimBlocks allows you to build, configure, and execute discrete-time systems
42
50
  using either:
43
51
 
44
52
  - A pure Python API
45
53
  - A graphical editor (PySide6)
46
- - YAML project configuration
54
+ - YAML project configuration with exportable Python runner (`run.py`)
47
55
  - Optional SOFA and hardware integration
48
56
 
49
- ![pySimBlocks graphical editor](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/User_Guide/images/gui_example.png)
50
-
51
- ## Features
52
-
53
- - Block-based modeling (Simulink-like)
54
- - Deterministic discrete-time simulation engine
55
- - PySide6 graphical editor
56
- - YAML-based project serialization
57
- - Exportable Python runner (`run.py`)
58
- - Extensible block architecture
57
+ ![pySimBlocks graphical editor](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/source/images/user_guide/gui_example.png)
59
58
 
60
59
  ## Installation
61
60
 
62
- ### From GitHub
63
-
64
- Install directly from GitHub using pip:
65
- ```
66
- pip install git+https://github.com/AlessandriniAntoine/pySimBlocks
61
+ ```bash
62
+ pip install pySimBlocks
67
63
  ```
68
64
 
69
- ### Locally
70
-
71
- Clone the repository and install locally:
72
- ```
73
- git clone https://github.com/AlessandriniAntoine/pySimBlocks.git
74
- cd pySimBlocks
75
- pip install .
76
- ```
65
+ Full documentation — user guide, tutorials, and API reference — is available on
66
+ [**Read the Docs**](https://pysimblocks.readthedocs.io).
77
67
 
78
68
  ## Getting Started
79
69
 
@@ -125,7 +115,7 @@ plot_from_config(logs, plot_cfg)
125
115
 
126
116
  The resulting plot should look like this:
127
117
 
128
- ![Noise filtered](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/User_Guide/images/quick_example.png)
118
+ ![Noise filtered](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/source/images/user_guide/quick_example.png)
129
119
 
130
120
  See [examples/quick_start/filter.py](./examples/quick_start/filter.py)
131
121
  to run the example yourself.
@@ -148,14 +138,14 @@ The quick-start GUI project is stored in a single
148
138
 
149
139
  #### Tutorials
150
140
 
151
- Three step-by-step tutorials are available detailed in the
152
- [guide](./docs/User_Guide/getting_started.md):
141
+ Three step-by-step tutorials are available in the
142
+ [documentation](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/index.html):
153
143
 
154
144
  | | Tutorial | Description |
155
145
  |---|---|---|
156
- | 1 | [Python API](./docs/User_Guide/tutorial_1_python.md) | Build a closed-loop PI control system in pure Python |
157
- | 2 | [GUI](./docs/User_Guide/tutorial_2_gui.md) | Build the same system visually with the graphical editor |
158
- | 3 | [SOFA](./docs/User_Guide/tutorial_3_sofa.md) | Replace the plant with a SOFA physics simulation |
146
+ | 1 | [Python API](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_1_python.html) | Build a closed-loop PI control system in pure Python |
147
+ | 2 | [GUI](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_2_gui.html) | Build the same system visually with the graphical editor |
148
+ | 3 | [SOFA](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_3_sofa.html) | Replace the plant with a SOFA physics simulation |
159
149
 
160
150
 
161
151
  #### Other Examples
@@ -164,7 +154,7 @@ A collection of basic and advanced examples is available in the
164
154
  [examples](./examples) directory, including:
165
155
 
166
156
  - Control system demonstrations
167
- - SOFA-based simulations (tested with SOFA v24.06 and later.)
157
+ - SOFA-based simulations (tested with SOFA v26.06 and later.)
168
158
  - Hardware and real-time use cases
169
159
  - Comparisons with external tools
170
160
 
@@ -1,44 +1,33 @@
1
1
  # pySimBlocks
2
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/pySimBlocks.svg)](https://pypi.org/project/pySimBlocks/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/pySimBlocks.svg)](https://pypi.org/project/pySimBlocks/)
5
+ [![License](https://img.shields.io/github/license/AlessandriniAntoine/pySimBlocks)](./LICENSE.md)
6
+ [![Documentation](https://readthedocs.org/projects/pysimblocks/badge/?version=latest)](https://pysimblocks.readthedocs.io)
7
+
8
+ ---
9
+
3
10
  A deterministic block-diagram simulation framework for discrete-time modeling,
4
11
  co-simulation and research prototyping in Python.
5
12
 
6
- pySimBlocks allows you to build, configure, and execute discrete-time systems
13
+ pySimBlocks allows you to build, configure, and execute discrete-time systems
7
14
  using either:
8
15
 
9
16
  - A pure Python API
10
17
  - A graphical editor (PySide6)
11
- - YAML project configuration
18
+ - YAML project configuration with exportable Python runner (`run.py`)
12
19
  - Optional SOFA and hardware integration
13
20
 
14
- ![pySimBlocks graphical editor](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/User_Guide/images/gui_example.png)
15
-
16
- ## Features
17
-
18
- - Block-based modeling (Simulink-like)
19
- - Deterministic discrete-time simulation engine
20
- - PySide6 graphical editor
21
- - YAML-based project serialization
22
- - Exportable Python runner (`run.py`)
23
- - Extensible block architecture
21
+ ![pySimBlocks graphical editor](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/source/images/user_guide/gui_example.png)
24
22
 
25
23
  ## Installation
26
24
 
27
- ### From GitHub
28
-
29
- Install directly from GitHub using pip:
30
- ```
31
- pip install git+https://github.com/AlessandriniAntoine/pySimBlocks
25
+ ```bash
26
+ pip install pySimBlocks
32
27
  ```
33
28
 
34
- ### Locally
35
-
36
- Clone the repository and install locally:
37
- ```
38
- git clone https://github.com/AlessandriniAntoine/pySimBlocks.git
39
- cd pySimBlocks
40
- pip install .
41
- ```
29
+ Full documentation — user guide, tutorials, and API reference — is available on
30
+ [**Read the Docs**](https://pysimblocks.readthedocs.io).
42
31
 
43
32
  ## Getting Started
44
33
 
@@ -90,7 +79,7 @@ plot_from_config(logs, plot_cfg)
90
79
 
91
80
  The resulting plot should look like this:
92
81
 
93
- ![Noise filtered](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/User_Guide/images/quick_example.png)
82
+ ![Noise filtered](https://raw.githubusercontent.com/AlessandriniAntoine/pySimBlocks/main/docs/source/images/user_guide/quick_example.png)
94
83
 
95
84
  See [examples/quick_start/filter.py](./examples/quick_start/filter.py)
96
85
  to run the example yourself.
@@ -113,14 +102,14 @@ The quick-start GUI project is stored in a single
113
102
 
114
103
  #### Tutorials
115
104
 
116
- Three step-by-step tutorials are available detailed in the
117
- [guide](./docs/User_Guide/getting_started.md):
105
+ Three step-by-step tutorials are available in the
106
+ [documentation](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/index.html):
118
107
 
119
108
  | | Tutorial | Description |
120
109
  |---|---|---|
121
- | 1 | [Python API](./docs/User_Guide/tutorial_1_python.md) | Build a closed-loop PI control system in pure Python |
122
- | 2 | [GUI](./docs/User_Guide/tutorial_2_gui.md) | Build the same system visually with the graphical editor |
123
- | 3 | [SOFA](./docs/User_Guide/tutorial_3_sofa.md) | Replace the plant with a SOFA physics simulation |
110
+ | 1 | [Python API](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_1_python.html) | Build a closed-loop PI control system in pure Python |
111
+ | 2 | [GUI](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_2_gui.html) | Build the same system visually with the graphical editor |
112
+ | 3 | [SOFA](https://pysimblocks.readthedocs.io/en/latest/user_guide/tutorials/tutorial_3_sofa.html) | Replace the plant with a SOFA physics simulation |
124
113
 
125
114
 
126
115
  #### Other Examples
@@ -129,7 +118,7 @@ A collection of basic and advanced examples is available in the
129
118
  [examples](./examples) directory, including:
130
119
 
131
120
  - Control system demonstrations
132
- - SOFA-based simulations (tested with SOFA v24.06 and later.)
121
+ - SOFA-based simulations (tested with SOFA v26.06 and later.)
133
122
  - Hardware and real-time use cases
134
123
  - Comparisons with external tools
135
124
 
@@ -18,6 +18,8 @@
18
18
  # Authors: see Authors.txt
19
19
  # ******************************************************************************
20
20
 
21
+ from __future__ import annotations
22
+
21
23
  import warnings
22
24
 
23
25
  import numpy as np
@@ -27,43 +29,26 @@ from pySimBlocks.core.block import Block
27
29
 
28
30
 
29
31
  class Pid(Block):
30
- """
31
- Discrete-time PID controller block.
32
-
33
- Summary:
34
- Implements a single-input single-output discrete PID controller,
35
- similar to the Simulink PID block. The controller computes a control
36
- command from an error signal using proportional, integral and/or
37
- derivative actions, depending on the selected control mode.
38
-
39
- Parameters (overview):
40
- controller : str
41
- Control mode. One of {"P", "PI", "PD", "PID"}.
42
- Kp : float
43
- Proportional gain.
44
- Ki : float
45
- Integral gain.
46
- Kd : float
47
- Derivative gain.
48
- u_min : float, optional
49
- Minimum output saturation.
50
- u_max : float, optional
51
- Maximum output saturation.
52
- sample_time : float, optional
53
- Controller sampling period.
54
-
55
- I/O:
56
- Inputs:
57
- e : error signal.
58
- Outputs:
59
- u : control command.
60
-
61
- Notes:
62
- - The block is strictly SISO.
63
- - Integral action introduces internal state.
64
- - If a parameter is not provided, the block falls back to its
65
- internal default value.
66
- - Output saturation is applied only if u_min and/or u_max are defined.
32
+ """Discrete-time PID controller block.
33
+
34
+ Implements a single-input single-output discrete PID controller,
35
+ similar to the Simulink PID block. The controller computes a control
36
+ command from an error signal ``e`` using proportional, integral, and/or
37
+ derivative actions depending on the selected control mode.
38
+
39
+ Output saturation is applied only if ``u_min`` and/or ``u_max`` are set.
40
+ Anti-windup clamps the integrator state to the saturation bounds.
41
+
42
+ Attributes:
43
+ controller: Active control mode (``"P"``, ``"I"``, ``"PI"``,
44
+ ``"PD"``, or ``"PID"``).
45
+ integration_method: Integration scheme for the I term
46
+ (``"euler forward"`` or ``"euler backward"``).
47
+ Kp: Proportional gain as a (1,1) array.
48
+ Ki: Integral gain as a (1,1) array.
49
+ Kd: Derivative gain as a (1,1) array.
50
+ u_min: Lower saturation bound as a (1,1) array, or None.
51
+ u_max: Upper saturation bound as a (1,1) array, or None.
67
52
  """
68
53
 
69
54
  def __init__(
@@ -78,6 +63,27 @@ class Pid(Block):
78
63
  integration_method: str = "euler forward",
79
64
  sample_time: float | None = None,
80
65
  ):
66
+ """Initialize a PID controller block.
67
+
68
+ Args:
69
+ name: Unique identifier for this block instance.
70
+ controller: Control mode. Must be one of ``{"P", "I", "PI",
71
+ "PD", "PID"}``.
72
+ Kp: Proportional gain. Must be scalar-like.
73
+ Ki: Integral gain. Must be scalar-like.
74
+ Kd: Derivative gain. Must be scalar-like.
75
+ u_min: Minimum output saturation bound. None to disable.
76
+ u_max: Maximum output saturation bound. None to disable.
77
+ integration_method: Integration scheme for the I term.
78
+ Must be ``"euler forward"`` or ``"euler backward"``.
79
+ sample_time: Sampling period in seconds, or None to use the
80
+ global simulation dt.
81
+
82
+ Raises:
83
+ ValueError: If ``controller`` or ``integration_method`` is
84
+ invalid, if any gain is not scalar-like, or if
85
+ ``u_min > u_max``.
86
+ """
81
87
  super().__init__(name, sample_time)
82
88
 
83
89
  controller = controller.upper()
@@ -95,7 +101,6 @@ class Pid(Block):
95
101
  f"[{self.name}] Unsupported method '{self.integration_method}'. Allowed: {allowed}"
96
102
  )
97
103
 
98
- # Gains (SISO, (1,1))
99
104
  self.Kp = self._to_siso("Kp", Kp)
100
105
  self.Ki = self._to_siso("Ki", Ki)
101
106
  self.Kd = self._to_siso("Kd", Kd)
@@ -109,13 +114,10 @@ class Pid(Block):
109
114
  f"[{self.name}] u_min ({self.u_min.item()}) must be <= u_max ({self.u_max.item()})."
110
115
  )
111
116
 
112
- # Warnings
113
117
  self._validate_gains()
114
118
 
115
- # Direct feedthrough policy
116
119
  has_p = "P" in self.controller
117
120
  has_d = "D" in self.controller
118
- has_i = "I" in self.controller
119
121
 
120
122
  if has_p or has_d:
121
123
  self.direct_feedthrough = True
@@ -123,11 +125,9 @@ class Pid(Block):
123
125
  # I-only
124
126
  self.direct_feedthrough = (self.integration_method == "euler backward")
125
127
 
126
- # Ports
127
128
  self.inputs["e"] = None
128
129
  self.outputs["u"] = None
129
130
 
130
- # State (SISO)
131
131
  self.state["x_i"] = np.zeros((1, 1), dtype=float)
132
132
  self.state["e_prev"] = np.zeros((1, 1), dtype=float)
133
133
  self.next_state["x_i"] = np.zeros((1, 1), dtype=float)
@@ -137,12 +137,25 @@ class Pid(Block):
137
137
  # --------------------------------------------------------------------------
138
138
  # Public methods
139
139
  # --------------------------------------------------------------------------
140
- def initialize(self, t0: float):
141
- # Start at zero command, keep internal states at zero.
140
+
141
+ def initialize(self, t0: float) -> None:
142
+ """Set the output to zero and keep internal states at zero.
143
+
144
+ Args:
145
+ t0: Initial simulation time in seconds.
146
+ """
142
147
  self.outputs["u"] = np.zeros((1, 1), dtype=float)
143
148
 
144
- # ------------------------------------------------------------------
145
- def output_update(self, t: float, dt: float):
149
+ def output_update(self, t: float, dt: float) -> None:
150
+ """Compute the PID control command from the current error input.
151
+
152
+ Args:
153
+ t: Current simulation time in seconds.
154
+ dt: Current time step in seconds.
155
+
156
+ Raises:
157
+ RuntimeError: If input ``e`` is not connected.
158
+ """
146
159
  e_in = self.inputs["e"]
147
160
  if e_in is None:
148
161
  raise RuntimeError(f"[{self.name}] Missing input 'e'.")
@@ -170,7 +183,6 @@ class Pid(Block):
170
183
 
171
184
  u = P + I + D
172
185
 
173
- # Saturation
174
186
  if self.u_min is not None:
175
187
  u = np.maximum(u, self.u_min)
176
188
  if self.u_max is not None:
@@ -178,8 +190,16 @@ class Pid(Block):
178
190
 
179
191
  self.outputs["u"] = u
180
192
 
181
- # ------------------------------------------------------------------
182
- def state_update(self, t: float, dt: float):
193
+ def state_update(self, t: float, dt: float) -> None:
194
+ """Update the integrator state and store the previous error.
195
+
196
+ Args:
197
+ t: Current simulation time in seconds.
198
+ dt: Current time step in seconds.
199
+
200
+ Raises:
201
+ RuntimeError: If input ``e`` is not connected.
202
+ """
183
203
  e_in = self.inputs["e"]
184
204
  if e_in is None:
185
205
  raise RuntimeError(f"[{self.name}] Missing input 'e'.")
@@ -188,13 +208,12 @@ class Pid(Block):
188
208
 
189
209
  has_i = "I" in self.controller
190
210
 
191
- # Integrator update only if I term is enabled
192
211
  if has_i:
193
212
  x_i_next = self.state["x_i"] + self.Ki * e * dt
194
213
  else:
195
214
  x_i_next = self.state["x_i"].copy()
196
215
 
197
- # Anti-windup (clamp integral state if saturation is defined)
216
+ # Anti-windup: clamp integral state to saturation bounds
198
217
  if self.u_min is not None:
199
218
  x_i_next = np.maximum(x_i_next, self.u_min)
200
219
  if self.u_max is not None:
@@ -207,10 +226,9 @@ class Pid(Block):
207
226
  # --------------------------------------------------------------------------
208
227
  # Private methods
209
228
  # --------------------------------------------------------------------------
229
+
210
230
  def _to_siso(self, name: str, value: ArrayLike) -> np.ndarray:
211
- """
212
- Normalize scalar-like into (1,1). Reject anything else (strict SISO).
213
- """
231
+ """Normalize a scalar-like value to a (1,1) array; reject anything else."""
214
232
  if np.isscalar(value):
215
233
  return np.array([[float(value)]], dtype=float)
216
234
 
@@ -227,8 +245,8 @@ class Pid(Block):
227
245
  f"[{self.name}] '{name}' must be scalar-like ((), (1,), or (1,1)). Got shape {arr.shape}."
228
246
  )
229
247
 
230
- # ------------------------------------------------------------------
231
248
  def _validate_gains(self) -> None:
249
+ """Warn if a gain is zero for a mode that requires it."""
232
250
  kp = float(self.Kp[0, 0])
233
251
  ki = float(self.Ki[0, 0])
234
252
  kd = float(self.Kd[0, 0])
@@ -18,45 +18,44 @@
18
18
  # Authors: see Authors.txt
19
19
  # ******************************************************************************
20
20
 
21
+ from __future__ import annotations
22
+
21
23
  import numpy as np
24
+ from numpy.typing import ArrayLike
25
+
22
26
  from pySimBlocks.core.block import Block
23
27
 
24
28
 
25
29
  class StateFeedback(Block):
26
- """
27
- Discrete-time state-feedback controller block.
28
-
29
- Summary:
30
- Implements a static discrete-time state-feedback control law:
31
- u = G @ r - K @ x
32
-
33
- Parameters:
34
- K : array-like, shape (m, n)
35
- State feedback gain matrix.
36
- G : array-like, shape (m, p)
37
- Reference feedforward gain matrix.
38
- sample_time : float, optional
39
- Block execution period.
40
-
41
- Inputs:
42
- r : array (p, 1)
43
- Reference vector.
44
- x : array (n, 1)
45
- State vector.
46
-
47
- Outputs:
48
- u : array (m, 1)
49
- Control vector.
50
-
51
- Notes:
52
- - Stateless block.
53
- - This block intentionally enforces column-vector inputs.
54
- - No implicit flattening is performed.
30
+ """Discrete-time state-feedback controller block.
31
+
32
+ Implements a static discrete-time state-feedback control law:
33
+
34
+ u = G @ r - K @ x
35
+
36
+ Both inputs must be column vectors. No implicit flattening is performed.
37
+
38
+ Attributes:
39
+ K: State feedback gain matrix of shape (m, n).
40
+ G: Reference feedforward gain matrix of shape (m, p).
55
41
  """
56
42
 
57
43
  direct_feedthrough = True
58
44
 
59
- def __init__(self, name: str, K, G, sample_time: float | None = None):
45
+ def __init__(self, name: str, K: ArrayLike, G: ArrayLike, sample_time: float | None = None):
46
+ """Initialize a StateFeedback block.
47
+
48
+ Args:
49
+ name: Unique identifier for this block instance.
50
+ K: State feedback gain matrix, array-like of shape (m, n).
51
+ G: Reference feedforward gain matrix, array-like of shape (m, p).
52
+ sample_time: Sampling period in seconds, or None to use the
53
+ global simulation dt.
54
+
55
+ Raises:
56
+ ValueError: If K or G are not 2D, or if their first dimensions
57
+ do not match.
58
+ """
60
59
  super().__init__(name, sample_time)
61
60
 
62
61
  self.K = np.asarray(K, dtype=float)
@@ -76,23 +75,27 @@ class StateFeedback(Block):
76
75
  f"K is {self.K.shape} while G is {self.G.shape} (first dimension must match)."
77
76
  )
78
77
 
79
- # cached expected sizes for input validation
80
78
  self._m = m
81
79
  self._n = n
82
80
  self._p = p
83
81
 
84
- # Ports
85
82
  self.inputs["r"] = None
86
83
  self.inputs["x"] = None
87
84
  self.outputs["u"] = None
88
85
 
89
- # freeze input shapes once seen (optional but consistent)
90
86
  self._input_shapes = {}
91
87
 
88
+
92
89
  # --------------------------------------------------------------------------
93
90
  # Public methods
94
91
  # --------------------------------------------------------------------------
95
- def initialize(self, t0: float):
92
+
93
+ def initialize(self, t0: float) -> None:
94
+ """Set the output to zero, or compute u if inputs are already available.
95
+
96
+ Args:
97
+ t0: Initial simulation time in seconds.
98
+ """
96
99
  r = self.inputs["r"]
97
100
  x = self.inputs["x"]
98
101
  if r is None or x is None:
@@ -106,22 +109,45 @@ class StateFeedback(Block):
106
109
  except Exception as _:
107
110
  self.outputs["u"] = np.zeros((self._m, 1))
108
111
 
109
- # ------------------------------------------------------------------
110
- def output_update(self, t: float, dt: float):
112
+ def output_update(self, t: float, dt: float) -> None:
113
+ """Compute the control output u = G @ r - K @ x.
114
+
115
+ Args:
116
+ t: Current simulation time in seconds.
117
+ dt: Current time step in seconds.
118
+
119
+ Raises:
120
+ RuntimeError: If input ``r`` or ``x`` is not connected.
121
+ ValueError: If input shapes do not match the gain matrices.
122
+ """
111
123
  r = self._require_col_vector("r", self._p)
112
124
  x = self._require_col_vector("x", self._n)
113
125
 
114
126
  self.outputs["u"] = self.G @ r - self.K @ x
115
127
 
116
- # ------------------------------------------------------------------
117
- def state_update(self, t: float, dt: float):
118
- pass
128
+ def state_update(self, t: float, dt: float) -> None:
129
+ """No-op: StateFeedback carries no internal state."""
119
130
 
120
131
 
121
132
  # --------------------------------------------------------------------------
122
133
  # Private methods
123
134
  # --------------------------------------------------------------------------
135
+
124
136
  def _require_col_vector(self, port: str, expected_rows: int) -> np.ndarray:
137
+ """Validate and return an input port value as a column vector.
138
+
139
+ Args:
140
+ port: Name of the input port to read.
141
+ expected_rows: Expected number of rows in the column vector.
142
+
143
+ Returns:
144
+ The input value as a 2D (n, 1) float array.
145
+
146
+ Raises:
147
+ RuntimeError: If the port value is None.
148
+ ValueError: If the array is not a column vector or has the
149
+ wrong number of rows.
150
+ """
125
151
  u = self.inputs[port]
126
152
  if u is None:
127
153
  raise RuntimeError(f"[{self.name}] Input '{port}' is not connected or not set.")
@@ -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
  ]