masfaraud / BMSpy

Python Block-Model Simulator. An alternative to simulink in python.
GNU Lesser General Public License v3.0
222 stars 36 forks source link

Combine Blocks into new Block #28

Open simon-zumbrunnen opened 5 years ago

simon-zumbrunnen commented 5 years ago

Hi @masfaraud

I love your project. Is there a way to combine multiple blocks into a new block?

masfaraud commented 5 years ago

Hi, You mean some kind of meta-block? It's not possible yet but not so difficult to implement. What kind of combination would you like to have (Serial...)

simon-zumbrunnen commented 5 years ago

Exactly. I simulated a simple control system today where the plant is a simple first order lag and a gain. Now I created a subclass of ODE for the first order lag and used it in combination with your gain block. Now I would like to combine those two into a "plant" block. I know I can just create a ODE block that combines the lag and the gain but with a more complex system I would not want to do this because it kind of defeats the purpose of the block based approach.

masfaraud commented 5 years ago

If you want to propose a pull request, you can add in core.py a MetaBlock class, inherinting from Block that takes a list of block as input. The Evaluate method of the block should then call each Evaluate method of its sub block sequentially.

simon-zumbrunnen commented 5 years ago

I don't know how to handle variables that way. Heres my approach:

from bms import DynamicSystem,  Variable
from bms.signals.functions import Step
from bms.blocks.continuous import ODE, Gain

class FirstOrderLag(ODE):
    def __init__(self, input_variable, output_variable, tau):
        a = [1]
        b = [1, tau]

        super().__init__(input_variable, output_variable, a, b)

def Plant(input, output):
    temp = Variable('temp', hidden=True)

    lag = FirstOrderLag(source, temp, tau=11e-3)
    gain = Gain(temp, output, value=-50e3)

    return [
        lag,
        gain
    ]

source = Step('source', amplitude=0.9, delay=50e-3)
output = Variable('output')

plant = Plant(source, output)

end_time = 150e-3
number_of_time_steps = 1000

model = DynamicSystem(end_time, number_of_time_steps, [
    *plant
])
model.Simulate()
model.PlotVariables()

Is there a better way?

masfaraud commented 5 years ago

You can try to have "local" variables in your block that the dynamic don't know