# Rotation of 3 vectors together

6 views (last 30 days)
Ozzy on 8 Nov 2021
Commented: William Rose on 9 Nov 2021
Hello, could you give me some tips about how to best transform 3 3D vectors together without changing the angles between them? I have 3 vectors as specified below:
x = [0;0;1];
y = [0;-0.9952;0.0976];
z = [0.9969;0.0433;0.0663];
Now, I want to create another 3 vectors which will preserve these same angle relationships between them, but each of these new angles will have a different angular relationship with their x-y-z pair. So for instance the angle between xNew and x will be 11.3, yNew and y will be 103.4, and zNew and z will be 83.2 degrees. But the angular relationships between xNew, yNew, and zNew will be the same as the relationships between x,y, and z. I am having a hard time imagining these vectors in 3D, so not sure if this is doable. If it is doable, is an iterative registration about 3 dimensions that tries to minimize the RMSE between the current and desired angle the way to go, or is there an easier way to find these new vectors?

William Rose on 9 Nov 2021
Edited: William Rose on 9 Nov 2021
Here is code that adjusts a rotation matrix to get the best fit. Best fit is defined as the minimum error between the desired angles between vectors and the actual angles between vectors. The root mean square difference between actual and desired angles, in this particular case, is 7.5 degrees.
I am also attaching notes that explain the code.

Matt J on 8 Nov 2021
Edited: Matt J on 9 Nov 2021
It's definitely not possible for an arbitrary combination of angles, but when a solution does exist, this should find it:
x = [0;0;1];
y = [0;-0.9952;0.0976];
z = [0.9969;0.0433;0.0663];
targetAngles=[60,60,0];
targetAngles=[11.3,103.4,83.2];
X=normalize([x,y,z],1,'norm',2);
t=cosd(targetAngles);
eps=1e-14;
opts=optimoptions('fmincon','OptimalityTolerance',eps,'StepTolerance',eps,...
'ConstraintTolerance',eps,'FunctionTolerance',eps,...
'MaxFunctionEvaluations',Inf,'MaxIterations',inf, ...
'Algorithm','interior-point');
UB=ones(3);
[R0,fval]=fmincon(@(R)Func(R,X,t), eye(3),[],[],[],[],-UB, UB,@nonlcon,opts);
Local minimum possible. Constraints satisfied. fmincon stopped because the size of the current step is less than the value of the step size tolerance and constraints are satisfied to within the value of the constraint tolerance.
[U,S,V]=svd(R0);
R=U*V'; %"round" to the nearest rotation matrix
Check = acosd(sum( (R*X).*X )) %Verify if target angles reached.
Check = 1×3
14.2603 94.9122 91.8032
RMS = norm(Check-targetAngles)/sqrt(3)
RMS = 7.1838
function F=Func(R,X,t)
F = norm(acos(sum( (R*X).*X ))-acos(t)).^2;
end
function [c,ceq]=nonlcon(R)
f2 = R*R.'-eye(3);
f3 = det(R)-1;
ceq=[f2(:);f3(:)]; c=[];
end
William Rose on 9 Nov 2021
Very impressive, @Matt J! Now Matt J minimizes the Func(R,X,t)=sum squared error between the actual dot products and the desired cosines. He uses fmincon() to adjust all 9 elements of R, to minimize Func(R,X,t). He uses the nonlinear constraint capability of fmincon() in a very smart way to make sure that as fmincon() adjusts R, it stays a rotation matrix, or very close to it. And he uses the upper and lower limits feature of fmincon() to constrain the guesses for the elements of R to the range [-1,+1].
An advantage of @Matt J's solution, compared to mine, is that he did not have to code the equations for the rotation matrix in terms of the Euler angles. There is potential for making mistakes when one does that. An advantage of my way is that it provides the Euler angles - which are sometimes important or useful to know. Euler angles provide a way of explaining the rotation, which the R matrix alone does not. Ofo course you can get the Euler angles from R, but that also takes more code.

William Rose on 9 Nov 2021
Rotations preserve angles between vectors. You multiply the array of column vectors by a 3x3 rotation matrix.
x = [0;0;1]; y = [0;-0.9952;0.0976]; z = [0.9969;0.0433;0.0663];
V=[z, y, x]; %each vector is a column of V
%By choosing the order [z,y,x], matrix V is close to the identity matrix.
%This may be useful later.
R=[1,0,0; 0,1,0; 0,0,1]; %rotation matrix (equals identity matrix, for now)
%Rotation by the identity matrix leaves the vectors where they are.
Vn=R*V; %Vnew= = RotationMatrix * V
The R matrix must follow certain rules in order to be a rotation. It must have determinant=1 (to preserve volume), and its inverse equals its transpose (for less obvious reasons). Although R has nine elements, R has only three adjustable parameters. The nine elements are functions of the three parameters.
Vectors x,y,z are unit vectors, or very close to it, and they are close to orthogonal. Let's determine the angles are between vectors x and y and z:
fprintf('angle(x,y)=%.1f degrees.\n',(180/pi)*acos(x'*y/(norm(x)*norm(y))));
angle(x,y)=84.4 degrees.
fprintf('angle(y,z)=%.1f degrees.\n',(180/pi)*acos(y'*z/(norm(y)*norm(z))));
angle(y,z)=92.1 degrees.
fprintf('angle(z,x)=%.1f degrees.\n',(180/pi)*acos(z'*x/(norm(z)*norm(x))));
angle(z,x)=86.2 degrees.
More later.

Ozzy on 9 Nov 2021
Thank you very much for both answers. That was of great help!

R2020a

### Community Treasure Hunt

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

Start Hunting!