Unable to run pinv (Moore Penrose) , get errors

Tried the following script:
r0=[0,0,0];
dq=double(pinv(J_BF_inB)*(rGoal-r0));
dq=double(subs(dq,[alpha,beta,gamma],[0,0.52,1.04]));
q=q0;
for n=1:10
q=q+dq;
end
I get the following errors:
Error using svd
First input must be single or double.
Error in pinv (line 18)
[U,s,V] = svd(A,'econ');
Error in solution (line 24)
dq=double(pinv(J_BF_inB)*(rGoal-r0));

2 Comments

what is class(J_BF_inB)
Sorry, I should have mentioned it:
J_BF_inB=@(alpha,beta,gama)[0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)];

Sign in to comment.

Answers (1)

You cannot take the pseudo-inverse of a function handle.
If you were to construct a symbolic array you might be able to pinv() that, but you would not be able to double() the results.
Are you expecting that the 3x3 matrix might not have full rank? If full rank is expected then this would look more like a job for the \ operator

12 Comments

All I am trying is to iteratively solve for the angular position (dq) of the robot to reach a final position from a starting i.e. r0 position. Not sure why I am getting so many errors.
J_BF_inB=@(alpha,beta,gama)[0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)];
Okay, that's a function handle.
dq=double(pinv(J_BF_inB)*(rGoal-r0));
What happens if we pinv() a function handle?
pinv(J_BF_inB)
Error using svd
First input must be single or double.

Error in pinv (line 18)
[U,s,V] = svd(A,'econ');
Was it maybe the wrong function handle?
pinv(@(x)1)
Error using svd
First input must be single or double.

Error in pinv (line 18)
[U,s,V] = svd(A,'econ');
No, even though pinv(1) would obviously be valid, pinv() of a function handle that would return 1, fails.
dq=double(pinv(J_BF_inB)*(rGoal-r0));
We can see from the position of the brackets, that whatever is returned by pinv(J_BF_inB)*(rGoal-r0) is to be converted to class double. Imagine that we had arranged J_BF_inB and rGoal-r0 to be something that double() could convert to double precision. Imagine, for example, that it returned [1 2 4; 3 5 6; 7 8 9]
dq=double([1 2 4; 3 5 6; 7 8 9])
dq = 3×3
1 2 4 3 5 6 7 8 9
whos dq
Name Size Bytes Class Attributes dq 3x3 72 double
Okay, dq is 3 x 3, class double. Now let us go on to the next line
dq=double(subs(dq,[alpha,beta,gamma],[0,0.52,1.04]));
and let us focus on the subs() part
subs(dq,[alpha,beta,gamma],[0,0.52,1.04])
Error using alpha
Too many output arguments.
... which is because we did not define alpha, beta or gamma
syms alpha beta gamma
So now we have defined them as symbolic
dq=double([1 2 4; 3 5 6; 7 8 9])
dq = 3×3
1 2 4 3 5 6 7 8 9
subs(dq,[alpha,beta,gamma],[0,0.52,1.04])
ans = 
But that's exactly the same as dq. Since you forced dq to be double precision in the line above, we can be certain that dq is not symbolic, so we can be certain that dq does not contain any symbolic variable alpha, beta, or gamma . So what is the point of doing the subs?
So maybe...
syms alpha beta gama
syms rGoal r0
J_BF_inB = [0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)]
Error using gamma
Not enough input arguments.
What happened? Well, notice your original code
J_BF_inB=@(alpha,beta,gama)[0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)];
declares J_BF_inB to be a function of alpha, beta and gama but then is written in terms of alpha, beta and gamma . Notice that gama and gamma are not the same thing, so the references to gamma inside your function handle were references to the function gamma() not to the named parameter gama
Thanks. Not sure what the conclusion is. As mentioned, J_BF_inB is the MPenrose Jacobian. I am using it to multiply with the position vector r (position of the 3 robot arms) to get the relative angles of the 3 arms. This is done iteratively, i.e. in a while loop to minimize the difference between the actual position vector r and the goal position vector rGoal, hence the tolerance 1e-4. So, it appears that this is not possible in Matlab.
So let us go for symbolic gamma:
syms alpha beta gamma
syms rGoal r0
J_BF_inB = [0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)]
Error using sym/cat>checkDimensions (line 68)
CAT arguments dimensions not consistent.

Error in sym/cat>catMany (line 33)
[resz, ranges] = checkDimensions(sz,dim);

Error in sym/cat (line 25)
ySym = catMany(dim, args);

Error in sym/vertcat (line 19)
ySym = cat(1,args{:});
dq = pinv(J_BF_inB)*(rGoal-r0)
dq = subs(dq,[alpha,beta,gamma],[0,0.52,1.04])
What now?
Well, that comma at the end of the first line of your definition of J_BF_inB: are the things on the second line intended to be a continuation of the first line? If so then you would have 5 components in the first row, but only 3 in the second row (which would start where you have the semi-colon)
With your current coding, you have
[value1,value2,value3,
value4,value5;...
value6,value7+...
value8,value9]
and the way continuation lines work in MATLAB, that would be equivalent to
[value1,value2,value3,
value4,value5; value6,value7+ value8,value9]
and within [], MATLAB treats end of line (not preceeded with ... continuation marker) as a semi-colon, so that would be equivalent to
[value1,value2,value3,;value4,value5; value6,value7+ value8,value9]
In MATLAB, it is valid to have an extra comma before a semi-colon, and the extra comma will be ignored. Also, value7+ value8 will be treated as a single addition, plus(value7,value8): the odd spacing of no space after the first term but space before the second term is acceptable in MATLAB, and is all part of the same expression. (In MATLAB, inside [] it is different to have [value7+ value8] than it is to have [value7 +value8] with the second of those being equivalent to [value7,+value8] which is [value8,uplus(value8)] where uplus is the "unary plus" operator.)
So, that would be equivalent to
[value1,value2,value3;value4,value5;value6,value7+value8,value9]
Notice that is 3 items in the first row, 2 items in the second row, and 3 items in the third row.... which is inconsistent.
I will arbitrarily add a value into the second row, to see if we can get further
tic
syms alpha beta gamma real
syms rGoal r0 real
syms arbitrary real
J_BF_inB = [0,-cos(beta+gamma)-cos(beta),cos(alpha)*(cos(beta+gamma)+cos(beta)+1),
arbitrary,-sin(alpha)*(sin(beta+gamma)+sin(beta)),-sin(beta+gamma)*sin(alpha);...
sin(alpha)*(cos(beta+gamma)+cos(beta)+1),cos(alpha)*(sin(beta+gamma)+...
sin(beta)),sin(beta+gamma)*cos(alpha)]
J_BF_inB = 
dq = pinv(J_BF_inB)*(rGoal-r0)
dq = 
dq = subs(dq,[alpha,beta,gamma],[0,0.52,1.04])
dq = 
toc
Elapsed time is 12.422751 seconds.
Well, at least that is something that could be double() if your arbitary and r_0 and rGoal were numeric.
If you try to put the arbitrary as the second or third element of the second row, then the result of the pinv will be something that gives a division by 0 when you substitute 0 for alpha.
Sorry, not sure how this helps solve my problem.
It helps solve your problem by pointing out where you went wrong on constructing the matrix.
It continues from there in stating that if you put in an arbitrary value for the 2nd or 3rd element of the middle row of the matrix (the one that is missing an element) then you get a singularity when you substitute alpha = 0, which makes it less likely (but not impossible) that the missing element is in the second or third position.
It then shows that if you put an arbitrary value as the first element of the second row, so that you can get out a 3 x 3 matrix, then you can calculate pinv(J_BF_inB)*(rGoal-r0) and then substitute in alpha, beta, gamma values .
How does it help you solve your overall question? Well it helps you debug the problem and shows you the kind of operations that can be done.
Does it solve the overall problem? Certainly not. As I have been explaining to you, your approach is wrong. Over in https://www.mathworks.com/matlabcentral/answers/1648515-unable-to-run-pinv-moore-penrose-with-accuracy-limit#answer_895320 I described the steps you need to take.
Thanks. Main problem is my limited knowledge of Matlab, hence unable to fully comprehend your suggestions. I felt your suggestion where you outlined the steps and rationale was really good. Hence I tried to use it and then got the error about single/double. That was due to using pinv on the handle as you mentioned often. So, I would like to use that approach if somehow I could circumvent the handle issue. The 3X3 matrix does not have full rank, hence iterative solution is used.

Sign in to comment.

Categories

Find more on Mathematics and Optimization in Help Center and File Exchange

Tags

Asked:

Ken
on 11 Feb 2022

Commented:

Ken
on 14 Feb 2022

Community Treasure Hunt

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

Start Hunting!