How to calculate the angle between two 3D vectors?

조회 수: 466 (최근 30일)
Unnamed User
Unnamed User 2024년 3월 11일
편집: James Tursa 2024년 3월 11일
I have two vectors that I want to calculate the angle between in 3D space, U and V. Vector U is calculated by subtracting where the first object was at Point 1 from where the object currently is at Point 2. Vector V is calculated by subtracting where the second object is at Point 2 from where the first object is at Point 2. This should essentially make vector V perpendicular-ish to vector U.
I have scoured these forums and come across multiple lines of code that apprently work:
angle = atan2(norm(cross(u,v)), dot(u,v))
CosTheta = max(min(dot(u,v)/(norm(u)*norm(v)),1),-1);
angle = acos(dot(u,v)/norm(u)*norm(v))
angle = acos(dot(u)/norm(u),v/norm(v))
All seem to produce the desired angle when I run it with changes only in 2D, so no movement in the Z domain. However as soon as I try use the above formula for 3D movement is starts producing wrong results. I've double checked what the angle should be by using an online calculator and doing the calculations by hand and the formula seem to always be off.
For example. Object 1 travelling from (128,97,138) to (78,47,88) and object 2 travelling from (0,0,0) to (50,50,0) should produce an angle of 144.735 degrees at the last step; but using any of the above formula gives 134 degrees.
Is there something I'm missing here?
Thanks!
  댓글 수: 1
James Tursa
James Tursa 2024년 3월 11일
You've got errors in the the last two formulae. See my post below for corrections.

댓글을 달려면 로그인하십시오.

답변 (2개)

James Tursa
James Tursa 2024년 3월 11일
편집: James Tursa 2024년 3월 11일
See a discussion here (includes a tiny angle example):
A comparison (correcting the formulae you wrote):
% most robust, most accurate, recovers tiny angles very well, slowest
atan2(norm(cross(u,v)), dot(u,v))
% robust, does not recover tiny angles, faster
max(min(dot(u,v)/(norm(u)*norm(v)),1),-1)
% not robust (may get domain error), does not recover tiny angles, fasterer
acos(dot(u,v)/(norm(u)*norm(v)))
% not robust (may get domain error), does not recover tiny angles, fasterer
acos(dot(u/norm(u),v/norm(v)))
% not robust (may get domain error), does not recover tiny angles, fastest
acos(dot(u,v)/sqrt(dot(u,u)*dot(v,v)))
By "domain error", I mean the dot( ) argument magnitude can be slightly larger than 1 in some u==v cases due to floating point numerical effects resulting in an unintended complex result. The "robust" methods are protected against this. Also, if one of the arguments is 0 vector, the atan2( ) method returns 0 while the other methods will return NaN. So the atan2( ) method is the "most robust" in this sense. Caveat: This assumes the language in use has atan2(0,0) coded this way (like MATLAB, Java, etc.), but is not guaranteed across all languages.
That last method is one I threw in that is essentially the same as method 3, except that only one sqrt( ) is needed instead of two norm( ) calls.
Finally, the relative speed rankings above are somewhat notional and can be highly dependent on the language being used and how the algorithm is coded. E.g., the dot( ) function is notoriously slow in MATLAB, so if I were to code the methods above I would use some form of matrix multiply instead. If u and v are column vectors, that last method could be coded as:
acos(u'*v/sqrt((u'*u)*(v'*v)))

Jonas
Jonas 2024년 3월 11일
look here:
P1=[78,47,88]-[128,97,138];
P2=[50,50,0]-[0,0,0];
a = atan2d(norm(cross(P1,P2)),dot(P1,P2))
a = 144.7356

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by