Hide minor edits - Show changes to markup
The delta-u formulation \Delta u(k) = u(k) - u(k-1)
is activated with the "deltaPenalty" filter
The delta-u formulation {$ \Delta u_k = u_k - u_{k-1} $} is activated with the "deltaPenalty" filter
Note that the partition of the explicit controller is defined in dimension three because the parametric variable is the current state {$x_k$}, the previous value of the input {$u_{k-1}$}, and the reference signal {$ r_k $}. This can be verified by plotting the partition of the controller
(:source lang=MATLAB -getcode:)ectrl.partition.plot()
and a closed form is created with the help of ClosedLoop
object:
and can be plotted with the help of fplot
function
ectrl.feedback.fplot()
In the next step, the explicit controller is employed in the closed loop object
Simulate the performance of the explicit controller in 20 samples and plot the closed loop trajectories
Simulate the performance of the explicit controller in 20 samples
subplot(2, 1, 1); plot(1:Nsim, data.X(1:Nsim)); title('state') subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
The tracking of a time-varying reference can be achieved by augmenting the state with an integrator state that predicts the steady state values. In MPT this can be achieved with the help of "integrator" filter that extends the model with an integrator state. Consider the unstable LTI system as in the previous example that operates under input and state constraints
and plot the closed loop trajectories
model = LTISystem('A', 1.5 , 'B', 1 ); model.x.min = -10; model.x.max = 10; model.u.min = -5; model.u.max = 5;
subplot(2, 1, 1); hold on; plot(1:Nsim, data.X(1:Nsim), 'linewidth', 2 ); plot(1:Nsim, model.x.max*ones(1,Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.x.min*ones(1,Nsim), 'k--', 'linewidth', 2); stairs(1:Nsim, xref, 'r--', 'linewidth', 2); axis([1, Nsim, -11, 11]); title('state') subplot(2, 1, 2); hold on; stairs(1:Nsim, data.U, 'linewidth', 2); plot(1:Nsim, model.u.max*ones(1, Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.u.min*ones(1, Nsim), 'k--', 'linewidth', 2); axis([1, Nsim, -6, 6]); title('input')
Activate the time-varying reference
The tracking of a time-varying reference can be achieved by augmenting the state with an integrator state that predicts the steady state values. In MPT this can be achieved with the help of "integrator" filter that extends the model with an integrator state. Consider the unstable LTI system as in the previous example that operates under input and state constraints
model.x.with('reference'); model.x.reference = 'free';
model = LTISystem('A', 1.5 , 'B', 1 ); model.x.min = -10; model.x.max = 10; model.u.min = -5; model.u.max = 5;
To add the integrator, one need to active the "integrator" filter as follows.
Activate the time-varying reference
model.with('integrator');
model.x.with('reference'); model.x.reference = 'free';
In the remainder of MPC set, the penalty on the predicted difference of the integrator state and the reference is provided
To add the integrator, one need to active the "integrator" filter as follows.
model.x.penalty = QuadFunction( 5 );
model.with('integrator');
as well as the penalty on the inputs
In the remainder of MPC set, the penalty on the predicted difference of the integrator state and the reference is provided
model.u.penalty = QuadFunction( 1 );
model.x.penalty = QuadFunction( 5 );
The resulting controller is exported to an explicit form
as well as the penalty on the inputs
ctrl = MPCController(model, 4); ectrl = ctrl.toExplicit();
model.u.penalty = QuadFunction( 1 );
and a closed form is created with the help of ClosedLoop
object:
The resulting controller is exported to an explicit form
loop = ClosedLoop( ectrl, model);
ctrl = MPCController(model, 4); ectrl = ctrl.toExplicit();
The simulation results are the same as in the previous example, but this time obtained with the integrator state
and a closed form is created with the help of ClosedLoop
object:
loop = ClosedLoop( ectrl, model); @] The simulation results are the same as in the previous example, but this time obtained with the integrator state (:source lang=MATLAB -getcode:) [@
subplot(2, 1, 1); plot(1:Nsim, data.X(1:Nsim) ); title('state') subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
The simulated data can be plotted together with the reference signal and constraints
(:source lang=MATLAB -getcode:)subplot(2, 1, 1); hold on; plot(1:Nsim, data.X(1:Nsim), 'linewidth', 2 ); plot(1:Nsim, model.x.max*ones(1,Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.x.min*ones(1,Nsim), 'k--', 'linewidth', 2); stairs(1:Nsim, xref, 'r--', 'linewidth', 2); axis([1, Nsim, -11, 11]); title('state') subplot(2, 1, 2); hold on; stairs(1:Nsim, data.U, 'linewidth', 2); plot(1:Nsim, model.u.max*ones(1, Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.u.min*ones(1, Nsim), 'k--', 'linewidth', 2); axis([1, Nsim, -6, 6]); title('input')
subplot(2, 1, 2); plot(1:30, data.U, 'linewidth', 2);
subplot(2, 1, 2); plot(1:Nsim, data.U, 'linewidth', 2);
subplot(2, 1, 1); plot(1:31, data.X); title('states') subplot(2, 1, 2); plot(1:30, data.U); title('inputs')
subplot(2, 1, 1); hold on; grid on; plot(1:Nsim, data.X(:,1:Nsim), 'linewidth', 2); stairs(1:Nsim, xref(2,:), 'k--', 'linewidth', 2); axis([1, Nsim, -3, 4]); title('states') subplot(2, 1, 2); hold on; grid on; plot(1:Nsim, data.U, 'linewidth', 2); axis([1, Nsim, -1, 1]); title('inputs')
subplot(2, 1, 1); plot(1:31, data.X); title('states') subplot(2, 1, 2); plot(1:30, data.U); title('inputs')
@] The results of the simulation can be plotted nicely (:source lang=MATLAB -getcode:) [@ subplot(2, 1, 1); plot(1:Nsim, data.X(:,1:Nsim), 'linewidth', 2); axis([1, Nsim, -2, 2]); grid on; title('states'); subplot(2, 1, 2); plot(1:30, data.U, 'linewidth', 2); axis([1, Nsim, -1, 1]); grid on; title('inputs');
subplot(2, 1, 1); plot(1:Nsim, data.Y); title('output') subplot(2, 1, 2); stairs(1:Nsim, data.U); title('input')
subplot(2, 1, 1); plot(1:Nsim, data.Y, 'linewidth', 2); hold on; grid on; plot(1:Nsim, model.y.max*ones(1, Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.y.min*ones(1, Nsim), 'k--', 'linewidth', 2); stairs(1:Nsim, yref, 'r--', 'linewidth', 2); axis([1, Nsim, -12, 12]); title('output') subplot(2, 1, 2); stairs(1:Nsim, data.U, 'linewidth', 2); hold on; grid on; plot(1:Nsim, model.u.max*ones(1, Nsim), 'k--', 'linewidth', 2); plot(1:Nsim, model.u.min*ones(1, Nsim), 'k--', 'linewidth', 2); axis([1, Nsim, -4, 4]); title('input')
The closed-loop simulation can be evaluated using the ClosedLoop
object
and plot the partition
loop = ClosedLoop(ectrl, model);
ectrl.partition.plot()
by providing the time varying reference signal yref
The closed-loop simulation can be evaluated using the ClosedLoop
object
loop = ClosedLoop(ectrl, model);
@]
by providing the time varying reference signal yref
(:source lang=MATLAB -getcode:) [@
subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
subplot(2, 1, 2); stairs(1:Nsim, data.U); title('input')
subplot(2, 1, 2); plot(1:40, U); title('input')
subplot(2, 1, 2); stairs(1:40, U); title('input')
u = 0;
u0 = 0;
xref = [repmat( xref1, 1, 10), repmat(xref2, 1, 10)];
data = loop.simulate(x0, Nsim, 'u.previous', u, 'x.reference', xref);
xref = [repmat( xref1, 1, Nsim/2), repmat(xref2, 1, Nsim/2)]; data = loop.simulate(x0, Nsim, 'u.previous', u0, 'x.reference', xref);
The simulation results are the same as in the previous example, but this time obtained with the integrator state
and a closed form is created with the help of ClosedLoop
object:
x0 = 0; u = 0; X = []; U = []; model.initialize( x0 ); for i=1:20
if i<10 xref = 5; else xref = -3; end X = [X, x0]; u = ectrl.evaluate(x0, 'u.previous', u, 'x.reference', xref); U = [U, u]; x0 = model.update(u);
end subplot(2, 1, 1); plot(1:20, X); title('state') subplot(2, 1, 2); plot(1:20, U); title('inputs')
loop = ClosedLoop( ectrl, model);
The simulation results are the same as in the previous example, but this time obtained with the integrator state
(:source lang=MATLAB -getcode:)x0 = 0; u0 = 0; xref1 = 5; xref2 = -3; Nsim = 20; xref = [repmat( xref1, 1, Nsim/2), repmat(xref2, 1, Nsim/2)]; data = loop.simulate(x0, Nsim, 'u.previous', u0, 'x.reference', xref); subplot(2, 1, 1); plot(1:Nsim, data.X(1:Nsim) ); title('state') subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
Simulate the performance of the explicit controller in 20 samples
For simulation purposes, the ClosedLoop
object is created with the explicit controller and the same model that was used for MPC design
x0 = 0;
loop = ClosedLoop( ectrl, model); @] Simulate the performance of the explicit controller in 20 samples and plot the closed loop trajectories (:source lang=MATLAB -getcode:) [@ x0 = 0;
X = []; U = []; model.initialize(x0); for i=1:20
if i<10 xref = 5; else xref = -3; end X = [X, x0]; u = ectrl.evaluate(x0, 'u.previous', u, 'x.reference', xref); U = [U, u]; x0 = model.update(u);
end subplot(2, 1, 1); plot(1:20, X); title('state') subplot(2, 1, 2); plot(1:20, U); title('inputs')
xref1 = 5; xref2 = -3; xref = [repmat( xref1, 1, 10), repmat(xref2, 1, 10)]; Nsim = 20; data = loop.simulate(x0, Nsim, 'u.previous', u, 'x.reference', xref); subplot(2, 1, 1); plot(1:Nsim, data.X(1:Nsim)); title('state') subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
subplot(2, 1, 2); plot(1:Nsim, data.U); title('inputs')
subplot(2, 1, 2); plot(1:Nsim, data.U); title('input')
subplot(2, 1, 2); plot(1:40, U); title('inputs')
subplot(2, 1, 2); plot(1:40, U); title('input')
The following simulation shows step-wise changes in the output reference over 30 samples that is obtained by evaluating the explicit controller
The closed-loop simulation can be evaluated using the ClosedLoop
object
loop = ClosedLoop(ectrl, model);
by providing the time varying reference signal yref
yref1 = 1; yref2 = -2; yref = [repmat(yref1, 1, 20), repmat(yref2, 1, 20)]; x0 = zeros(2,1); Nsim = 40; data = loop.simulate(x0, Nsim, 'y.reference', yref);
The simulation results are stored in the output variable data
and can be plotted
subplot(2, 1, 1); plot(1:Nsim, data.Y); title('output') subplot(2, 1, 2); plot(1:Nsim, data.U); title('inputs')
In the next code sample you can find the manual decomposition of the simulation which shows the step-wise changes in the output reference over 30 samples and the input is obtained by evaluating the explicit controller
model.y.penalty = OneNormFunction(3); model.u.penalty = OneNormFunction(0.5);
model.y.penalty = OneNormFunction( 3 ); model.u.penalty = OneNormFunction( 0.5 );
ctrl = MPCController(model, 3)
ctrl = MPCController(model, 3);
subplot(2,1,1); plot(1:40,Y); title('output') subplot(2,1,2); plot(1:40,U); title('inputs')
subplot(2, 1, 1); plot(1:40, Y); title('output') subplot(2, 1, 2); plot(1:40, U); title('inputs')
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
subplot(2, 1, 1); plot(1:20, X); title('state') subplot(2, 1, 2); plot(1:20, U); title('inputs')
model.initialize(x0);
model.initialize( x0 );
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
subplot(2, 1, 1); plot(1:20, X); title('state') subplot(2, 1, 2); plot(1:20, U); title('inputs')
subplot(2,1,1); plot(1:40,Y); title('output') subplot(2,1,2); plot(1:40,U); title('inputs')
subplot(2,1,1); plot(1:40,Y); title('output') subplot(2,1,2); plot(1:40,U); title('inputs')
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
ectrl = ctrl.toExplicit;
ectrl = ctrl.toExplicit();
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
model.x.penalty = OneNormFunction(diag([0.5, 1, 0]) ); model.u.penalty = OneNormFunction(eye(2));
model.x.penalty = OneNormFunction( diag([0.5, 1, 0]) ); model.u.penalty = OneNormFunction( eye(2) );
cl = ClosedLoop(ctrl,model);
loop = ClosedLoop(ctrl, model);
data = cl.simulate(x0, Nsim, 'x.reference', xref)
data = loop.simulate(x0, Nsim, 'x.reference', xref)
data = cl.simulate(x0, Nsim, 'x.reference', xref);
data = loop.simulate(x0, Nsim, 'x.reference', xref);
subplot(2,1,1); plot(1:30,X); title('states') subplot(2,1,2); plot(1:30,U); title('inputs')
subplot(2,1,1); plot(1:30,X); title('states') subplot(2,1,2); plot(1:30,U); title('inputs')
subplot(2,1,2); plot(1:30, data.U); title('inputs')
subplot(2, 1, 2); plot(1:30, data.U); title('inputs')
subplot(2,1,1); plot(1:31, data.X); title('states') subplot(2,1,2); plot(1:30, data.U); title('inputs')
subplot(2, 1, 1); plot(1:31, data.X); title('states') subplot(2, 1, 2); plot(1:30, data.U); title('inputs')
model.u.min = [-2;-3];
model.u.min = [-2; -3];
d = cl.simulate(x0, Nsim, 'x.reference', xref) subplot(2,1,1); plot(1:31,d.X); title('states') subplot(2,1,2); plot(1:30,d.U); title('inputs')
data = cl.simulate(x0, Nsim, 'x.reference', xref) subplot(2, 1, 1); plot(1:31, data.X); title('states') subplot(2,1,2); plot(1:30, data.U); title('inputs')
d = cl.simulate(x0, Nsim, 'x.reference', xref); subplot(2,1,1); plot(1:31,d.X); title('states') subplot(2,1,2); plot(1:30,d.U); title('inputs')
data = cl.simulate(x0, Nsim, 'x.reference', xref); subplot(2,1,1); plot(1:31, data.X); title('states') subplot(2,1,2); plot(1:30, data.U); title('inputs')
d = cl.simulate(zeros(3,1),30,'x.reference',[0; 1; 0])
x0 = [0; 0; 0]; Nsim = 30; xref = [0; 1; 0]; d = cl.simulate(x0, Nsim, 'x.reference', xref)
For a time-varying referece, the simulation is decomposed into a for-loop and the reference is changing step-wise after 10 samples
The simulate
method also allows to provide time-varying profiles of references, e.g.
xref1 = [0; 1; 0]; xref2 = [0; 2; 0]; xref3 = [0; 3; 0]; xref = [repmat(xref1, 1, 10), repmat(xref2, 1, 10), repmat(xref3, 1, 10)]; x0 = [0; 0; 0]; Nsim = 30; d = cl.simulate(x0, Nsim, 'x.reference', xref); subplot(2,1,1); plot(1:31,d.X); title('states') subplot(2,1,2); plot(1:30,d.U); title('inputs') @] The same result can be obtained manually using a for-loop as follows: (:source lang=MATLAB -getcode:) [@
yref = [0; 1; 0];
xref = [0; 1; 0];
yref = [0; 2; 0];
xref = [0; 2; 0];
yref = [0; 3; 0];
xref = [0; 3; 0];
u = ctrl.evaluate(x0, 'x.reference', yref);
u = ctrl.evaluate(x0, 'x.reference', xref);
ectrl = ctrl.toExplicit;
ectrl = ctrl.toExplicit();
ectrl = ctrl.toExplicit;
ectrl = ctrl.toExplicit();
The tracking of a time-varying reference can be achieved by augmenting the state with an integrator state that predicts the steady state values. In MPT this can be achieved with the help of "integrator" filter that extends the model with an integrator state. Consider the unstable LTI system as in the previous example that operates under input and state constraints
(:source lang=MATLAB -getcode:)model = LTISystem('A', 1.5 , 'B', 1 ); model.x.min = -10; model.x.max = 10; model.u.min = -5; model.u.max = 5;
Activate the time-varying reference
(:source lang=MATLAB -getcode:)model.x.with('reference'); model.x.reference = 'free';
To add the integrator, one need to active the "integrator" filter as follows.
(:source lang=MATLAB -getcode:)model.with('integrator');
In the remainder of MPC set, the penalty on the predicted difference of the integrator state and the reference is provided
(:source lang=MATLAB -getcode:)model.x.penalty = QuadFunction( 5 );
as well as the penalty on the inputs
(:source lang=MATLAB -getcode:)model.u.penalty = QuadFunction( 1 );
The resulting controller is exported to an explicit form
(:source lang=MATLAB -getcode:)ctrl = MPCController(model, 4); ectrl = ctrl.toExplicit;
The simulation results are the same as in the previous example, but this time obtained with the integrator state
(:source lang=MATLAB -getcode:)x0 = 0; u = 0; X = []; U = []; model.initialize(x0); for i=1:20 if i<10 xref = 5; else xref = -3; end X = [X, x0]; u = ectrl.evaluate(x0, 'u.previous', u, 'x.reference', xref); U = [U, u]; x0 = model.update(u); end subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
Consider the following unstable LTI system subject to input and state constraints
(:source lang=MATLAB -getcode:)model = LTISystem('A', 1.5 , 'B', 1); model.x.min = -10; model.x.max = 10; model.u.min = -5; model.u.max = 5;
The objective is to follow a time-varying state signal subject to delta-u formulation. The activation of the time-varying signal is achived via "reference" filter
(:source lang=MATLAB -getcode:)model.x.with('reference'); model.x.reference = 'free'; model.x.penalty = QuadFunction(5);
The delta-u formulation \Delta u(k) = u(k) - u(k-1)
is activated with the "deltaPenalty" filter
model.u.with('deltaPenalty'); model.u.deltaPenalty = QuadFunction(1);
The online MPCController
object is created with a horizon 4 and exported to an explicit form
ctrl = MPCController(model, 4); ectrl = ctrl.toExplicit;
Simulate the performance of the explicit controller in 20 samples
(:source lang=MATLAB -getcode:)x0 = 0; u = 0; X = []; U = []; model.initialize(x0); for i=1:20 if i<10 xref = 5; else xref = -3; end X = [X, x0]; u = ectrl.evaluate(x0, 'u.previous', u, 'x.reference', xref); U = [U, u]; x0 = model.update(u); end subplot(2,1,1); plot(1:20,X); title('state') subplot(2,1,2); plot(1:20,U); title('inputs')
Consider a simple PWA system that comprises of two modes and has one output
(:source lang=MATLAB -getcode:)mode1 = LTISystem('A', [ 0.4 0.69; -0.69 0.4], 'B', [0;1], 'C', [1, 0]); mode1.setDomain('x', Polyhedron('A', [1 0], 'b', 0) ); mode2 = LTISystem('A', [ 0.4 -0.69; 0.69 0.4], 'B', [0;1], 'C', [1, 0]); mode2.setDomain('x', Polyhedron('A', [-1 0], 'b', 0) ); model = PWASystem([mode1, mode2]);
The model is subject to input/output constraints
(:source lang=MATLAB -getcode:)model.u.min = -3; model.u.max = 3; model.y.min = -10; model.y.max = 10;
The objective is to track the time varying output while satisfying the constraints. To incorporate a time varying signal one needs to active the appropriate reference filter and mark it as "free"
(:source lang=MATLAB -getcode:)model.y.with('reference'); model.y.reference = 'free';
To finalize the MPC setup, penalty on inputs and outputs are provided
(:source lang=MATLAB -getcode:)model.y.penalty = OneNormFunction(3); model.u.penalty = OneNormFunction(0.5);
and the online MPCController
object is constructed with horizon 3
ctrl = MPCController(model, 3)
After testing the performance of the online-controller, one can export it to the explicit form as follows:
(:source lang=MATLAB -getcode:)ectrl = ctrl.toExplicit;
The following simulation shows step-wise changes in the output reference over 30 samples that is obtained by evaluating the explicit controller
(:source lang=MATLAB -getcode:)x0 = zeros(2,1); Y = []; U = []; model.initialize(x0); for i=1:40 if i<20 yref = 1; else yref = -2; end u = ectrl.evaluate(x0, 'y.reference', yref); U = [U, u]; [x0, y] = model.update(u); Y = [Y, y]; end subplot(2,1,1); plot(1:40,Y); title('output') subplot(2,1,2); plot(1:40,U); title('inputs')
Consider an LTI system with 3 states and 2 inputs subject to state and input constraints
(:source lang=MATLAB -getcode:)model = LTISystem('A', [ -0.79 -0.3 -0.1; 0.5 0.82 1.23; 0.52 -0.3 -0.5], 'B', [ -2.04 -0.21; -1.28 2.75; 0.29 -1.41]); model.x.min = [-10; -9; -8]; model.x.max = [10; 9; 8]; model.u.min = [-2;-3]; model.u.max = [2; 3];
The objective is to track the second state that varies in time. To provide a time-varying reference the reference
filter is activated on the state signal and the value is set to "free", indicating a time-varying reference.
model.x.with('reference'); model.x.reference = 'free';
In the remainder of the MPC setup, the penalties on the states and inputs are provided.
(:source lang=MATLAB -getcode:)model.x.penalty = OneNormFunction(diag([0.5, 1, 0]) ); model.u.penalty = OneNormFunction(eye(2));
and the online MPCController
object is constructed with horizon 4:
ctrl = MPCController(model, 4)
For simulation purposes, a closed loop object is constructed and simulated for a constant reference value [0; 1; 0] over 30 samples
(:source lang=MATLAB -getcode:)cl = ClosedLoop(ctrl,model); d = cl.simulate(zeros(3,1),30,'x.reference',[0; 1; 0]) subplot(2,1,1); plot(1:31,d.X); title('states') subplot(2,1,2); plot(1:30,d.U); title('inputs')
For a time-varying referece, the simulation is decomposed into a for-loop and the reference is changing step-wise after 10 samples
(:source lang=MATLAB -getcode:)x0 = zeros(3,1); X = []; U = []; model.initialize(x0); for i=1:30 X = [X, x0]; if i<10 yref = [0; 1; 0]; elseif i<20 yref = [0; 2; 0]; else yref = [0; 3; 0]; end u = ctrl.evaluate(x0, 'x.reference', yref); U = [U, u]; x0 = model.update(u); end subplot(2,1,1); plot(1:30,X); title('states') subplot(2,1,2); plot(1:30,U); title('inputs')
Back to MPC synthesis overview.