Does MATLAB have a way to solve for a variable in a nonlinear equation? (i.e. cos(x) + sin(y), solve for y in terms of x using symbols)

I have a very long, complicated equation in which is a variable for which I need solved. Basically, what I did was take the typical rotation matrix form and turn it in to a series of nonlinear equations.
xb = xa*(cosd(b)*cosd(c))+ya*((cosd(c)*sind(b)*sind(a))+(sind(c)*cosd(a)))+za*((sind(c)*sind(a)-(cosd(c)*sind(b)*cosd(a))));
yb = xa*(-sind(c)*cosd(b))+ya*(cosd(a)*cosd(c)-sind(a)*sind(b)*sind(c))+za*(sind(c)*sind(b)*cosd(a)+cosd(c)*sind(a));
zb = xa*(sind(b))+ya*(-cosd(b)*sind(a))+za*(cosd(a)*cosd(b));
I solved for two of the angles with respect to the other angle and the vector. What i need to do now is solve for the last angle in terms of just the vector.
Does anyone know if MATLAB can solve for a variable in terms of other variables?
Thank you!

Answers (2)

If you have the Optimization Toolbox, there is fsolve(), but it is a numerical solver, i.e., the output is always a number.
If you have the Symbolic Toolbox, you can try to get a closed form symbolic expression for the solution using solve(), but a symbolic solution doesn't always exist for a set of equations.
Additionally, as I told you in an earlier thread, the solutions to the equations you've shown are highly non-unique.

11 Comments

I understand they are non-unique, which does prove to be a problem, and you have been much help. I really cannot thank you enough.
I have tried the fsolve function, but as you said it is numeric only and proved to be useless here.
I tried using solve, BUT it seems that MATLAB cannot compute trigonometric functions with symbols, so I am stuck there as well. I really liked your function you showed me in the earlier thread, and I do not know if you saw my question afterwards, but do you happen to know of another way, other than quaternions, to solve this problem?
One closed-form solution to the problem is given by Rodrigues' formula
with k=cross(vector1, vector2).
It assumes the rotation you want is about an axis perpendicular to both vectors. It's not clear, though, if that's the particular solution you want. There are infinite other solutions.
OK thanks! I'll look through this. I was also told, by one of my professors, that there is a way using something of the form: TAT^-1. But he could not remember it exactly. Do you happen to know anything about this as a way of going between two vectors?
Yes, suppose A is a rotation matrix in some reference coordinate system and the columns of S are a set of rotated axes expressed in the reference coordinates. Now suppose x is a position vector measured with respect to the rotated axes, then
(S^-1*A*S)*x
will perform rotation A on x, but give the result in the rotated coordinate system (as opposed to the reference system).
I'm pretty sure MuPAD can handle solve() of trig functions. For example,
solve('cos(theta)=1/2','theta')
Trig functions are, though, difficult to resolve in more complex equations.
I tried running that exact code and it told me there was an error.
Error using solve>processString (line
354)
' cos(theta)=1/2 ' is not a valid
expression or equation.
Error in solve>getEqns (line 284)
eqns = processString(eqns, v,
vc);
Error in solve (line 160)
[eqns,vars,options] =
getEqns(varargin{:});
Error in testmyfun (line 26)
solve('cos(theta)=1/2','theta')
I also tried running it without the =1/2 and it said it was not a valid expression. I tried running it without the quotes as well. It said there was an undefined function theta, so I defined it to be a symbol and it spat out a numerical answer of pi/2. I do not want a numerical answer and that's why I'm trying to use symbols.
Any other suggestions? Thank you very much for talking through this with me. It's being very helpful.
Update, I may have just been debugging incorrectly. I will let you know if this sym business pans out!
Re-Update:
I was presented with this error:
Error using mupadmex
Error in MuPAD command: Array sizes
must match.
Error in sym/privBinaryOp (line 1693)
Csym =
mupadmex(op,args{1}.s,
args{2}.s, varargin{:});
Error in sym/plus (line 7)
X = privBinaryOp(A, B, 'symobj::zip',
'_plus');
Error in testmyfun (line 27)
solve(-xb +
p*(cos(b)*cos(2*(atan((0.5*sqrt((2*q*sin(2*(atan((sqrt(-p.^2*(sin(b)).^2+2*p*z*sin(b)+q.^2*(cos(b)).^2+r.^2*(cos(b)).^2-z.^2)-q*cos(b))/(-p*sin(b)+r*cos(b)+z))+pi*n))*sin(b)-2*r*cos(a)*s
The equation I'm trying to solve for is above partially. I'll reprint it for "easy" access and viewing:
c = 2*(atan((0.5*sqrt((2*q*sin(a)*sin(b)-2*r*cos(a)*sin(b)+2*p*cos(b)).^2-4*(-q*cos(a)-r*sin(a)+y)*(q*cos(a)+r*sin(a)+y))-q*sin(a)*sin(b)+r*cos(a)*sin(b)-p*cos(b))/(q*cos(a)+r*sin(a)+y))+pi*n);
a = 2*(atan((sqrt(-p.^2*(sin(b)).^2+2*p*z*sin(b)+q.^2*(cos(b)).^2+r.^2*(cos(b)).^2-z.^2)-q*cos(b))/(-p*sin(b)+r*cos(b)+z))+pi*n);
xb = xa*(cosd(b)*cosd(c))+ya*((cosd(c)*sind(b)*sind(a))+(sind(c)*cosd(a)))+za*((sind(c)*sind(a)-(cosd(c)*sind(b)*cosd(a))));
solve(xb, b)
Basically what I did was I took:
xb = xa*(cosd(b)*cosd(c))+ya*((cosd(c)*sind(b)*sind(a))+(sind(c)*cosd(a)))+za*((sind(c)*sind(a)-(cosd(c)*sind(b)*cosd(a))));
yb = xa*(-sind(c)*cosd(b))+ya*(cosd(a)*cosd(c)-sind(a)*sind(b)*sind(c))+za*(sind(c)*sind(b)*cosd(a)+cosd(c)*sind(a));
zb = xa*(sind(b))+ya*(-cosd(b)*sind(a))+za*(cosd(a)*cosd(b));
And re-aranged them to solve:
zb for a
yb for c
and substituted these in to xb so everything is in terms of b.
Now I just need to solve for b.
When I try this code with everything as symbols, it tells me my matrix dimensions do not line up.
I am surprised that solve('cos(theta)','theta') did not work. Unfortunately I do not have that toolbox so I cannot experiment.
When you got pi/2 did it literally say pi/2 with pi in words, or did it say 1.5707963267949 ? If it said pi/2 then that was symbolic and would be the correct solution to cos(theta)=0 .
It said, literally, pi/2 for the solve(cos(theta),theta). So that's at least a step in the right direction!
Now I just need to solve for b.
I suspect you will not be able to solve for b. Again, because the solution is non-unique, there have to be some free variables left over. Think of trying to solve the single equation
x+y=1
for both x and y. I'm impressed that the solver took you as far as this, actually.
Make sure that n, p, q, r, x, y, z, a, b, c, are all defined as symbols and not functions or arrays. You might want to check with size()

Sign in to comment.

In general you can solve some kinds of equations using the Symbolic Toolbox if you have it (it is part of the Student Version license.)
I suggest you see previous discussions about rotation matrices, such as http://www.mathworks.co.uk/matlabcentral/answers/15411-recover-basic-rotations

1 Comment

Thank you! I will check out these threads. I have used solve, but it doesn't seem to work for arguments of type "sym" with trigonometric functions.

Sign in to comment.

Asked:

on 7 Nov 2013

Commented:

on 8 Nov 2013

Community Treasure Hunt

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

Start Hunting!