iosobjective-ccocoacore-motion

How multiplyByInverseOfAttitude (CMAttitude Class ) is implemented?


I need to implement the same behaviour used by multiplyByInverseOfAttitude from the CMAttitude iOS class. Please note that I cannot directly use it but I have the right CMAttitude objects. Anyone can point me to the right direction?


Solution

  • As you are not allowed to create an instance of CMAttitude on your own, the only way is to create a new quaternion and take this for any further calculations. I recommend using your own customised quaternions class instead of the simple struct CMQuaternion. A good starting point is the cocoamath project where you can take Quaternion.m, Quaternion.h and QuaternionOperations.m from trunk and I will use it for this sample code.

    First you have to save an instance from the complex conjugate of your reference quaternion (taken from CMAttitude.quaternion) to use for all subsequent multiplications i.e.

    MyClass.h

    Quaternion* inverseReferenceQuaternion;
    

    MyClass.c

    // initialising code run only once after each call to [motionManager startDeviceMotionUpdates];
    CMAttitude firstAttitude = [motionManager deviceMotion].attitude;
    CMQuaternion q = firstAttitude.quaternion;
    inverseReferenceQuaternion = [[Quaternion alloc] initWithRe:q.w i:-q.x j:-q.y k:-q.z];
    

    In your timer loop (or handler block) you need a quaternion multiplication:

    // on every update
    CMAttitude attitude = [motionManager deviceMotion].attitude;
    CMQuaternion current = attitude.quaternion;
    Quaternion currentMultiplied = initAsProductOf:inverseReferenceQuaternion And:current
    

    Now currentMultiplied should contain what you are looking for.

    Quaternions are pretty if you are new to this subject, but it's worth to read some tutorials like for example OpenGL:Tutorials:Using Quaternions to represent rotation or Quaternion Powers.