Как определить пройденное расстояние с помощью гироскопа и акселерометра?

Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние), используя гироскоп + акселерометр. GPS здесь не нужен.

Как мне подойти к этой проблеме?


person Ruchir Agile    schedule 11.07.2011    source источник


Ответы (7)


Основное исчисление этой проблемы находится в выражении

введите здесь описание изображения

(и аналогичные выражения для перемещений по y и z), а основная геометрия - это теорема Пифагора

введите здесь описание изображения

Итак, после того как вы пропустили сигналы акселерометра через фильтр нижних частот и объединили их по времени с интервалом дискретизации dt, вы можете найти смещение по x как (простите за C...)

float dx=0.0f;
float vx=0.0f;
for (int i=1; i<n; i++)
 {
   vx+=(acceleration_x[i-1] + acceleration_x[i])/2.0f*dt;
   dx+=vx*dt;
 }

и аналогично для dy и dz. Здесь

float acceleration_x[n];

содержит значения x-ускорения от начала до конца измерения в моменты времени 0, dt, 2*dt, 3*dt, ... (n-1)*dt.

Чтобы найти полное перемещение, вы просто делаете

dl=sqrt(dx*dx + dy*dy + dz*dz);

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

person drlemon    schedule 11.07.2011
comment
Хороший. Я только что увидел, что спрашивающий никогда не голосовал и не принимал ответа, поэтому +1 от меня :-) На практике я столкнулся с проблемой через несколько секунд из-за распространения ошибок даже с правилом Симпсона для интеграции. - person Kay; 11.07.2011
comment
Спасибо Кей, у меня было подозрение, что дьявол кроется в деталях, уверен, что это не невозможно исправить. Навскидку, отклик акселерометра может быть нелинейным по амплитуде на высоких частотах, или они могут недостаточно точно вычитать гравитацию. В обоих случаях должны помочь фильтрация проблемных частот (вероятно, все, что выше 30 Гц, должно быть подавлено) и калибровка во время работы (удерживайте неподвижность в течение 1 секунды и измеряйте дрейф, чтобы компенсировать его). Думаю, теперь я должен попробовать это на своем Android. - person drlemon; 12.07.2011
comment
Это все еще нерешенная проблема, чтобы получить точные результаты, то есть что-то, что вы действительно можете использовать для игры или чего-то еще. Как сказал Али, Дэвид Сакс провел небольшое исследование Android (ссылка Али на Google Tech Talk). Вы можете найти полезные идеи по ссылке, которую я предоставил в своем ответе ниже. Будьте готовы к сложной математике (фильтр Калмана и производные). - person Kay; 12.07.2011
comment
@drlemon: почему ты делаешь - (acc_x[i-1]+acc_x[i])/2? - person Ashwin; 22.10.2012
comment
@drlemon: разве это не должно быть более точным? stackoverflow.com/questions/12926459/ - person Ashwin; 22.10.2012

Вы получаете позицию, дважды интегрируя линейное ускорение, но ошибка ужасна. На практике это бесполезно.

Вот объяснение почему (Google Tech Talk) в 23:20. Я очень рекомендую это видео.

Похожие вопросы:


Обновление (24 февраля 2013 г.): @Simon Да, если вы знаете больше о движении, например, о человеке, идущем, и датчик находится на его ноге, то вы можете сделать гораздо больше. Это называется

допущения для конкретного домена.

Они с треском ломаются, если предположения не выполняются, и могут быть довольно громоздкими для реализации. Тем не менее, если они работают, вы можете делать забавные вещи. См. ссылки в моем ответе Точность акселерометра Android (инерционная навигация) при позиционировании в помещении.

person Ali    schedule 11.07.2011
comment
Знаете ли вы, пытался ли кто-нибудь найти источник ужасных систематических ошибок? Помогает ли подавление высоких частот или калибровка перед измерением? - person drlemon; 12.07.2011
comment
Посмотрите видео с 23:20, Google Tech Talk, ссылку на который я дал в своем ответе. Это объясняет, почему вы получаете эту ужасную ошибку. Ни фильтрация, ни калибровка не помогут. - person Ali; 12.07.2011
comment
Я не думаю, что они что-то объясняют. Он говорит, что есть несколько способов улучшить оценку линейного движения... но действительно важны любые ошибки ориентации, всевозможные ошибки, включая такие вещи, как ошибка поперечной оси между акселерометром и гироскопом. Мне кажется, что они просто не знают, что происходит, потому что если бы они знали, они могли бы предложить что-то, чтобы улучшить результаты. Спасибо за видео, очень познавательно! Мне придется поиграть с этим акселерометром сейчас, когда у меня будет время. - person drlemon; 12.07.2011
comment
есть ли другой способ сделать это точно? Какие другие электронные устройства можно использовать для получения точных измерений? - person Simon; 28.12.2012
comment
@Simon В зависимости от вашего приложения вы можете найти мой ответ полезным (шагомер или локализация на основе RSSI). Источником неточности является белый шум гироскопов; с кольцевым лазерным гироскопом (1 фунт плюс батареи :)) вы можете добиться большей точности, и это то, что они делают в самолетах. - person Ali; 28.12.2012
comment
@Ali, а что вы думаете о: x-io.co.uk/ products/x-imu дороговато, но может стоит собрать что-то подобное на компонентах Arduino? Насколько оно может быть точным? - person Simon; 04.01.2013
comment
@Simon Это не помогает, это просто еще один гироскоп MEMS с хорошим маркетингом. См. техническое описание. Тем не менее, его значительно проще использовать в качестве программатора на стороне приложения, так как аппаратное обеспечение делает все сложные вещи за вас. Если вы хотите выполнить двойной интеграл, вам понадобится кольцевой лазерный гироскоп вместо гироскопа MEMS. . - person Ali; 05.01.2013
comment
@Ali Я уже читал об этом кольцевом лазерном гироскопе (вы упоминали об этом ранее), но я думаю, что это немного выходит за рамки моего диапазона :). Я хотел построить что-то маленькое и довольно дешевое, поэтому моей первой мыслью было использовать аппаратное обеспечение в телефонах. Чем больше я читаю, тем больше понимаю, что это слишком сложно. Позже я подумал, что, может быть, какое-то внешнее оборудование было бы лучше, но, как вы указали, это та же проблема. Но в их презентациях это выглядит довольно эффектно и достаточно точно (особенно презентация с лестницей). Насколько лучше/хуже/быстрее это может быть, чем аппаратное обеспечение + программное обеспечение в Android/iPhone? - person Simon; 07.01.2013
comment
@Simon Где эта презентация? Честно говоря, я не провел слишком много времени на этом сайте. Я только что заметил, что это также гироскоп MEMS, такая же проблема. Я очень сомневаюсь, что вы можете сделать что-то существенное, что могло бы улучшить ситуацию: гироскопы MEMS недостаточно точны, чтобы вычислить двойной интеграл. - person Ali; 07.01.2013
comment
@ Саймон Хорошо, я посмотрю, но смогу сделать это позже. Пожалуйста, дайте мне немного времени. - person Ali; 07.01.2013
comment
Я собираю информацию в свободное время, поэтому я не ожидаю, что вы сделаете это мгновенно :) Не торопитесь. - person Simon; 07.01.2013
comment
@Simon Это обсуждение было случайно потеряно. Я думаю, вы продвинулись дальше, в любом случае я обновил свой ответ, чтобы ответить на ваш вопрос. - person Ali; 24.02.2013
comment
видео показывает дрейф 20 см в секунду для линейной оценки расстояния. я не назову это ужасным. транспортное средство, движущееся со скоростью 15 м/с и имеющее только 20-сантиметровый занос, не считается ужасным заносом! - person AlexWien; 30.05.2013
comment
@AlexWien Посмотрите еще раз с 24:40. Настоящая проблема заключается в ошибке ориентации. В этом примере дрейф составляет 8,5 метра за первую секунду и увеличивается квадратично. Это ужасно даже для описанного вами сценария. - person Ali; 30.05.2013
comment
Али, вы похоже завалили ТАК своими отрицательными ответами под десятком одинаковых вопросов. Хотя я нахожу ваши ссылки полезными, спасибо за это, но мне также кажется странным, что вы продвигаете отрицательный ответ на открытый вопрос. Оглянитесь вокруг, здесь, на SO, есть несколько интересных ответов. Какова ваша мотивация на самом деле? - person mojuba; 07.07.2013
comment
@mojuba Оглядываясь назад, я согласен, что повторяющиеся вопросы должны были быть закрыты. В эти дни я голосую за закрытие повторяющегося вопроса вместо того, чтобы давать один и тот же ответ снова и снова. Я согласен с вами в этом. Что касается «Осмотрись», здесь на SO есть несколько интересных ответов. пожалуйста, дайте мне несколько ссылок, где они действительно решили проблемы, связанные с вычислением двойного интеграла. - person Ali; 07.07.2013
comment
@mojuba Какова твоя мотивация на самом деле? Я даю эти ответы в надежде, что они будут полезны. Я потратил много времени и усилий, пытаясь решить задачу двойного интеграла, и пришел к выводу, что это невозможно. Для меня это время потрачено впустую, но я надеюсь, что смогу помочь другим не тратить время попусту. У меня только благие намерения. Еще раз подчеркиваю, повторяющиеся вопросы надо было закрывать, в этом я с вами согласен. - person Ali; 07.07.2013
comment
@mojuba Кстати, я планировал написать что вы можете сделать вместо печально известного двойного интеграла, просто в последнее время был слишком занят, чтобы сделать это. - person Ali; 07.07.2013
comment
@Ali: Любой намек на то, что вы можете сделать вместо этого? Мне также нужно преодолеть ограничения этой техники - person Aki; 26.02.2014
comment
@Aki Аки, я должен знать больше о твоем приложении. Но это всегда сводится к следующему: используйте ориентацию и/или делайте предположения, специфичные для предметной области. - person Ali; 26.02.2014
comment
@Ali: каковы будут предположения, специфичные для предметной области, для отслеживания боксера с двумя датчиками на перчатках? - person Aki; 28.02.2014
comment
Я имею в виду, что это не машина, я использую 9 степеней свободы и буду искать алгоритмы слияния датчиков, но, как было сказано в выступлении GoogleTech, двойные интегралы неприятны. Моя единственная надежда состояла бы в том, чтобы использовать DSA с Калманом, но я не могу найти ни одного. Что, если эти предположения иногда нарушаются? - person Aki; 28.02.2014
comment
@ Аки О, я пробовал что-то подобное. Ваша основная проблема будет более серьезной, чем двойной интеграл: потеря данных. При каждом попадании вы получите огромный всплеск, выходящий далеко за пределы диапазона, который может измерить датчик. В моей ситуации решением было снять видео и обработать изображение... :( В случае боксера каждое попадание также является ударом для сенсора, даже если вы его идеально откалибровали, после нескольких попаданий измеренные значения снова отключены. Извините за плохие новости. - person Ali; 28.02.2014
comment
@Ali: Ну, если всплеск есть, его можно, по крайней мере, использовать, чтобы узнать, когда произошел удар, а затем просто забыть о данных и подделать их, экстраполируя предыдущие данные? Можно ли просто отказаться от обработки пиковых данных и получить точные результаты до конца сеанса? - person Aki; 28.02.2014
comment
@ Аки, я очень сомневаюсь. :( По моему опыту, обработка изображений/видео гораздо более плодотворна для приложений такого типа (по крайней мере, так было в моем случае). - person Ali; 28.02.2014
comment
@Ali: тебе повезло ;). Мне нужен способ обойти это. Я буду продолжать экспериментировать, пока не получу что-то полезное. Спасибо за ваше руководство! - person Aki; 28.02.2014
comment
@Aki Что, если бы приложение измеряло высоту прыжка при кайтсерфинге, были бы проще предположения, специфичные для предметной области. Мы должны уметь определять взлет и посадку доски по вибрации, когда доска движется по воде. Высота точки запуска и приземления на 90% совпадает. Это поможет? - person zirinisp; 03.04.2014

Вы должны использовать интерфейс Core Motion, как описано в Простое обнаружение движения iPhone. Особенно все вращения можно отслеживать очень точно. Если вы планируете сделать что-то, связанное с линейными движениями, это очень сложный материал. Взгляните на Получение смещения из данных акселерометра с помощью Core Motion .

person Kay    schedule 11.07.2011
comment
Проголосовал. Удивительно, сколько раз всплывает этот вопрос, и люди продолжают заново изобретать колесо в форме квадрата... :( - person Ali; 29.01.2012
comment
@Ali Да, я планирую в ближайшие месяцы написать статью в блоге о прояснении этого и публикации моих результатов (решение не нашел, но есть хороший обходной путь), а затем опубликовать реферат в качестве часто задаваемых вопросов здесь, в SO. Не по теме: я не знаю, как с вами связаться через этот чат :( Вы тоже занимаетесь программированием для iPhone? У меня есть запрос (через SO :) на заключение контракта (Прага), но я занят. Напишите мне. электронная почта через мой веб-сайт, если вы заинтересованы. Кстати: Поздравляю с достижением 2k реп :))) - person Kay; 29.01.2012
comment
Спасибо :) Я только что сбросил вам и электронной почте, так что у вас будет мой адрес электронной почты для дальнейшего использования. Я также думал о написании статьи, очищающей этот беспорядок. К сожалению, у меня нет на это времени. :( В любом случае, пожалуйста, сообщите мне, когда вы закончите со своим, чтобы я мог рассказать об этом людям! - person Ali; 29.01.2012

Я попробовал это и сдался (поздно ночью, похоже, ничего не получалось). Это для проекта Unity3d.

Если кто-то захочет продолжить с того места, где я остановился, я буду рад подробно рассказать о том, что все это делает.

По сути, после некоторых из того, что оказалось ложными срабатываниями, я подумал, что попробую отфильтровать это с помощью фильтра нижних частот, затем попытался удалить отскоки, найдя тренд, затем (acc_x[i-1]+acc_x[i] )/2.

Похоже, ложное срабатывание все еще исходит из-за наклона, который я пытался убрать.

Если этот код полезен или ведет вас куда-то, пожалуйста, дайте мне знать!

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// [email protected]
/// </summary>
public class AccelerometerInput : MonoBehaviour 
{

    Transform myTransform;
    Gyroscope gyro;
    GyroCam gyroCam;

    void Awake()
    {
        gyroCam= FindObjectOfType<GyroCam> ();
        myTransform = transform;
        if (SystemInfo.supportsGyroscope) {
            gyro = Input.gyro;
            gyro.enabled = true;
        }
    }

    bool shouldBeInitialized = false; 
    void Update () 
    {

        transform.Translate (GetAccelerometer ());// * Time.deltaTime * speed);

        //GetComponent<Rigidbody> ().AddForce (GetAccelerometer ());

    }

    public float speed = 10.0F;

    public Vector3 dir;
    public float f;
    Vector3 GetAccelerometer()
    {

        dir = Input.acceleration;

        dir.x *= gyro.attitude.x;
        dir.z *= gyro.attitude.z;

        if (Mathf.Abs (dir.x) < .001f)
            dir.x = 0;
        dir.y = 0;
        if (Mathf.Abs (dir.z) < .001f)
            dir.z = 0;

        RecordPointsForFilter (dir);

        //print ("Direction : " + dir.ToString("F7"));

        return TestPointsForVelocity();
    }

    Vector3[] points = new Vector3[20];
    int index;
    void RecordPointsForFilter(Vector3 recentPoint)
    {
        if (index >= 20)
            index = 0;
        points [index] = EvaluateTrend (recentPoint);;
        index++;
    }

    //try to remove bounces
    float xTrend = 0;
    float zTrend = 0;
    float lastTrendyX = 0;
    float lastTrendyZ = 0;
    Vector3 EvaluateTrend(Vector3 recentPoint)
    {

        //if the last few points were positive, and this point is negative, don't pass it along
        //accumulate points into a trend
        if (recentPoint.x > 0)
            xTrend += .01f;
        else
            xTrend -= .1f;

        if (recentPoint.z > 0)
            zTrend += .1f;
        else
            zTrend -= .1f;

        //if point matches trend, keep it
        if (xTrend > 0) {
            if (recentPoint.x > 0)
                lastTrendyX = recentPoint.x;
        } else  // xTrend < 0
            if (recentPoint.x < 0)
            lastTrendyX = recentPoint.x;

        if (zTrend > 0) {
            if (recentPoint.z > 0)
                lastTrendyZ = recentPoint.z;
        } else  // xTrend < 0
            if (recentPoint.z < 0)
                lastTrendyZ = recentPoint.z;

        return new Vector3( lastTrendyX, 0, lastTrendyZ);
    }

    Vector3 TestPointsForVelocity()
    {
        float x = 0;
        float z = 0;

        float xAcc = 0;
        float zAcc = 0;

        int successfulHits = 0;
        for(int i = 0; i < points.Length; i++)
        {
            if(points[i]!=null)
            {
                successfulHits ++;
                xAcc += points[i].x;
                zAcc += points[i].z;
            }
        }

        x = xAcc / successfulHits;
        z = zAcc / successfulHits;

        return new Vector3 (x, 0, z);

    }
}
person user887973    schedule 19.05.2015

(acc_x[i-1]+acc_x[i])/2 — фильтр нижних частот, это среднее значение между двумя измерениями во времени.

также посмотрите здесь: http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf стр. :3

person Enrico Cupellini    schedule 07.05.2014

Нависенс.

https://navisens.com/#how-work

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

Опробовали демонстрационное приложение, которое работает в основном для картографирования перемещений без служб определения местоположения или Wi-Fi после установки исходного местоположения и направления.

iOS SDK — https://github.com/navisens/iOS-SDK

Android SDK — https://github.com/navisens/Android-SDK

Примечание. Это не открытый исходный код

person Anulal S    schedule 17.12.2019

Вот ответ. Кто-то спрашивал раньше.

Существует приложение под названием RangeFinder, делающее то же самое (доступно в App Store).

person Raptor    schedule 11.07.2011