-
-
Notifications
You must be signed in to change notification settings - Fork 496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Certain unit quaternions produce invalid rotation matrices #1481
Comments
I reproduced the same behavior, but I think that matrix is a valid rotation (it's orthonormal and its determinant is 1). Here's the code I'm running to quickly verify: use nalgebra::{UnitQuaternion, Quaternion};
fn main() {
let q = UnitQuaternion::new_normalize(Quaternion::new(
0.1045170328727042,
-0.6993398242910853,
0.10451703287270421,
0.6993398242910854,
));
let R = q.to_rotation_matrix();
dbg!(R);
dbg!(R.matrix().determinant());
dbg!(R.transpose() * R);
} Which yields: [tmp/src/main.rs:15:5] R = [
[
-1.6653345369377348e-16,
0.0,
-1.0000000000000002,
],
[
-0.2923716936184902,
-0.9563047593579446,
2.7755575615628914e-17,
],
[
-0.9563047593579445,
0.29237169361849025,
1.6653345369377348e-16,
],
]
[tmp/src/main.rs:17:5] R.matrix().determinant() = 1.0000000000000007
[tmp/src/main.rs:19:5] R.transpose() * R = [
[
1.0000000000000004,
2.0934092284956047e-17,
-7.276719334102089e-18,
],
[
2.0934092284956047e-17,
1.0000000000000007,
-5.551115123125782e-17,
],
[
-7.276719334102089e-18,
-5.551115123125782e-17,
1.0000000000000004,
],
] Because the set of orthonormal matrices with determinant 1 is a unique representation of SO(3), there should be a unique set of Euler angles for it. Furthermore, I don't think there's any other such matrix which represents the same orientation. If you let me know which code you're running that results in a NaN or other numerical issues, I'm happy to have a look. Feel free to let me know if I've missed anything. |
Taking asin/acos of a value larger than 1.0 produces NAN on most architectures. So... A pure rotation matrix, by construction, simply can't have the absolute value of its elements be greater than 1. Here's a specific example where this breaks: use nalgebra::*;
fn main() {
let q = UnitQuaternion::new_normalize(Quaternion::new(
0.1045170328727042,
-0.6993398242910853,
0.10451703287270421,
0.6993398242910854,
));
dbg!(q.to_rotation_matrix().euler_angles_ordered(
[
UnitVector3::new_normalize(Vector3::z()),
UnitVector3::new_normalize(Vector3::y()),
UnitVector3::new_normalize(Vector3::x())
],
false
));
} outputs (
[
2.677945044588987,
NaN,
0.0,
],
false,
) |
|
There's an argument that |
That being said, I guess there may be performance reasons not to do it this way (as it would have to be done any time the matrix is touched, not just when it's constructed), so I'm fine with just adding a clamp to |
Then you're going to have a bad time. Rounding errors will happen as a result of any operation, e.g. composing rotations together. It's generally your responsibility to renormalize and clamp as needed. |
Frankly, that's a very strange stance to take. If this "A valid Rotation3 isn't guaranteed to remain valid via valid operations, and will eventually throw NANs at you if you don't police it" is the official stance, then I suggest it should be written in large letters all over its docs, because I would guess most people don't expect it to behave that way. |
Doc PRs would be very welcome! This is the behavior throughout nalgebra. |
FTR, |
As I said in #1481 (comment), that's the responsibility of the logic that has that constraint, i.e. |
Case in point, take this quaternion:
then convert it to rotation matrix:
You'll likely get:
Notice that the last component of the first row is less than -1. This will create issues (of the NAN variety) if, say, this matrix is then converted to Euler angles.
The text was updated successfully, but these errors were encountered: