PHP Цикл через GPX для расчета общего подъема/спуска трека

Я хочу зациклить файл gpx и рассчитать общий подъем и спуск. У меня есть функция, которая может вычислить разницу в высоте между двумя наборами длинных точек, и я настроил simplexml для чтения и цикла через точки trkseg файла gpx.

Проблема в том, что это не точно (на самом деле не точно, как на самом деле).

Эти две линии приведут к разным подъемам и спускам, как и в реальной жизни:

$total_ascent += ($val - $last_elevation);
$total_descent += ($val - $last_elevation);

Кто-нибудь знает, как поточнее рассчитать общий подъем и спуск трека?

Это мой текущий фрагмент кода для его вычисления ($track_elevations — это массив с высотами всего трека):

if (!empty($track_elevations)) {
        $total_ascent = $total_descent = 0
        $lowest_elevation = $highest_elevation = $last_elevation = null;

        foreach ($track_elevations as &$val) {
            if (!is_null($last_elevation)) {
                if ($last_elevation < $val) {
                    $total_ascent += ($val - $last_elevation);
                }
                elseif ($last_elevation > $val) {
                    $total_descent += ($last_elevation - $val);
                }
            }

            if (is_null($lowest_elevation) or $lowest_elevation > $val) {
                $lowest_elevation = $val;
            }

            if (is_null($highest_elevation) or $highest_elevation < $val) {
                $highest_elevation = $val;
            }

            $last_elevation = $val;
        }
    }

Пример массива $track_elevations:

$track_elevations = array(
    327.46,
    328.27,
    329.32,
    330.11,
    329.46,
    329.39,
    329.68,
    331.04,
    333.23,
    333.46,
    332.97,
    332.88,
    332.99,
    332.75,
    332.74,
    334.01,
    333.62
)

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

Чего я хочу достичь:

Я постараюсь объяснить это подробнее - когда я еду на ф.е. 20 км по ровной дороге (почти без подъемов и спусков), сумма подъемов и спусков должна быть близка к 0. Но когда я суммирую $track_elevations (как в моем фрагменте кода), я получаю $total_ascent и $total_descent т.е. 500 метров... Это из-за того, что между каждым элементом массива в $track_elevations есть разница в пару сантиметров, а я пока еду по ровной дороге... И в сумме соберется на большое количество метров... Надеюсь теперь это более понятно.


person Legionar    schedule 21.05.2015    source источник
comment
Можете ли вы предоставить несколько примеров значений для массива track_elevations?   -  person Stephen    schedule 26.05.2015
comment
Я, вероятно, неправильно понял вопрос, но похоже, что вы поднялись и спустились на пару метров (на основе предоставленного массива). Что именно вы хотите посчитать?   -  person Ynhockey    schedule 26.05.2015
comment
Я постараюсь объяснить это подробнее - когда я еду на ф.е. 20 км по ровной дороге (почти без подъемов и спусков), общий подъем и спуск должен быть близок к 0. Но когда я суммирую $track_elevations (как в моем фрагменте кода), я получаю $total_ascent и $total_descent т.е. 500 метров... Это из-за того, что между каждым элементом массива в $track_elevations есть разница в пару сантиметров, а я пока еду по ровной дороге... И в сумме соберется на большое количество метров... Надеюсь теперь это более понятно.   -  person Legionar    schedule 26.05.2015
comment
Так что, чтобы быть действительно ясным - вы хотите знать свой общий подъем или спуск из исходной исходной позиции, или сумму всех подъемов и спусков? например если вы начинаете со 100 м, поднимаетесь на 10, спускаетесь на 9, поднимаетесь на 5 и спускаетесь на 6 - вы хотите, чтобы ваш общий подъем был рассчитан как 15 или 0?   -  person Stephen    schedule 26.05.2015
comment
Да, но я думаю, что я должен использовать некоторую точность, потому что, когда я иду по ровной дороге, где высота еще, скажем, 349,0 м - 351,0 м, она вернется f.e. через 20 километров общий подъем и спуск около 500 метров, но это конечно неправда, просто посчитано по частям на каждую разницу примерно в пару сантиметров...   -  person Legionar    schedule 26.05.2015
comment
Не могли бы вы бросить это бессмысленное редактирование вопросов? Заранее спасибо.   -  person Your Common Sense    schedule 18.04.2016


Ответы (3)


Проблема в том, что если вы вычислите $lastHeight - $track_elevations[$i] для ascentet, вы получите значения ниже 0, и поэтому вы получите большие различия между $total_asc и $total_desc.

<?php
$track_elevations = array(
    327.46,
    328.27,
    329.32,
    330.11,
    329.46,
    329.39,
    329.68,
    331.04,
    333.23,
    333.46,
    332.97,
    332.88,
    332.99,
    332.75,
    332.74,
    334.01,
    333.62
);

$lastHeight = $track_elevations[0];
$total_ascent = 0;
$total_descent = 0;
for ($i=1;$i<count($track_elevations);$i++) {
    if ($track_elevations[$i] > $lastHeight) {
        $total_ascent += -1 * ($lastHeight - $track_elevations[$i]);
    }
    else {
        $total_descent += ($lastHeight - $track_elevations[$i]);
    }
    $lastHeight = $track_elevations[$i];
}
echo $total_ascent ."\n";
echo $total_descent . "\n\n--\n";
echo $total_ascent  - $total_descent . "\n";

--

$ php -f gpx.php
8.1
1.94

--
6.16

-- ручной расчет значений:

Ascent:
0.81
1.05
0.79
0.29
1.36
2.19
0.23
0.11
1.27
---
8.1

Descent:
0.65
0.07
0.49
0.09
0.24
0.01
0.39
---
1.94    
person take    schedule 26.05.2015
comment
Мой фрагмент кода никогда не получит значения ниже 0... Когда вы возрастаете - if ($last_elevation < $val) {, чем это $total_ascent += ($val - $last_elevation); будет больше 0; когда вы спускаетесь - elseif ($last_elevation > $val) {, чем это $total_descent += ($last_elevation - $val); будет больше 0. Кстати: я использую функцию abs в конце моей функции расчета. Но это все равно не решит проблему, что все не так, как в жизни... - person Legionar; 26.05.2015
comment
Когда я запускаю ваш код с данными вашего примера, я получаю $total_descent = -1.94. Я рассчитал данные вашего примера вручную и добавил их в свой ответ. - person take; 26.05.2015
comment
Да, я знаю. Но проблема не в этом - разница между $total_ascent и $total_descent. AD1: Я использую abs(), поэтому оно будет больше 0. AD2: в моем примере есть только несколько высот, обычно их около 1000, а общее количество подъемов и спусков составляет около 500 метров. Но, как я уже сказал, я ехал на велосипеде 20 километров по ровной дороге, поэтому общий подъем и спуск должен составлять всего пару метров (т.е. 5 - 10, а не 500). Вот в этом и проблема моего вопроса... И в этой паре высот, которые я указал, я точно не пролез 9,1 м, а может всего 50 см... - person Legionar; 26.05.2015

Вы уверены, что это "плоский"? flat?Можете ли вы предоставить полный набор данных? Также я не думаю, что это проблема точности PHP. Ваши точки данных имеют точность только до двух цифр. Может датчик округляет?

person Greg    schedule 01.06.2015
comment
Это не проблема в PHP. Сенсор округляет его как-то странно. Это все еще между 328 и 334 м, но дорога была ровной. Я просто спрашиваю, должен ли я использовать некоторую точность, чтобы не учитывать небольшие изменения высоты... - person Legionar; 01.06.2015

Даже если вы едете по идеально ровной дороге, данные о высоте, полученные с помощью GPS, всегда будут немного увеличиваться и уменьшаться. GPS не очень точно определяет высоту даже в идеальных условиях.

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

Есть несколько вариантов получения лучших результатов, но все они более или менее сложны: вы можете «сгладить» кривую высот с помощью соответствующих алгоритмов. Вы можете отбросить данные GPS о высоте и заменить их предварительно записанными данными о высоте для всех координат на Земле (так называемые данные SRTM).
Вы можете использовать данные SRTM и разумно смешать их с вашими собственными данными GPS.

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

person Joeuser    schedule 27.08.2015