title: Tilted magnetometer output -pitch and roll tilt compensation - i am lost
body: <p>I have wasted 2 days (and nights) on this specific issue and completely failed in tilt compensating my magnetometer output.<br>
  I tried about everything I could read on Google and in open source examples, nothing guided me to a proper tilt compensation for both (roll and pitch).  .</p>
  
  <p>The Setup:
  I use calibrated values but not unity values.<br>
  I have a fused gravity vector which is working properly and exact.<br>
  The sensor is a 9dof BMX055 (<a href="http://www.mouser.com/ds/2/621/BST-BMX055-DS000-01-274824.pdf" rel="nofollow">http://www.mouser.com/ds/2/621/BST-BMX055-DS000-01-274824.pdf</a>)
  The magnetometer min/max are +- 512 on each axis (with small differences but all axes are zero'd out).
  The hardware is Sam3X8e (Cortex M3), all written in C.<br>
  Floating point and trigonometry can be done quite fast, so that's no problem.
  The BMX055 chip is aligned so that the pins 20,19,18 point to the front.<br>
  Datasheet page 159-161 show the orientation.
  Pitch rises when I rise the front.<br>
  Roll rises when I rise the left side.  </p>
  
  <p>Example values:<br>
  Pointing at a direction my algorithm calls 305deg when leveled horizontal</p>
  
  <pre><code>Pitch: 0  , Roll 0   : MAG cal:  x 132   y  93  z   -364  
  Pitch: +24, Roll 0   : MAG cal:  x -109   y  93  z   -397  
  Pitch: +46, Roll 0   : MAG cal:  x -303   y  89  z   -351  
  Pitch: 0  , Roll -44 : MAG cal:  x 151   y  352  z   -235  
  Pitch: 0  , Roll +36 : MAG cal:  x 130   y  -140  z   -328  
  Pitch: 78 , Roll -2  : MAG cal:  x -503   y  93  z   -199  
  Pitch: 7  , Roll -53 : MAG cal:  x 135   y  424  z   -180
  </code></pre>
  
  <p>The alignment should always have been around 305 degree (as good as I could do it), maybe +- 5 degree.  </p>
  
  <p>The formula:  (same one used about everywhere)</p>
  
  <pre><code>uint16_t compass_tilt_compensation(float roll_radians, float pitch_radians,float mag_y, float mag_x, float mag_z) 
  {
  
    float tilt_compensated_heading;
    float MAG_X;
    float MAG_Y;
    float cos_roll;
    float sin_roll;
    float cos_pitch;
    float sin_pitch;
    int16_t heading;
    //pitch_radians =roll_radians;
    //roll_radians *= -1;
    //mag_x *= -1;
    //roll_radians=0.0f;
    //pitch_radians=0;v
    //pitch_radians *=-1;
  
    cos_roll = cos(roll_radians);
    sin_roll = sin(roll_radians);
    cos_pitch = cos(pitch_radians);
    sin_pitch = sin(pitch_radians);
  
  
  #if 0
    MAG_X = mag_x*cos_pitch+mag_y*sin_roll*sin_pitch+mag_z*cos_roll*sin_pitch;
    MAG_Y = mag_y*cos_roll-mag_z*sin_roll;
    tilt_compensated_heading = atan2f(-MAG_Y,MAG_X); 
  #else
      MAG_X = mag_x * cos_pitch + mag_z * sin_pitch;
      MAG_Y = mag_x * sin_roll * sin_pitch + mag_y * cos_roll - mag_z * sin_roll * cos_pitch;
      tilt_compensated_heading = atan2f(-MAG_Y,MAG_X);
      //tilt_compensated_heading = atan2f(-mag_y,mag_x); // works fine when leveled
  #endif
  
  //convert to degree from 0-3599
      heading = tilt_compensated_heading * RAD_TO_DEG * 10;
       if ( heading &lt; 0 ) 
       {
           heading += 3600;
       }
  
    return heading;
  }
  </code></pre>
  
  <p>I tried various combinations, I tried to only fix one axis and leave one always at 0, exchanging X/Y pitch/roll, *-1 on any of the inputs.</p>
  
  <p>The results are always completely wrong.
  Sometimes (depending on where I try to invert or not invert a value by trial/error) the values seem to be off nearly linear. Sometimes one axis is compensated in positive areas.<br>
  However rolling and pitching always causes 'random' jumps and changes of the heading.<br>
  Math has never been my favourite, now I regret it.  </p>
  
  <p>My personal guess is that the formula is right in principe, the mag is working in principe (after all I get proper degrees when leveled) but I am somehow feeding something wrong.
  (Like Y and X need to be exchanged, z*-1, pitch needs to be *-1)</p>
  
  <p>Could someone who is good in this subject maybe take a look and guide me how to get a proper heading ?<br>
  Would be great to have a few hours sleep this night without having to dream about a dysfunctional algorithm again :)  </p>
  
  <p>Update:
  The tilt compensation here works for negative roll when pointing at the 305deg heading.
  It is also used here: <a href="http://www.emcu.it/MEMS/Compass/MEMS_Compass_A_RTM1v3.pdf" rel="nofollow">http://www.emcu.it/MEMS/Compass/MEMS_Compass_A_RTM1v3.pdf</a></p>