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

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

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

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

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

2

Решение

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

0

Другие решения

Высота 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;
}
}
2

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

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

0