Code covered by the BSD License  

Highlights from
QCAT

image thumbnail
from QCAT by Ola Harkegard
Quadratic Programming Control Allocation Toolbox

alloc_sim(method,B,v,plim,rlim,T,varargin)
function [u,A,time,iter] = alloc_sim(method,B,v,plim,rlim,T,varargin)

% ALLOC_SIM - Control allocation simulation.
%
%  [u,A,iter,time] = alloc_sim(method,B,v,plim,rlim,T,varargin)
%
% Subroutine not intended to be called directly by user.
  
% Performs control allocation for a sequence of virtual control
% commands stored in v.
%
%  Inputs:
%  -------
% method   control allocation method: 'qp'   l2-optimal allocation
%				      'dyn'  dynamic allocation
%				      'dir'  direct allocation
% B	   control effectiveness matrix (k x m)
% v        commanded virtual control trajectory (k x N)
% plim     position limits [min max] (m x 2)
% rlim	   rate limit = [min max] (m x 2) 
% T	   sampling time
% options  options, see code
%
%  Outputs:
%  -------
% u     optimal control
% A     active constraints in u
% iter  no. of iterations
% time  average computation time per sample
  
% Number of variables
  [k,m] = size(B);
  % Coplanar controls? Only in SLS_ALLOC
  copl = iscoplanar(B);
  % Number of samples
  N = size(v,2);
  % Allocate output variables
  u = zeros(m,N);
  A = zeros(m,N);
  iter = zeros(1,N);
  time = zeros(1,N);
  
  % Set default values of optional arguments
  switch method
   case {'qp','dyn'}
    alg  = 'wls';
   case 'dir'
    alg = 'dir';
  end
  M    = 1;	     % no of repetitions
  imax = 100;	     % no of iterations
  gam  = 1e6;	     % weight
  tol  = 1e-6;       % tolerance in IP solver
  hs   = 1;	     % hotstart
  ui   = [];	     % initial control
  Wi   = zeros(m,1); % initial working set
  Wv   = eye(k);     % QP allocation
  Wu   = eye(m);
  ud   = zeros(m);
  W1   = eye(m);     % Dynamic allocation
  W2   = zeros(m);
  S    = pinv(B);
  
  for i=1:2:length(varargin)
    switch(varargin{i})
      % --- General options ---
     case 'alg'  % solver, algorithm
      alg = varargin{i+1};
     case 'rep'  % no of repetitions
      M = varargin{i+1};

      % --- Method specific options ---
     case 'imax' % number of iterations
      imax = varargin{i+1};
     case 'gam'  % LS weight
      gam = varargin{i+1};
     case 'tol'  % IP tolerance
      tol = varargin{i+1};
     case 'hot'  % hotstart
      hs = varargin{i+1};
     case 'ui'   % active set (also fix-point)
      ui = varargin{i+1};
     case 'Wi'
      Wi = varargin{i+1};
     case 'Wv'   % QP allocation
      Wv = varargin{i+1};
     case 'Wu'
      Wu = varargin{i+1};
     case 'ud'
      ud = varargin{i+1};
     case 'W1'   % dynamic allocation
      W1 = varargin{i+1};
     case 'W2'
      W2 = varargin{i+1};
     case 'S'
      S = varargin{i+1};
     
     otherwise
      error(sprintf('Unknown option: %s',varargin{i}));
    end
  end

  if strcmp(alg,'ip')
    % Weighting matrices must be unit matrices.
    if any(any(Wv ~= eye(k))) | any(any(Wu ~= eye(m)))
      disp(' ')
      disp(['** Warning: Non-unit matrices Wv and Wu not handled by' ...
	    ' IP_ALLOC **']) 
      disp(' ')
    end
    % Dynamic allocation almost always requires non-unit matrix Wu.
    if strcmp(method,'dyn')
      disp(' ')
      disp(['** Warning: Dynamic allocation not handled by IP_ALLOC,' ...
	    ' resorting to WLS_ALLOC **'])
      disp(' ');
      alg = 'wls';
    end
  end
  
  if isempty(ui)
    % Set default initial conditions
    switch method
     case 'qp'
      [ui,Wi] = wls_alloc(B,v(:,1),plim(:,1),plim(:,2),Wv,Wu,ud);
     case 'dyn'
      [ui,Wi] = wls_alloc(B,v(:,1),plim(:,1),plim(:,2),Wv,W1,S*v(:,1));
     case 'dir'
      ui = dir_alloc(B,v(:,1),plim(:,1),plim(:,2));
    end
  end
  
  % Hotstart?
  if hs
    u0 = ui;
    W0 = Wi;
  end
  
  % Precompute matrices used in dynamic allocation
  if strcmp(method,'dyn')
    W1sq = W1^2;
    W2sq = W2^2;
    Wu = sqrtm(W1sq+W2sq);
    invWusq = inv(W1sq+W2sq);
  end
  
  % Allocate control signals to produce the demanded virtual
  % control trajectory.
  uprev = ui;
  for i=1:N
    % Compute feasible upper and lower bounds.
    if isempty(rlim)
      umin = plim(:,1);
      umax = plim(:,2);
    else
      umin = max(plim(:,1),uprev+rlim(:,1)*T);
      umax = min(plim(:,2),uprev+rlim(:,2)*T);
    end
    if ~hs
      u0 = (umin+umax)/2;
      W0 = zeros(m,1);
    end
    % Update u0 to reflect working set. Crucial when rate limits
    % are included and hotstart is used.
    i_min = W0 == -1;
    i_max = W0 == +1;
    u0(i_min) = umin(i_min);
    u0(i_max) = umax(i_max);
    % For dynamic allocation, merge the position and rate terms
    % into one term ||Wu(u-ud)||.
    if strcmp(method,'dyn')
      us = S*v(:,i);
      ud = invWusq*(W1sq*us+W2sq*uprev);
    end
    % Solve control allocation problem M times
    tic;
    for l = 1:M
      switch alg
       case 'sls'
	[u(:,i),W,iter(i)] = ...
	    sls_alloc(B+copl*j,v(:,i),umin,umax,Wv,Wu,ud,u0,W0,imax);
       case 'mls'
	[u(:,i),W,iter(i)] = ...
	    mls_alloc(B,v(:,i),umin,umax,Wv,Wu,ud,u0,W0,imax);
       case 'wls'
	[u(:,i),W,iter(i)] = ...
	    wls_alloc(B,v(:,i),umin,umax,Wv,Wu,ud,gam,u0,W0,imax);
	% --- FoT25 allocation routine, not in standard QCAT ---
       case 'wls_c'
	[u(:,i),W,iter(i)] = ...
	    wls_alloc_c(B,v(:,i),umin,umax,Wv,Wu,ud,gam,u0,W0,imax);
	% ------------------------------------------------------
       case 'wlsc'
	[u(:,i),W,iter(i)] = ...
	    wlsc_alloc(B,v(:,i),umin,umax,Wv,Wu,ud,gam,u0,W0,imax);
       case 'ip'
	[u(:,i),iter(i)] = ...
	    ip_alloc(B,v(:,i),umin,umax,ud,gam,tol,imax);
       case 'fxp'
	u(:,i) = fxp_alloc(B,v(:,i),umin,umax,Wv,Wu,ud,gam,u0,imax);
       case 'cgi'
	u(:,i) = cgi_alloc(B,v(:,i),umin,umax,Wv,Wu,ud,imax);
       case 'dir'
	u(:,i) = dir_alloc(B,v(:,i),plim(:,1),plim(:,2));
       otherwise
	error(sprintf('Unknown allocation algorithm: %s',alg));
      end
    end
    % Register elapsed time
    time(i) = toc/M;
    % Limit control (only necessary with rate limits and direct alloc)
    u(:,i) = max(umin,min(umax,u(:,i)));
    % Determine active constraints in the final point.
    % +/- : max or min
    % 1/2 : position or rate limit
    A(:,i) = - 2*(u(:,i)==umin) + (u(:,i)==plim(:,1)) ...
	     + 2*(u(:,i)==umax) - (u(:,i)==plim(:,2));
    % Update uprev
    uprev = u(:,i);
    % Hotstart?
    if hs
      u0 = u(:,i);
      if any(strcmp(alg,{'sls','wls','wls_c','wlsc','mls'}))
	W0 = W;
      end
    end
  end

Contact us at files@mathworks.com