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


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

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

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

Правка 28.05.2013: То ответ Брайса вывел меня на правильный путь. Я начал искать в интернете и нашел очень простой фильтр низких частот, который легко реализовать. Я сделал это в c++

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

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 для сглаживания я получаю довольно хорошие результаты. Тем не менее мне нужно будет записать больше треков и сравнить результаты. Также есть независимая реализация частоты кадров на веб-сайте, где я нашел этот фильтр низких частот, и я хочу играть с реализацией скользящей средней.

Простой фильтр нижних частот

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

3 2

3 ответа:

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

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

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

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

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;
    }
}

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

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