I need help figuring out how to calculate the magnitude of a dual number and then how to use it to normalize the number.
The closest answer I found was this: Properly normalizing a dual quaternion
However, there is either an error there or (more likely) I do not understand the notation. The reply to that post states that the magnitude of a unit dual quaternion (still a form of a dual number) is as follows:
QQ' = (R, D)(R*, D*) = (RR*, RD* + DR*) = (1, 0)
Note that this is a dual number, not a single value. I have seen this same result in many articles on dual quaternions, but none of them explain why the dual number is 0 (zero).
I assume that, if a dual quaternion is normalized, then its real and dual component quaternions are also normalized. In this case, the quaternion conjugate is equivalent to it's inverse, and RR* does indeed = 1. But if they are not normalized, then RR* does not = 1, so what do I do then?
Additionally, RD* + DR* is not 0 (unless I'm reading the notation wrong), but rather
RD* + DR* = [2(R.scalar)(D*.scalar) + 2dot(R.vector,D.vector), <0,0,0>]
which is a quaternion with non-zero scalar and a "zero vector", so to speak. This quaternion is certainly not of magnitude 0.
Besides, the wiki on dual quaternions, this blog post (be very careful when reading the terms, because he uses bold q's and normal q's and q's with subscripts for dual quaternions, quaternions, and real numbers, which is terribly confusing, but it is correct: http://simonstechblog.blogspot.com/2011/11/dual-quaternion.html), and my own calculations confirmed that a dual number times it's conjugate is another dual number, NOT a single value.
Do I divide the dual number by it's dual number magnitude to normalize? How does that work? I'm stuck.
Related
I recently found a way here on stackoverflow to calculate modulus using the fx991es. It must be configured to use radiants in order to make this work.
Pol(-Rec(1/(2π) , 2π×A/B), Y)(π - Y)B
How to calculate a Mod b in Casio fx-991ES calculator
However I do not really understand how this works. I see that its some math-hack using polar coordinates and stuff. But why does this actually work?
I don't know much about this calculator specifically. But intuitively, using angles should be because they naturally are modulo 2π.
But first, we need to understand what the functions do.
Pol takes 2 arguments that are Cartesian coordinates of a point (X,Y), and stores in these variables the polar coordinates : X receives the radius r, and Y the angle.
Rec takes 2 arguments that are polar coordinates of a point (r,angle), and stores in these variables the Cartesian coordinates : r receives the X, and the angle receives Y.
Both these functions return the first argument if used inside an expression, i.e. Pol returns the radius r, and Rec returns X. It also says that Pol returns the angle in the angle unit defined as default in the calculator, and that it is expressed in the range [-π,+π[
Let us now resolve your expression according to the order of priorities in the calculator
Rec
Rec(1/(2π) , 2π×A/B) returns the X coordinate of a point at a distance 1/2π from the center, and with an angle 2πA/B, which will be taken modulo 2π, effectively taking (A/B modulo 1) * 2π.
You say that Rec overwrites Y with the second coordinate -- I trust you on that, since I don't have the calculator myself and can't seem to find an emulator.
So the expression is Pol(-X, Y)(π - Y)B
Pol
We now have Pol(-X,Y). Flipping the sign of X has no effect on the radius, in polar coordinates, but it changes the angle from a value A to π-A.
So we now get in the Y variable the modified the angle, thus π-2πA/B reduced in [-π,+π[ modulo 2π. And Pol returns the radius, thus 1/(2π).
The formula is now 1/(2π)(π-Y)B.
Tying up loose ends
π-Y gives us now the angle shifted in [0,2π[, and dividing it by 2π yields simply A/B modulo 1. Multiplying by B gives then A modulo B.
TL;DR
Going to/from polar coordinates gives a free modulo 2π calculation, applied to A/B to get its fractional part, and the π-Y trick done twice (one written like that, the other by doing -X) is because the angle is not directly given in a range [0,2π[, but rather [-π,+π[.
I have this formula
B = tan(atan(A) + C)
where A is the input, B is output and C is a constant. The problem is that sin, cos and tan functions are computationally expensive and also there is quite a big loss of precision along the formula when calculated as 4 byte floats. I am in the process of optimizing my code so is there any way to avoid using these functions even if the total number of calculations is several times higher?
Further background: the numbers A, B and C are the ratio's of x/y coordinate for 3 points on a 2 dimensional plane
According to Wolfram Alpha, tan(atan(A)+C) can be written as (A+tan(C))/(1-A*tan(C)).
You can easily derive this by hand from the tangent sum formula:
tan(a + b) = (tan a + tan b)/(1 - tan a tan b).
If the implementation of tan in your math library is slow or inaccurate it's possible that faster or more precise implementations exist.
I'll presume that your formula is correct. Mark's comment essentially comes down to the idea that C must have units of an angle for the formula to make sense, but if C is a ratio, then it won't have the proper units. Mark has a valid question.
In the end, you will still need to compute a tangent, but there are things you can do to help a bit.
First, apply a simple trig identity, for the tangent of a sum. This, combined with the fact that tan(atan(A)) = A, reduces your formula to
B = (A + tan(C))/(1 - A*tan(C))
Thus you still need to compute ONE tangent, that of C. (Thus precompute tan(C), once.) Nothing will get you around that.
However, there are ways to compute a tangent more efficiently than as a ratio sin(C)/cos(C). For example, a direct series approximation might be better. Or there is a trick using a series for the versine, which is itself more efficient to compute than the tangent series. And for small angles it can be rapidly convergent. You can assure small angles using range reduction tricks for that versine. Other tricks exist too.
atan(A) = atan(x_a/y_a) for some point is the angle between vector (x_a,y_a) and Oy. Because C is a constant, you can precompute some vector c=(x_c,y_c) with unit length and inclined to Oy with angle C. Then cos(atan(A)+C) can be expressed as inner product of these vectors divided by length of a. From cos you can get tan using main identity. In the end a got:
B = sqrt((x_a^2 + y_a^2)/(x_a*x_c + y_a*y_c)^2 - 1)
This might be more effective. Be careful with signs.
(In three dimensions) I'm looking for a way to compute the signed angle between two vectors, given no information other than those vectors. As answered in this question, it is simple enough to compute the signed angle given the normal of a plane to which the vectors are perpendicular. But I can find no way to do this without that value. It's obvious that the cross product of two vectors produces such a normal, but I've run into the following contradiction using the answer above:
signed_angle(x_dir, y_dir) == 90
signed_angle(y_dir, x_dir) == 90
where I would expect the second result to be negative. This is due to the fact that the cross product cross(x_dir, y_dir) is in the opposite direction of cross(y_dir, x_dir), given the following psuedocode with normalized input:
signed_angle(Va, Vb)
magnitude = acos(dot(Va, Vb))
axis = cross(Va, Vb)
dir = dot(Vb, cross(axis, Va))
if dir < 0 then
magnitude = -magnitude
endif
return magnitude
I don't believe dir will ever be negative above.
I've seen the same problem with the suggested atan2 solution.
I'm looking for a way to make:
signed_angle(a, b) == -signed_angle(b, a)
The relevant mathematical formulas:
dot_product(a,b) == length(a) * length(b) * cos(angle)
length(cross_product(a,b)) == length(a) * length(b) * sin(angle)
For a robust angle between 3-D vectors, your actual computation should be:
s = length(cross_product(a,b))
c = dot_product(a,b)
angle = atan2(s, c)
If you use acos(c) alone, you will get severe precision problems for cases when the angle is small. Computing s and using atan2() gives you a robust result for all possible cases.
Since s is always nonnegative, the resulting angle will range from 0 to pi. There will always be an equivalent negative angle (angle - 2*pi), but there is no geometric reason to prefer it.
Signed angle between two vectors without a reference plane
angle = acos(dotproduct(normalized(a), normalized(b)));
signed_angle(a, b) == -signed_angle(b, a)
I think that's impossible without some kind of reference vector.
Thanks all. After reviewing the comments here and looking back at what I was trying to do, I realized that I can accomplish what I need to do with the given, standard formula for a signed angle. I just got hung up in the unit test for my signed angle function.
For reference, I'm feeding the resulting angle back into a rotate function. I had failed to account for the fact that this will naturally use the same axis as in signed_angle (the cross product of input vectors), and the correct direction of rotation will follow from which ever direction that axis is facing.
More simply put, both of these should just "do the right thing" and rotate in different directions:
rotate(cross(Va, Vb), signed_angle(Va, Vb), point)
rotate(cross(Vb, Va), signed_angle(Vb, Va), point)
Where the first argument is the axis of rotation and second is the amount to rotate.
If all you want is a consistent result, then any arbitrary way of choosing between a × b and b × a for your normal will do. Perhaps pick the one that's lexicographically smaller?
(But you might want to explain what problem you are actually trying to solve: maybe there's a solution that doesn't involve computing a consistent signed angle between arbitrary 3-vectors.)
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).
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.