Skip to content

Quaternion representation of rotations, written in rust

License

Notifications You must be signed in to change notification settings

ssmichael1/rust-quaternions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

qrotate

The qrotate crate provides Quaternion representations of rotations of 3-element vectors representing points in 3-dimensional space. 3-element vectors can use rust standard library types, or vectors from the ndarray crate.





Copyright (c) 2023 Steven Michael (ssmichael@gmail.com)

Overview


Quaternion rotations are represented as multiply (*) operations, and possible on the following repersentations of 3D vectors, where T is a template parameter matching a floating-point type, f32 or f64.


[T; 3] 3-element fixed-size array
&[T; 3] Reference to 3-element fixed size array
&[T] Slice containing 3 elements
std::vec::Vec<T> standard library vector with 3 elements
&std::vec::Vec<T> Reference to standard library vector with 3 elements
ndarray::Array1<'a, T> 1D array from ndarray crate (with ndarray feature enabled)
ndarray::ArrayView1<'a, T> View into 1D array from ndarray crate (with ndarray feature enabled)

Quaternions can also be multiplied with other quaternions via the * operator to represent a concatenation of rotations.

The above operations are also defined to work when used by a reference to a quaternion.

Note: this quaternion represetntation uses the "conventional" definition of a quaternion, which when constructed from an axis and and angle, defines a right-handed rotation of a vector about the given axis by the given angle.





Examples


Simple Rotation

Rotation of the x-axis unit vector about the z axis by π/2

use std::f64::consts::PI;
let xhat = [1.0, 0.0, 0.0];
let yhat = qrotate::Quaternion::<f64>>rotz(PI / 2.0) * xhat
// yhat = [0.0, 1.0, 0.0];

Concatenated Rotations

Rotation of the x-axis unit vector about z axis by π/2 then y axis by π/3

use std::f64::consts::PI;
let xhat = [1.0, 0.0, 0.0];
let q1 = qrotate::Quaternion::<f64>::rotz(PI / 2.0);
let q2 = qrotate::Quaternion::<f64>::roty(PI / 3.0);
let result q2 * q1 * xhat

Find quaternion to rotate between two vectors

Find quaterion that rotates from xhat vector to yhat vector

let xhat = [1.0, 0.0, 0.0];
let yhat = [0.0, 1.0, 0.0];
let q = qrotation::qv1tov2(&xhat, &yhat);

Direction-Cosine Matrix

Represent quaternion as a direction-cosine matrix (DCM) that left-multiplies a vector to perform a rotation or a direction-cosine matrix that right-multiples a 2D (Nx3) column matrix to perform a rotation

use std::f64::consts::PI;
let q = qrotate::Quaternion::<f64>::rotz(PI / 2.0);

// get [[f64; 3]; 3] representation of quaternion as DCM
// that left-multiples row vector
let dcm = q.ldcm();

// Same thing, excpet DCM as ndarray::Array2<f64> 
let dcm_ndarr = q.ldcm_ndarr();

// Same thing, except DCM as ndarray::Array2<f64>
// that right-multiplies column vector
let dcm_ndarr = q.rdcm_ndarr();

Convert Direction-Cosine Matrix (DCM) to quaternion

use std::f64::consts::PI;
let q = qrotate::Quaternion::<f64>::rotz(PI / 2.0);

// get [[f64; 3]; 3] representation of quaternion as DCM
// that left-multiples row vector
let dcm = q.ldcm();

// Convert back to quaternion
let q2 = Quaternion::<f64>::from_ldcm(dcm);

Axis, Angle

Convert quaternion to and from axis and angle of rotation representations

// Construct quaternion representing rotation about zhat axis by PI/2
let zhat = [0.0, 1.0, 0.0]
let theta = std::f64::consts::PI / 2.0;
let q = Quaternion::<f64>::from_axis_angle(zhat, theta);
// Result is same as zhat
let axis: [f64; 3] = q.axis();
// result is PI / 2.0
let angle: f64 = q.angle();

Other Operations

Miscelaneous operations below

// Construct identity quaternion (no rotation)
let mut q = Quaternion::<f64>::identity();

// now rotate about y axis
q = Quaternion::<f64>::qroty(0.1) * q;

// Get conjugate
let qc = q.conjugate();

// Get quaternion norm (should be 1.0 most of the time)
let n = q.norm();

// Scale quaternion
q = q * 2.0;

// Get normalized version of quaternion
let qn = q.normalized();

// Normalize quaternion in place
q.normalize();

// Get vector elements of quaternion
let v: [f64; 3] = q.vector();

// Get scalar elements of quaternion
let w: f64 = q.scalar();

Python Bindings

By enabling the python feature, the crate also has the option to compile into a python library. The library makes available a "Quaternion" class which can be used to rotate 3-element NumPy vectors (and each element of a Nx3 NumPy "matrix"). Many of the functions described above are available in python

About

Quaternion representation of rotations, written in rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published