Датчик Android TYPE_LINEAR_ACCELERATION — что он показывает?

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

Затем, предполагая, что ориентация телефона не меняется, я записал данные акселерометра за указанное время и рассчитал параметры движения, одним из которых является скорость автомобиля в конце теста.

На прямой горизонтальной дороге работает неплохо: погрешность в несколько процентов.

Но потом я узнал, что в API-level 10 есть виртуальный датчик с именем TYPE_LINEAR_ACCELERATION и, насколько я понимаю, он должен делать то, что мне нужно: фильтровать гравитацию, менять ориентацию - так что я могу использовать его и получить чистое линейное ускорение. мобильного устройства.

НО в реальной жизни..

Я сделал простое приложение, которое выполняет небольшой тест:

//public class Accelerometer implements SensorEventListener { ...
public void onSensorChanged(SensorEvent se) 
{
    if(!active)
        return;

    lastX = se.values[SensorManager.DATA_X];
    lastY = se.values[SensorManager.DATA_Y];
    lastZ = se.values[SensorManager.DATA_Z];
    long now = System.currentTimeMillis();
    interval = now - lastEvetn;
    lastEvetn = now;
    out.write(Float.toString(lastX) + ";" + 
                    Float.toString(lastY) + ";" + 
                    Float.toString(lastZ) + ";" + 
                    Long.toString(interval) + "\n");
}

Я связываю слушателя со следующими параметрами:

  mSensorManager.registerListener(linAcc,
                mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
                SensorManager.SENSOR_DELAY_GAME);

Работает нормально, но когда я анализировал дамп данных, вычисляя скорость вида V = V0 + AT, где сначала V0 = 0, потом - скорость интервала до этого, A = acceleration (SQRT (x*x+y*y+z*z)) (t = время интервала), в итоге получаю очень низкую скорость - в три раза меньше чем реальная скорость.

Изменение типа датчика на TYPE_ACCELEROMETER, калибровка и использование той же формулы для расчета скорости - я получаю хорошие результаты, гораздо ближе к реальности.

Итак, вопрос:

Что на самом деле показывает Sensor.TYPE_LINEAR_ACCELERATION?

Где я не прав, или что-то не так с Sensor.TYPE_LINEAR_ACCELERATION реализацией?

Я использовал телефон Samsung Nexus S.


person Maep    schedule 22.10.2011    source источник
comment
Очень интересно! Sensor.TYPE_LINEAR_ACCELERATION делает именно то, что вы пишете. Почему вы вычисляете длину ускорения (SQRT (xx+yy+z*z)? Насколько хорошо вы проверили свой предыдущий метод? Всего несколько измерений? Что мне действительно интересно, так это что ваш предыдущий метод дает довольно точные результаты. Эти датчики могут отслеживать скорость менее секунды, поэтому я удивлен. Несмотря на то, что это для положения, скорость не лучше, см. ссылка.   -  person Ali    schedule 22.10.2011
comment
Привет. Если датчик показывает ускорение в направлениях x,y,z, то значение A равно SQRT(xx+yy+z*z). Если датчик показывает что-то другое - это вопрос. что показывает?   -  person Maep    schedule 23.10.2011
comment
Если датчик показывает что-то другое - это вопрос. что показывает? Мой предыдущий метод был протестирован много раз, с разными скоростями. В машине, где положение телефона хорошо зафиксировано - работает достаточно точно, НИКОГДА не дает погрешность более 10%. Это результат, я думаю. Вот почему я не понимаю - почему линейный акселерометр ведет себя так странно... Если интересно, могу выслать исходный код рабочего метода.   -  person Maep    schedule 23.10.2011
comment
Вы правильно поняли линейное ускорение, это именно то, что вы написали. Я так и не понял, зачем нужен SQRT(xx+yy+z*z). Пожалуйста, проверьте мой код, из строк 134 и 148, v0 — начальная скорость, v — скорость. длина ускорения никогда не требуется при вычислении скорости, поэтому опубликуйте свой код, показывающий, почему вы его используете.   -  person Ali    schedule 23.10.2011
comment
Спасибо за ваш код. длина ускорения есть значение самого ускорения. Итак, вычисление скорости, не интересуясь ее направлением, требует значения ускорения. Если у меня есть вектор ускорения (1,5,4), v0 = 0, время = 1 секунда, v = 0 + 6,48 = 6,48 м/с. Vx = 1 м/с, Vy=5 м/с, Vz = 4 м/с, но |v| = 6,48 м/с   -  person Maep    schedule 23.10.2011
comment
вот кусок кода, он может быть очень полезным ‹code›private void calc(){ //averagePoint - среднее ускорение эксперимента Acceleration = this.xaveragePoint.getX() + this.y AveragePoint.getY() + this.zaveragePoint.getZ(); ускорение = ускорение / ((float)Math.sqrt(averagePoint.getForce())); float t = ((float) интервал / 1000f); скоростьПосле = скоростьДо + ускорение * t; расстояние = скорость доt + ускорениеtt/2; }   -  person Maep    schedule 23.10.2011
comment
ИЗВИНИТЕ, я пока не понимаю, как пометить код в комментарии :(   -  person Maep    schedule 23.10.2011
comment
Вот мой код, который работает с датчиком TYPE_ACCELEROMETER maephv. blogspot.com/2011/10/   -  person Maep    schedule 24.10.2011
comment
В вычислении вам нужен вектор ускорения, а не его длина. Представьте себе следующее: автомобиль ускоряется со скоростью 1 м/с^2 в течение 1 с, затем с -1 м/с^2 в течение 1 с (замедление). Изменение скорости равно нулю, однако, если вы используете длину ускорения, вы вычисляете что-то еще. Другими словами: если вы используете только длину, то, например, вы не сможете отличить ускорение от замедления. Я быстро просмотрел ваш код, но не понял, что происходит.   -  person Ali    schedule 26.10.2011
comment
Али, в моей программе я вычисляю проекцию вектора на средний вектор, и он подписан. Так что в этом случае он будет работать корректно. Во всяком случае, я проверил linear_accelerometer с прямым движением с постоянным ускорением - безрезультатно. Мой код с type_accelerometer отлично работает   -  person Maep    schedule 26.10.2011
comment
Хорошо, моя ошибка, я не понял эту часть, извините.   -  person Ali    schedule 26.10.2011
comment
В любом случае, спасибо.. подождем новый Android, может быть, они это исправят :)   -  person Maep    schedule 30.10.2011
comment
Вот что я заметил, пытаясь использовать TYPE_LINEAR_ACCELERATION. Когда я поворачиваю устройство вокруг одной оси, компонент ускорения, на который больше всего влияет вращение, кажется, неправильно различает ускорение и замедление. Например, я увижу, что компонент X ускорения начинается около нуля, увеличивается до 2 или 3, а затем уменьшается до нуля, когда я останавливаю вращение. Я ожидаю, что компонент X увеличится, достигнет пика, уменьшится обратно через ноль и станет отрицательным, достигнет пика в отрицательном направлении и, наконец, вернется к нулю, когда я остановлю вращение.   -  person Neal Stublen    schedule 02.12.2011
comment
Извините, @Maep, я не понял вашего объяснения отличия ускорения от замедления. в моей программе я вычисляю проекцию вектора на средний вектор, и он подписан. Можете ли вы рассказать об этом подробнее, пожалуйста   -  person Nazerke    schedule 27.03.2013
comment
@Maep, не могли бы вы поделиться математическим кодом для расчета расстояния с помощью акселерометра ???   -  person Erum    schedule 17.10.2014


Ответы (6)


Очень интересный вопрос!!!!

Я разрабатываю что-то похожее на ваше приложение. То, что я узнал о TYPE_LINEAR_ACCELERATION, меня не устраивает.

1) TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, ecc реализованы только для Android 2.3 (и выше). Так что у меня Android 2.2, и я не могу их протестировать.

2) TYPE_LINEAR_ACCELERATION не так точен, как мог бы быть, потому что есть некоторая простая проблема, когда вычитается гравитация. На самом деле это «слияние датчиков», в котором используется акселерометр и ориентация, чтобы узнать, куда направлена ​​сила тяжести, а затем субмарины. Это.

Здесь я нашел очень полезный ответ, который объясняет это:

https://groups.google.com/forum/#!topic/android-developers/GOm9yhTFZaM

TYPE_ACCELEROMETER использует акселерометр и только акселерометр. Он возвращает необработанные события акселерометра с минимальной обработкой или вообще без нее.

TYPE_GYROSCOPE (если присутствует) использует гироскоп и только гироскоп. Как и выше, он возвращает необработанные события (угловая скорость в единицах рад/с) без какой-либо обработки (без компенсации смещения/масштаба).

TYPE_ORIENTATION устарел. Он возвращает ориентацию как рыскание/тангаж/крен в градусах. Он не очень четко определен, и на него можно положиться только тогда, когда у устройства нет «ролла». Этот датчик использует комбинацию акселерометра и магнитометра. Незначительно лучшие результаты можно получить с помощью помощников SensorManager. Этот датчик сильно "обработан".

TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, TYPE_ROTATION_VECTOR – это "слитные" датчики, которые возвращают соответственно линейное ускорение, силу тяжести и вектор вращения (кватернион). Не определено, как они реализованы. На некоторых устройствах они реализованы в ч/б, на некоторых устройствах используется акселерометр + магнитометр, на некоторых других устройствах используется гироскоп.

На Nexus S и Xoom гироскоп в настоящее время НЕ используется. Они ведут себя так, как будто гироскоп недоступен, как на Nexus One или Droid. Мы планируем исправить эту ситуацию в будущем выпуске.

В настоящее время единственный способ воспользоваться преимуществами гироскопа — это использовать TYPE_GYROSCOPE и интегрировать выходные данные вручную.

Надеюсь, это поможет,

Матиас

Во всяком случае, в разных местах в Интернете я не нашел лучшего слова о сенсорах телефона и их потенциале из-за того, что они не точны ...

Некоторой большей точности можно достичь с помощью фильтра Калмана, но я понятия не имею, как...

person Lork    schedule 04.11.2011
comment
у меня андроид 2.3.4, но не работает линейное ускорение. в любом случае, акселерометр дает довольно хорошие результаты. Я сравниваю с GPS и могу сказать - для кратковременного запроса данных акселерометр лучше: GPS лагает и не часто обновляется. Посмотрите на мой график здесь: синий цвет — данные акселерометра, красный — GPS, черная метка — скорость автомобиля в конце эксперимента, проверенная спидометром. Я продолжаю работать над этим методом, чтобы повысить точность img84.imageshack.us/img84/6991/accpn. .png - person Maep; 21.11.2011
comment
@Maep: вы, кажется, получаете хороший результат от акселерометра. Не могли бы вы мне помочь? ком/вопросы/12926459/ - person Ashwin; 17.10.2012
comment
Полезно, но нельзя использовать с NDK. В NDK вроде нет типа GRAVITY. Есть ASENSOR_TYPE_ACCELEROMETER, но нет ASENSOR_TYPE_GRAVITY. Некоторые источники предостерегают от получения его в JAVA и переноса его на C через JNI, поскольку он потребляет слишком много батареи. - person Bram; 16.07.2014
comment
@Lork, ты знаешь, как определить движение ВЕРХА к низу? Я имею в виду, как разбить ваше устройство? - person Skizo-ozᴉʞS; 25.01.2016

Я понимаю, что мой ответ довольно поздно. Я наткнулся на эту ветку, когда искал информацию о TYPE_LINEAR_ACCELERATION.

Неправильно делать a = sqrt(ax^2+ay^2+az^2), а затем v=u+at. Это будет работать только тогда, когда v и a находятся в одном и том же направлении. И любое отклонение приведет к тому, что ошибки будут складываться. Ускорение и скорость являются векторными величинами и должны рассматриваться как таковые. Вы должны сделать vx=ux+axt, vy=uy+ayt и vz=uz+azt. а затем v = sqrt (vx ^ 2 + vy ^ 2 + vz ^ 2).

person sudP    schedule 14.11.2015
comment
что такое переменные ux, axt, uy, ayt, uz, azt, vx, vy и vz? что представляет каждый? - person angel; 16.08.2016
comment
ux — x-компонент начальной скорости. ax представляет собой x компонент ускорения. vx — x-компонент конечной скорости, и так далее. - person sudP; 17.08.2016

TYPE_LINEAR_ACCELERATION не показывает «сырые» данные с датчика, он показывает данные, обработанные высокочастотным фильтром, поэтому постоянное ускорение, такое как сила тяжести или любое другое медленно изменяющееся ускорение, не может пройти через фильтр.

Ваш автомобиль имеет довольно постоянное ускорение, которое не может пройти через фильтр. Если вы очень быстро меняете ускорение, нажимая на тормоз, затем на педаль акселерометра, а затем обратно на тормоз, тогда TYPE_LINEAR_ACCELERATION покажет довольно правильный результат, иначе он всегда будет показывать меньше, чем реальное значение ускорения.

Используйте TYPE_ACCELEROMETER, а затем удалите G (9.81) вручную. Фактически, вы должны измерить G самостоятельно, когда реальное ускорение равно 0, а затем использовать значение TYPE_ACCELEROMETER в качестве G. В моем случае это 9,6.

TYPE_ACCELEROMETER хорош для быстрого изменения ускорения, которое длится менее 1 секунды, например, движение руки, имитирующее ящик или бой на мечах.

person Dmitry    schedule 28.06.2015

TYPE_LINEAR_ACCELERATION — это трехмерный вектор, указывающий ускорение вдоль каждой оси устройства, не включая гравитацию. TYPE_ACCELEROMETER = TYPE_GRAVITY + TYPE_LINEAR_ACCELERATION

person Evgeny Karpov    schedule 21.02.2015

Вы должны умножить свой абсолютный вектор, полученный из TYPE_LINEAR_ACCELERATION, на инвертированную матрицу из TYPE_ROTATION_VECTOR.

person thxmxx    schedule 27.08.2019

Как говорит @thxmxx, вектор TYPE_LINEAR_ACCELERATION задается в системе координат устройства. Следовательно, чтобы оценить скорость в инерциальной (мировой) системе координат, перед интегрированием необходимо повернуться на предполагаемую ориентацию устройства.

Однако, даже если вы это сделаете, маловероятно, что расчетная скорость будет точной в течение длительного времени. Предположим, ваша оценка ускорения постоянно отклоняется на 0,1 м/с^2 по оси X устройства. Это примерно 1/100 ускорения свободного падения — это небольшая погрешность относительно величины ускорений, которые устройство должно измерять. Затем, посидев неподвижно в течение десяти секунд, ваша оценка скорости будет равна 1 м/с по оси X устройства.

Даже маленькие ошибки складываются в большие. Если вы дополнительно интегрируете свою оценку скорости, чтобы сформировать оценку положения, ошибки будут накапливаться еще быстрее.

Чтобы получить надежную оценку скорости, вам необходимо:

  • Датчик, который измеряет скорость, например, статическая система Пито в самолете или колесный одометр в автомобиле.
  • Датчик, который измеряет положение, такой как GPS, LIDAR или SLAM на основе зрения, и алгоритм объединения датчиков, который использует последовательность оценок положения во времени для исправления дрейфа в оценке скорости.
  • Чрезвычайно точный IMU, подобный типу, используемому в ракетах.

Второй вариант наиболее удобен для приложений на базе телефона.

person japreiss    schedule 12.02.2020