How to manually simulate linear system without lsim
Show older comments
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!
Accepted Answer
More Answers (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 Comments
Sam Chak
on 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
on 28 Apr 2024
Categories
Find more on Dynamic System Models in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!







