UnitQuaternion::rotation_between gives result with NaN entries for certain nearly-identical inputs
Minimal complete example:
extern crate nalgebra;
use nalgebra::{UnitQuaternion, Vector3};
fn main() {
// Values derived from real-world occurrence
// Seems to be difficult to reproduce with synthetic values
let axis_0 = Vector3::new(
0.5248905449027862,
-0.30304569551237415,
-0.7953950102334741,
);
let axis_1 = Vector3::new(
// *very* slightly different!
0.5248905432722237,
-0.30304569833659056,
-0.795395010233474,
);
// prints UnitQuaternion with NaN entries:
println!("{:#?}", UnitQuaternion::rotation_between(&axis_0, &axis_1));
}
Thank you for reporting this. Are you using the latest version of nalgebra, i.e., 0.14.0 ? It includes some changes for ::rotation_between which might fix your bug already.
Running this code in 0.14.0 returns a quaternion of (0, 0, 0, 1).
Finished dev [unoptimized + debuginfo] target(s) in 0.55 secs
Running `target/debug/mybin`
Some(
Unit {
value: Quaternion {
coords: Matrix {
data: [
0.0,
0.0,
0.0,
1.0
]
}
}
}
)
I also get NaN when calling https://docs.rs/nalgebra/0.19.0/nalgebra/geometry/type.Rotation3.html#method.rotation_to and https://docs.rs/nalgebra/0.19.0/nalgebra/geometry/type.Rotation3.html#method.angle_to. This was quite frustrating to debug because it happened in a unit test where I wasn't expecting an issue and led me to believe my code didn't work for a few days.
I would recommend adding some documentation that explains that, for very small rotations, the returned rotation or angle may be NaN.
Ran into this issue with this minimal case:
use nalgebra::{Rotation3, Vector3};
fn main() {
let a = Vector3::<f32>::new(0.20790969, 2.2353943e-6, -0.9781481);
let a = Vector3::<f32>::new(0.20790969, 2.2353943e-6, -0.9781481);
// Rotation matix of NaN:
println!("{:?}", Rotation3::rotation_between(&a, &b));
}
However the same vectors just return an identity with UnitQuaternion::rotation_between. Doing a bit of digging the issue is in scaled_rotation_between.
Rotation uses a one liner: https://github.com/dimforge/nalgebra/blob/8964bf28a8d7ca90e8886b81337585ceb6cd2fc4/src/geometry/rotation_specialization.rs#L633
While UnitQuaternian breaks out the dot product from the arc-cosine: https://github.com/dimforge/nalgebra/blob/8964bf28a8d7ca90e8886b81337585ceb6cd2fc4/src/geometry/quaternion_construction.rs#L555-L564
When experimenting with this I found the dot product ends up floating up to 1.0000001, which is what is causing the NaN.
Sounds like the dot product needs to be clamped.