Android 安卓手机倾斜时会受到污染
我有一个非常恼人的问题,AR视图就像一个指南针。因此,当我以纵向方式握住手机(这样屏幕就指向我的脸),然后我调用Android 安卓手机倾斜时会受到污染,android,math,augmented-reality,compass-geolocation,Android,Math,Augmented Reality,Compass Geolocation,我有一个非常恼人的问题,AR视图就像一个指南针。因此,当我以纵向方式握住手机(这样屏幕就指向我的脸),然后我调用remapCoordinateSystem,当我以纵向方式握住手机时,音高为0。方位角(指南针功能)是完美的,但一旦我倾斜手机,方位角就会被破坏,如果我向前弯曲,方位角就会增加,如果我向后弯曲,方位角就会减少 我使用两个传感器获取读数,Sensor.TYPE\u MAGNETIC\u FIELD和Sensor.TYPE\u GRAVITY 我使用了一个非常基本的低通滤波器,它是用alp
remapCoordinateSystem
,当我以纵向方式握住手机时,音高为0。方位角(指南针功能)是完美的,但一旦我倾斜手机,方位角就会被破坏,如果我向前弯曲,方位角就会增加,如果我向后弯曲,方位角就会减少
我使用两个传感器获取读数,Sensor.TYPE\u MAGNETIC\u FIELD
和Sensor.TYPE\u GRAVITY
我使用了一个非常基本的低通滤波器,它是用alpha常量实现的,直接用于从传感器读取的值
这是我的密码:
float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrix(rotationMatrix, null, gravitymeterValues,
magnetometerValues);
float[] remappedRotationMatrix = new float[9];
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Z, remappedRotationMatrix);
float results[] = new float[3];
SensorManager.getOrientation(remappedRotationMatrix, results);
float azimuth = (float) (results[0] * 180 / Math.PI);
if (azimuth < 0) {
azimuth += 360;
}
float pitch = (float) (results[1] * 180 / Math.PI);
float roll = (float) (results[2] * 180 / Math.PI);
float[]旋转矩阵=新浮点[9];
SensorManager.getRotationMatrix(rotationMatrix,null,重力测量值,
磁强计值);
float[]remappedRotationMatrix=新float[9];
SensorManager.剩余协调系统(旋转矩阵、SensorManager.AXIS_X、,
SensorManager.AXIS_Z,重新映射到Matrix);
浮动结果[]=新浮动[3];
SensorManager.getOrientation(重新显示运动矩阵,结果);
浮动方位=(浮动)(结果[0]*180/Math.PI);
中频(方位角<0){
方位+=360;
}
浮动节距=(浮动)(结果[1]*180/Math.PI);
浮动辊=(浮动)(结果[2]*180/Math.PI);
正如你所看到的,这里没有魔法。当重力仪值和磁力仪值准备好使用时,我调用这段代码
我的问题是,当我倾斜手机时,如何防止方位角变得疯狂
我在谷歌Play商店Compass上查看了一个免费应用程序,但它并没有解决这个问题,但我希望有一个解决方案
我有两个解决方案:
pitch>=-5&&pitch的内容,有关完整的代码,请参见
保留历史记录和平均值,我不知道俯仰和横滚的正确解释,因此以下代码仅用于方位角
班级成员
private List<float[]> mRotHist = new ArrayList<float[]>();
private int mRotHistIndex;
// Change the value so that the azimuth is stable and fit your requirement
private int mHistoryMaxLength = 40;
float[] mGravity;
float[] mMagnetic;
float[] mRotationMatrix = new float[9];
// the direction of the back camera, only valid if the device is tilted up by
// at least 25 degrees.
private float mFacing = Float.NAN;
public static final float TWENTY_FIVE_DEGREE_IN_RADIAN = 0.436332313f;
public static final float ONE_FIFTY_FIVE_DEGREE_IN_RADIAN = 2.7052603f;
private List mRotHist=new ArrayList();
私人国际贸易指数;
//更改该值,使方位角稳定并符合您的要求
私有int mHistoryMaxLength=40;
浮动利率;
浮磁;
浮动[]mRotationMatrix=新浮动[9];
//背面摄像头的方向,仅当设备向上倾斜
//至少25度。
私人浮动汇率=float.NAN;
公共静态最终浮动二十五度弧度=0.436332313f;
公共静态最终浮动1度50度5度弧度=2.7052603f;
onSensorChanged
@Override
public void onSensorChanged(SensorEvent event)
{
if (event.sensor.getType() == Sensor.TYPE_GRAVITY)
{
mGravity = event.values.clone();
}
else
{
mMagnetic = event.values.clone();
}
if (mGravity != null && mMagnetic != null)
{
if (SensorManager.getRotationMatrix(mRotationMatrix, null, mGravity, mMagnetic))
{
// inclination is the degree of tilt by the device independent of orientation (portrait or landscape)
// if less than 25 or more than 155 degrees the device is considered lying flat
float inclination = (float) Math.acos(mRotationMatrix[8]);
if (inclination < TWENTY_FIVE_DEGREE_IN_RADIAN
|| inclination > ONE_FIFTY_FIVE_DEGREE_IN_RADIAN)
{
// mFacing is undefined, so we need to clear the history
clearRotHist();
mFacing = Float.NaN;
}
else
{
setRotHist();
// mFacing = azimuth is in radian
mFacing = findFacing();
}
}
}
}
private void clearRotHist()
{
if (DEBUG) {Log.d(TAG, "clearRotHist()");}
mRotHist.clear();
mRotHistIndex = 0;
}
private void setRotHist()
{
if (DEBUG) {Log.d(TAG, "setRotHist()");}
float[] hist = mRotationMatrix.clone();
if (mRotHist.size() == mHistoryMaxLength)
{
mRotHist.remove(mRotHistIndex);
}
mRotHist.add(mRotHistIndex++, hist);
mRotHistIndex %= mHistoryMaxLength;
}
private float findFacing()
{
if (DEBUG) {Log.d(TAG, "findFacing()");}
float[] averageRotHist = average(mRotHist);
return (float) Math.atan2(-averageRotHist[2], -averageRotHist[5]);
}
public float[] average(List<float[]> values)
{
float[] result = new float[9];
for (float[] value : values)
{
for (int i = 0; i < 9; i++)
{
result[i] += value[i];
}
}
for (int i = 0; i < 9; i++)
{
result[i] = result[i] / values.size();
}
return result;
}
@覆盖
传感器更改时的公共无效(传感器事件)
{
if(event.sensor.getType()==sensor.TYPE\u重力)
{
mGravity=event.values.clone();
}
其他的
{
mmamagnetic=event.values.clone();
}
if(mGravity!=null和&mmamagnetic!=null)
{
if(SensorManager.getRotationMatrix(mRotationMatrix,null,mRavity,mMagnetic))
{
//倾斜度是装置的倾斜度,与方向无关(纵向或横向)
//如果小于25度或大于155度,则该装置被视为平放
浮动倾角=(浮动)数学.acos(mRotationMatrix[8]);
如果(倾斜度<二十五度
||倾角>一度五十度五度弧度)
{
//制造业尚未定义,因此我们需要清除历史记录
clearRotHist();
mFacing=Float.NaN;
}
其他的
{
setRotHist();
//mFacing=方位角以弧度为单位
mFacing=findFacing();
}
}
}
}
私有无效清除列表()
{
if(DEBUG){Log.d(标记,“clearRotHist()”);}
mRotHist.clear();
mRotHistIndex=0;
}
私有无效设置列表()
{
if(DEBUG){Log.d(标记,“setRotHist()”);}
float[]hist=mRotationMatrix.clone();
if(mRotHist.size()=mHistoryMaxLength)
{
mRotHist.remove(mRotHistIndex);
}
添加(mRotHistIndex++,hist);
mRotHistIndex%=mHistoryMaxLength;
}
私人浮动findFacing()
{
if(DEBUG){Log.d(标记,“findFacing()”);}
float[]averageRotHist=平均值(mRotHist);
return(float)Math.atan2(-averageRotHist[2],-averageRotHist[5]);
}
公共浮动[]平均值(列表值)
{
浮点[]结果=新浮点[9];
for(float[]值:值)
{
对于(int i=0;i<9;i++)
{
结果[i]+=值[i];
}
}
对于(int i=0;i<9;i++)
{
结果[i]=结果[i]/values.size();
}
返回结果;
}
低通滤波器是什么?使用类型\重力时不需要过滤。@HoanNguyen我是否需要低通传感器。类型\磁场
?现在我同时使用了低通传感器。输入\u磁场和传感器。输入\u重力
。不,使用低通滤波器是为了消除x和y方向的加速度。getRotationMatrix要求第三个参数近似于z方向上的加速度。如果您使用类型\重力,则不需要低通滤波器,但许多设备没有类型\重力,因此您需要为没有类型\重力的设备使用类型\加速度计和低通滤波器。好的,谢谢。但当我倾斜手机时,我的方位角值不好,你知道怎么解决吗?我会保存一段历史记录,并将结果平均。我可以前后弯曲,方位角当然可以改变,但不能超过2或3度。很棒的东西!现在我的方位角好多了,唯一的问题是在快速移动时,它会跳很多,但我想你必须接受这一点。非常感谢您的代码。还有一个问题:你的更新率是多少