Success in Syms Implementation


Development

I tested out using syms with the NR logic:

%% Reset
clear;   % resets all the variables since syms can be a bit fucky wucky

%% Equations 
m = 2;                     % number of variables 
syms x [m 1]               % syms variable array
% syms F(x)                  % syms function definition
F(x) = [-2*cos(x1)+3*cos(x2);10*sin(x1)+15*sin(x2)-18];   % function array (test from Num Math Chp 6)
D = jacobian(F,x);       % Jacobian matrix

%% Parameters
% x_in = input('What is your guess?'); % intial guess
x_in = [0.59;0.99];
n = 0; % number of steps
n_max = 10; % step timeout
tol = 1e-15;  % tolerance for successful zero

%% Solving 
x_sol = zeros([m 1]);
x_sol = x_in;              % setting the initial guess 
f_out = subs(F,x,x_sol(:,1));    % evaluating the inital guess function value
df_out = subs(D,x,x_sol(:,1));   % evaluating the inital guess jacobian value
ep = sum(double(f_out));         % error
while (abs(ep)>=tol) && (n<n_max)
    x_sol(:,n+2) = x_sol(:,n+1) - (inv(df_out) * f_out);    % NR Method multivariable 
    f_out = subs(F,x,x_sol(:,n+2));                         % update function value
    df_out = subs(D,x,x_sol(:,n+2));                        % update jacobian
    ep = sum(double(f_out));                                % update the error
    n = n+1;
end
x_out = vpa(x_sol)

Then I developed this NR function script for ease of use:

function [n,xout] = NRfunc(F,x,x_in,tol,n_max)
    D = jacobian(F,x);                        % Jacobian matrix
    x_sol = x_in;                             % setting the initial guess 
    n = 0;                                    % number of steps
    f_out = subs(F,x,x_sol(:,1));             % evaluating the inital guess function value
    df_out = subs(D,x,x_sol(:,1));            % evaluating the inital guess jacobian value
    ep = sum(double(f_out));                  % error
    while (abs(ep)>=tol) && (n<n_max)
        x_sol= x_sol - (inv(df_out) * f_out); % NR Method multivariable 
        f_out = subs(F,x,x_sol);              % update function value
        df_out = subs(D,x,x_sol);             % update jacobian
        ep = sum(double(f_out));              % update the error
        n = n+1;                              % update the steps
    end
    xout = vpa(x_sol);                       % send output
end

Here is the function used with the four bar linkage:

%% System Parameters 
a = 2.0;
b = 0.5;
l1 = 1.0;
l2 = 3.0;
l3 = 2.2;
m = 3;
syms t
syms O [m 1]

%% Equations
phi(O) = [l1*cos(O1)+l2*cos(O2)+l3*cos(O3)-a; ...
    l1*sin(O1)+l2*sin(O2)+l3*sin(O3)-b;...
    O1-pi/2];

%% Solution Parameters 
O_in = [pi/2;0.4;0.6];  % initial guess
n_max = 10;             % max steps
tol = 1e-15;  % tolerance for successful zero

%% Solution
[n,xout] = NRfunc(phi,O,O_in,tol,n_max);
fprintf("In %d steps\n",n)
disp(xout)

Not working, not sure why. Gonna try hard coding it in.

I noticed the computations and conversions between syms and double are what are causing the long wait time.

I also tried using fsolve to check my answers:

%% Parameters 
a = 2.0;
b = 0.5;
l1 = 1.0;
l2 = 3.0;
l3 = 2.2;

%% Equations
phi = @(O)([l1*cos(O(1))+l2*cos(O(2))+l3*cos(O(3))-a; ...
    l1*sin(O(1))+l2*sin(O(2))+l3*sin(O(3))-b; ...
    O(1)-pi/2]);
%% Solving using NR Multivariable Method (fsolve)
theta0 = [pi/2;0.58;1.3]; % initial guess
fsolve(phi,theta0)

I also attempted to solve it analytically https://de.mathworks.com/help/symbolic/solve-a-system-of-algebraic-equations.html

%% System Parameters 
a = 2.0;
b = 0.5;
l1 = 1.0;
l2 = 3.0;
l3 = 2.2;
m = 3;
syms t
syms O [m 1]

%% Equations
phi = [l1*cos(O1)+l2*cos(O2)+l3*cos(O3)-a==0; ...
    l1*sin(O1)+l2*sin(O2)+l3*sin(O3)-b==0;...
    O1-pi/2==0];

%% Solution
S = solve(phi,O);
num_sol_1 = double([S.O1(1);S.O2(1);S.O3(1)])
num_sol_2 = double([S.O1(2);S.O2(2);S.O3(2)])

Sources

“[Kehrein, Primer for Numerics]”

“[Brandt, 2909 Multibody Dynamics]”