📄 place.m
字号:
function K = place(A,B,P)
%PLACE K = place(A,B,P) computes the state feedback matrix K such that
% the eigenvalues of A-B*K are those specified in vector P.
% The complex eigenvalues in the vector P must appear in consecu-
% tive complex conjugate pairs. No eigenvalue may be placed with
% multiplicity greater than the number of inputs.
%
% The displayed "ndigits" is an estimate of how well the
% eigenvalues were placed. The value seems to give an estimate
% of how many decimal digits in the eigenvalues of A-B*K match
% the specified numbers given in the array P.
%
% A warning message is printed if the nonzero closed loop poles
% are greater than 10% from the desired locations specified in P.
%
% See also: LQR and RLOCUS.
% M. Wette 10-1-86
% UCSB ECE, Santa Barbara, CA 93106, (805) 961-4691
% E-mail: riccati@hub.ucsb.edu
% Revised 9-25-87 JNL
% Revised 8-4-92 Wes Wang
%
% Ref:: Kautsky, Nichols, Van Dooren, "Robust Pole Assignment in Linear
% State Feedback," Intl. J. Control, 41(1985)5, pp 1129-1155
%
% Copyright (c) 1986-93 by the MathWorks, Inc.
NTRY=5; % - number of iterations for "optimization" -
%
[nx,na] = size(A);
P = P(:);
if length(P)~=nx, error('P must have the same number of states as A.'); end
[n,m] = size(B);
if (nx == 0 | n == 0),
error('A and B matrices cannot be empty.')
end
nx=0; i=1; while (i<=n),
if imag(P(i))~=0.0,
pr = [pr real(P(i))]; pi = [pi imag(P(i))];
cmplx = [cmplx 1]; i = i+2;
else,
pr = [pr real(P(i))]; pi = [pi 0.0];
cmplx = [cmplx 0]; i = i+1;
end;
nx = nx+1;
end;
%
m = rank(B);
% Make sure there are more inputs than repeated poles:
ps = sort(P);
for i=1:n-m
imax = min(n,i+m);
if all(ps(i:imax) == ps(i))
error('Can''t place poles with multiplicity greater than the number of inputs.');
end
end
nmmp1 = n-m+1; mp1 = m+1; jj = sqrt(-1);
[Qb,Rb] = qr(B); q0 = Qb(:,1:m); q1 = Qb(:,mp1:n); Rb = Rb(1:m,:);
%
% - special case: (#inputs)==(#states) - efficient, but not clean
if (m==n),
A = A - diag(real(P));
i=0; for j=1:nx,
i = i+1;
if cmplx(j),
A(i,i+1) = A(i,i+1) + pi(j);
A(i+1,i) = A(i+1,i) - pi(j);
i = i+1;
end;
end;
disp(sprintf('place: ndigits= %g', fix(log10(1.0/eps))))
K = Rb\q0'*A;
return; % escape here!
end
%
% - compute bases for eigenvectors -
I = eye(n);
for i=1:nx,
[Q,R] = qr(((pr(i)+jj*pi(i))*I-A)'*q1);
Bx = [ Bx Q(:,nmmp1:n) ];
end;
%
% - choose basis set -
% at each iteration of i pick the eigenvector Xj, j~=i,
% which is "most orthogonal" to the current eigenvector Xi
%Wes changed the following
nn=1;
for i=1:nx,
X(:,i) = Bx(:,(i-1)*m+1);
if m>1 %check if X is a full rank matrix. If it is not, make it up
for ii = 2:m
nnx = nn + cmplx(i);
Y(:,nnx) = imag(X(:,i)); %if cmplx(i)==1 take imag part, else empty action
Y(:,nn) = real(X(:,i));
if rank(Y) < nnx,
X(:,i) = Bx(:,(i-1)*m+ii);
else
ii = m;
end; % if rank(Y) < nnx,
end; %for ii = 2:m
nn = nn + 1 + cmplx(i);
end; %if m>1
end; %for i=1:nx,
% Wes changed the above
if (m>1),
for k = 1:NTRY,
for i = 1:nx,
S = [ X(:,1:i-1) X(:,i+1:nx) ]; S = [ S conj(S) ];
[Us,Ss,Vs] = svd(S);
Pr = Bx(:,(i-1)*m+1:i*m); Pr = Pr*Pr';
X(:,i) = Pr*Us(:,n); X(:,i) = X(:,i)/norm(X(:,i));
end
end
end
for i = 1:nx,
if cmplx(i),
Xf = [ Xf X(:,i) conj(X(:,i)) ];
else,
Xf = [ Xf X(:,i) ];
end;
end;
cnd = cond(Xf);
if (cnd*eps >= 1.0),
disp('place: can''t place eigenvalues there');
return;
end
disp(sprintf('place: ndigits= %g', fix(log10(cnd/eps))))
%
% - compute feedback -
K = Rb\q0'*(A-real(Xf*diag(P,0)/Xf));
% Check results. Start by removing 0.0 pole locations
P = sort(P);
i = find(P ~= 0);
P = P(i);
Pc = sort(eig(A-B*K));
Pc = Pc(i);
if max(abs(P-Pc)./abs(P)) > .1
disp('Warning: Pole locations are more than 10% in error.')
end
% --- last line of place ---
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -