2012-06-06 3 views
1

Что я хочу, это переназначить систему координат, когда телефон отвернулся от «естественной» ориентации. Чтобы при использовании телефона, и он был в ландшафте, он должен читать те же значения, что и в портрете.Изменение координат датчика

Я проверяю, является ли поворот равным Surface.ROTATION_90, и если да, то переназначьте систему координат.

Я признаю, что не совсем понимаю, как это сделать должным образом, и может использовать небольшое руководство.

Итак, вам нужно запустить эти два метода:

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

Что требуется, чтобы пройти в эти методы? Я создал новый массив с плавающей точкой, а затем передал только данные orientationsensor в магнитное поле, которое не сработало. Итак, я зарегистрировал как акселерометр, так и датчики магнитного поля. Извлеките данные из обоих из них в метод getRotatioMatrix, и я всегда получаю NullPointerException (хотя JavaDoc говорит, что некоторые аргументы могут быть нулевыми). Я даже пробовал передавать данные по каждому аргументу и все равно получил NullPointerException.

Вопрос в том, какие данные мне нужно передать в метод getRotationMatrix?

ответ

0

это мой код, и он работает без NPE. Обратите внимание, что у меня есть только один прослушиватель, но вы должны зарегистрировать его для прослушивания обоих датчиков (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 метод делает некоторое сглаживание результатов датчика и выглядит, что (альфа-значение может перейти от 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 бит - я не уверен, что это необходимо, просто прочитайте его где-нибудь и добавьте его.

6

Я нашел, что очень простой способ сделать это - тот, который используется в образце SDK АкселерометрPlay.

Сначала вы получите ваш дисплей, как это, например, в 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; 
    } 
} 

Надеется, что это поможет.

Смежные вопросы