Element Factories¶
ControlSBML
provides factories for making elements of closed loops.
Elements constructed from these factories are control.NonlinearIOSystem
objects.
Elements are classified as signal generators that produce a signal or system elements that transform signals.
- Signal generators
Step
Sine
Arbitrary signal
- Systems
PID controller
Filter
Adder
Multiplier
Passthru
All factory methods have a single positional argument: the name of the element, and they
return an NonlinearIOSystem
with the specified names and names for its inputs and outputs.
Signal generators¶
All signal generator factories
have the keyword arguments
start_time
(which defaults to 0) and end_time
(which defaults to None
).
Signal generator factories also have keyword arguments
that specify specifics of the signal.
The factory returns an NonlinearIOSystem
that has
no input and a single output named out
.
Step¶
makeStep
is a factory that creates step signals.
It has the signal specific keyword argument step_size
that specifies the
magnitude of the step. The code below illustrates the creation of a step signal generator for
a step of size 3 that starts at time 1 and ends at time 3.
factory = ctl.IOSystemFactory()
step = factory.makeStep("step", 2, start_time=1, end_time=3)
Below is an example of creating an control.InterconnectedSystem
that consists only of a step function. Then, we plot the result.
1# Create an InterconnectedSystem
2connected_system = control.interconnect(
3[step], # systems
4outlist=["step.out"],
5)
6# Simulate the system and plot the result.
7ts = ctl.simulateSystem(connected_system, output_names=["step.out"], end_time=end_time)
8ctl.plotOneTS(ts, figsize=(5,5))
Sinusoid¶
makeSinusoid
is a factory that creates sinusoid signals and has the keyword arguments amplitude
, frequency
,
phase
, and dc_offset
(cosntant addition to the sinusoid).
Below is an example of creating a cosine.
factory = ctl.IOSystemFactory()
cosine = factory.makeSinusoid("cosine", amp=2, frequency=2, phase=np.pi/2)
Below is an example of creating an control.InterconnectedSystem
that consists only of a step function. Then, we plot the result.
1# Create an InterconnectedSystem
2connected_system = control.interconnect(
3[cosine], # systems
4outlist=["cosine.out"],
5)
6# Simulate the system and plot the result.
7ts = ctl.simulateSystem(connected_system, output_names=["cosine.out"])
8ctl.plotOneTS(ts, figsize=(5,5))
Arbitrary Signal¶
makeArbitrarySignal
is a factory that creates a signal specified in a user provided function.
It has the keyword argument signal_function
that specifies the function that defines the signal.
We illustrate this factory by creating an NonlinearIOSystem
object that generates a ramp.
The signal_function
is
# Make a unit ramp
def rampFunction(time):
return time
Creating the ramp generator is illustrated below.
factory = ctl.IOSystemFactory()
ramp = factory.makeArbitrarySignal("ramp", signal_function=rampFunction)
Here’s an example of constructing a system with ramp
and simulating the system.
1# Create an InterconnectedSystem
2connected_system = control.interconnect(
3[ramp], # systems
4outlist=["ramp.out"],
5)
6# Simulate the system and plot the result.
7ts = ctl.simulateSystem(connected_system, output_names=["ramp.out"])
8ctl.plotOneTS(ts, figsize=(5,5))
System generators¶
Systems are elements that transform signals.
NonlinearIOSystem
objects constructed by system factories have
one or more input and one or more output.
Elements with a single input and a single output use the names in
and out
.
PID controller¶
Proportional, integral, and differential (PID) control is widely used in control systems.
The factory makePIDController
has the keyword arguments
kp
, ki
, and kd
that correspond to the parameters of a
PID controller.
The default value of these arguments is 0 to facilitate making various combinations of
proportional, integral, and differential control.
Below is an example of construcing a proportional controller with a gain of 2.
A controller as the input in
and the output out
.
factory = ctl.IOSystemFactory()
controller = factory.makePIDController("controller", kp=2)
Below, we simulate this system and plot the results.
1# Create a ramp signal in the same factory
2ramp = factory.makeArbitrarySignal("ramp", signal_function=rampFunction)
3# Create an InterconnectedSystem
4connected_system = control.interconnect(
5[ramp, controller], # systems
6 connections=[
7 ['controller.in', 'ramp.out'],
8],
9outlist=["controller.out"],
10)
11# Simulate the system and plot the result.
12ts = ctl.simulateSystem(connected_system, output_names=["controller.out"])
13ctl.plotOneTS(ts, figsize=(5,5))
Filters¶
Filters are elements that remove undesirable charaacteristics of signals.
The factory method makeFilter
returns a NonlinearIOSystem
that implements a first order low pass filter,
a filter function likes a moving average.
Let the input to the filter is \(u(t)\) and the output be \(y(t)\). The filter is defined by the differential equation:
The filter has a DC gain of 1 so that it produces a correct average value.
The constant \(-a\) is the time constant of the filter.
Below is an example of filtering a sinusoidal input.
A filter has the input in
and the output out
.
factory = ctl.IOSystemFactory()
filter = factory.makeFilter("filter", 0.1)
1# Create a ramp signal in the same factory
2sine = factory.makeSinusoid("sine", amplitude=1, frequency= 10, dc_offset=5)
3# Create an InterconnectedSystem
4connected_system = control.interconnect(
5[sine, filter], # systems
6 connections=[
7 ['filter.in', 'sine.out'],
8],
9outlist=["filter.out", "sine.out"],
10)
11# Simulate the system and plot the result.
12ts = ctl.simulateSystem(connected_system, output_names=["filter.out", "sine.out"], end_time=10)
13ctl.plotOneTS(ts, figsize=(5,5), )
Adder¶
An adder inputs one or more signals and outputs their sum. A signal is subtracted if its name begins with a minus (-
).
The example below shows an adder that inputs a step, a sine, and the negative of a ramp.
1# Create a sum of a step and a sine minus a ramp
2step = factory.makeStep("step", step_size=1)
3sine = factory.makeSinusoid("sine", amplitude=1, frequency= 10)
4ramp = factory.makeArbitrarySignal("ramp", signal_function=lambda t: t) # Define Ramp with a lambda function
5#
6factory = ctl.IOSystemFactory()
7adder = factory.makeAdder("adder", input_names=["step_in", "sine_in", "-ramp_in"])
Below shows how the adder is used in an InterconnectedSystem``system and the simulation of that ``InterconnectedSystem
.
1# Create an InterconnectedSystem
2connected_system = control.interconnect(
3[step, sine, ramp, adder], # systems
4 connections=[
5 ['adder.step_in', 'step.out'],
6 ['adder.sine_in', 'sine.out'],
7 ['adder.ramp_in', 'ramp.out'],
8],
9outlist=["adder.out", "step.out", "sine.out", "ramp.out"],
10)
11# Simulate the system and plot the result.
12ts = ctl.simulateSystem(connected_system, output_names=["adder.out", "step.out", "sine.out", "ramp.out"], end_time=10)
13ctl.plotOneTS(ts, figsize=(5,5), )
Multiplier¶
A multiplier inputs one signal and outputs the product of this signal with a constant factor. This is illustrated below.
# Create a multiplier
factory = ctl.IOSystemFactory()
multiplier = factory.makeMultiplier("multiplier", factor=3)
Below shows how the multiplier is used in an InterconnectedSystem``system and the simulation of that ``InterconnectedSystem
.
1ramp = factory.makeArbitrarySignal("ramp", signal_function=lambda t: t) # Define Ramp with a lambda function
2# Create an InterconnectedSystem
3connected_system = control.interconnect(
4[ramp, multiplier], # systems
5 connections=[
6 ['multiplier.in', 'ramp.out'],
7],
8outlist=["multiplier.out", "ramp.out"],
9)
10# Simulate the system and plot the result.
11ts = ctl.simulateSystem(connected_system, output_names=["multiplier.out", "ramp.out"])
12ctl.plotOneTS(ts, figsize=(5,5), )
Passthru¶
Example (FINISH)¶
This section illustrates how to use the factory constructed elements. An important part of this is knowing the inputs and outputs defined for each.