How to accurately find angle between these two vectors ? (Data Provided).

3 views (last 30 days)
Cenker Canbulut on 24 Jul 2020
Edited: Matt J on 26 Jul 2020
Hi Everyone,
I am struggling so hard to accurately find angle between two vectors. I don't know where I am doing mistake but the angle result of cos(theta) from formula gives incorrect angle.
If you will be asking where I know that it is incorrrect, I know it because I am using rotation matrix to rotate one of them along Z-axis to fit one vector to another.
I basically want to rotate vector1 x,y,z with the angle found between vector1 and vector2.
Here is the angle I am trying to find.
and actually finding it with formula.
Angle Formula :
Rotation Formula along z-Axis (CLOCKWISE) :
|x cos(-θ) − y sin(-θ)| |x'|
|x sin(-θ) + y cos(-θ)| = |y'|
| z | |z'|
Graph rotates respectively and without deformation but much more than the found cousine value.
AFTER ROTATION:
Data
Image Analyst on 26 Jul 2020
Why can't you attach your data here? Also, if you could make it easy for us to help you, not hard, then provide the code to make those plots and also to extract the linear parts of the curves into their own arrays, without all the other curving stuff. That would make it easy for us to compute a transform that will rotate and shift the one set to align and overlap with the other.
Cenker Canbulut on 26 Jul 2020
Edited: Cenker Canbulut on 26 Jul 2020
Here is my Data before rotation.
DATA 1 - VRDataX, VRDataY, VRDataZ
DATA 2 - NewMocapX, NewMocapY, NewMocapZ
I will provide my solution and rest of your demands tomorrow.
Thank you for answer and the time you spread on this manner.

Matt J on 26 Jul 2020
Edited: Matt J on 26 Jul 2020
function [theta, Nrm]=vecrot(vstart,vend)
%Find rotation carrying one vector toward another about their common perpendicular
%axis.
%
%IN:
%
% vstart: Initial vector, 3D
% vend: Final vector, 3D
%
%OUT:
%
% theta: the rotation angle in degrees
% Nrm: the rotation axis, directed so that rotation is clock-wise by theta about Nrm
vstart=vstart(:)/norm(vstart);
vend=vend(:)/norm(vend);
Nrm=cross(vstart,vend);
b=vend.'*vstart;
theta = atan2d(sqrt(1-b^2),b);
Cenker Canbulut on 26 Jul 2020
With your solution, I used theta and the result wasn't as I wanted using the below rotation formula.
%Rotation for NewVRData to fit on MocapData on plot3
NewVRX = VRDataX * cos(-theta) - VRDataY * sin(-theta);
NewVRY = VRDataX * sin(-theta) + VRDataY * cos(-theta);
figure;
plot3(NewVRX,NewVRY,VRDataZ);
plot3(NewMocapX,NewMocapY,NewMocapZ);
blue is the VR data rotated with taken theta. It looks way off the Mocap Data
Matt J on 26 Jul 2020
Edited: Matt J on 26 Jul 2020
Since theta is in degrees, you should be using sind and cosd. Also, the rotation formula that you are using assumes inappropriately that Vector1 and Vector2 both lie in the xy-plane, and therefore that the rotation is about the z-axis. This is clearly not true:
Old=[VRDataX,VRDataY,VRDataZ].';
New=[NewMocapX,NewMocapY,NewMocapZ].';
Vector1=Old(:,end),
Vector2=New(:,end),
Vector1 =
149.3790
7.3849
4.0263
Vector2 =
149.3610
0.1810
3.8730
The actual rotation axis is returned in the Nrm output argument from the code I gave you. You can perform the rotation about this axis (or any other), using my AxelRot utility on the File Exchange
OldRotated=AxelRot(Old,theta,Nrm,[]);
hold on
scatter3(Old(1,:),Old(2,:),Old(3,:),'MarkerFaceColor','g','MarkerEdgeColor','none')
scatter3(New(1,:),New(2,:),New(3,:),'MarkerFaceColor','r','MarkerEdgeColor','none')
scatter3(OldRotated(1,:),OldRotated(2,:),OldRotated(3,:),'MarkerFaceColor','b','MarkerEdgeColor','none')
hold off
legend('Old','New','Old (Rotated)')
The alignment is not as good as my other answer, because the single-angle calibration model is not good (or so it seems). It ignores origin shift between the two data sets.

Matt J on 26 Jul 2020
Edited: Matt J on 26 Jul 2020
I don't know what your ultimate purpose is with this rotation you are trying to perform. If the goal is to make the two loci overlap as much as possible, I think you should be doing more than just a one degree-of-freedom angle match-up. I think you should be doing a full 6 degree-of-freedom rigid registration. You can do this with absor from the File Exchange, which for me gives pretty good overlap:
Old=[VRDataX,VRDataY,VRDataZ].';
New=[NewMocapX,NewMocapY,NewMocapZ].';
[reg,OldRotated,err]=absor(Old,New);
hold on
scatter3(New(1,:),New(2,:),New(3,:),'MarkerFaceColor','r')
scatter3(OldRotated(1,:),OldRotated(2,:),OldRotated(3,:),'MarkerFaceColor','b')
hold off
legend('New','Old (Rotated)')
Cenker Canbulut on 26 Jul 2020
I really don't think taking a data point and fixing it with some expression is a good idea in my case. I really would rather do it and hard code it myself but explain it to committee with good relief with mathematically satisfying answers than do something that involves many complex calculations at the background.
Matt J on 26 Jul 2020
Edited: Matt J on 26 Jul 2020
Well, use my other answer then, but fix the problems with your rotation code that I mentioned above.