Android - Как рассчитать пройденное расстояние - PullRequest
0 голосов
/ 01 апреля 2020

Я использую FusedLocationProviderClient для получения locationUpdates после настройки свойств LocationRequest.

Для вычисления «пройденного расстояния» я подумал, что сделаю следующее:

Location lastLocation;   // initialized to start location with getLocation() - code not shown.
LocationCallback locationCallback;
Double DistanceTraveled = 0.0;

locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        if (locationResult != null) {
            // Get last location in result if more than one are returned.
            Location thisLocation = locationResult.getLastLocation();
            // Sum up DistanceTraveled
            DistanceTraveled = DistanceTraveled + lastLocation.distanceTo(thisLocation);
            // Save thisLocation for next time onLocationResult() is called
            lastLocation.set(thisLocation);
        }
    }
}

Ну, это не не очень хорошо работает При каждом обратном вызове точное местоположение изменяется случайным образом от 0 до 10 метров только из-за точности результата. Так что, если я стою на месте в течение 10 минут с 5-секундным обновлением с использованием этого алгоритма, это подытожит несколько метров, которые я прошел, когда я вообще не двигался!

Каким я должен быть делать, чтобы получить точный учет моего пройденного расстояния? Какие варианты существуют?

1 Ответ

0 голосов
/ 15 апреля 2020

Хорошо - прошло 12 дней с тех пор, как я разместил здесь свой вопрос. Много чтения, тестирования, кодирования, больше тестирования, больше чтения. Теперь я обязан внести свой вклад в сайт, который так много дает мне. Итак, начнем.

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

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

Теперь к проблеме этого поста. Расчет расстояния пройден. Это совсем другая проблема. И это то, что я искал при публикации вопроса. Как люди получают точный учет пройденного расстояния при ходьбе? Потому что просто регистрация на обновления местоположения, а затем суммирование Location1.distanceTo (Location2) обычно дает одно сильно раздутое общее расстояние. Почему? Я не понял проблему. Теперь я делаю. И если бы у меня было это понимание, то путь к решению был бы более ясным.

Позвольте мне привести пример. Допустим, я хожу 10 секунд. На втором 0 (t0) это то, с чего я начинаю. И скажем, я двигаюсь на 1 метр к моменту времени t1. Я стою в этом положении до t5, а затем иду еще 5 секунд до t10. Комбинация ходьбы / стояния помогает проиллюстрировать проблему.

Каждое обновление местоположения GPS содержит координаты (широта / долгота) или точку вместе с оценкой точности в метрах. Наряду с другими данными, но единственное, что меня волнует, это время в миллисекундах. В этом примере всегда на 1000 мс больше, чем в последнем обновлении.

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

Итак, в момент времени t0 мое истинное местоположение может быть на 20 м выше, чем сообщалось. Я иду на 1 метр вперед и обновляю местоположение в момент t1, сообщая, что я на 20 метров впереди того места, где я на самом деле. Итак, вычисление t0.distanceTo (t1) сообщает, что я переместился на 40 м, когда я действительно переместился только на 1 м. Начинаешь видеть картинку? Читайте дальше ...

Теперь я стою здесь до t5. И я получаю еще 4 обновления местоположения, которые, например, для целей, находятся на 20 метров впереди, 20 метров позади, 20 метров слева и 20 метров справа от меня. (Это крайний пример, но для иллюстрации используются простые цифры). Таким образом, в дополнение к моим предполагаемым 40 м пути через 1 секунду, теперь он думает, что я переместился примерно на 20x4 или 80 м больше, в общей сложности на 120 м. И я только перешел 1 м в реальности! Продолжайте идти еще 5 метров до t10, и ваше расстояние может снова составить 5x20 или 100 метров, в общей сложности 220 метров, если вы прошли всего 6 метров за 10 секунд. Вот почему простое суммирование пройденного расстояния никогда не будет точным, если есть ошибка в точности.

В этом проблема. И до тех пор, пока вы не поймете это, вы будете озадачены тем, как эта дурацкая Galaxy S9 делает это с вами.

Как насчет усреднения очков? «средняя точка (t0, t1) .distanceTo (средняя точка (t2, t3)» и т. д. Это всегда будет приводить к расстоянию, которое меньше истинного пройденного расстояния. В зависимости от движения, иногда на много.

Существует множество методов (см. Ссылку выше), которые можно попробовать, чтобы уменьшить ошибку в расчетах пройденного расстояния. Я обнаружил, что мой метод ниже дает более точные результаты при ходьбе, чем приложение MyTracks от Google. Я неоднократно проверял на дистанциях 200, 500 и 1000 м. И это постоянно дает хорошие результаты, как правило, с ошибкой <10%. В половине случаев, Google MyTracks говорит, что я прошел 500 м + в тесте 200 м. </p>

onLocationResult(LocationResult locationResult) {

    lastLocationReceived.set(locationResult.getLastLocation());
    // Throw away updates that don't meet a certain accuracy. e.g. 30m
    if (lastLocationReceived.hasAccuracy() && locatLocationReceived.getAccuracy() <= MIN_ACC_METERS_FOR_DISTANCE_TRAVELED) {
        // Don't use it if the current accuracy X 1.5 > distance traveled since last valid location
        if ((lastLocationReceived.getAccuracy() * 1.5) < loastLocationReceived.distanceTo(lastLocationUsedForDistanceTraveled) {
            // Calculate speed of travel to last valid location; avg walking speed is 1.4m/s; I used 2.0m/s as a high end value. 
            // Throw away values that are too high because it would have required that you run to get there.
            // Sometimes the location is somewhere you could not have gotten to given the time.
            long timeDelta = lastLocationReceived.getTime() - lastLocationUsedForDistanceTraveled.getTime();
            if ((lastLocationReceived.distanceTo(lastLocationUsedForDistanceTraveled) / timeDelta) > MAX_WALKING_SPEED) {
                // NOW we have a value we can use to minimize error
                distanceTraveled += lastLocationReceived.distanceTo(lastLocationUsedForDistanceTraveled);
                // Update last valid location
                lastLocationUsedForDistanceTraveled.set(lastLocationReceived);
            }
        }
    }
};

Примечания:

  1. onPause () для остановки остановки активности.
  2. onResume () restart locationUpdates.
  3. Установка / использование locationRequest.setSmallestDisplacement () дала мне странные результаты. Я никогда не устанавливал это значение в моем locationRequest. Как он узнал, что вы продвинулись на 5 метров, когда точность составляет 20 метров?
  4. Я не вижу необходимости постоянно получать обновления местоположения при приостановленном приложении (в кармане). Как только вы вытаскиваете свой телефон из кармана, чтобы использовать его для записи прицела, он восстанавливается довольно быстро. Дальнейшее тестирование может доказать, что это подвержено ошибкам. Но пока, похоже, все в порядке.

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

В своем тестировании я создал действие, которое позволило мне корректировать настройки locationRequest () в режиме реального времени (остановка и перезапуск locationUpdates, необходимые для изменений); а также изменение минимальных уровней точности и множителя точности (используется выше в коде как 1.5). Так что я смог протестировать и поиграть с различными настройками параметров, чтобы увидеть, какие результаты дают наилучшие результаты.

Надеюсь, это поможет другим начать этот путь впервые. Хотелось бы услышать комментарии, исправления, улучшения, если у кого-то есть.

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