GPS-трек, вычисление разницы высот

Я реализовал GPS-трекер для Android. Пока это работает довольно хорошо, но у меня есть проблемы с вычислением правильной разницы высот для дорожки. Хочу подвести итоги всех метров, на которые "влез" и "спустился" аппарат. Я делаю это в фоновом сервисе, сравнивая текущий объект местоположения с предыдущим и сохраняя разницу непосредственно в виде столбца в базе данных. Если я суммирую это после того, как трасса закончена, я получаю значение, которое примерно в 2,5 раза выше (1500 м против 650 м), измеренное с помощью велосипедного спидометра, использующего барометр.

Я знаю, что высота, измеренная устройством GPS, неточна. Есть ли способ «нормализовать» измеренную высоту? Должен ли я, например, игнорировать все изменения высоты ниже 2 метров? Другой возможностью было бы использование дополнительных датчиков, поскольку некоторые устройства также имеют барометр. Но это поможет только на некоторых устройствах.

Спасибо за любые советы или подсказки по этому вопросу!

РЕДАКТИРОВАТЬ 28.05.2013: Ответ Брайса помог мне встать на правильный путь. Я начал искать в Интернете и нашел очень простой фильтр нижних частот, который легко реализовать. Я сделал это на С++

Класс узла, представляющий одну путевую точку:

class Node {
private:
    double distance;
    double altitude;
    double altitudeup;
    double altitudedown;
    double latitude;
    double longitude;
    long timestamp;

public:
    Node(double dist, double alti, double altiup, double altidown, double lat, double lon, long ts);
    double getAltitude();
    double getAltitudeup();
    double getAltitudedown();
};

Вот функция, которая выполняет фактическую работу и вычисляет значения общего восхождения и спуска:

void SimpleLowPass::applySLP()
{
    double altiUp = 0;
    double altiDown = 0;
    double prevAlti = this->nodeList[0]->getAltitude();
    double newAlti = prevAlti;
    for (auto n : this->nodeList)
    {
        double cur = n->getAltitude();
//        All the power of the filter is in the line
//        newAlti += (cur - newAlti) / smoothing.
//        This finds the difference between the new value and the current (smoothed)
//        value, shrinks it based on the strength of the filter, and then adds it
//        to the smoothed value. You can see that if smoothing is set to 1 then the
//        smoothed value always becomes the next value. If the smoothing is set to
//        2 then the smoothed value moves halfway to each new point on each new
//        frame. The larger the smoothing value, the less the smoothed line is
//        perturbed by new changes.
        newAlti += (cur - newAlti) / 20.0;
        std::cout << "newAlti: " << newAlti << std::endl;
        if (prevAlti > newAlti)
        {
            altiDown += prevAlti - newAlti;
        }
        if (newAlti > prevAlti)
        {
            altiUp += newAlti - prevAlti;
        }
        prevAlti = newAlti;

    }
    std::cout << "Alti UP total: " << altiUp << std::endl;
    std::cout << "Alti DOWN total: " << altiDown << std::endl;
}

Это быстрая и грязная реализация. Но со значением 20 для сглаживания я получаю довольно хорошие результаты. Тем не менее мне нужно будет записать больше треков и сравнить результаты. Также на веб-сайте, где я нашел этот фильтр нижних частот, есть независимая от частоты кадров реализация, и я хочу поиграть с реализацией скользящего среднего.

простой низкочастотный фильтр

Спасибо за все ваши ответы!


person Christian Rapp    schedule 25.05.2013    source источник
comment
Я бы предположил, что барометр значительно менее точен, чем GPS. Кроме того, уверены ли вы, что ваш велосипедный высотомер отслеживает сумму всех подъемов/спусков, а не только общую разницу высот между начальной и конечной точками?   -  person 323go    schedule 26.05.2013
comment
@323go барометр, если гораздо точнее, но только для дельт.   -  person Bryce    schedule 26.05.2013
comment
Я проверил дельты с помощью трека, который я создал в онлайн-картографическом сервисе. У меня 720 м вверх и вниз, поэтому значения моего велосипедного альтиметра должны быть в порядке.   -  person Christian Rapp    schedule 26.05.2013


Ответы (3)


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

person Bryce    schedule 25.05.2013
comment
Что я узнал из своих данных, так это то, что есть много записей с минимальными различиями. Насколько я понимаю, это из-за неточности устройства GPS. Какую фильтрацию/сглаживание вы бы порекомендовали для данных о высоте? Я уже использую Douglas-Peucker, чтобы сгладить свой трек (на основе широты/долготы). - person Christian Rapp; 26.05.2013
comment
Я экспериментировал с несколькими фильтрами, но еще не нашел фильтра-убийцы. Простейшими в реализации, которые все еще дают достойные результаты, являются фильтры нижних частот и блочные фильтры. Другой вариант, а не фильтрация, это какая-то аппроксимация кривой. Аппроксимация кривой немного завышает оценку подъема, а фильтрация немного занижает. - person Bryce; 26.05.2013
comment
Не могли бы вы привести несколько примеров низкочастотных или прямоугольных фильтров? - person Christian Rapp; 26.05.2013
comment
Извините, имелся в виду фильтр товарных вагонов (en.wikipedia.org/wiki/Boxcar_function). Вы можете реализовать его как скользящее среднее, где размер окна определяется как расстояние. Я бы попробовал это сначала, если результаты все еще недостаточно хороши, возможно, стоит подумать о поиске библиотеки Java, которая предоставляет фильтры FIR (конечная импульсная характеристика). - person Bryce; 26.05.2013
comment
Я принял ваш ответ, потому что он навел меня на правильный путь, спасибо! - person Christian Rapp; 28.05.2013

Высота GPS сильно колеблется, и каждый из этих скачков выглядит как подъем или спуск. По моему опыту датчик барометра колеблется в гораздо более узком диапазоне.

Что вам нужно сделать, так это измерить каждый подъем (где подъем определяется как постоянное увеличение высоты) и суммировать подъемы, чтобы определить общую высоту подъема.

С любым датчиком (GPS или барометром) высота будет немного колебаться, и мы не хотим, чтобы эти небольшие скачки регистрировались как короткие спуски и подъемы. Поэтому, когда мы поднимаемся, мы хотим игнорировать небольшие перепады высоты.

double THRESHOLD = 10;
Direction climbingOrDescending = Direction.NONE;

double totalAscent = 0;
double totalDescent = 0;

double climbStart;
double maxAltitude;

double descentStart;
double minAltitude;

public void onSample(double sample) {
    if (climbingOrDescending == Direction.NONE) {
        // First sample
        climbingOrDescending = Direction.CLIMBING; // Arbitrary
        climbStart = sample;
        maxAltitude = sample;
    } else if (climbingOrDescending == Direction.CLIMBING) {
        if (sample > maxAltitude) {
            maxAltitude = sample;
        } else if (sample < (maxAltitude - THRESHOLD) ) {
            // bounces in sample that are smaller than THRESHOLD are ignored. If 
            // the sample is far below maxAltitude... it is not a bounce, record
            // the climb and move to a descending state
            double altitudeGainedThisClimb = maxAltitude  - climbStart;
            totalAscent +=  altitudeGainedThisClimb;
            // Prepare for descent.
            climbingOrDescending = Direction.DESCENDING;
            descentStart = maxAltitude;
            minAltitude = sample;
        }
    } else { // climbingOrDescending == DESCENDING
        // similar code goes here to measure descents
    }
}

public double getTotalAscent() {
    if (climbingOrDescending == Direction.CLIMBING) {
        return totalAscent + (maxAltitude - climbStart);
    } else {
        return totalAscent;
    }
}
person abh    schedule 25.05.2013
comment
Мне трудно понять ваш ответ :) Не могли бы вы привести пример из реального мира с некоторыми произвольными данными. Мне не нужен код, просто несколько цифр, которые помогут понять вашу идею. - person Christian Rapp; 26.05.2013

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

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

person Paul Lammertsma    schedule 25.05.2013
comment
Мои измерения высоты лежат между 350 м и 800 м. Что я получу, если вычту 350 м из всех путевых точек относительно перепадов высот? - person Christian Rapp; 26.05.2013
comment
Я только хотел подчеркнуть, что вы не должны хранить разницу между отдельными неточными образцами. Независимо от того, хотите ли вы пост-анализировать свои данные, зависит от вас, но имейте в виду, что каждый образец должен быть независимой точкой данных. - person Paul Lammertsma; 26.05.2013