Quartic solver using Embedded matlab function

조회 수: 1 (최근 30일)
Amir Khan
Amir Khan 2011년 9월 1일
Hello,
I have used an embedded matlab function in simulink to solve a general quartic. Following is the code that I have written in this block
function t = my_quartic (C1,C2,C3,C4,C5)
%eml.extrinsic('p');
p=[C1 C2 C3 C4 C5];
t=roots(p);
%function t=roots(p)
I have used constant blocks to provide the values of C1=3,C2=6,C3=-123, C4=-126 AND C5=1080. I have used the "to file" block as a sink to store the values of t.
Now for the values of coeficients shon above, the roots of t should come out to be 5,3,-4,-6. But when I run the simulation, I get the following error: Data 't' (#23) is inferred as a variable size matrix, while its specified type is something else.
I have tried changing the properties of t in the editor, but its not working. Can someone help me on this? I will be greatly thankful for any comments.
Best Regards, Amir

채택된 답변

Mike Hosea
Mike Hosea 2011년 9월 2일
The problem here is that ROOTS always returns a variable-size result. That's because it ignores leading zeros (or extremely small entries, relative to the other coefficients). So you will find that both codegen and MATLAB versions of ROOTS behave this way. I can think of three easy options here. One is to use variable-size signals in Simulink. You can do this by navigating to the MATLAB Function Block (or Embedded MATLAB Block) in the Model Explorer, clicking on the output signal, checking the "Variable size" check-box on the Size line of the General tab and entering [4,1] for the size.
Another alternative, is to stick with fixed-size calculations by using eig(compan(p)) instead of roots(p), since you probably do not care about dealing efficiently with leading and trailing zeros and such.
Another alternative is
function t = my_quartic (C1,C2,C3,C4,C5)
r = roots([C1 C2 C3 C4 C5]);
t = complex(zeros(4,1));
t(1:numel(r)) = r(:);
That uses variable-size arrays internally, but the output signal is fixed-size.
Do not consider "extrinsic" in this matter. It won't help. -- Mike
  댓글 수: 6
Mike Hosea
Mike Hosea 2011년 9월 3일
The numerical analyst in me wants to make one more comment. Although I couldn't bear to compare equality of imag(R) to zero, I did resist getting too fancy with "thresh". However, you may need to account for very large or very small roots, so you might want to compare abs(imag(R)) to some multiple of eps(real(R)) instead of to a constant. Point is that comparing to zero is naive, but how fancy you want to get in diagnosing "real" roots is up to you. Normally we would argue that r=1e100+1e80i is numerically indistinguishable from r=1e100 in IEEE double precision. Likewise r=1e-100+1e-80i might be regarded as indistinguishable from r=1e-80i rather than r=1e-100.
Harshal
Harshal 2011년 9월 21일
Thanks Mike!! This works perfect.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Walter Roberson
Walter Roberson 2011년 9월 1일
Before the t = roots(p) call, add the line
t = zeros(1,4);
Yes, this will assign a value to t and then overwrite it on the very next line, but doing this will give enough information to the embedded coder to know the size to expect for t.
By the way: why are you specifying p to be extrinsic, as it is not an external function? I could understand if you had said that 'roots' was extrinsic ?
  댓글 수: 3
Walter Roberson
Walter Roberson 2011년 9월 1일
Ummm, I'm not sure, but as an experiment, try changing the last line to
t(1:4) = roots(p);
Walter Roberson
Walter Roberson 2011년 9월 1일
By the way, I am not certain that you need to construct p explicitly. I think you _might_ be able to use
function t = my_quartic (C1,C2,C3,C4,C5)
t = zeros(1,4);
t(1:4) = roots([C1,C2,C3,C4,C5]);
Though it would not surprise me if it turned out that you needed to declare roots as extrinsic at some point.

댓글을 달려면 로그인하십시오.

Community Treasure Hunt

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

Start Hunting!

Translated by