nalgebra icon indicating copy to clipboard operation
nalgebra copied to clipboard

UnitQuaternion::rotation_between gives result with NaN entries for certain nearly-identical inputs

Open exists-forall opened this issue 7 years ago • 5 comments

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));
}

exists-forall avatar Feb 07 '18 11:02 exists-forall

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.

sebcrozet avatar Feb 08 '18 10:02 sebcrozet

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
                ]
            }
        }
    }
)

ChristopherRabotin avatar Mar 26 '18 00:03 ChristopherRabotin

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.

vadixidav avatar Feb 18 '20 06:02 vadixidav

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.

george-ainc avatar Aug 29 '25 00:08 george-ainc

Sounds like the dot product needs to be clamped.

Ralith avatar Aug 29 '25 02:08 Ralith