Skip to content

Latest commit

 

History

36 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rotlib

This is a collection of functions allowing interconversion between four commonly used rotation representations:

  • Quaternion
  • Axis-angle
  • Direction cosine matrix
  • Euler angles

Axis-angle The axis must be a unit vector and the angle should be in [0, $\pi$).

Euler angles We consider six sequences of Euler angles with non-repeated axes: (1) XYZ, (2) XZY, (3) ZXY, (4) ZYX, (5) YZX, and (6) YXZ. For example, the sequence 'XYZ' (in the world frame) = [phi, theta, psi] signifies first rotation by phi about X, second rotation by theta about Y, and the third rotation by psi about Z axis of the world (i.e. fixed) frame.

Euler angle ranges

Sequence phi theta psi
XYZ, ZYX [-pi, pi] [-pi/2, pi/2] [-pi, pi]
XZY, YZX [-pi, pi] [-pi, pi] [-pi/2, pi/2]
ZXY, YXZ [-pi/2, pi/2] [-pi, pi] [-pi, pi]

Functions for converting from one euler sequence to another are also available.

The above convention the same as the sequence used in the Blender blenlib code.

In contrast, the 'XYZ' sequence is understood in the aerospace community as: First rotation about Z-axis, second rotation about Y-axis, and the third rotation about X-axis of the body frame.

The functions are available in C, Fortran, and python. The source files are in c/src, fortran/src, and python/rotlib, respectively.

Installation

C version

A makefile is available for the GCC compiler in c/build. The command make lib will create a static library librotlib.a put it in the c/lib directory. A calling program can link appropriately to this library.

Tests are available in c/test. The command make test will build the tests as an executable c/test/test_main.

Documentation is generated using Doxygen. The command make doc will build the HTML documentation in docs/c_api.

The function aa_rand() requires a random number generator. In the code, the library functions srand() and rand() have been used as the random number generation is not crucial for the rest of the functions. If a better random number generator is required, the files c/src/ran_num.c and c/src/ran_num.h provide an interface to the random number generation routines of the Intel Math Kernel Library (MKL). The implementation of aa_rand() may be modified (as well as the makefile) to incorporate the routines from MKL.

Fortran version

A makefile is available for the gfortran compiler in fortran/build. The command make lib will create a static library librotlib.a put it in the fortran/lib directory. A calling program can link appropriately to this library.

Tests are available in fortran/test. The command make test will build the tests as an executable fortran/test/test_main.

Documentation is generated using FORD. The command make doc will build the HTML documentation in docs/fortran_api.

Fortran intrinsic functions are used for random number generation which are good enough for our purposes.

Python version

Dependency The code has been tested with python >= 3.11. The only dependency is numpy (>=2.0.0).

The rotlib module can be installed directly from the GitHub repo. In a virtual environment with python >= 3.11, run the command below. If numpy is not found, pip will install it as well.

pip install "rotlib @ git+https://github.com/saridut/rotlib.git/#subdirectory=python"

To use the functions, it is sufficient to import it as import rotlib in the user code.

A makefile for Sphinx autogenerated HTML documentaion is available in python/docs.

Tests are available in python/tests. The file python/pyproject.toml contains directives for ruff, pytest, and tox.

Documentation

Autogenerated documentation for the functions are available here.

Usage

Examples in python

Convert a set of euler angles to unit quaternion and back.

import rotlib
import numpy as np
# Euler angle sequence
ea = np.array([0.2, 0.5, 1.0]) 
# Convert euler to unit quaternion. Assume the sequence is 'XYZ' in the  world frame. 
q = rotlib.euler_to_quat(ea, seq='XYZ', world=True) 
#Convert the unit quaternion back to euler with the same sequence.
ea_ = rotlib.quat_to_euler(q, seq='XYZ', world=True)
#Check: ea and ea_ must be same within floating point precision
print(f"ea = {ea}\n q = {q}\n ea_ = {ea_}")

The output is

ea = [0.2 0.5 1. ]
q = [ 0.8578941  -0.03313079  0.26240747  0.44052512]
ea_ = [0.2 0.5 1. ]

Examples in C

Tha same example as above in C.

double q[4], ea[3], ea_[3];
ea[0] = 0.2; /* Rotation about X */
ea[1] = 0.5; /* Rotation about Y */
ea[2] = 1.0; /* Rotation about Z */
euler_to_quat(ea, ES_XYZ, true, q); /* enum ES_XYZ defined in rotation.h */
quat_to_euler(q, ES_XYZ, true, ea_);
/* using the function allclose() defined in `utils_math.h` to check closeness */
printf("ea == ea_? %d\n", allclose(3, ea, ea_, 1e-8, 1e-14) )

Examples in fortran

Tha same example as above in fortran.

real(rp) q[4], ea[3], ea_[3] 
! `rp` defined in constants_m. It is set to `iso_fortran_env:real64`.
ea = (0.2_rp, 0.5_rp, 1.0_rp)
call euler_to_quat(ea, 'XYZ', .true., q)
call quat_to_euler(q, 'XYZ', .true., ea_)
! using the function allclose() defined in `utils_math_m` to check closeness
write(*,'(a,1l)') "ea == ea_? ", allclose(ea, ea_, 1e-8_rp, 1e-14_rp)

For further examples, check the files c/test/test_main.c, fortran/test/test_main.f90, and python/tests/test_main.py.

About

Interconversion between rotation representations: Quaternion, Euler angles, direction cosine matrix, and axis-angle

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages