fu5ha/ultraviolet

The terms "Rotation in the xz plane" and "Rotation arround the y axis" can lead to confusion

thenlevy opened this issue · 2 comments

n ultraviolet, Bivector are represented in the basis (xy xz yz), and user are invited to think of rotation as happening in a plane rather than around and axis.

When thinking about rotations as happening around an axis, one must chose a convention for which direction is the "positive" rotation direction. Often, the convention used is the "right hand rule"

However, from the "right hand rule" perspective, a rotation in the plane xz is a rotation around the axis -y .

Because of that, some behaviors of ultraviolet may seem counterintuitive. For example

The method Rotor3::from_rotation_xz(theta) and Mat3::from_rotation_y(theta) produce two rotations that go in the opposite direction.

use ultraviolet::*; 

fn main() {
    let yaw = 0.3;
    let vec_1 = Rotor3::from_rotation_xz(yaw) * Vec3::unit_x();
    let vec_2 = Mat3::from_rotation_y(yaw) * Vec3::unit_x();
    println!("{:?}", vec_1);
    println!("{:?}", vec_2); // the z coordinates are opposed 
}

In my opinion the following things could reduce the confusion

  • Replace the methods Mat3::from_rotation_y by Mat3::from_rotation_xz (and adjust the implementation) as well as all the Mat3::from_rotation_....`
  • Add some special warnings about this behavior in the documentation, especially when converting from/to Euler angles
fu5ha commented

I think the best solution to this problem is actually to change the Bivec3 to use the zx plane rather than xz... doing so is also the most common choice in the GA literature, so it makes sense. I've been meaning to for a little while but just haven't had the time to go back and redo the derivations/rewrite the code. It should just be a matter of adding/removing some -s.

I'm probably misunderstanding something here, but the documentation for Mat4::from_euler_angles reads:

pub fn from_euler_angles(roll: f32, pitch: f32, yaw: f32) -> Self
Angles are applied in the order roll -> pitch -> yaw

Roll is rotation inside the xy plane (“around the z axis”)
Pitch is rotation inside the yz plane (“around the x axis”)
Yaw is rotation inside the xz plane (“around the y axis”)

So if I pass 0. for roll and pitch, the Y axis should not change, right? But when I run dbg!(ultraviolet::Mat4::from_euler_angles(0., 0., std::f32::consts::PI / 2.));, I get this:

[src/main.rs:157] ultraviolet::Mat4::from_euler_angles(0., 0., std::f32::consts::PI / 2.) = Mat4 {
    cols: [
        Vec4 {
            x: -4.371139e-8,
            y: 1.0,
            z: -0.0,
            w: 0.0,
        },
        Vec4 {
            x: -1.0,
            y: -4.371139e-8,
            z: 0.0,
            w: 0.0,
        },
        Vec4 {
            x: 0.0,
            y: 0.0,
            z: 1.0,
            w: 0.0,
        },
        Vec4 {
            x: 0.0,
            y: 0.0,
            z: 0.0,
            w: 1.0,
        },
    ],
}

It looks to me like a rotation in the XY plane; the X axis gets transformed to Y, and the Y axis ends up at -X. Through experimentation I think it's interpreting the arguments as from_euler_angles(pitch, yaw, roll) instead. What am I missing? Or is this a bug?