html5 - Calculate compass heading from DeviceOrientation Event API -


for augmented reality web app smartphones i'm trying calculate compass heading when user holding device in hand, screen in vertical plane , top of screen pointing upwards.

i have taken suggested formula http://dev.w3.org/geo/api/spec-source-orientation (see worked example) , implemented following function:

function compassheading(alpha, beta, gamma) {     var a1, a2, b1, b2;     if ( beta !== 0 || gamma !== 0 ) {         a1 = -math.cos(alpha) * math.sin(gamma);         a2 = math.sin(alpha) * math.sin(beta) * math.cos(gamma);         b1 = -math.sin(alpha) * math.sin(gamma);         b2 = math.cos(alpha) * math.sin(beta) * math.cos(gamma);         return math.atan((a1 - a2) / (b1 + b2)).todeg();     }     else {         return 0;     } } 

while .todeg() number object extension courtesy http://www.movable-type.co.uk/scripts/latlong.html

/** converts radians numeric (signed) degrees */ if (typeof number.prototype.todeg == 'undefined') {     number.prototype.todeg = function() {         return * 180 / math.pi;     }; }   

however, problem calculated compass heading value jumps -75 80 if device (google galaxy nexus) mounted hold static position. seems happen in both google chrome beta , ff beta 23.

does see error in approach or know more reliable way calculate compass heading?

the steps need determine compass heading according worked example provided in specification* follows:

  • convert returned deviceorientation alpha, beta , gamma values degrees radians alpharad, betarad, gammarad.
  • compute rotationa (ra) , rotationb (rb) components per worked example in specification using alpharad, betarad , gammarad (as shown in example code below).
  • compute compassheading = math.atan(ra / rb).
  • convert returned half unit circle headings whole unit circle headings in range [0-360) degrees.
  • convert compassheading radians degrees (optional).

here worked example specification implemented in javascript:

function compassheading(alpha, beta, gamma) {    // convert degrees radians   var alpharad = alpha * (math.pi / 180);   var betarad = beta * (math.pi / 180);   var gammarad = gamma * (math.pi / 180);    // calculate equation components   var ca = math.cos(alpharad);   var sa = math.sin(alpharad);   var cb = math.cos(betarad);   var sb = math.sin(betarad);   var cg = math.cos(gammarad);   var sg = math.sin(gammarad);    // calculate a, b, c rotation components   var ra = - ca * sg - sa * sb * cg;   var rb = - sa * sg + ca * sb * cg;   var rc = - cb * cg;    // calculate compass heading   var compassheading = math.atan(ra / rb);    // convert half unit circle whole unit circle   if(rb < 0) {     compassheading += math.pi;   }else if(ra < 0) {     compassheading += 2 * math.pi;   }    // convert radians degrees   compassheading *= 180 / math.pi;    return compassheading;  }  window.addeventlistener('deviceorientation', function(evt) {    var heading = null;    if(evt.absolute === true && evt.alpha !== null) {     heading = compassheading(evt.alpha, evt.beta, evt.gamma);   }    // 'heading'...  }, false); 

you can view demo of code provided above.

as of time of writing (17th feb 2014) works in:

  • google chrome android
  • opera mobile android
  • firefox beta android

other browsers not yet conform deviceorientation calibration described in deviceorientation event specification and/or not provide absolute deviceorientation data values making impossible determine compassheading non-complete data.

* determining compass heading of horizontal component of vector orthogonal device's screen , pointing out of of screen.


Comments

Popular posts from this blog

plot - Remove Objects from Legend When You Have Also Used Fit, Matlab -

java - Why does my date parsing return a weird date? -

Need help in packaging app using TideSDK on Windows -