Приблизительное позиционирование в помещении с использованием интегрирования линейного ускорения

Я пытаюсь рассчитать приблизительное положение телефона Android в комнате. Я пробовал разные методы, такие как местоположение (что ужасно в помещении) и гироскоп + компас. Мне нужно знать только примерное положение после ходьбы в течение 5-10 секунд, поэтому я думаю, что интегрирования линейного ускорения может быть достаточно. Я знаю, что ошибка ужасна из-за распространения ошибки, но, возможно, это сработает в моей настройке. Мне нужно только приблизительное положение, чтобы направить камеру на телефон Android.

Я закодировал двойную интеграцию, но я делаю что-то неправильно. ЕСЛИ телефон статичен на столе, позиция (x, y, z) всегда увеличивается. В чем проблема?

 static final float NS2S = 1.0f / 1000000000.0f;
    float[] last_values = null;
    float[] velocity = null;
    float[] position = null;
    float[] acceleration = null;
    long last_timestamp = 0;
    SensorManager mSensorManager;
    Sensor mAccelerometer;

public void onSensorChanged(SensorEvent event) {
         if (event.sensor.getType() != Sensor.TYPE_LINEAR_ACCELERATION)
             return;

         if(last_values != null){
                float dt = (event.timestamp - last_timestamp) * NS2S;

                acceleration[0]=(float) event.values[0] - (float) 0.0188;
                acceleration[1]=(float) event.values[1] - (float) 0.00217;
                acceleration[2]=(float) event.values[2] + (float) 0.01857;

                for(int index = 0; index < 3;++index){
                    velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
                    position[index] += velocity[index] * dt;
                }
            }
            else{
                last_values = new float[3];
                acceleration = new float[3];
                velocity = new float[3];
                position = new float[3];
                velocity[0] = velocity[1] = velocity[2] = 0f;
                position[0] = position[1] = position[2] = 0f;
            }
            System.arraycopy(acceleration, 0, last_values, 0, 3);
            last_timestamp = event.timestamp;
    }

Вот такие позиции я получаю, когда телефон лежит на столе (без движения). Значения (x, y, z) увеличиваются, но телефон остается неподвижным. введите здесь описание изображения

И это позиции после расчета скользящего среднего для каждой оси и вычитания из каждого измерения. Телефон тоже пока. введите здесь описание изображения

Как улучшить код или другой способ получить примерное положение внутри комнаты?


person nabrugir    schedule 09.07.2013    source источник


Ответы (3)


В акселерометре неизбежны ошибки измерения. Они вызваны незначительными вибрациями стола, несовершенством изготовления и т. д. и т. д. Накопление этих ошибок с течением времени приводит к Случайное блуждание. Вот почему системы позиционирования могут использовать акселерометры только в качестве вспомогательного средства позиционирования через некоторый фильтр. Им по-прежнему требуется какая-то форма счисления пути, такая как GPS (который плохо работает в дверях).

В настоящее время проводится большое количество исследований систем внутреннего позиционирования. Некоторыми областями исследований систем, которые могут использовать преимущества существующей инфраструктуры, являются Wi-Fi и позиционирование светодиодного освещения. Пока нет очевидного решения, но я уверен, что нам понадобится специальное решение для точного и надежного позиционирования внутри помещений.

Вы сказали, что позиция всегда продолжает увеличиваться. Вы имеете в виду, что компоненты x, y и z становятся положительными только после нескольких сбросов? Или вы имеете в виду, что позиция продолжает дрейфовать от нуля?

Если вы выводите необработанные измерения ускорения, когда телефон неподвижен, вы должны увидеть ошибки измерения. Поместите кучу этих измерений в электронную таблицу Excel. Вычислите среднее значение и стандартное отклонение. Среднее значение должно быть равно нулю для всех осей. Если нет, то есть смещение, которое вы можете удалить в своем коде с помощью простого фильтра усреднения (рассчитайте скользящее среднее и вычтите его из каждого результата). Стандартное отклонение покажет вам, как далеко вы можете ожидать отклонения по каждой оси после N временных шагов, как стандартное_отклонение * sqrt(N). Это должно помочь вам математически определить ожидаемую точность как функцию времени (или N временных шагов).

person Brian Heilig    schedule 09.07.2013
comment
Позиция всегда продолжает увеличиваться. Я построил измерения на Matlab, и среднее значение не равно нулю. Кажется, существует предвзятость, которая продолжает увеличивать значения для каждой позиции. Я могу попытаться удалить его с помощью среднего фильтра, но мне интересно, связано ли это смещение с ошибкой в ​​моем коде или с накопительной ошибкой. Есть ли у вас хорошие сведения о позиционировании на основе ускорения и/или фильтрации (усредненный фильтр или другие типы)? - person nabrugir; 10.07.2013
comment
Если вы печатаете вывод event.values[index], как ваш код может вызывать смещение? Также нормальным является смещение в необработанных измерениях акселерометра. Я не могу придумать ни одной ссылки, которая не перегрузила бы вас деталями, которые вам не нужны. Предположим, что смещение фиксировано на протяжении всего жизненного цикла вашего приложения, но отличается от мобильного телефона к мобильному телефону. Просто рассчитайте скользящее среднее по каждой оси и вычтите его из измерения. - person Brian Heilig; 10.07.2013
comment
Если вы обеспокоены тем, что смещение будет меняться в течение всего срока службы вашего приложения, вы можете использовать экспоненциальная скользящая средняя. Выберите альфа от 0 до 1. Большие значения альфа означают, что ваш фильтр будет быстрее приспосабливаться к изменениям среднего значения, но будет более восприимчив к шуму. Может быть, вы можете поиграть с некоторыми графиками в Matlab. Если вы действительно интересуетесь теорией фильтров, я бы начал с книги «Понимание обработки цифровых сигналов», Лайонс. - person Brian Heilig; 10.07.2013
comment
Я рассчитываю скользящее среднее на Matlab (используя фильтр скользящего среднего) и вычитаю из измерений. Проблема та же, поэтому я думаю, что делаю какую-то ошибку в коде, может быть, когда я вычисляю позицию с помощью двойной интеграции? Я отредактировал вопрос, добавив значения, которые я получаю, когда телефон все еще находится на столе. до и после вычитания скользящего среднего из каждой оси. - person nabrugir; 11.07.2013
comment
Можете ли вы обновить свой код, чтобы показать, как вы вычисляете скользящее среднее и вычитаете его? Вы должны рассчитать три скользящих средних для каждого event.values[index] и вычесть это среднее значение из каждого event.values[index]. Вы не должны усреднять позицию. - person Brian Heilig; 11.07.2013
comment
Я рассчитал скользящее среднее, используя фильтр скользящего среднего в Matlab. Затем я вычитал из каждой оси. Код загружен сейчас. - person nabrugir; 11.07.2013
comment
Набругир, ты когда-нибудь до этого доходил? - person erik; 22.06.2014

Брайан прав, уже развернуты внутренние системы позиционирования, работающие с инфраструктурой, которую можно легко найти (почти) в любой комнате. Одним из решений, которое оказалось наиболее надежным, является снятие отпечатков пальцев WiFi. Я рекомендую вам взглянуть на indoo.rs — www.indoo.rs — они являются пионерами в отрасли и уже имеют довольно развитую систему.

person Jimmy    schedule 10.07.2013

Возможно, это не самое элегантное и надежное решение, но в моем случае оно служит цели.

Примечание. В моем случае я фиксирую местоположение еще до того, как пользователь сможет начать действие, для которого требуется позиционирование в помещении... и меня интересует только приблизительная оценка того, насколько далеко он продвинулся.

У меня есть диспетчер датчиков, который создает матрицу вращения на основе ориентации устройства. (используя Sensor.TYPE_ROTATION_VECTOR) Это, очевидно, не дает мне движения вперед, назад или из стороны в сторону, а только ориентацию устройства. С такой ориентацией устройства у меня есть хорошее представление о направлении пользователя в градусах (в какую сторону он смотрит) и, используя Sensor_Step_Detector, доступный в KitKat 4.4, я делаю предположение, что шаг составляет 1 метр в направлении, в котором смотрит пользователь.

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

каждый раз, когда обнаруживается шаг, я в основном вызываю эту функцию:

public void computeNewLocationByStep() {
       Location newLocal = new Location("");
       double vAngle = getBearingInDegrees(); // returns my users bearing
       double vDistance = 1 / g.kEarthRadiusInMeters; //kEarthRadiusInMeters =  6353000;
        vAngle = Math.toRadians(vAngle);

        double vLat1 = Math.toRadians(_location.getLatitude());
        double vLng1 = Math.toRadians(_location.getLongitude());

        double vNewLat = Math.asin(Math.sin(vLat1) * Math.cos(vDistance) +
                      Math.cos(vLat1) * Math.sin(vDistance) * Math.cos(vAngle));

        double vNewLng = vLng1 + Math.atan2(Math.sin(vAngle) * Math.sin(vDistance) * Math.cos(vLat1),
                              Math.cos(vDistance) - Math.sin(vLat1) * Math.sin(vNewLat));



        newLocal.setLatitude(Math.toDegrees(vNewLat));
        newLocal.setLongitude(Math.toDegrees(vNewLng));

        stepCount =0;
        _location = newLocal;

    }
person erik    schedule 23.06.2014