Rotate a vector with a quaternion

Rotate a vector with a quaternion#

Build a unit quaternion and use it to rotate a vector 90 degrees.

Time: ~2 min · Runs on: CPU · You need: Quaternions

Hide code cell source

%run ../_shared/setup.py
running on: cpu

A quaternion is stored in a plain aether::Vec4d, in (w, x, y, z) order. .quatRotate(v) applies it to a Vec3d, one method call:

A rotation by angle theta about an axis uses the half-angle: w = cos(theta/2), and the axis scaled by sin(theta/2) fills (x, y, z). For 90 degrees about z, that is (cos 45, 0, 0, sin 45), and it must send (1, 0, 0) to (0, 1, 0):

print(run_cpp(r"""
    using aether::Vec3d;
    using aether::Vec4d;

    const double half_angle = std::numbers::pi / 4.0;   // 90 deg rotation
    Vec4d q{std::cos(half_angle), 0.0, 0.0, std::sin(half_angle)};
    Vec3d v{1.0, 0.0, 0.0};

    Vec3d rotated = q.quatRotate(v);
    std::printf("rotated = (%.3e, %.6f, %.6f)\n", rotated(0), rotated(1), rotated(2));
""", includes=("<cmath>", "<numbers>")))
rotated = (2.220e-16, 1.000000, 0.000000)

Expected: (0, 1, 0). The tiny nonzero first component above (around machine epsilon, 2e-16) is floating-point reassociation noise – rounding error from the order .quatRotate’s internal sandwich product, q * (0, v) * q^-1, does its multiplications in, not a bug; see the tolerance note in Quaternions.