How do I know if two vectors are near parallel - vector

I am having some trouble finding parallel vectors because of floating point precision. How can I determine if the vectors are parallel with some tolerance?
I also need a check for orthogonality with tolerance.

For vectors v1 and v2 check if they are orthogonal by
abs(scalar_product(v1,v2)/(length(v1)*length(v2))) < epsilon
where epsilon is small enough. Analoguously you can use
scalar_product(v1,v2)/(length(v1)*length(v2)) > 1 - epsilon
for parallelity test and
scalar_product(v1,v2)/(length(v1)*length(v2)) < -1 + epsilon
for anti-parallelity.

If you have 3D vectors the answer is simple. Compute the cross product and if it is nearly zero, your vectors are nearly parallel:
http://mathworld.wolfram.com/ParallelVectors.html
For 2d vectors you can convert them into 3D vectors just by adding a coordinate with zero
(1;2) => (1;2;0), (4; 5.6) => (4; 5.6; 0) and so on
Two vectors are orthogonal or perpendicular, if there dot product ist zero:
http://mathworld.wolfram.com/CrossProduct.html
-edit
http://mathworld.wolfram.com/Perpendicular.html

If you're working with 3D vectors, you can do this concisely using the toolbelt vg. It's a light layer on top of numpy and it supports single values and stacked vectors.
import numpy as np
import vg
v1 = np.array([1.0, 2.0, 3.0])
v2 = np.array([-2.0, -4.0, -6.0])
vg.almost_collinear(v1, v2)
# True
I created the library at my last startup, where it was motivated by uses like this: simple ideas which are verbose or opaque in NumPy.

Related

Rotation matrix, normalization, determinant -1

I'm currently implementing an algorithm for 3D pointcloud filtering following a scientific paper.
I run in some problems when computing the rotation matrix for specific values. The goal is to rotate points into the coordinatesystem which is defined by the direction of the normal vector ( Z Axis). Since the following query is rotationally symmetric in X,Y axis, the orientation of these axis does not matter.
R is defined as follows: Rotationmatrix
[1 1 -(nx+ny)/nz]
R = [ (row1 x row3)' ]
[nx ny nz ]
n is normalized. The problem occures when n_z becomes really small or zero. Therefore i considered to normalize row 1 before computing the crossproduct for row 2.
Nevertheless the determinant becomes -1. Will the rotationmatrix sill lead to correct results? R is orthogonal but det|R| not +1
thanks for any suggestions
You always get that
det(a, a×b, b) = - det( a, b, a×b)
= - dot(a×b, a×b)
is always negative. Thus you need to change the second row by negating it or by re-arranging the overall order of the rows.
Are you interested in rotating points around arbitrary axis? If yes, maybe quaternions is good solution.
You can check this if you want to transform a quaternion to matrix before you actually use it.

Scale vector along plane

I'm trying to apply friction to a 3D collision. The information I have is:
The velocity of the collision
The surface normal of the collider
An arbitrary friction coefficient (0 - 1 inclusive)
What I would like to do is multiply the portion of the velocity that is parallel to the plane by the friction coefficient, while leaving the portion parallel to the normal intact.
How can I go about performing this operation?
I was thinking perhaps this will involve the use of the dot-product, but then I started reading about matrices, then vector projection, and now I'm pretty lost.
I was able to solve the problem by doing the following:
Get a tangent vector for the normal
Use the normal and the tangent vector to get a rotation matrix for the surface
Use the inverse of the rotation matrix to transform the velocity vector
Scale the x and z components of the transformed vector by the friction coefficient
Use the rotation matrix to transform the velocity back again
I doubt this is the most efficient way of doing it, but it seems to have worked.
If you can do vector addition, scalar multiplication (i.e. multiplying a vector by a number) and the dot product, then this is all you need:
Vin = (V•Vnormal)Vnormal
Vpar = V - Vin
Vpar = kVpar (where k is the coefficient, and "=" means assignment)
Vin = -Vin
V = Vin + Vpar

Calculate 3D Euler angle between two 3D vectors?

Say I have 2 3D vectors, each describing a direction in 3D space (or a rotation, but I'm not sure if that terminology is correct). How would I calculate the difference between the two vectors as an Euler angle? That is, if I applied the angle to the first vector, it would rotate to equal the other? I understand how Euler angles have issues and are implementation-dependant, but I don't know what the implications of this are on a question such as mine.
To clarify a little, when I say "3D vectors", I'm picturing the "translation" gizmo you get in most 3D modelling packages or in Unity (which is what I'm using).
EDIT: Actually I just reviewed the "vectors" that I'm using, and what I said is not quite correct. I actually have 6 vectors, 3 for each rotation. Each vector is a position in 3D space offset from the centre of rotation. This probably makes an already-difficult question near-impossible, right?
ADDITIONAL INFORMATION: Ok, so I've worked out what I actually want to ask (because this question is really badly done), and it applies more to Unity, so I've asked a more Unity-specific question over on Unity Answers.
I'm don't normally understand mathematical formulae that are posted online, so C++-styled pseudo-code would be by far the most helpful for me.
Any help would be much appreciated, and if my question lacks certain information, please just ask for more :)
If you are going to do 3d you need to understand linear algebra and matrix notation.[1] Affine 4x4 matrices are the basis of space transformations in all 3d applications I've ever seen, (Euler angles just give alternate means to describe that matrix). Even unity uses matrices, although to be able to efficiently do the Euler-Lagrange particle motion equation they prefer to have the decomposed form. A matrix encodes a entire space with 4 vectors. This is conceptually easy in this case (not the only use for matrices), the matrix encodes the directions x y z and offset vector w.
The reason matrix notation is useful is: It becomes possible to manipulate the things like normal math symbols. If you remember from school solving x from:
a * x = b
Divide both sides by a and you get
a/a * x = b /a ->
x = b / a
Now if you have 2 spaces with 3 vectors each you essentially have 2 fully formed spaces at origin. Assuming the vectors span a 3D space (in other words dont point all in one plane, its even better if they are orthogonal to each other in which case you can just use transformation functions directly). That means you have 3 spaces. So your problem is given you know 2 spaces. You need to know the space transform form space A -> space B (its customary to give matrices big letters to denote they are more complex). This is mathematically:
A * X = B
Where * is a matrix multiplications and A, X and B are transformation matrices. So then divide by A, but alas there's no matrix division, fortunately there is inverse and division is multiplication by inverse so that's what we do instead. Also one other note rotations are not commutative so we need to specify on which side we multiply so because A is before X we multiply on the left hand side with inverse of A. So we get:
A^-1 * A * X = A^-1 * B
Where ^-1 denotes matrix inverse. This simplifies to :
I * X = A^-1 * B ->
X = A^-1 * B
X is the rotation space. In unity code this looks like:
X = A.inverse * B
Where X, A and B are Matrix4x4 elements The language you use may have other conventions I'm using the java script reference here. You can covert this matrix to a quaternion and from there to Euler angles an example of this can be found here.
How to form A and B from the vectors? Just put the vector for starting space to A's columns 0-2 and destination spaces correspondingly to B columns[2].
[1] Yes its compulsory, its much simpler than it may seem at first. While you can live quite far without them they aren't any harder to use than saying rotate about x axis fro so and so. Also learn quats.
[2] I should check this, but unity seems to use column matrices so it should be right
PS: By the way if you have noisy data and more then 3 vectors per instance then you can use least squares to average the matrix t a 3 by 3 sub matrix.

error between two rotations?

sorry - I should know this but I don't.
I have computed the position of a reference frame (S1) with respect to a base reference frame (S0) through two different processes that give me two different 4x4 affine transformation matrices. I'd like to compute an error between the two but am not sure how to deal with the rotational component. Would love any advice.
thank you!
If R0 and R1 are the two rotation matrices which are supposed to be the same, then R0*R1' should be identity. The magnitude of the rotation vector corresponding to R0*R1' is the rotation (in radians, typically) from identity. Converting rotation matrices to rotation vectors is efficiently done via Rodrigues' formula.
To answer your question with a common use case, Python and OpenCV, the error is
r, _ = cv2.Rodrigues(R0.dot(R1.T))
rotation_error_from_identity = np.linalg.norm(r)
You are looking for the single axis rotation from frame S1 to frame S0 (or vice versa). The axis of the rotation isn't all that important here. You want the rotation angle.
Let R0 and R1 be the upper left 3x3 rotation matrices from your 4x4 matrices S0 and S1. Now compute E=R0*transpose(R1) (or transpose(R0)*R1; it doesn't really matter which.)
Now calculate
d(0) = E(1,2) - E(2,1)
d(1) = E(2,0) - E(0,2)
d(2) = E(0,1) - E(1,0)
dmag = sqrt(d(0)*d(0) + d(1)*d(1) + d(2)*d(2))
phi = asin (dmag/2)
I've left out some hairy details (and these details can bite you). In particular, the above is invalid for very large error angles (error > 90 degrees) and is imprecise for large error angles (angle > 45 degrees).
If you have a general-purpose function that extracts the single axis rotation from a matrix, use it. Or if you have a general-purpose function that extracts a quaternion from a matrix, use that. (Single axis rotation and quaternions are very closely related to one another).

Combine Rotation Axis Vectors

I'm experimenting with using axis-angle vectors for rotations in my hobby game engine. This is a 3-component vector along the axis of rotation with a length of the rotation in radians. I like them because:
Unlike quats or rotation matrices, I can actually see the numbers and visualize the rotation in my mind
They're a little less memory than quaternions or matrices.
I can represent values outside the range of -Pi to Pi (This is important if I store an angular velocity)
However, I have a tight loop that updates the rotation of all of my objects (tens of thousands) based on their angular velocity. Currently, the only way I know to combine two rotation axis vectors is to convert them to quaternions, multiply them, and then convert the result back to an axis/angle. Through profiling, I've identified this as a bottleneck. Does anyone know a more straightforward approach?
You representation is equivalent to quaternion rotation, provided your rotation vectors are unit length. If you don't want to use some canned quaternion data structure you should simply ensure your rotation vectors are of unit length, and then work out the equivalent quaternion multiplications / reciprocal computation to determine the aggregate rotation. You might be able to reduce the number of multiplications or additions.
If your angle is the only thing that is changing (i.e. the axis of rotation is constant), then you can simply use a linear scaling of the angle, and, if you'd like, mod it to be in the range [0, 2π). So, if you have a rotation rate of α raidans per second, starting from an initial angle of θ0 at time t0, then the final rotation angle at time t is given by:
θ(t) = θ0+α(t-t0) mod 2π
You then just apply that rotation to your collection of vectors.
If none of this improves your performance, you should consider using a canned quaternion library as such things are already optimized for the kinds of application you're disucssing.
You can keep them as angle axis values.
Build a cross-product (anti-symmetric) matrix using the angle axis values (x,y,z) and weight the elements of this matrix by multiplying them by the angle value. Now sum up all of these cross-product matrices (one for each angle axis value) and find the final rotation matrix by using the matrix exponential.
If matrix A represents this cross-product matrix (built from Angle Axis value) then,
exp(A) is equivalent to the rotation matrix R (i.e., equivalent to your quaternion in matrix form).
Therefore,
exp (A1 + A2) = R1 * R2
probably a more expensive calucation in the end...
You should use unit quaternions rather than scaled vectors to represent your rotations. It can be shown (not by me) that any representation of rotations using three parameters will run into problems (i.e. is singular) at some point. In your case it occurs where your vector has a length of 0 (i.e. the identity) and at lengths of 2pi, 4pi, etc. In these cases the representation becomes singular. Unit quaternions and rotation matrices do not have this problem.
From your description, it sounds like you are updating your rotation state as a result of numerical integration. In this case you can update your rotation state by converting your rotational rate (\omega) to a quaternion rate (q_dot). If we represent your quaternion as q = [q0 q1 q2 q3] where q0 is the scalar part then:
q_dot = E*\omega
where
[ -q1 -q2 -q3 ]
E = [ q0 -q3 q2 ]
[ q3 q0 -q1 ]
[ -q2 q1 q0 ]
Then your update becomes
q(k+1) = q(k) + q_dot*dt
for simple integration. You could choose a different integrator if you choose.
Old question, but another example of stack overflow answering questions the OP wasn't asking. OP already listed out his reasoning for not using quaternions to represent velocity. I was in the same boat.
That said, the way you combine two angular velocities, with each represented by a vector, which represents the axis of rotation with its magnitude representing the amount of rotation.
Just add them together. Component-by-component. Hope that helps some other soul out there.

Resources