How to manually simulate linear system without lsim
Mostra commenti meno recenti
I have a 3rd order continuous system of the following form identified with System Identification Toolbox:
y = Cx + Du + e
dx/dt = Ax + Bu + Ke
I can simulate it by using lsim as follows:
simulatedOutput = lsim(systemModel, inputVector, timeVector, initialStateVector)
Now I need to convert this model into code that uses only loops and simple matrix/vector arithmetic. I cannot use lsim, ODE, Runge-Kutta, or any other Matlab-specific solver or functions (I used only interp1 which is easy to convert into code).
I wrote a simple script that will read the same input file used to identify the model, but the output is completely wrong, and I cannot figure out why.
Fig. 1: output from lsim (expected)

Fig. 2: output from manual simulation (actual - code below)

The following is my attempt to simulate the identified system by using a Matlab script with only basic vector/matrix arithmetic and a loop:
% A weights (3x3 matrix)
A = [ ...
0.0356, -3.4131, -14.9525;
-1.0591, 85.8128, 334.3098;
1.5729, -95.1123, -175.5517;
];
% B weights (3x1 vector)
B = [ ...
-0.0019;
0.0403;
-0.0225;
];
% C weights (1x3 vector)
C = [ -5316.9, 24.87, 105.92 ];
% D weight (scalar)
D = 0;
% K weights (3x1 vector)
K = [ ...
-0.0025;
-0.0582;
0.0984;
];
% Initial state
x0 = [ ...
-0.0458;
0.0099;
-0.0139;
];
% Read input file
csv = readmatrix('https://raw.githubusercontent.com/01binary/systemid/main/input.csv');
% Select column vectors
time = csv(:,1);
measurement = csv(:,2);
input = csv(:,3);
% Simulate
x = x0;
timeStep = 0.02;
output = zeros(length(input), 1);
for i = 1:length(input)
t = time(1) + (i - 1) * timeStep;
u = interp1(time, input, t);
[y, dx] = systemModel(A, B, C, D, K, x, u, 0);
x = x + dx * timeStep;
output(i) = y;
end
% Plot against original measurements
plot(time, measurement, time, output);
function [y, dx] = systemModel(A, B, C, D, K, x, u, e)
% y = Cx + Du + e
y = ...
C * x + ... % Add contribution of state
D * u + ... % Add contribution of input
e; % Add disturbance
% dx/dt = Ax + Bu + Ke
dx = ...
A * x + ... % Add contribution of state
B * u + ... % Add contribution of input
e * K; % Add contribution of disturbance
end
I am trying to keep everything really simple and minimal... could someone spot what I am missing?
Thank you!
Risposta accettata
Più risposte (1)
Hi @Valeriy
Other than lsim, you have two options for solving the differential equations: you can use the built-in ODE solver or a custom numerical solver like Runge-Kutta 4. Below, you can find a comparison of results between the lsim command and the ode45 solver.
%% data extraction
csv = readmatrix('input.csv');
time = csv(:,1);
measurement = csv(:,2);
input = csv(:,3);
%% data processing (lsim requires evenly-spaced input signal)
ta = time(1);
tb = time(end);
tspan = linspace(ta, tb, (tb-ta)/0.01 + 1);
u = interp1(time, input, tspan);
%% state-space system
A = [0.0356, -3.4131, -14.9525;
-1.0591, 85.8128, 334.3098;
1.5729, -95.1123, -175.5517];
B = [-0.0019;
0.0403;
-0.0225];
C = [-5316.9, 24.87, 105.92];
D = 0;
% x'= A·x + B·u
% y = C·x + D·u
sys = ss(A, B, C, D);
%% initial values
x0 = [-0.0458;
0.0099;
-0.0139];
Approach #1: Run simulation using 'lsim()' command
%% response of state-space system via lsim
lsim(sys, u, tspan, x0), grid on
Approach #2: Run simulation using 'ode45()' solver
%% call ode45 solver
options = odeset('Reltol', 1e-9, 'Abstol', 1e-6);
[t, x] = ode45(@(t, x) odesys(t, x, A, B, C, D, time, input), tspan, x0, options);
[~, y] = odesys(t', x', A, B, C, D, time, input);
plot(t, y), grid on, xlim([0 round(tb)])
xlabel('t'), ylabel('y(t)'), title('ode45 Simulation Results')
%% Identified State-Space System
function [dx, y] = odesys(t, x, A, B, C, D, time, input)
u = interp1(time, input, t);
y = C*x + D*u(:,1);
dx = A*x + B*u(:,1);
end
3 Commenti
Sam Chak
il 28 Apr 2024
Hi @Valeriy
I'm glad to hear that you have resolved the problem. Initially, I misunderstood your intention and thought you wanted to replicate the response of the continuous-time system generated by lsim. That's why I suggested using a custom-designed numerical algorithm, which doesn't necessarily have to be RK4.
Previously, I was unaware that this is a homework exercise aimed at testing a specific time integration method for solving the initial value problem of the identified state-space system. By the way, you mentioned that the Runge-Kutta method is not allowed, but it's worth noting that the standard Euler method is generally considered as a 1st-order Runge-Kutta method.
Valeriy
il 28 Apr 2024
Categorie
Scopri di più su State-Space Control Design and Estimation in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!








