I'm working with the Myo armband through the myo_ros package. The device is able to provide IMU measurements comprising orientation, linear acceleration and angular velocity. The orientation is expressed wrt an (unknown) reference frame, chosen when the device is turned on. We can refer to this frame as myo_ref. The linear acceleration is expressed wrt the myo_raw frame, which is a north-west-up moving frame attached to the device. I want to manually remove the gravity component from the accelerometer data. These are the steps I'm doing:
- calibration: I record the orientation when the accelerometer measure +9.81 over the z-axis (so I'm sure the device is aligned with the Earth's z-axis pointing upward). This orientation, let's call it
q_ref2aligned
is used to publish a static transformation, describing the new frame myo_aligned wrt the frame myo_ref; - each IMU measurement has an orientation, let's call it
q_ref2raw
which expresses the current pose of the armband wrt the frame myo_ref - To the best of my knowledge, the inverse quaternion of
q_ref2aligned
, that isq_aligned2ref
, describes the transformation from the frame myo_aligned to the frame myo_ref q_aligned2ref * q_ref2raw = q_aligned2raw
should represent the current orientation of the armband wrt the frame aligned with the Earth's z-axis, right?- if lin_acc is the acceleration recorded in the current IMU measurement (so wrt the myo_raw frame) and G = [0, 0, 9.81] is the gravity vector, if I multiply lin_acc by
q_aligned2raw
and then substract G I should be able to remove the gravity component, correct?
To accomplish this, I first turn q_aligned2raw
into a rotation matrix M
with tf.transformations.quaternion_matrix, then I use the matrix-vector multiplication with lin_acc and finally just substract G.
Am I missing something? This approach fails. Here are some experiments:
1.
- IMU lin_acc reading [x, y, z]: [-0.32561143, -0.80924016, 9.88805286]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [-1.76936953, -4.4546028 , 8.69254434]
2.
- IMU lin_acc reading [x, y, z]: [-0.19153613, -0.01915361, -9.62947908]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [ 1.58807182, 9.41955642, -1.23040848]
3.
- IMU lin_acc reading [x, y, z]: [-0.09576807, -9.61990227, 2.36068284]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [-8.92865455, -4.05394425, 1.40327425]
4.
- IMU lin_acc reading [x, y, z]: [-0.36391865, 9.62947908, 0.70389529]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [-8.56518971, 3.71455092, -2.48885704]
5.
- IMU lin_acc reading [x, y, z]: [9.60553706e+00, 4.78840332e-03, 9.57680664e-03]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [ 1.43719352, 7.26609646, -6.11594423]
6.
- IMU lin_acc reading [x, y, z]: [-10.07480059, -0.16280571, 0.09576807]
- expected lin_acc after rotation: [~0, ~0, ~9.81 ]
- observed lin_acc after rotation: [ 1.86515326, 7.72080671, -6.20061538]