# SECOND_ORDER_SYSTEM

This block has a 2nd order exponential function and is designed to be used in a LOOP with an APPEND block. Inputs ------ default : Scalar PID node output. Params: d1 : float The first time constant. d2 : float The second time constant. Returns: out : Scalar The most recent value of the second order function.
Python Code
from numpy import exp, ndarray, insert, zeros
from flojoy import flojoy, OrderedPair, DefaultParams, SmallMemory, Vector, Scalar

memory_key = "SECOND_ORDER_SYSTEM"

def SECOND_ORDER_SYSTEM(
default: OrderedPair | Vector | Scalar,
default_params: DefaultParams,
d1: float = 250,
d2: float = 100,
) -> OrderedPair:
"""This block has a 2nd order exponential function and is designed to be used in a LOOP with an APPEND block.

Inputs
------
default : Scalar
PID node output.

Parameters
----------
d1 : float
The first time constant.
d2 : float
The second time constant.
Returns
-------
Scalar
The most recent value of the second order function.
"""

# Let's first define things that won't change over
# each iteration: time constants, etc ...
def_key = default.c

node_id = default_params.node_id

# ... and now some helper functions
x1 = exp(-1.0 / d1) if d1 > 0 else 0.0
x2 = exp(-1.0 / d2) if d2 > 0 else 0.0
ac = (1.0 - x1) * (1.0 - x2)
bpd = x1 + x2
bd = x1 * x2

# Now we require memory. The only thing we need in memory is the last two
# values the system had in this basic example.
if data is None:
initialize = True
elif type(data) == ndarray:
initialize = False
else:

# We're going to store and read the data in reverse order to
# how it is accessed here. We will write the functionality
# below to assume the most recent time step is the first
# index. However, for visualization and external access,
# it makes the most sense to have the first time step
# as the first index!
y_primes = zeros((2, 1)) if initialize else data[::-1]

# Using input from controller as v.y ...
response = ac * def_key + bpd * y_primes - bd * y_primes
y_primes = y_primes

# prepend the most recent result to the front of the histrory
y_primes = insert(y_primes, 0, response)
# We now write to memory, reversing the order ...
SmallMemory().write_to_memory(node_id, memory_key, y_primes[::-1])
# ... and return the result!
return Scalar(float(y_primes))  # returns input output pair


Find this Flojoy Block on GitHub

## Example

This example demonstrates an active PID controller for a mock non-linear system to be driven to a given setpoint using SECOND_ORDER_SYSTEM node.