【问题标题】:Remapping sensor coordinates重新映射传感器坐标
【发布时间】:2012-06-06 17:16:21
【问题描述】:

我想要做的是重新映射坐标系,当手机远离它的“自然”方向时。因此,当使用手机时,如果它处于横向状态,它应该读取相同的值,就好像它被纵向握持一样。

我正在检查旋转是否等于Surface.ROTATION_90,如果是,则重新映射坐标系。

我承认我不太明白如何正确地做到这一点,并且可以使用一些指导。

所以,你需要运行这两个方法:

SensorManager.getRotationMatrix(inR, I, grav, mag); 
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outR);

传递到这些方法需要什么?我创建了一个新的浮点数组,然后只将方向传感器数据传递给了磁场,但这不起作用。所以,我注册了加速度计和磁场传感器。将这两个数据都输入getRotatioMatrix 方法,我总是得到NullPointerException(即使JavaDoc 说某些参数可以为空)。我什至尝试将数据传递给每个参数,但仍然得到NullPointerException

我的问题是,我需要传递给 getRotationMatrix 方法的正确数据是什么?

【问题讨论】:

    标签: android orientation


    【解决方案1】:

    我发现一种非常简单的方法是 SDK 示例 AccelerometerPlay 中使用的方法。

    首先你得到这样的显示,例如在 onResume() 中:

    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    mDisplay = windowManager.getDefaultDisplay();
    

    然后在 onSensorChanged() 中你可以使用这个简单的代码:

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
            return;
    
        switch (mDisplay.getRotation()) {
            case Surface.ROTATION_0:
                mSensorX = event.values[0];
                mSensorY = event.values[1];
                break;
            case Surface.ROTATION_90:
                mSensorX = -event.values[1];
                mSensorY = event.values[0];
                break;
            case Surface.ROTATION_180:
                mSensorX = -event.values[0];
                mSensorY = -event.values[1];
                break;
            case Surface.ROTATION_270:
                mSensorX = event.values[1];
                mSensorY = -event.values[0];
                break;
        }
    }
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      这是我的代码,它可以在没有 NPE 的情况下工作。请注意,我只有一个 Listener,但您必须注册它才能监听两个传感器(ACCELEROMETER 和 MAGNETICFIELD)。

      private SensorEventListener mOrientationSensorsListener = new SensorEventListener() {
      
          private float[] mR = new float[9];
          private float[] mRemappedR = new float[9];
          private float[] mGeomagneticVector = new float[3];
          private float[] mGravityVector = new float[3];
      
          @Override
          public void onSensorChanged(SensorEvent event) {
              synchronized(this) {
                  if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                      mGravityVector = Util.exponentialSmoothing(event.values, mGravityVector, 0.2f);
                  } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                      mGeomagneticVector = Util.exponentialSmoothing(event.values, mGeomagneticVector, 0.5f);
      
                      SensorManager.getRotationMatrix(mR, null, mGravityVector, mGeomagneticVector);
                      SensorManager.remapCoordinateSystem(mR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, mRemappedR);
                  }
              }
          }
      

      exponentialSmoothing 方法对传感器结果进行了一些平滑处理,看起来像这样(alpha 值可以从 0 到 1,其中 1 表示完全没有平滑处理):

      public static float[] exponentialSmoothing(float[] input, float[] output, float alpha) {
          for (int i=0; i<input.length; i++) {
              output[i] = output[i] + alpha * (input[i] - output[i]);
          }
          return output;
      } 
      

      至于synchronized 位——我不确定它是否需要,只是在某处阅读并添加它。

      【讨论】:

        猜你喜欢
        • 2011-06-24
        • 1970-01-01
        • 2021-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-09
        • 2023-04-01
        • 1970-01-01
        相关资源
        最近更新 更多