java 计算移动设备实际行驶的距离

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34551318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:01:58  来源:igfitidea点击:

calculate actual distance travelled by mobile

javaandroidiosobjective-cgoogle-maps

提问by Haris

I want to calculate actual distance traveled by mobile (iOS and Android). I know through google map API, we can find optimum route distance between 2 coordinates. But I want to calculate distance, actual path mobile(in vehicle) has covered.

我想计算移动设备(iOS 和 Android)的实际行驶距离。我知道通过谷歌地图 API,我们可以找到 2 个坐标之间的最佳路线距离。但我想计算距离,移动(在车辆中)已经覆盖的实际路径。

One Algo I came to know is saving coordinates after x seconds, lets say after 5 or 10 seconds, and then calculate distance between consecutive coordinates, and there sum will give total distance.

我开始知道的一种算法是在 x 秒后保存坐标,假设在 5 或 10 秒后,然后计算连续坐标之间的距离,总和将给出总距离。

I want to discuss better approach of its solution , Is there any better solution?

我想讨论其解决方案的更好方法,有没有更好的解决方案?

Edit : How Apps like Nike running app and Uber works?

编辑:耐克跑步应用程序和优步等应用程序如何工作?

回答by Alban

------------------UPDATE----------------------

------------------更新----------------------

There is two major point in your question.

你的问题有两个要点。

1) get the phone coordinates (which has been treated in the first part of this response)

1)获取电话坐标(在本响应的第一部分已经处理过)

2) Calculate the realdistance between this two coordinates

2)计算这两个坐标之间的实际距离

IMHO, calculus could be done by a web service: calculation based only on the distance between two coordinates can lead to really wrong result.

恕我直言,微积分可以通过网络服务完成:仅基于两个坐标之间的距离的计算可能会导致真正错误的结果。

Here is an exemple of such a web service https://graphhopper.com/#directions-api

这是此类 Web 服务的 示例 https://graphhopper.com/#directions-api

The demo app: https://graphhopper.com/api/1/examples/

演示应用程序:https: //graphhopper.com/api/1/examples/

It's based on traffic flow (as many of this tools) So you have to be careful with the order of the coordinates because it can bring wrong result.

它基于交通流量(与许多此类工具一样)因此您必须小心坐标的顺序,因为它可能会带来错误的结果。

For exemple with two point in the right order: enter image description here

例如,以正确的顺序有两个点: 在此处输入图片说明

This gives a good result

这给出了一个很好的结果

But if you give wrong order (with the same coordinates) enter image description here

但是如果你给出错误的顺序(具有相同的坐标) 在此处输入图片说明

For the same coordinates, it can lead to an extremely different result.

对于相同的坐标,可能会导致截然不同的结果。

So for coordinates ABCD (in chrnological order) you need to do:

因此,对于坐标 ABCD(按时间顺序),您需要执行以下操作:

A->B B->C C->D

A->B B->C C->D

Graphhopper seems able to do offline distance calculus

Graphhopper 似乎能够进行离线距离计算

Here are the lib on iOS and Android

这是 iOS 和 Android 上的库

https://github.com/graphhopper/graphhopper-ios/

https://github.com/graphhopper/graphhopper-ios/

https://github.com/graphhopper/graphhopper/tree/master/android

https://github.com/graphhopper/graphhopper/tree/master/android

---------------------------------------------------

-------------------------------------------------- ——

You have to define how your app work. Foreground or background?

您必须定义您的应用程序的工作方式。前景还是背景?

As said in other responses, you'll have to get the user position every X seconds. Then calculate the distance.

正如其他回复中所说,您必须每 X 秒获取一次用户位置。然后计算距离。

For iOS:

对于 iOS:

  1. You can use information on this website: http://mobileoop.com/
  1. 您可以使用本网站的信息:http: //mobileoop.com/

It talks about tracking user location on iOS when the app is in background.

它讨论了当应用程序在后台时在 iOS 上跟踪用户位置。

  1. Here is the github: https://github.com/voyage11/Location
  1. 这是github:https: //github.com/voyage11/Location

Then you have to convert the point thanks to

然后你必须转换点感谢

CLLocationDistance distance = [aCLLocationA distanceFromLocation:aCLLocationB];

You can also check this (from apple doc) https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html:

您还可以检查这个(来自苹果文档)https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html

Make sure the location manager's pausesLocationUpdatesAutomatically property is set to YES. When this property is set to YES, Core Location pauses location updates (and powers down the location hardware) whenever it makes sense to do so, such as when the user is unlikely to be moving anyway. (Core Location also pauses updates when it can't obtain a location fix.)

Assign an appropriate value to the location manager's activityType property. The value in this property helps the location manager determine when it is safe to pause location updates. For an app that provides turn-by-turn automobile navigation, setting the property to CLActivityTypeAutomotiveNavigation causes the location manager to pause events only when the user does not move a significant distance over a period of time.

确保位置管理器的 pausesLocationUpdatesAutomatically 属性设置为 YES。当此属性设置为 YES 时,Core Location 会在有意义的时候暂停位置更新(并关闭位置硬件),例如当用户不太可能移动时。(核心位置在无法获得位置修复时也会暂停更新。)

为位置管理器的 activityType 属性分配适当的值。此属性中的值可帮助位置管理器确定暂停位置更新的安全时间。对于提供逐向汽车导航的应用程序,将该属性设置为 CLActivityTypeAutomotiveNavigation 会导致位置管理器仅在用户在一段时间内没有移动很远的距离时才暂停事件。

CLActivityTypeAutomotiveNavigationinsure you to get a position which is on a road.

CLActivityTypeAutomotiveNavigation确保您获得在路上的位置。

For Android:

对于安卓:

  1. You can use this project: https://github.com/quentin7b/android-location-tracker
  1. 你可以使用这个项目:https: //github.com/quentin7b/android-location-tracker

That can easily helps you to get the user's position thru time Thanks to the TrackerSettings object

多亏了 TrackerSettings 对象,这可以轻松地帮助您通过时间获取用户的位置

TrackerSettings settings =
        new TrackerSettings()
            .setUseGPS(true)
            .setUseNetwork(true)
            .setUsePassive(true)
            .setTimeBetweenUpdates(30 * 60 * 1000)
            .setMetersBetweenUpdates(100);
  1. To find the distance between two point on Android, you can check this: Get the distance between two geo points
  1. 要在 Android 上找到两点之间的距离,您可以查看: 获取两个地理点之间的距离

Both OS

两个操作系统

Based on a position picked up every X second you have to reduce time between picking location data to improve accuracy.

根据每 X 秒拾取的位置,您必须减少拾取位置数据之间的时间以提高准确性。

As you want to calculate distance on a road context, setup the Location manager in navigation mode, this mode gives you coordinates that are on road.

当您要计算道路环境中的距离时,请在导航模式下设置位置管理器,此模式为您提供道路上的坐标。

Finally

最后

If you want to improve the accuracy of your distance calculus, you can use a google API: https://developers.google.com/maps/documentation/distance-matrix/intro

如果您想提高距离演算的准确性,可以使用谷歌 API:https: //developers.google.com/maps/documentation/distance-matrix/intro

By setting the right modeparameter:

通过设置正确的模式参数:

Optional parameters

mode (defaults to driving) — Specifies the mode of transport to use when calculating distance. Valid values and other request details are specified in the Travel Modes section of this document.

可选参数

模式(默认为驾驶)— 指定计算距离时使用的交通方式。本文档的旅行模式部分指定了有效值和其他请求详细信息。

回答by TDG

I'm working on something similar on Andoriod, but the principals are the same for iOS either:

我正在 Andoriod 上做类似的事情,但 iOS 的原理是相同的:

  1. For each GPS sample, check its accuracy. If it's over some threshold (say 20 meters) - ignore it.
  2. Remember that even if the mobile device is static, different GPS samples will give you different locations, depending on the accuracy. A car standing still for a long time in a traffic light, will show that you've advanced few dozens of meters, so add a method that detects if the mobile is static or not. I've implemented this by reading the accelerometer - if the delta between two readings if bigger than some threshold - the device is moving. If it's too small - ignore the GPS.
  3. If you intend to use it in a car, you can read the GPS whenever it has a new reading (in Android use the onLocationChangedmethod). If you use it for running/walking, take into account that your speed is slow - two consecutive readings will be relativly close, but due to the GPS's accuracy, you can get quite a large distance betwwen them. It can be fixed by increasing the time between two consecutive readings, or by ignoring some of them (i.e. take into account only each 10th reading).
  4. Use the Haversine formulato calculate the distance between two consecutive readings. In Android it can be done with the Location.distanceTo()method.
  1. 对于每个 GPS 样本,检查其准确性。如果它超过某个阈值(比如 20 米) - 忽略它。
  2. 请记住,即使移动设备是静态的,不同的 GPS 样本也会为您提供不同的位置,具体取决于精度。汽车在红绿灯前长时间静止,表明您已经前进了几十米,因此添加一种检测移动设备是否静止的方法。我通过读取加速度计来实现这一点 - 如果两个读数之间的增量大于某个阈值 - 设备正在移动。如果它太小 - 忽略 GPS。
  3. 如果您打算在汽车上使用它,您可以在 GPS 有新读数时读取它(在 Android 中使用该onLocationChanged方法)。如果您将其用于跑步/步行,请考虑到您的速度较慢 - 连续两次读数会相对接近,但由于 GPS 的准确性,您可以在它们之间获得相当大的距离。可以通过增加两次连续读数之间的时间或忽略其中一些读数(即仅考虑第 10 次读数)来修复。
  4. 使用Haversine 公式计算两个连续读数之间的距离。在 Android 中,它可以通过该Location.distanceTo()方法来完成。

You'll have to test it against the odometer in your car and adjust the thresholds for the accelerometer.

您必须对照汽车中的里程表对其进行测试,并调整加速度计的阈值。

回答by Geeky Singh

4 years ago, I just made an app called Landsurvayor that calculates the actual distance of two geo-graphical points drawn on Google Map. I don't know that might help you or not but there is a formula called Haversine formulathat calculates the actual distance between two geo-graphical points. You might give it a try and see whether it is useful for you or not. Below is the sample code of Haversine formula:

4 年前,我刚刚制作了一个名为 Landsurvayor 的应用程序,它可以计算在 Google 地图上绘制的两个地理点的实际距离。我不知道这对你有没有帮助,但有一个叫做Haversine 公式的公式可以计算两个地理点之间的实际距离。您可以尝试一下,看看它是否对您有用。下面是Haversine公式的示例代码:

public double CalculationByDistance(double initialLat, double initialLong,
                            double finalLat, double finalLong){
int R = 6371; // km
double dLat = toRadians(finalLat-initialLat);
double dLon = toRadians(finalLong-initialLong);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);

double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
return R * c;
}

public double toRadians(deg) {
  return deg * (Math.PI/180)
}

More about Haversine formula: https://en.wikipedia.org/wiki/Haversine_formula

有关Haversine 公式的更多信息:https://en.wikipedia.org/wiki/Haversine_formula

There is another simple Android SDK built-in approach to calculate distance between two lat, lng:

还有另一种简单的 Android SDK 内置方法来计算两个 lat, lng 之间的距离:

Location locationA = new Location("point A");     
locationA.setLatitude(latA); 
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB); 
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB) ;

I hope it might help you.

我希望它可以帮助你。

回答by Snazzy Sanoj

You can achieve more accuracy with a combination of the following strategies.

您可以通过组合以下策略来获得更高的准确性。

  1. As mentioned in other Answers, you can store the position of the mobile every X seconds(say 10 seconds) using GPS and measure the consecutive time between the points.

  2. Also when the user makes quick turns, make sure to read that by using Magnetic Sensor values too, so in such event, decrease the "timing between position storing" to say 1-2 seconds(Will be needed for accuracy)

  3. As a final step, use Map data(such as Google Maps etc.) to make sure you are being tracked properly(if on road).

  1. 正如其他答案中所述,您可以使用 GPS每 X 秒(比如 10 秒)存储一次移动设备的位置,并测量点之间的连续时间。

  2. 此外,当用户快速转弯时,请确保也使用磁性传感器值读取该值,因此在这种情况下,将“位置存储之间的时间”减少到 1-2 秒(将需要准确性)

  3. 最后一步,使用地图数据(例如谷歌地图等)确保您被正确跟踪(如果在路上)。

And then sum up all the values to get the accurate distance.

然后将所有值相加以获得准确的距离。

P.S. I gave information about the strategies alone since I'm not sure about its implementation in Android(or iOS).

PS 我只提供了有关策略的信息,因为我不确定它在 Android(或 iOS)中的实现。

Hope this helps :)

希望这可以帮助 :)

回答by Jotiram Chavan

Use GPS to get lat lon of both places and after getting both pass it below method.Its will return distance in km

使用 GPS 获取两个地方的经纬度,然后在方法下方通过它。它将以公里为单位返回距离

public static double getDistanceFromLatLonInKm(double lat1, double lon1,
        double lat2, double lon2) {



    double R = 6371; // Radius of the earth in km
    double dLat = deg2rad(lat2 - lat1); // deg2rad below
    double dLon = deg2rad(lon2 - lon1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
            * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = R * c; // Distance in km


    return d;

}

public static double deg2rad(double deg) {
    return deg * (Math.PI / 180);
}

}

}

回答by muminers

If accuracy is critical, you can use data from accelerometer and gyroscope. You can find very simple formula for solving simple cinematic task so you get acc in global axis. Than you just have to use integral twice (first to get velocity, than to get position). Just to show another perspective.

如果精度至关重要,您可以使用来自加速度计和陀螺仪的数据。您可以找到解决简单电影任务的非常简单的公式,以便您在全局轴上获得 acc。比你只需要使用两次积分(首先获得速度,而不是获得位置)。只是为了展示另一个视角。

回答by Calteran

If you are looking for exact (or nearly exact) distance information, you need to track the path followed, which means checking coordinates every few seconds (depending upon expected speed traveled). You can save space by discarding the old coordinates after calculating each segment and just storing current distance traveled.

如果您正在寻找精确(或接近精确)的距离信息,则需要跟踪所遵循的路径,这意味着每隔几秒钟检查一次坐标(取决于预期的行驶速度)。您可以通过在计算每个线段后丢弃旧坐标并仅存储当前行驶距离来节省空间。

回答by Daniel Netzer

Android :: how to calculate distance while walking in android?

Android ::如何在android中行走时计算距离?

There are different ways to do this:

1.GPS: Keep adding GPS distance between 2 points every X seconds (say 10 sec). Check Android Location.distanceTo or distanceBetween. Check My Tracks app, it is open source. GPS is not available indoors and would have error if user is changing direction very frequently (read every 1-2 second) 2.Accelerometer: Look for code/library for step detection using accelerometer. Distance comes from double integration of acceleration, errors can add up very quickly here. 3.Step detector: Built-in in Nexus 5. Google must have taken care of accelerometer errors to extent possible. This is hardware-based computation, consumes less battery but not available in most of handsets as of date.

有不同的方法可以做到这一点:

1.GPS:每 X 秒(比如 10 秒)继续在 2 个点之间添加 GPS 距离。检查 Android Location.distanceTo 或 distanceBetween。检查 My Tracks 应用程序,它是开源的。GPS 在室内不可用,如果用户非常频繁地改变方向(每 1-2 秒读取一次),则会出现错误。 2.加速度计:使用加速度计查找用于步进检测的代码/库。距离来自加速度的双重积分,这里的误差加起来非常快。3.步检测器:Nexus 5 内置。谷歌必须尽可能地处理加速度计错误。这是基于硬件的计算,消耗更少的电池,但迄今为止在大多数手机中都不可用。

The 2nd option seem very similar to what you suggested and I do think its the best way to achieve it since iOS and Android defer in code and in functionality therefor the best method to achieve it is saving currentLocationand previousLocationin a while loop that will .sleep()and just sum the entire loop as the distance traveled. the bigger question is this supposedly app is a distance summerizing app? does it just a small function inside of it? how do you decide when to stop calculating the distance?

第二个选项似乎与您建议的非常相似,我确实认为这是实现它的最佳方法,因为 iOS 和 Android 在代码和功能中推迟,因此实现它的最佳方法是在 while 循环中保存currentLocationpreviousLocation 。 sleep()并将整个循环与行进的距离相加。更大的问题是这个所谓的应用程序是一个远程夏季应用程序?它只是它内部的一个小功能吗?你如何决定何时停止计算距离?

回答by John Cook

One problem with using GPS coordinates is that they (obviously) are not accurate. If you are travelling in a straight line, the GPS coordinates might show you travelling on a zig-zag path, hence returning a greater distance travelled than the true distance. Even with good GPS accuracy this error can be significant. Using less coordinates could result in a more accurate calculation, or not.

使用 GPS 坐标的一个问题是它们(显然)不准确。如果您沿直线行驶,GPS 坐标可能会显示您在锯齿形路径上行驶,因此返回的行驶距离大于实际距离。即使具有良好的 GPS 精度,此误差也可能很大。使用较少的坐标可能会导致更准确的计算,或者不会。

What you need is a way to smooth the GPS path plotted, with due consideration to your required accuracy (again a trade-off).

您需要的是一种平滑绘制的 GPS 路径的方法,同时适当考虑您所需的准确性(再次权衡)。

My first thought is to break the points into groups, and fit line segments to each group (look up "linear regression"). Then find where each consecutive line-pair overlap to define each line segment. Then simply sum the line segment lengths.

我的第一个想法是将点分组,并将线段拟合到每组(查找“线性回归”)。然后找到每个连续线对重叠的地方来定义每个线段。然后简单地将线段长度相加。

You could curve-fit segments, but that's much more intense mathematically, and might not yield a better result (and which curve formula to use?). There may be better mathematical ways I'm not aware of.

您可以对段进行曲线拟合,但这在数学上要强得多,并且可能不会产生更好的结果(以及使用哪种曲线公式?)。可能有我不知道的更好的数学方法。

Hope this helps.

希望这可以帮助。

回答by lawonga

Log points every x seconds (maybe 2-3?) and use distance formula below for every point logged.

每 x 秒记录一个点(可能是 2-3?),并对记录的每个点使用下面的距离公式。

Distance = sqrt((x2?x1)^2+(y2?y1)^2)

Sum them all up and you get distance

把它们加起来,你就会得到距离