Example 2
Description of the problem
Consider the synthetic continuous bilinear dynamical system given in its state-space form by
with
The procedure in Python using the package systemID is highlighted below, with \(N_1 = N_2 = 10\), a frequency of acquisition \(f = 20\) Hz for a total time of \(5\) seconds. As is the case for linear systems, the realized system matrices are not unique, because the state space description is not unique. However, the input/output mapping should be unique and the linear part of the identified system matrix should have the same eigenvalues as the true system matrix. The errors in the system matrix eigenvalues (between true and identified) are
The identified system was subject to some test inputs and the response from the true system to the same test inputs was performed. The test inputs applied to the plants are
Code using systemID
## Imports
import numpy as np
from scipy import interpolate
from systemID.ClassesGeneral.ClassSystem import ContinuousBilinearSystem
from systemID.ClassesGeneral.ClassSignal import ContinuousSignal, OutputSignal, DiscreteSignal, subtract2Signals
from systemID.ClassesGeneral.ClassExperiments import Experiments
from systemID.ClassesSystemID.ClassBilinear import BilinearSystemID
## Define continuous time system matrices and parameters
state_dimension = 3
input_dimension = 2
output_dimension = 2
def A(t):
return np.array([[0, 1, 0], [-1, 0, 0], [0, 0, 0.3]])
def N(t):
return np.array([[1, -1, 0, 0, 0, 1], [0, 2, 1, 1, 0, 1], [1, 3, 4, 4, 2, 1]])
def B(t):
return np.array([[1, 0], [0, 2], [1, 1]])
def C(t):
return np.array([[1, 0, 1], [-1, 1, 2]])
def D(t):
return np.array([[0, 0], [0, 0]])
## Identification parameters
p = 10
## Signal parameters
frequency = 20
dt = 1 /frequency
total_time_training = 6
total_time_testing = 5
number_steps_training = total_time_training * frequency + 1
number_steps_testing = total_time_testing * frequency + 1
tspan_training = np.linspace(0, total_time_training, number_steps_training)
tspan_testing = np.linspace(0, total_time_testing, number_steps_testing)
## Create system
x0 = np.zeros(state_dimension)
system = ContinuousBilinearSystem(state_dimension, input_dimension, output_dimension, [(x0, 0)], 'Nominal system', A, N, B, C, D)
## Test signal
def u(t):
return np.array([np.sin(7*t), np.cos(10*t)])
test_signal = ContinuousSignal(input_dimension, signal_shape='External', u=u)
test_signal_d = DiscreteSignal(input_dimension, total_time_testing, frequency, signal_shape='External', data=u(tspan_testing))
true_output = OutputSignal(test_signal, system, tspan=tspan_testing)
## Experiments
N1 = 10
data_inputs_1 = np.zeros([input_dimension, number_steps_training, N1])
data_inputs_1[:, 0, :] = np.random.randn(input_dimension, N1)
N2 = 10
data_inputs_2 = np.zeros([input_dimension, number_steps_training, N2, N2])
for i in range(N2):
random_input = data_inputs_1[:, 0, i]
data_inputs_2[:, 0, :, i] = data_inputs_1[:, 0, 0:N2]
data_inputs_2[:, 1, :, i] = np.outer(random_input, np.ones(N2))
inputs_1 = []
inputs_2 = []
systems = []
for i in range(N1):
inputs_1.append(ContinuousSignal(input_dimension, signal_shape='External', u=interpolate.interp1d(tspan_training, data_inputs_1[:, :, i], kind='zero')))
systems.append(system)
for i in range(N2):
inputs_2.append([])
for j in range(N2):
inputs_2[-1].append(ContinuousSignal(input_dimension, signal_shape='External', u=interpolate.interp1d(tspan_training, data_inputs_2[:, :, j, i], kind='zero')))
experiments_1 = Experiments(systems, inputs_1, tspan=tspan_testing, total_time=total_time_testing, frequency=frequency)
experiments_2 = []
for i in range(N2):
experiments_2.append(Experiments(systems[0:N2], inputs_2[i], tspan=tspan_testing, total_time=total_time_testing, frequency=frequency))
## Identification
bilinear = BilinearSystemID(experiments_1, experiments_2, state_dimension, dt, p=p)
## Identified system
x0_id = x0
identified_system = ContinuousBilinearSystem(state_dimension, input_dimension, output_dimension, [(x0_id, 0)], 'Identified system', bilinear.A, bilinear.N, bilinear.B, bilinear.C, bilinear.D)
## Test
identified_output = OutputSignal(test_signal, identified_system, tspan=tspan_testing)
Results
Output profiles obtained from the true and identified systems are compared below.
The singular value decomposition plot is displayed at different time instants.