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

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
All answers are welcomed

5 Comments

can you post your code used to generate that result?
by the way, i don't know how much the paths are expected to match, but i don't think a simple rotation about z will cut it...if you look at the straight part, it looks like you also need at least a shift.
Yes Alex. I will do the shift at later stage. I don't think It will be hard to obtain since I have all data for y-axis. I am not at my workplace yet. I will post my solution tomorrow in the morning.
If you could, You can get my data provided with the download link: https://we.tl/t-auUXB2YMvv
DATA 1 - VRDataX, VRDataY, VRDataZ
DATA 2 - NewMocapX, NewMocapY, NewMocapZ
Basically Plot3(built-in function) for both datas will give the result before rotation.
The angle on both x-axis for Data1 and Data2 should be found and rotated (3D Rotation) approximately(mathematically accurate enough) to fit one to another at x axis.
As I said, I have my solution and will post it tomorrow. But If you could give a try for this task I would appriciate.
Thank you.
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.
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.

Sign in to comment.

 Accepted Answer

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);

5 Comments

I will check it tomorrow and let you know.
Could you integrate this data onto this function, If you can. If not, I will just do it myself and show it here.
Thank you for your answer. Very much appriciated.
Matt Could you look at my data and place the right input at right places. Because I am getting same result as my solution. Here's how I called the given function and did the rotation with rotation formula.
[theta, Nrm]=vecrot([VRDataX(1),VRDataY(length(VRDataY)),VRDataZ(length(VRDataZ))],[NewMocapX(1),NewMocapY(length(NewMocapY)),NewMocapZ(length(NewMocapZ))]);
load('MyData.mat')
Old=[VRDataX,VRDataY,VRDataZ].';
New=[NewMocapX,NewMocapY,NewMocapZ].';
[theta,Nrm]=vecrot(Old(:,end),New(:,end))
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
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:
load('MyData.mat')
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.

Sign in to comment.

More Answers (1)

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:
load('MyData.mat')
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)')

6 Comments

In my purpose, data shouldn't be manipulated or error shouldn't be included to exactly match one to another. I need this rotation for calibrating 2 different world axises taken from 2 different devices.
VR (Virtual Reality) has its own world axis.
TradeMill (Mocap) has its own.
I calibrated them at the research center as much as I can manually and thought I could do the math to calibrate their world axis later on using matlab. But seems miserably hard work to do..
But your data don't seem to share a comon z-axis or xyz origin as you appear to be assuming. absor will calibrate the orientation of all 3 axes as well as the origin translation between them.
I basically don't need a common z-axis. Their axises are independent. All I need is to calibrate their World Space. Their XYZ is independent but act quite similiar as both devices are doing basically same thing (track position of user movement). Their World axis is different. All I need is to find an axis at both that can be aproximately direct the same way as one another(In my case x axis). Basically, find between 2 vectors a mathematically quite accurate angle which will be quite satisfying and rotate one of them to fit another's direction to closely calibrate their world axis. This is for a research to analyze two devices.
As I said, those two devices do same thing. Track position. And both of them have good reference to know at what direction they are moving. This way, I can calibrate one's world axis to another by calculating the angle between one x axises and rotate 3D vector at given angle.
P.S They both track one user at a time. So, that is why data is quite similar but not calibrated.
I need just world axis aligment. Nothing else. No data manipulation with taken error or some sort.
What you are saying, in effect, is that you do not need a very accurate axes calibration. But then there is no reason not to use the calibration that absor gives you. It is at least as accurate as the calibration that you were already planning to use. The only difference is that instead of doing a single-theta rotation to transform points, you would use the transform parameters reg that absor gives you:
NewPoints=reg.R*OldPoints+reg.t
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.
Well, use my other answer then, but fix the problems with your rotation code that I mentioned above.

Sign in to comment.

Asked:

on 24 Jul 2020

Edited:

on 26 Jul 2020

Community Treasure Hunt

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

Start Hunting!