Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Using Fsolve interatively with changing constants?

Asked by Henry Astley on 29 Dec 2012
Latest activity Commented on by Matt J on 6 Nov 2013

I'm trying to use Fsolve to convert 5 data inputs into 5 data outputs. I've tried the pen-and-paper method, and it's beyond my meager abilities to derive explicit formulae, so I need MATLAB to do it for me.

Basically, I have 5 equations, 5 outputs, and 5 sensor inputs that would serve as constants, repeated up to 400 time points. If inputs are x and outputs y, general format would be:

X1=Y2*X3+Y4*X5

X2=Y1-Y3*X1

etc.

Or, rearranged:

0=Y2*X3+Y4*X5-X1

0=Y1-Y3*X1-X2

etc.

So for each timepoint, I would like to use actual sensor readings to put real numbers in for X1 through X5, then find the values for Y1 through Y5 with fsolve inside a For loop.

Problem is, I can't figure out how the inputs and such would work, and how to handle "constants that vary within a loop" (I'm sure there's a real term I don't know). I know fsolve wants me to write a function, but if I feed that function all 10 inputs, how will Fsolve know which ones to solve for and which ones need to remain constant? I have no code to post because I am completely flumoxed - I can't even begin to think of how to do this.

Short version: I need fsolve to solve a system of 5 equations over and over again with 5 different constants each time. I know fsolve wants me to write a function, but if I give that function all 10 inputs (guesses + constants), how will Fsolve know which ones to solve for and which ones need to remain constant?

1 Comment

Walter Roberson on 29 Dec 2012

Do you have access to the symbolic math toolbox? If so then you might want to use it's solve() to find the Y in terms of X.

Henry Astley

Products

No products are associated with this question.

2 Answers

Answer by Matt J on 29 Dec 2012
Edited by Matt J on 29 Dec 2012

See here,

http://www.mathworks.com/help/optim/ug/passing-extra-parameters.html

However, it doesn't look like FSOLVE is the appropriate tool here. Your equalities are all linear in Y, so the solution space should be given by A\b where the matrix A and vector b are derived from the Xi

3 Comments

Matt J on 29 Dec 2012

Or, if X contains noise, then a total least squares approach is possible with a known algebraic solution

http://en.wikipedia.org/wiki/Total_least_squares#Algebraic_point_of_view

Henry Astley on 30 Dec 2012

Sorry, I need more help with this.

I can't use a matrix method because the formulae contain instances where two inputs or two outputs are multiplied together.

I can't figure out how to get solve to give me anything useful. I enter is as so:

[Fx,Fy,xoff,yoff,Tz]=solve('Fx-Tz*yoff-Fsx=0','Fy-Tz*xoff-Fsy=0','Fy*zoff-Fz*yoff-Msx=0','Fz*xoff-Fx*zoff-Msy=0','Fx*yoff-Fy*xoff-Msz=0');

...and while it gives me answers, it doesn't give me ones that are useful - all the answers still have outputs defined by other outputs.

I tried anonymizing with fsolve, and it gave me errors. Here's my code for the function (the last 6 are my sensor readings (anything with an 's' in it), the first six are values I want):

function fcns = Tzfcns(Fx,Fy,Fz,xoff,yoff,Tz,Fsx,Fsy,Fsz,Msx,Msy,Msz)
    fcns(1)=Fx-Tz*yoff-Fsx;
    fcns(2)=Fy-Tz*xoff-Fsy;
    fcns(3)=Fz-Fsz;
    fcns(4)=Fy*(-0.018)-Fz*yoff-Msx;
    fcns(5)=Fz*xoff-Fx*(-0.018)-Msy;
    fcns(6)=Fx*yoff-Fy*xoff-Msz;
end

And my script, after getting the sensor inputs from a file, is:

for i=1:len
    f = @(Fx,Fy,Fz,xoff,yoff,Tz)Tzfcns(Fx,Fy,Fz,xoff,yoff,Tz,Fsx(i),Fsy(i),Fsz(i),Msx(i),Msy(i),Msz(i));
    g=[1,1,1,1,1,1];
    x=fsolve(f,g);
end

which gives me an error

??? Input argument "Fy" is undefined.
Error in ==> @(Fx,Fy,Fz,xoff,yoff,Tz)Tzfcns(Fx,Fy,Fz,xoff,yoff,Tz,Fsx(i),Fsy(i),Fsz(i),Msx(i),Msy(i),Msz(i))
Error in ==> fsolve at 254
            fuser = feval(funfcn{3},x,varargin{:});
Caused by:
    Failure in initial user-supplied objective function evaluation. FSOLVE cannot continue.

I still can't figure out what I'm doing wrong. I assume I did something wrong with the anonymizing, but the example text given only has one variable. Can it only work with one variable? Or am I just formatting it incorrectly?

Matt J on 6 Nov 2013

I assume I did something wrong with the anonymizing, but the example text given only has one variable.

No, the example has 2 unknowns x(1) and x(2). The thing you're doing wrong is that you are passing all 6 unknowns as separate arguments to Tzfcns, whereas you should be bundling them all into a single unknown vector:

function fcns = Tzfcns(unknowns,knowns)
     unknowns=num2cell(unknowns);
     [Fx,Fy,Fz,xoff,yoff,Tz] = deal(unknowns{:});
     knowns=num2cell(knowns);
     [Fsx,Fsy,Fsz,Msx,Msy,Msz] = deal(knowns{:});
      fcns(1)=Fx-Tz*yoff-Fsx;
      fcns(2)=Fy-Tz*xoff-Fsy;
      fcns(3)=Fz-Fsz;
      fcns(4)=Fy*(-0.018)-Fz*yoff-Msx;
      fcns(5)=Fz*xoff-Fx*(-0.018)-Msy;
      fcns(6)=Fx*yoff-Fy*xoff-Msz;
end

and then

g=[1,1,1,1,1,1];
for i=1:len
    knowns=[Fsx(i),Fsy(i),Fsz(i),Msx(i),Msy(i),Msz(i)];
    f = @(unknowns) Tzfcns(unknowns,knowns);
    x=fsolve(f,g);
end
Matt J
Answer by Walter Roberson on 30 Dec 2012

You did not specify which variables to solve for, so solve() used its own ideas about which to use and those did not match your expectations. Specify the variables yourself:

syms Fsx, Fsy, Fx, Fy, Fz, Msx, Msy, Msz, Tz, xoff, yoff, zoff
[Fx,Fy,xoff,yoff,Tz] = solve(Fx-Tz*yoff-Fsx, Fy-Tz*xoff-Fsy, Fy*zoff-Fz*yoff-Msx, Fz*xoff-Fx*zoff-Msy, Fx*yoff-Fy*xoff-Msz, Fx, Fy, xoff, yoff, Tz);

You might find that the solutions are all expressed as multiples of an expression involving a RootOf() term. That RootOf() term will be a way of expressing that at that point you should substitute the two solutions to a quadratic function,

RootOf(Msz*zoff^2*Z^2+(-Msx*zoff*Fsy-zoff*Fsx*Msy-Msy^2+Msx^2)*Z-Fsy*Fz*Msy-Fsx*Fz*Msx-Msz*Fz^2, Z)

The RootOf() represents the roots, the set of values of Z such that the expression in the first term becomes 0. There is, of course, an analytic form of that, but it would be messy to write.

If you extract the RootOf() term using op(), then you can subs() another variable name (e.g., "R") for the expression in each of the formulas you got, in order to give you pretty compact representations of those formulas. That is not necessary, but it can make things much easier to understand. But from there through the rest of your program you need to keep in mind that each of the variables you calculated has two values, one corresponding to each of the two roots.

0 Comments

Walter Roberson

Contact us