Quaternions and ddd

78 views
Skip to first unread message

Martin Flecmart

unread,
Jul 14, 2015, 9:22:28 AM7/14/15
to kivy-...@googlegroups.com
Hi,

i want to rotate an Object with quaternions. Is this possible with the ddd module from the Kivy garden?

I have a Python Queue with Quaternions that gets updated continuously. Can I update somehow the Object's or Cam's rotation through this queue? I know that it should be possible after going through some theory about quaternions and rotation matrices, but at the moment I don't really know what would be the best way to implement this behavious in kivy. DDD would be great because I loaded the object I want to rotate with ddd.

Thank you :-)

Alexander Taylor

unread,
Jul 14, 2015, 10:17:18 AM7/14/15
to kivy-...@googlegroups.com, flec...@gmail.com
Is it a new quaternion each time (specifying a frame relative to some fixed reference), or a relative frame to the previous one (e.g. you're supposed to multiply the quaternions)?

If the former, you can just convert each individual quaternion to angles in any convenient representation - not sure what ddd uses out of the box, but you could use axis/angle representation with a single Rotate instruction, and just modify the properties for the axis and the angle.

tshirtman had a similar problem to this, so probably ddd can do what you want if it's similar.

Martin Flecmart

unread,
Jul 14, 2015, 10:33:04 AM7/14/15
to kivy-...@googlegroups.com, flec...@gmail.com
Thanks for your quick reply!

I am not quite sure yet. The concept of quaternions was new to me. But your comment raises hope for me to solve the problem quicker than I thaught :-)

I calculate new quaternions at a defined sample rate (from inertial sensor data). They are the output of a datafusion method called "complementary filter" which has accelerometer, gyroscope and magnetometer data as input. I think that the next estimated quaternion depends on the value of the last quaternion. At the moment I am not sure what the quaternions I have now are representing.

Gabriel Pettier

unread,
Jul 14, 2015, 11:06:55 AM7/14/15
to kivy-...@googlegroups.com, flec...@gmail.com
I have a version of ddd that can take cam orientation from a quaternion
(using transformation to matrix) or axis angle notation, as well as from
euler angles (as previously), it's not merged in the original
repository, for lack of time and because i've been thinking about
overhauling ddd, and didn't manage to do so yet, anyway, you can find
the code here, where it's used as a submodule of another project.

https://github.com/TangibleDisplay/twiz/tree/quaternion_rotation/ddd

mainly, the changes are in object_renderer, and you can have a look in
main.py of the parent project to see how to use the rotation (though the
results aren't consistent yet, you get a different rendering through the
matrix notation than from the axis-angle and euler ones, i'm not sure
why).

I'm sorry it's probably a bit messy to dig into, hope it'll help anyway.

ps: the project is probably very related to yours, we (my company) are
building an inetrial module, called the twiz, that uses fusion from
gyroscope and magnetometer, as well as accelerometers.
> --
> You received this message because you are subscribed to the Google Groups "Kivy users support" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

signature.asc

Martin Flecmart

unread,
Jul 15, 2015, 4:01:30 AM7/15/15
to kivy-...@googlegroups.com, flec...@gmail.com
Thank you! Looks like a cool project - I will try this ddd modification and report if it works for me or if I find any more out about quaternions and kivy. :-)
Message has been deleted
Message has been deleted

Martin Flecmart

unread,
Jul 15, 2015, 4:16:51 PM7/15/15
to kivy-...@googlegroups.com, flec...@gmail.com
Hello again,

For now I use the object_renderer from your quaternion branch and generate a view in my kv file like this:

View:
   
id: rendering
   
canvas.before:
       
Color:
           
rgba: 1, 1, 1, 1
       
Rectangle:
           
pos: self.pos
            size
: self.size
   
scene: 'skateboard.obj'
   
obj_scale: 3
    display_all
: True
   
#ambiant: 0.5
   
#diffuse: 0.5
   
#specular: 0.5
    mode
: 'triangles'
   
#light_radius: 10
   
#nb_lights: 7
   
#move_light: True
    cam_mode
: 'quaternions'
   
cam_rotation: quat_to_matrix(root.sensor.quaternions.get())
    cam_translation
: 0, 0, -8

   
light_sources:
       
{
        x
: ([float(y) * 10 - 5 for y in bin(x)[2:].rjust(3, '0')] + [1.0])
       
for x in range(8)
       
}


quaternions (from the bold line) is a python Queue that I fill up with the new quaternions. The scene renders, but the rotation of my object stays constant and the Queue just gros, so I guess .get() is never called. Do I miss something here? When will the quat_to_matrix function be called? Do I have to setup a Callback with Kivy's Clock?


Am Dienstag, 14. Juli 2015 17:06:55 UTC+2 schrieb tshirtman:

Gabriel Pettier

unread,
Jul 15, 2015, 8:26:00 PM7/15/15
to kivy-...@googlegroups.com, flec...@gmail.com
Sorry i hadn't seen your messages earlier

This issue comes from the fact you are trying to update the cam_rotation
from kv, but without storing the value in a kivy Property, so kivy
doesn't automatically binds to its values, and so doesn't automatically
calls update.

One way to do it would indeed be to call quat_to_matrix(sensor.get())
regularly (using a clock) to put the result in rendering.cam_rotation.


On Wed, Jul 15, 2015 at 01:16:51PM -0700, Martin Flecmart wrote:
> Hello again,
>
> For now I use the object_renderer from your quaternion branch and generate
> a view in my kv file like this:
>
> View:
> id: rendering
> canvas.before:
> Color:
> rgba: 1, 1, 1, 1
> Rectangle:
> pos: self.pos
> size: self.size
> scene: 'skateboard.obj'
> obj_scale: 3
> display_all: True
> #ambiant: 0.5
> #diffuse: 0.5
> #specular: 0.5
> mode: 'triangles'
> #light_radius: 10
> #nb_lights: 7
> #move_light: True
> cam_mode: 'quaternions'
> *cam_rotation: quat_to_matrix(root.sensor.quaternions.get())*
> > an email to kivy-users+...@googlegroups.com <javascript:>.
signature.asc

Gabriel Pettier

unread,
Jul 15, 2015, 8:29:51 PM7/15/15
to kivy-...@googlegroups.com
For this error, you need to update your kivy, or just use the previous's
commit version of ddd in this repo
(https://github.com/TangibleDisplay/twiz/tree/cc1733c791ec9abe2b9068be2e3c62935631de03/ddd),
because this version fixed it for latest kivy master.

the diff, though, is pretty basic, you can revert it easily
https://github.com/TangibleDisplay/twiz/commit/0f186f0ab7673832159dcb560ded379497493259


good luck

On Wed, Jul 15, 2015 at 09:20:18AM -0700, Martin Flecmart wrote:
> Hello again,
>
> I tried to adapt the changes concerning quaternions to ddd. I still don't
> get how to pass the quaternions to the View:
>
> In my kv file, I defined a View and set the cam_mode to 'quaternion' like
> (see the last 2 lines):
>
>
>
>
>
>
>
>
>
> View:
>
> id: rendering
>
> canvas.before:
>
> Color:
>
> rgba: 1, 1, 1, 1
>
> Rectangle:
>
> pos: self.pos
>
> size: self.size
>
>
>
> scene: 'skateboard.obj'
>
> obj_scale: 3
>
> display_all: True
>
> ambiant: 0.5
>
> diffuse: 0.5
>
> specular: 0.5
>
> on_parent: self.reset()
>
> mode: 'triangles'
>
> light_radius: 10
>
> nb_lights: 7
>
> move_light: True
>
> cam_mode: 'quaternions'
>
> cam_rotation: quat_to_matrix(root.sensor.quaternions.get())
>
>
> My root widget has an object Property sensor that has a Queue that contains
> the quaternions. I get the error: AttributeError: 'NoneType' object has no
> attribute 'quaternions' - Do I have to define the queue as ObjectProperty,
> too to make the reference to the kv file?
>
>
> For test purposes I tried *cam_rotation: quat_to_matrix([1,0,0,0]) *but
> then I get: TypeError: set() takes no keyword arguments
>
>
> Can you give me a hint what I might do wrong? I guess I did not fully
> understand the way kv language handles events and references.
>
>
> Thank you,
>
> Martin
signature.asc

Martin Flecmart

unread,
Jul 16, 2015, 2:46:59 AM7/16/15
to kivy-...@googlegroups.com
I forgot to say that the python queue is a kivy object property. I defined it like:

quaternions = ObjectProperty()

And then in init of the sensor class:

self.quaternions = Queue()
self.quaternions.put([1,0,0,0])

So won't this do the binding automatically? Thanks for your help, I'll try setting up a trigger first, that puts the new data in rendering.cam_rotation whenever new data is there.

Martin Flecmart

unread,
Jul 16, 2015, 10:28:13 AM7/16/15
to kivy-...@googlegroups.com
Wow, I was able too achieve my first success with your modified renderer :-)

The object rotates when I rotate the sensor, btu there are two issues
  1. Axis of sensor and the View seem to be different
  2. The Visualization of the Rotation is too sensitiv: When I rotate the sensor just a bit around one axis, the object in the View rotates like 20 times around the axis.
For issue one, obviously I have to take care that the axis of the sensor and of the reference frame are the same. Is there a good way to change the axis of the object_renderer?
For issue two I have no idea at the moment. Have you seen such a thing in your project?

I hope I don't bother you with too many questions @tshirtman - you pushed me in the right direction so far... thank you for that!

Martin Flecmart

unread,
Jul 17, 2015, 1:23:20 PM7/17/15
to kivy-...@googlegroups.com, flec...@gmail.com
Hi Alexander,

what would I do if I calculate a quaternion relative to the previous one? How can I calculate the resulting Matrix() for OpenGL/Kivy?

Thank you,
Martin

Am Dienstag, 14. Juli 2015 16:17:18 UTC+2 schrieb Alexander Taylor:

Alexander Taylor

unread,
Jul 17, 2015, 1:24:53 PM7/17/15
to kivy-...@googlegroups.com
What does 'relative to the previous one' mean? If you want their
combined rotation then you can multiply the quaternions and use the new
one to get the rotation frame. The ease of doing this is the reason
people use quaternions in the first place.
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Kivy users support" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/kivy-users/Mcrq2AxBRnQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> kivy-users+...@googlegroups.com
> <mailto:kivy-users+...@googlegroups.com>.
signature.asc

Martin Flecmart

unread,
Jul 17, 2015, 3:57:42 PM7/17/15
to kivy-...@googlegroups.com
In ddd, the rotation is implemented like this:

def on_cam_rotation(self, *args):

   
...some alternative modes...

   
elif self.cam_mode == 'quaternions':
       
m = Matrix()
       
m.set(self.cam_rotation)
       
self.cam_rot.matrix = m


When I want to update my GUI now like:

def update_ui(self, *args):

   
"""Scheduled with Clock

    """


   
# another thread calculates quaternions and puts them in the queue, so I get always the latest here, right?
   
new_quat = self.sensor.quaternions.get()  

   
self.rendering.cam_rotation = quat_to_matrix(new_quat)


Would that be correct under the condition that new_quat describes the rotation of the object relative to the OpenGL coordinate system?

In tshirtmans ddd there is a function that calculates a 4x4 OpenGL Matrix (the quat_to_matrix() function used in the above code snippet - is the resulting Matrix the "total" orientation?
I am not quite sure if my quaternions represent the whole orientation or just the changes between the orientations (I use the MadgwickAHRS algorithm for datafusion). When I run my App and rotate my sensor the GUI response in the right directions, but the object in the GUI totally "overreacts"... Another thing I recognized: the Queue I use for InterThreadCommunication grows constantly. I think it is because the thread runs more often then my scheduled function that updates the orientation in the GUI - but if i always get the latest item from the Queue that schould not be a problem, shoudln't it? I use a Queue because it is thread safe.

I am just trying to describe my problems and observations because I hope someone can give me a hint what might go wrong... after 8 hours of thinking and failing I have no idea what to try next :D

Thank you,
Martin
Reply all
Reply to author
Forward
0 new messages