Boost logo

Boost :

Subject: Re: [boost] Trying out QVM with multiple library implementations
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2015-08-04 21:07:53

On Tue, Aug 4, 2015 at 2:57 PM, Andrew Hundt <athundt_at_[hidden]> wrote:

> I'd really like to try out QVM because I have to switch between a half
> dozen matrix, vector and quaternion types constantly and would prefer not
> to write functions for each conversion and operations between them.

You need to define (partial) specializations for q_traits, v_traits and
m_traits template. They define things like scalar type and dimensions, and
provide access to the elements of a Quaternion, Vector or a Matrix through
the r, w, ir and iw member functions. See the tutorial section in

Once that is done, you can call the make<> function template to explicitly
convert to any registered Q, V or M type:

If you just want to assign a Q, V or M object to another compatible object,
use the assign function template:

Operations between compatible Q, V and M objects will should "just work",
however note that some operations need to deduce a return type. For
example, if you have two matrices m1 and m2 that are of different (but
compatible) types, by default m1*m2 will return a compatible qvm::mat<>
object. You can specialize the deduce_m2 template to specify a different

Examples of the formats I need to handle are:
> *Eigen <>:*
> Eigen::Affine3d
> Eigen::Quaterniond

This should be trivial, but let me know if you need help.

> + rotation and translation versions

I don't understand what you mean by "rotation and translation versions".

> *vrep
> <
> >:*
> float[3] (vrep vector)
> float[4] (vrep quaternion)
> float[12] (vrep homogeneous transform matrix)

QVM can handle array types out of the box, just include
boost/qvm/q_traits_array.hpp, boost/qvm/v_traits_array.hpp or
boost/qvm/m_traits_array.hpp. Do note that if you have

float a[3], b[3];

you can't just write a*b (that can't be overloaded). At least one of the
operands of op* must be of user-defined type, so in this case use vref(a)*b
instead. Also, if the size of the array is not statically known, e.g. if a
is of type float * but you know that it points to a 3D vector, use
ptr_vref<3>(a). Similarly you can use ptr_mref<R,C>(m) to make a pointer
look like RxC array (use transp() on top of that if the physical layout
doesn't match, see below.)

One problem is that QVM does not yet have explicit support for homogeneous
transforms (3x4 matrices). You can of course define m_traits that plugs 3x4
matrices as 4x4 matrices into QVM, by returning 0,0,0,1 for the elements of
the last row.

> *cisstVector <
> >:*
> vctDynamicVector
> <
> >
> vctQuaternion
> <
> >
> vctDynamicMatrix
> <
> >
> There are also fixed versions of the "Dynamic" objects.
> + rotation & translations

Also should be trivial, but let me know.

> Is there any particular concerns I need to take regarding alignment,
> ordering (row vs column major) etc?

QVM is neutral towards the physical layout of Q, V or M objects since
elements are accessed through the r, w, ir, or iw member functions of
q_traits/v_traits/m_traits specializations.

Logically, matrix elements are accessed as zero-based "row, column", e.g.
r<1,3> refers to the fourth element of the second row of the matrix. When
multiplying matrices and vectors, the vectors appear on the right and are
assumed to be columns (logically). This means that m1*m2*v will "apply" the
m2 transform "before" the m1 transform.

For the quaternion *a + bi + cj + dk*, the elements are assumed to be in
the following logical order: *a*, *b*, *c*, *d.*

I hope this helps,

Emil Dotchevski
Reverge Studios, Inc.

Boost list run by bdawes at, gregod at, cpdaniel at, john at