acker(): "Error using sym/poly". Why?

55 views (last 30 days)
John
John on 14 Jul 2023
Commented: Walter Roberson on 17 Jul 2023
I'm trying to find the eigenvalues of a matrix H manually, where H represents some system dynamics.
(The system is defined by H, so eigs are solutions to det(H-lamba*I) = 0)
Once i find those eigs, i input them to acker() for pole placement to find gains.
(1) Why am i getting an error when inputting what i think are a set of normal numbers to acker()? See code below.
Note: I compare this to the normal eig(H) results to see if it's working, so i can see the normal method works with acker().
(2) Why is vpa() needed, ie why is solve() returning functions of z? I thought solve() would return numbers, since it's just trying to find solutions to det(H-lamba*I) = 0), which evaluates to:
lam^6 - 15999360000*lam^4 + 16000160000000000*lam^2 - 160000000000000000000000 == 0
and that seems like returned solutions should be just normal complex numbers.
A = [0 1;
-4e5 -400];
B = [0; 4e5];
C = [1 0];
Aaug = [A, zeros(2,1); -C, 0];
Baug = [B; 0];
H = 1.0e+12 * [0 0.000000000001000 0 0 0 0;
-0.000000400000000 -0.000000000400000 0 0 -0.160000000000000 0;
-0.000000000001000 0 0 0 0 0;
-0.000000100000000 0 0 0 0.000000400000000 0.000000000001000;
0 -0.000000000000100 0 -0.000000000001000 0.000000000400000 0;
0 0 -1.000000000000000 0 0 0];
% ~~~~~~~ Built-in eigs ~~~~~~~
% These are a set of numbers
eigs1 = eig(H)
eigs1 =
1.0e+05 * -1.2648 + 0.0000i 1.2648 + 0.0000i -0.0135 + 0.0115i -0.0135 - 0.0115i 0.0135 + 0.0115i 0.0135 - 0.0115i
whichNegEig = find(real(eigs1)<0);
K = acker(Aaug, Baug, eigs1(whichNegEig))
K = 1×3
1.0e+06 * 0.0009 0.0000 -1.0000
% ~~~~~~~ Manually find eigs ~~~~~~~
syms lam;
sysDet = det(H - lam*eye(size(H)));
polySys = solve(sysDet == 0, lam)
polySys = 
eigs2= vpa(polySys)
eigs2 = 
% These SHOULD be a set of numbers. Are they not?
whichNegEig2 = find(real(eigs2)<0);
% They SEEM the same as whichNegEig, so seem correct.
eigs2(whichNegEig2)
ans = 
% Why is this giving this error:
% "Error using sym/poly
% SYM/POLY has been removed. Use CHARPOLY instead."
K2 = acker(Aaug, Baug, eigs2(whichNegEig2))
Error using sym/poly
SYM/POLY has been removed. Use CHARPOLY instead.

Error in acker (line 41)
k = ctrb(a,b)\polyvalm(real(poly(p)),a);
  4 Comments
John
John on 15 Jul 2023
Thanks @Star Strider. "it converts the symbolic results to numeric results" How can i tell they are symbolic results?
IeI tried a few "isxyz()" commands -- how would i identify it as a symbolic type?
I also tried
sympref('FloatingPointOutput',true);
before solve(), but no change. I thought that would give floating point outputs, if possible.
Star Strider
Star Strider on 15 Jul 2023
My pleasure!
If it is not obvious by the context, one option is to use the whos function.
Example —
x = 1
x = 1
whos x
Name Size Bytes Class Attributes x 1x1 8 double
syms x
y = x
y = 
x
whos y
Name Size Bytes Class Attributes y 1x1 8 sym
The sympref call:
sympref('FloatingPointOutput',true);
produces floating-point representation with four digits after the decimal, instead of producing fractional constants. It does not automatically invoke vpa. See Display Symbolic Results in Floating-Point Format for a full explanation.
.

Sign in to comment.

Accepted Answer

Paul
Paul on 15 Jul 2023
Hi John,
A = [0 1;
-4e5 -400];
B = [0; 4e5];
C = [1 0];
Aaug = [A, zeros(2,1); -C, 0];
Baug = [B; 0];
H = 1.0e+12 * [0 0.000000000001000 0 0 0 0;
-0.000000400000000 -0.000000000400000 0 0 -0.160000000000000 0;
-0.000000000001000 0 0 0 0 0;
-0.000000100000000 0 0 0 0.000000400000000 0.000000000001000;
0 -0.000000000000100 0 -0.000000000001000 0.000000000400000 0;
0 0 -1.000000000000000 0 0 0];
syms lam;
sysDet = det(H - lam*eye(size(H)));
Here, solve trying to solve for closed form expressions of a sixth order polynomial, which can't be done in general. In some cases, solve will revert to vpasolve, but I guess not in this case.
polySys = solve(sysDet == 0, lam)
polySys = 
However, here sysDet has a form that solve can (arguaby) handle a bit better if we ask it to
polySys = solve(sysDet == 0, lam,'MaxDegree',3)
polySys = 
At this point, polySys is of class sym
class(polySys)
ans = 'sym'
Now, we can convert polySys to "numbers"
eigs2= vpa(polySys)
eigs2 = 
but eigs2 is still of class sym
class(eigs2)
ans = 'sym'
Calling acker with sym inputs just isn't allowed, hence the need to convert to double. Some functions outside the Symbolic Math Toolbox that ordinarily expect numeric inputs can deal with sym inputs, but acker isn't one of those.
Having said that, acker is pretty simple and I think you could implement it pretty easily with sym variables, at least the basic part that computes the gains.
  10 Comments
Paul
Paul on 17 Jul 2023
It isn't? According to its doc page, eig is eligible for C/C++ code generation. I don't do code generation, so don't know any more than that.
Walter Roberson
Walter Roberson on 17 Jul 2023
Nothing in the Symbolic Toolbox can be compiled with MATLAB Compiler or MATLAB Coder.
roots can be used to compute numeric roots of a polynomial that has been abstracted to its list of coefficients of descending powers.
A strategy that can be used is to use an interactive session to generate the symbolic eigenvalues down to the root() or rootOf() structure. Then use children() to extract the symbolic polynomial from inside the root() or rootOf() structure, and use sym2poly() to get the list of coefficients of each power, in symbolic form.
Now you can matlabFunction() that list, asking to write to a file; you might need to request Optimize false unless they have fixed the optimization bugs from the last several releases.
The result would be a .m file that you could invoke from a different program -- the program that needs to be compiled.
The symbolic form of eigenvalues is often pretty long, and most of the time it is faster and more accurate to use eig() -- which has been supported for code generation for a number of releases (earlier than R2018b)

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 15 Jul 2023
acker() is a now-undocumented function in the Control Systems Toolbox, in a directory reserved for "obsolete" functions. In other words, it was withdrawn and should not be used in any new code.
I see people recommending place instead.
  3 Comments
Paul
Paul on 17 Jul 2023
Keep in mind that place has a constraint on the desired pole locations.
rng(100)
A = rand(2);B = rand(2,1);
place(A,B,[-2 , -2]);
Error using place
The "place" command cannot place poles with multiplicity greater than rank(B).
John
John on 17 Jul 2023
Yes, thanks. That's why i was hoping to use acker(). But, i guess this is now a limitation.

Sign in to comment.

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!