function [y,u,t,p,UU,t_open,t_ppp,t_est,its_ppp,its_est] = ppp_nlin_run(system_name,i_ppp,i_par,A_u,w_s,N_ol,Q,extras)
## usage: [y,u,t,p,U,t_open,t_ppp,t_est,its_ppp,its_est] =
## ppp_nlin_run (system_name,i_ppp,i_par,A_u,w_s,N_ol[,extras])
##
## y,u,t System output, input and corresponding time p
## Estimated parameters U PPP weight vector t_open The
## open-loop interval t_ppp Time for each ppp optimisation t_est
## Time for each estimation i_ppp Matrix of ppp gain indices: col.
## 1 Gain indices in sensitivity system col. 2 Gain sensitivity
## indices in sensitivity system col. 3 Gain indices in system
## i_par Matrix of indices of estimated parameters col. 1 Parameter
## indices in sensitivity system col. 2 Parameter sensitivity
## indices in sensitivity system col. 3 Parameter indices in system
## A_u Basis function generating matrix w_s w_star: That part
## of the moving horizon setpoint within the optimisation horizon.
## N_ol The number of open-loop intervals to be computed extras
## Extra parameters in a structure: extras.alpha ??
## extras.criterion Optimisation convergence criterion
## extras.emulate_timing Simulate some real-time features
## extras.estimate Estimate parameters and states
## extras.max_iterations Maximum optimisation iterations
## extras.simulate 1 for simulation (not real-time) extras.vInitial Levenberg-Marquardt parameter
## extras.verbose 1 for extra info display
##
## Real-time implementatipn of nonlinear PPP Copyright (C) 2001,2002
## by Peter J. Gawthrop
## Globals to pass details to simulation
global system_name_sim i_ppp_sim x_0_sim y_sim u_sim A_u_sim simpar_sim
## Defaults
if nargin<8
extras.alpha = 0.1;
extras.criterion = 1e-5;
extras.emulate_timing = 0;
extras.max_iterations = 10;
extras.simulate = 1;
extras.v = 1e-5;
extras.verbose = 0;
extras.visual = 0;
endif
##Estimate if we have some adjustable parameters
estimating_parameters = (length(i_par)>0);
## Names
s_system_name = sprintf("s%s", system_name);
## System details -- defines simulation within ol interval
par = eval(sprintf("%s_numpar;", system_name));
simpar = eval(sprintf("%s_simpar;", system_name));
dt = simpar.dt; # Sample interval
simpar_est = simpar; # Initial estimation simulation params
simpar_model = simpar; # Initial internal model simulation params
simpar_pred = simpar; # Initial prediction simulation params
T_ol_0 = simpar.last; # The initial specified interval
n_t = round(simpar.last/simpar.dt); # Corresponding length
x_0 = eval(sprintf("%s_state(par);", system_name));
x_0_model = x_0;
[n_x,n_y,n_u] = eval(sprintf("%s_def;", system_name));
if nargin<8
Q = ones(n_y,1);
endif
## Sensitivity system details -- defines moving horizon simulation
simpars = eval(sprintf("%s_simpar;", s_system_name));
pars = eval(sprintf("%s_numpar;", s_system_name));
x_0s = eval(sprintf("%s_state(pars);", s_system_name));
x_0_models = x_0s;
## Times
## -- within opt horizon
n_Tau = round(simpars.last/simpars.dt);
dtau = simpars.dt;
Tau = [0:n_Tau-1]'*dtau;
[n_tau,n_w] = size(w_s);
tau = Tau(n_Tau-n_tau+1:n_Tau);
w = w_s(n_tau,:); # Final value of setpoint
## Main simulation loop
y = [];
x = [];
u = [];
t = [];
p = [];
t_last = 0;
UU = [];
UU_l =[];
UU_c =[];
t_ppp = [];
t_est = [];
its_ppp = [];
its_est = [];
t_open = [];
x_nexts = zeros(2*n_x,1);
## Initial U is zero
[n_U,junk] = size(A_u);
U = zeros(n_U,1);
## Create input basis functions
u_star_tau = ppp_ustar(A_u,1,Tau',0,0,n_u-n_U);
## Reverse time to get "previous" U
U_old = U;
if (extras.simulate==1)
## Set up globals for simulation
system_name_sim = system_name;
i_ppp_sim = i_ppp;
x_0_sim = x_0;
y_sim = []; # Junk
u_sim = []; # Junk
A_u_sim = A_u;
simpar_sim = simpar;
T_total = simpar.last;
endif
for i = 0:N_ol # Main loop
printf("%i",i);
if (extras.simulate==1)
[y_ol,u_ol] = ppp_RT_sim(U); # Simulate
else
[y_ol,u_ol] = ppp_RT(U); # Real thing
endif
t_start = time; # Initialise time
if (i==0) # Data is rubbish at i=0 - ignore
usleep(T_ol_0*1e6); # Hang about
else
## Set up time information for the gathered data
n_ol = length(y_ol); # How many data points?
t_ol = [0:n_ol-1]'*dt;
T_ol = n_ol*dt; # Length of ol interval
t_open = [t_open;T_ol];
## Generate input to actual system
u_star_t = ppp_ustar(A_u,1,t_ol',0,0,n_u-n_U);
## Tune parameters/states
if (estimating_parameters==1)
## Save up the estimated parameters
par_est = pars(i_par(:,1));
p = [p; par_est'];
## Set up according to interval length
if (T_ol>T_ol_0) ## Truncate data
simpar_est.last = T_ol_0;
y_est = y_ol(1:n_t+1,:);
else
simpar_est.last = T_ol;
y_est = y_ol;
endif
simpar_pred.last = T_ol_0; # Predicted length of next interval
pars(i_ppp(:,1)) = U_old; # Update the simulation ppp weights
## Optimise
tick = time;
[pars,Par,Error,Y,its] = \
ppp_optimise(s_system_name,x_0_models,pars,simpar_est,u_star_t,y_est,i_par,extras);
if extras.visual
figure(11);
title("Parameter optimisation");
II = [1:length(y_est)]; plot(II,y_est,"*", II,Y);
endif
est_time = time-tick;
t_est = [t_est;est_time];
its_est = [its_est; its-1];
endif
## Update internal model
par(i_ppp(:,3)) = U_old; # Update the internal model ppp weights
if (estimating_parameters==1)
par(i_par(:,3)) = pars(i_par(:,1)); # Update the internal model params
endif
simpar_model.last = T_ol;
[y_model,x_model] = eval(sprintf("%s_sim(x_0_model, par, simpar_model, \
u_star_t);",system_name));
x_0 = x_model(n_ol+1,:)'; # Initial state of next interval
## x_0 = x_model(n_ol-1,:)'; # Initial state of next interval
x_0_model = x_0;
x_0_models(1:2:(2*n_x)-1) = x_0_model;
## Compute U by optimisation
tick = time;
## Predict state at start of next interval
par(i_ppp(:,3)) = U;
[y_next,x_next] = eval(sprintf("%s_sim(x_0, par, simpar, \
u_star_t);",system_name));
x_next = x_next(n_t+1,:)'; # Initial state for next time
x_nexts(1:2:(2*n_x)-1) = x_next; # And for internal sensitivity model
## Optimize for next interval
U_old = U; # Save previous value
U = expm(A_u*T_ol)*U; # Initialise from continuation trajectory
pars(i_ppp(:,1)) = U; # Put initial value of U into the parameter vector
[U, U_all, Error, Y, its] = ppp_nlin(system_name,x_nexts,pars,simpars,u_star_tau,w_s,i_ppp,Q,extras);
if extras.visual
figure(12);
title("PPP optimisation");
II = [1:length(w_s)]; plot(II,w_s,"*", II,Y);
figure(1);
endif
ppp_time = time-tick;
t_ppp = [t_ppp;ppp_time];
its_ppp = [its_ppp; its-1];
## Total execution time
T_total = time - t_start;
if (extras.simulate==1)&&(extras.emulate_timing!=1)
printf(".");
T_diff = 0; # Always correct interval
else
T_diff = T_total - T_ol_0; # Compute difference
if T_diff<0
printf("-");
usleep(-T_diff*1e6);
T_total = time - t_start;
else
printf("+");
endif
printf("%2.2f",T_total);
endif
T_total = simpar.dt*round(T_total/simpar.dt); # Whole no. of intervals
pars(i_ppp(:,1)) = U; # Put final value of U into the parameter vector
## Save up data
y_ol = y_ol(1:n_ol,:);
y = [y; y_ol];
u = [u; u_ol];
UU = [UU; U'];
t = [t; t_ol+t_last*ones(n_ol,1) ];
t_last = t_last + T_ol;
endif
if (extras.simulate==1) # Do the actual simulation
if (extras.emulate_timing==1) # Emulate timing
simpar_sim.last = T_total; # simulate for actual execution time
endif
ppp_RT_sim_compute (U_old);
endif
endfor
printf("\n");
endfunction