/Matrix

Lightweight, dependency free Matrix library (BSD)

Primary LanguageC++BSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

matrix

ARCHIVED - PX4-Matrix is now maintained within PX4-Autopilot. https://github.com/PX4/PX4-Autopilot/tree/4a3d64f1d76856d22323d1061ac6e560efda0a05/src/lib/matrix

A simple and efficient template based matrix library.

License

  • (BSD) The Matrix library is licensed under a permissive 3-clause BSD license. Contributions must be made under the same license.

Features

  • Compile time size checking.
  • Euler angle (321), DCM, Quaternion conversion through constructors.
  • High testing coverage.

Limitations

  • No dynamically sized matrices.

Library Overview

  • matrix/math.hpp : Provides matrix math routines.

    • Matrix (MxN)
    • Square Matrix (MxM, has inverse)
    • Vector (Mx1)
    • Scalar (1x1)
    • Quaternion
    • Dcm
    • Euler (Body 321)
    • Axis Angle
  • matrix/filter.hpp : Provides filtering routines.

    • kalman_correct
  • matrix/integrate.hpp : Provides integration routines.

    • integrate_rk4 (Runge-Kutta 4th order)

Testing

The tests can be executed as following:

mkdir build
cd build
cmake  -DTESTING=ON ..
make check

Formatting

The format can be checked as following:

mkdir build
cd build
cmake  -DFORMAT=ON ..
make check_format

Example

See the test directory for detailed examples. Some simple examples are included below:

    // define an euler angle (Body 3(yaw)-2(pitch)-1(roll) rotation)
    float roll = 0.1f;
    float pitch = 0.2f;
    float yaw = 0.3f;
    Eulerf euler(roll, pitch, yaw);

    // convert to quaternion from euler
    Quatf q_nb(euler);

    // convert to DCM from quaternion
    Dcmf dcm(q_nb);

    // you can assign a rotation instance that already exist to another rotation instance, e.g.
    dcm = euler;

    // you can also directly create a DCM instance from euler angles like this
    dcm = Eulerf(roll, pitch, yaw);

    // create an axis angle representation from euler angles
    AxisAngle<float> axis_angle = euler;

    // use axis angle to initialize a DCM
    Dcmf dcm2(AxisAngle(1, 2, 3));
    
    // use axis angle with axis/angle separated to init DCM
    Dcmf dcm3(AxisAngle(Vector3f(1, 0, 0), 0.2));

    // do some kalman filtering
    const size_t n_x = 5;
    const size_t n_y = 3;

    // define matrix sizes
    SquareMatrix<float, n_x> P;
    Vector<float, n_x> x;
    Vector<float, n_y> y;
    Matrix<float, n_y, n_x> C;
    SquareMatrix<float, n_y> R;
    SquareMatrix<float, n_y> S;
    Matrix<float, n_x, n_y> K;

    // define measurement matrix
    C = zero<float, n_y, n_x>(); // or C.setZero()
    C(0,0) = 1;
    C(1,1) = 2;
    C(2,2) = 3;

    // set x to zero
    x = zero<float, n_x, 1>(); // or x.setZero()

    // set P to identity * 0.01
    P = eye<float, n_x>()*0.01;

    // set R to identity * 0.1
    R = eye<float, n_y>()*0.1;

    // measurement
    y(0) = 1;
    y(1) = 2;
    y(2) = 3;

    // innovation
    r = y - C*x;

    // innovations variance
    S = C*P*C.T() + R;

    // Kalman gain matrix
    K = P*C.T()*S.I();
    // S.I() is the inverse, defined for SquareMatrix

    // correction
    x += K*r;

    // slicing
    float data[9] = {0, 2, 3,
                     4, 5, 6,
                     7, 8, 10
                    };
    SquareMatrix<float, 3> A(data);

    // Slice a 3,3 matrix starting at row 1, col 0,
    // with size 2 x 3, warning, no size checking
    Matrix<float, 2, 3> B(A.slice<2, 3>(1, 0));

    // this results in:
    // 4, 5, 6
    // 7, 8, 10