Puck.js magnetometer as a compass ?

Posted on
  • I have been trying to use the magnetometer to accurately compute compass heading . However, I seem to be getting results that render the measurement somewhat useless. After I compute the Atan of mag.x and mag.y then calculate for 360 degrees, I find that my puck is very quickly jumping past 270 to 360 and relatively slowly projecting 0 to 270. Sort of like 90 degrees measurement occurs in 10 degrees of rotation and 270 degrees measurement occurs in 350 degrees rotation. I have tried moving the puck into an entirely demagnetized space away from every possible external magnet source and still get these ranges. I’m trying to lay the puck flat on the table and turn the puck as if it were a volume knob.
    Is the magnetometer not capable of being used as a compass ?

  • this is the simplest code that I am using:

    var Vec3 = require("Vec3");
    var vmin = new Vec3(Puck.mag());
    var vmax = vmin;
    function onMag(xyz) {
      vmin = vmin.min(xyz);
     vmax = vmax.max(xyz);
     var c = vmin.add(vmax).mul(0.5).sub(xyz); 
     var a = (Math.atan2(c.x,c.y)*180/Math.PI);
    if(a <0) a+=360;
        console.log( vmin);
        console.log( vmax);
       console.log( c);
        console.log( a.toFixed(0) );
    Puck.on('mag', onMag);

    I get consistent 0 to 360 degree measurements, but with 0 to 270 actually between 0 and 350 and 270 to 360 occuring in the last 10 degrees.

  • Hi - what you've got there looks pretty good to me. The magnetometer has a DC offset on it, so you need to account for that with min/max which is what you're doing.

    Are you sure that when you upload this you're turning the Puck 360 degrees around (and maybe rolling at different angles as well) first? That allows min/max to be calibrated and will give you much more accurate readings.

    You'd hope that when you do this, vmax.sub(vmin) will have roughly the same values in each axis (which would be the earth's magnetic field strength), and if you measure c.mag() that should stay about the same size no matter where you hold the Puck too.

    edit: just to add the Puck would also need to be held perpendicular to the magnetic field when using Math.atan2(c.x,c.y) - if it's off-axis then some of the field ends up in c.z which will make the values for angle seem very nonlinear

  • here's a video of one sample rotation after calibration.
    0-80 = 80 degrees
    80-200 = 120 degrees
    200-250 = 50 degrees
    250-360 = 110 degrees

    1 Attachment

  • One thing I notice from that is that the values in c vary by +/- 200ish

    However the values for min/max are anywhere from 1000 to 1600 apart, so basically however you calibrated it, it must have been near a much bigger magnetic field somehow so the min/max values (and hence the center) are way out.

    If you do vmin = vmax = new Vec3(Puck.mag()); when the Puck is on the paper as you had it, and then rotate it slowly by 360 degrees I'd expect that then vmin/vmax will end up around 400 apart, and at that point you'll get a much better reading.

    Getting the compass calibrated is a right pain - it's why even on phones where they've got sometimes billions in R&D budget the phone still occasionally asks you to rotate it in circles to recalibrate.

    If you know the field strength where you are (looks like ~160ish for you?), you can effectively just keep track of the center point (rather than min/max) and then if the reading is ever more than 160 away from the center point you just update the center point.

  • Got it. I tried to remove all magnetic fields from my environment. But there must just be too many magnets inside of every computer, tablet, and camera in my room, or the earth is just annoyingly uncentered at my altitude/long/lat.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Puck.js magnetometer as a compass ?

Posted by Avatar for user158028 @user158028