从DeviceOrientation Event API计算罗盘标题 [英] Calculate compass heading from DeviceOrientation Event API
问题描述
对于智能手机的增强现实网络应用程序,我试图计算指南针的标题,当用户手中拿着设备时,屏幕在垂直平面上,屏幕顶端朝上。
我已经从 http://dev.w3.org/geo/api/spec-source-orientation (见工作示例),并实现了以下功能:
<$ p $函数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; $。
$ b $ / code $ / pre
而.toDeg()是一个Number对象的扩展礼貌 http://www.movable-type.co.uk/scripts/latlong.html
$ b $
/ **将弧度转换为数字(带符号)度* /
if(typeof Number。 prototype.toDeg =='undefined'){
Number.prototype.toDeg = function(){
return this * 180 / Math.PI;
};
$ / code>
然而,问题是计算出来的罗盘航向值从-75到80即使设备(谷歌Galaxy Nexus)被安装来保持一个静态的位置。这似乎发生在谷歌浏览器BETA和FF BETA 23中。
有人在我的方法中看到错误,或知道计算罗盘标题的更可靠的方法吗? / p>
- 转换返回的DeviceOrientation
alpha
,从
,alphaRad
,从度数到弧度的beta
和gamma
betaRadgammaRad
。 - 计算rotationA(
rA $ c $使用
alphaRad
,和rotationB(
和rB
) > betaRadgammaRad
(如下面的示例代码所示)。
- 计算
compassHeading = Math.atan(rA / rB)
。
- 将返回的半个单位圆标题转换为整个单元c
- 将
>compassHeading
从弧度转换回角度(可选)。
- 计算
function compassHeading(alpha ,beta,gamma){
//将度数转换为弧度
var alphaRad = alpha *(Math.PI / 180);
var betaRad = beta *(Math.PI / 180);
var gammaRad = gamma *(Math.PI / 180);
//计算方程组件
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);
//计算A,B,C旋转分量
var rA = - cA * sG - sA * sB * cG;
var rB = - sA * sG + cA * sB * cG;
var rC = - cB * cG;
//计算指南针标题
var compassHeading = Math.atan(rA / rB);
//从半个单位圆转换为整个单位圆
if(rB <0){
compassHeading + = Math.PI;
} else if(rA <0){
compassHeading + = 2 * Math.PI;
}
//将弧度转换为度
compassHeading * = 180 / Math.PI;
return compassHeading;
$ b window.addEventListener('deviceorientation',function(evt){
var heading = null;
if(evt.absolute === true& evt.alpha!== null){
heading = compassHeading(evt.alpha,evt.beta,evt.gamma);
}
//用标题...做一些事情...
},false);
>截至撰写本文时(2014年2月17日),该工具目前适用于:
- Google Chrome for Android
- 适用于Android的Opera Mobile
- 适用于Android的Firefox Beta
其他浏览器不符合DeviceOrientation事件规范中描述的DeviceOrientation校准和/或不提供绝对
DeviceOrientation数据值,因此无法确定compassHeading
与非完整数据。
* 确定正交矢量的水平分量的罗盘方向到设备的屏幕并指出屏幕的背面。
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 vertical plane and the top of the screen pointing upwards.
I have taken the suggested formula from http://dev.w3.org/geo/api/spec-source-orientation (see Worked Example) and implemented the 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() is a Number object extension courtesy http://www.movable-type.co.uk/scripts/latlong.html
/** Converts radians to numeric (signed) degrees */ if (typeof Number.prototype.toDeg == 'undefined') { Number.prototype.toDeg = function() { return this * 180 / Math.PI; }; }
However, the problem is that the calculated compass heading value jumps from about -75 to 80 even if the device (Google Galaxy Nexus) is mounted to hold a static position. This seems to happen in both Google Chrome BETA and FF BETA 23.
Does somebody see an error in my approach or know a more reliable way to calculate the compass heading?
解决方案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
andgamma
values from degrees to radians asalphaRad
,betaRad
,gammaRad
. - Compute rotationA (
rA
) and rotationB (rB
) components per the worked example in the specification usingalphaRad
,betaRad
andgammaRad
(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 determinecompassHeading
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.
这篇关于从DeviceOrientation Event API计算罗盘标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Convert returned DeviceOrientation