1

I'm trying to convert a list of quaternions to their corresponding orientation matrix using the Transforms3d python package.

Each quaternion is a 4 element list/array of the inputs and using the transforms3d.quaternions.quat2mat(q) function it returns the 3x3 orientation matrix.

I have a list of some 10K-100K quaternions that need converting (nx4 array) and while it's easy enough to do this with a loop, I think it could be quicker if there was some way of vectorising the process.

Some searching suggested I could simply do something like np.vectorize() but I'm struggling to make that work. A list comprehension works fine, but I guess the numpy vector solution would be much quicker.


orientations = np.array([[ 0.6594993 , -0.06402525, -0.74797227, -0.03871606],
       [ 0.78091967, -0.15961452, -0.44240183, -0.41105753]])

rotMatrix = [quat2mat(orient) for orient in orientations]

vfunc=np.vectorize(quat2mat, signature='(m,n)->()')

vfunc(orientations)

unfortunately i can't even get the numpy version to run, both with and without the signature (which is possibly wrong).

> Traceback (most recent call last):

File "", line 1, in vfunc(aa)

File "c:\wpy64-3740\python-3.7.4.amd64\lib\site-packages\numpy\lib\function_base.py", line 2091, in call return self._vectorize_call(func=func, args=vargs)

File "c:\wpy64-3740\python-3.7.4.amd64\lib\site-packages\numpy\lib\function_base.py", line 2157, in _vectorize_call res = self._vectorize_call_with_signature(func, args)

File "c:\wpy64-3740\python-3.7.4.amd64\lib\site-packages\numpy\lib\function_base.py", line 2198, in _vectorize_call_with_signature results = func(*(arg[index] for arg in args))

File "c:\wpy64-3740\python-3.7.4.amd64\lib\site-packages\transforms3d\quaternions.py", line 133, in quat2mat w, x, y, z = q

ValueError: not enough values to unpack (expected 4, got 2)

jpmorr
  • 500
  • 5
  • 25
  • `np.vectorize` is not quicker; read the docs at least to the point that you see that disclaimer. I was also going to say it passes scalar values, but I see you are using the `signature`. I tested that mode a few times; it's a little tricky to use, and even slower than the regular mode. – hpaulj Aug 27 '19 at 14:32
  • 1
    Another note on `vectorize` - it's most useful when you have several input arrays that need broadcasting against each other. For one array, and one dimension, simple iteration is simpler. The key to true `numpy` vectorization lies in `quat2mat`, not something that you can wrap around it. It's each call to that function that costs time. – hpaulj Aug 27 '19 at 14:49
  • @hpaulj Thanks for pointing out that disclaimer - I completely missed it. Yes, it looks like I'll have to dig in to `quat2mat` to speed things up. – jpmorr Aug 27 '19 at 15:06

1 Answers1

1

As was suggested, the best way to improve performance was to vectorise quat2mat, and the results (%timeit) support that:

quat2mat() in loop for 2000 quaternions:

17.3 ms ± 482 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

vectorised quat2mat_array() for 2000 quaternions:

1.11 ms ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Should have just done that first instead of messing with np.vectorise()! Thanks for the re-focus!

jpmorr
  • 500
  • 5
  • 25