Calculate compass heading from DeviceOrientation Event API

前端 未结 3 1489
孤城傲影
孤城傲影 2020-12-06 08:07

For an augmented reality web app for smartphones I\'m trying to calculate the compass heading when the user is holding the device in their hand, with the screen in a vertica

相关标签:
3条回答
  • 2020-12-06 08:21

    I have also played some with the DeviceOrientationEvent (might adopt you formula...) and seen similar problems from time to time. You might wanna try a calibration as in this video. You could search youtube for more examples.

    0 讨论(0)
  • 2020-12-06 08:25

    It seems that getting compass heading from device orientation events is deprecated, perhaps for privacy reasons. You should look at the Geolocation API, which requires permissions. The events have Coordinates.heading.

    0 讨论(0)
  • 2020-12-06 08:46

    The steps you need to determine the compass heading according to the worked example provided in the specification* are as follows:

    • Convert returned DeviceOrientation alpha, beta and gamma values from degrees to radians as alphaRad, betaRad, gammaRad.
    • Compute rotationA (rA) and rotationB (rB) components per the worked example in the specification using alphaRad, betaRad and gammaRad (as shown in the example code below).
    • Compute compassHeading = Math.atan(rA / rB).
    • Convert returned half unit circle headings to whole unit circle headings in the range [0-360) degrees.
    • Convert compassHeading from radians back to degrees (optional).

    Here is the worked example from the specification implemented in JavaScript:

    function compassHeading(alpha, beta, gamma) {
    
      // Convert degrees to 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 from half unit circle to whole unit circle
      if(rB < 0) {
        compassHeading += Math.PI;
      }else if(rA < 0) {
        compassHeading += 2 * Math.PI;
      }
    
      // Convert radians to 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);
      }
    
      // Do something with 'heading'...
    
    }, false);
    

    You can also view a demo of the code provided above.

    As of the time of writing (17th Feb 2014) this currently works in:

    • Google Chrome for Android
    • Opera Mobile for Android
    • Firefox Beta for Android

    Other browsers do not yet conform to the DeviceOrientation calibration described in the DeviceOrientation Event specification and/or do not provide absolute DeviceOrientation data values making it impossible to determine compassHeading with non-complete data.

    * Determining the compass heading of the horizontal component of a vector which is orthogonal to the device's screen and pointing out of the back of the screen.

    0 讨论(0)
提交回复
热议问题