Преобразовать значения DESSOR.TYPE_ORIENTATION на углы Эйлера?
-
27-09-2019 - |
Вопрос
Я должен написать приложение компаса в Android. Единственное, что пользователь видит на экране, - это куб с красной стеной, который должен указывать на север. Это не важно. Что важно, это то, что мне нужно соответственно вращать этот куб к вращению самого устройства, чтобы красная стена продолжала указывать на север, независимо от того, как телефон проводится. Мой код прост и простой:
@Override
public void onSensorChanged(SensorEvent event) {
synchronized (this) {
switch (event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
direction = event.values[2];
break;
case Sensor.TYPE_ORIENTATION:
if (direction < 0) {
angleX = event.values[1];
angleY = -event.values[2];
angleZ = event.values[0];
} else {
angleX = -event.values[1];
angleY = -event.values[2];
angleZ = event.values[0];
}
break;
}
}
}
Я добавил эту дополнительную переменную направления, которая просто хранит, указывает ли дисплей телефона вниз или вверх. Я не знаю, нужен ли мне это, но это, кажется, исправляет некоторые ошибки. Я использую Сенсимулятор Для Android, но всякий раз, когда мой ползунок выходит в интервал [-90, 90], другие переменные получают смешивание. Как будто они получают компенсацию 180. Но я не могу обнаружить, когда я нахожусь в этом интервале, потому что диапазон шага от -90 до 90, поэтому я могу переместить этот ползунок слева, чтобы написать, и я всегда буду в этом интервале.
Это было просто, чтобы показать вам, насколько далеко мой код расширен. Я не говорю, как эта проблема должна быть решена, потому что я, вероятно, пошучу только в тупик. Видите ли, я пытался написать это приложение в течение 3 дней, и вы можете себе представить, насколько разозлился мой босс. Я прочитал всевозможные учебные пособия и попробовал каждую формулу, которую я мог найти или думать о. Поэтому, пожалуйста, помогите мне. Все, что мне нужно сделать, это знать, как повернуть свой куб, углы вращения которых являются углы эулера в градусах.
Решение
Вот какой-то код, который я написал, чтобы сделать что-то довольно похожее, действительно только заботу о вращении устройства в направлении рулона. Надеюсь, поможет! Он просто использует значения акселерометра для определения поля, не нужно получать ориентацию вида.
public void onSensorChanged(SensorEvent event) {
float x = -1 * event.values[0] / SensorManager.GRAVITY_EARTH;
float y = -1 * event.values[1] / SensorManager.GRAVITY_EARTH;
float z = -1 * event.values[2] / SensorManager.GRAVITY_EARTH;
float signedRawRoll = (float) (Math.atan2(x, y) * 180 / Math.PI);
float unsignedRawRoll = Math.abs(signedRawRoll);
float rollSign = signedRawRoll / unsignedRawRoll;
float rawPitch = Math.abs(z * 180);
// Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes
// adjust the filter weight based on pitch, as roll is harder to define as pitch approaches 180.
float filterWeight = rawPitch > 165 ? 0.85f : 0.7f;
float newUnsignedRoll = filterWeight * Math.abs(this.roll) + (1 - filterWeight) * unsignedRawRoll;
this.roll = rollSign * newUnsignedRoll;
if (Float.isInfinite(this.roll) || Float.isNaN(this.roll)) {
this.roll = 0;
}
this.pitch = filterWeight * this.pitch + (1 - filterWeight) * rawPitch;
for (IAngleListener listener : listeners) {
listener.deviceRollAndPitch(this.roll, this.pitch);
}
}