计算手机实际行驶的距离[关闭]
Posted
技术标签:
【中文标题】计算手机实际行驶的距离[关闭]【英文标题】:calculate actual distance travelled by mobile [closed] 【发布时间】:2016-04-05 17:08:50 【问题描述】:我想计算移动设备(ios 和 android)的实际行驶距离。我知道通过google map API,我们可以找到2个坐标之间的最佳路线距离。但是我想计算距离,移动(在车辆中)已经覆盖的实际路径。
我知道的一个算法是在 x 秒后保存坐标,比如说 5 或 10 秒后,然后计算连续坐标之间的距离,总和将给出总距离。
我想讨论其解决方案的更好方法,有没有更好的解决方案?
编辑:像耐克跑步应用和优步这样的应用是如何工作的?
【问题讨论】:
我相信您对 GPS 跟踪的建议是目前最好的解决方案。给出小于 5 秒的间隙将为此提供更准确的结果。 假设我想从家里去办公室,它应该计算我走过的路径的距离,天气我走了更长或更短的路径。 耐克和优步等应用不断地对 GPS 进行采样 @srikanthk 他们是怎么做到的?通过每 x 秒获得 lat,long 吗?并计算距离? 是的。他们经常获得纬度/经度,并且只计算相邻点之间的距离。 【参考方案1】:------------------更新------------------ -
您的问题有两个要点。
1) 获取手机坐标(已在此响应的第一部分处理)
2) 计算这两个坐标之间的真实距离
恕我直言,微积分可以通过网络服务完成:仅基于计算 两个坐标之间的距离会导致非常错误的结果。
以下是此类 Web 服务的示例 https://graphhopper.com/#directions-api
演示应用:https://graphhopper.com/api/1/examples/
它基于流量(与许多此类工具一样) 所以你必须小心坐标的顺序 因为它会带来错误的结果。
以正确顺序的两点为例:
这给出了一个很好的结果
但是如果你给出错误的顺序(坐标相同)
对于相同的坐标,可能会导致截然不同的结果。
所以对于坐标 ABCD(按时间顺序) 你需要做的:
A->B B->C C->D
Graphhopper 似乎能够进行离线距离计算
这是 iOS 和 Android 上的库
https://github.com/graphhopper/graphhopper-ios/
https://github.com/graphhopper/graphhopper/tree/master/android
------------------------------------------ --------
您必须定义应用的工作方式。前景还是背景?
正如其他回复中所说,您必须每 X 秒获取一次用户位置。然后计算距离。
对于 iOS:
-
您可以使用本网站上的信息:http://mobileoop.com/
它谈到了当应用处于后台时在 iOS 上跟踪用户位置。
-
这里是github:https://github.com/voyage11/Location
那么你必须转换点感谢
CLLocationDistance distance = [aCLLocationA distanceFromLocation:aCLLocationB];
你也可以检查这个(来自苹果文档)https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html:
确保位置管理器的 pausesLocationUpdatesAutomatically 属性设置为 YES。当此属性设置为 YES 时,Core Location 会在有意义的时候暂停位置更新(并关闭定位硬件),例如当用户不太可能移动时。 (Core Location 在无法获得位置修复时也会暂停更新。)
为位置管理器的 activityType 属性分配一个适当的值。此属性中的值有助于位置管理器确定何时可以安全地暂停位置更新。对于提供转弯汽车导航的应用,将属性设置为 CLActivityTypeAutomotiveNavigation 会导致位置管理器仅在用户在一段时间内没有移动很长距离时才会暂停事件。
CLActivityTypeAutomotiveNavigation 确保您获得道路上的位置。
对于 Android:
-
你可以使用这个项目:
https://github.com/quentin7b/android-location-tracker
这可以很容易地帮助您通过时间获得用户的位置 感谢 TrackerSettings 对象
TrackerSettings settings =
new TrackerSettings()
.setUseGPS(true)
.setUseNetwork(true)
.setUsePassive(true)
.setTimeBetweenUpdates(30 * 60 * 1000)
.setMetersBetweenUpdates(100);
-
要在 Android 上查找两点之间的距离,您可以检查以下内容:
Get the distance between two geo points
两个操作系统
根据每 X 秒拾取的位置,您必须缩短拾取位置数据之间的时间以提高准确性。
当您想在道路环境中计算距离时,请将位置管理器设置为导航模式,此模式会为您提供道路上的坐标。
终于
如果您想提高距离演算的准确性, 您可以使用谷歌 API: https://developers.google.com/maps/documentation/distance-matrix/intro
通过设置正确的mode参数:
可选参数
mode(默认为驾驶)— 指定计算距离时要使用的交通方式。本文档的“旅行模式”部分中指定了有效值和其他请求详细信息。
【讨论】:
另外看看来自 GraphHopper 的地图匹配组件:github.com/graphhopper/map-matching @Alban 谢谢。早些时候,我尝试使用 Google Map way points API 计算行驶距离。问题是汽车中的移动设备有时会给出不准确的位置。说,在一条小路的错误一侧。这会破坏距离计算,因为注册的路线不正确。关于上述库中位置准确性的考虑程度有什么想法吗?【参考方案2】:我正在 Andoriod 上做类似的事情,但 iOS 的原理也是一样的:
-
对于每个 GPS 样本,检查其准确性。如果它超过某个阈值(比如 20 米) - 忽略它。
请记住,即使移动设备是静态的,不同的 GPS 样本也会根据精度为您提供不同的位置。车子在红绿灯里长时间静止,会显示你已经前进了几十米,所以添加一个检测手机是否静止的方法。我通过读取加速度计来实现这一点 - 如果两个读数之间的增量大于某个阈值 - 设备正在移动。如果它太小 - 忽略 GPS。
如果您打算在汽车中使用它,您可以在 GPS 有新读数时读取它(在 Android 中使用
onLocationChanged
方法)。如果您将它用于跑步/步行,请考虑到您的速度很慢 - 两个连续的读数将相对接近,但由于 GPS 的准确性,您可以在它们之间获得相当大的距离。可以通过增加两次连续读数之间的时间或忽略其中一些(即仅考虑每 10 次读数)来解决此问题。
使用Haversine formula 计算两个连续读数之间的距离。在 Android 中,可以使用 Location.distanceTo()
方法完成。
您必须根据汽车的里程表对其进行测试,并调整加速度计的阈值。
【讨论】:
【参考方案3】: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)
更多关于Haversine公式: https://en.wikipedia.org/wiki/Haversine_formula
还有另一种简单的 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) ;
希望对你有帮助。
【讨论】:
【参考方案4】:您可以通过以下策略的组合获得更高的准确性。
正如其他答案中提到的,您可以存储手机的位置 每 X 秒(比如 10 秒)使用 GPS 并测量 点之间的连续时间。
此外,当用户快速转弯时,请务必通过以下方式阅读 也使用磁性传感器值,因此在这种情况下,降低 “位置存储之间的时间”表示 1-2 秒(将需要准确性)
作为最后一步,使用地图数据(例如 Google 地图等)确保 您正在被正确跟踪(如果在路上)。
然后将所有值相加得到准确的距离。
附:我只提供了有关策略的信息,因为我不确定它在 Android(或 iOS)中的实施情况。
希望这会有所帮助:)
【讨论】:
您能否详细说明您的答案的第 2 部分?我如何检测到用户正在“快速转弯”?提前致谢 查看@Alban 答案以获取更多关于急转弯的细节***.com/a/34596071/3831833【参考方案5】:如果您正在寻找准确(或接近准确)的距离信息,您需要跟踪所遵循的路径,这意味着每隔几秒检查一次坐标(取决于预期的行驶速度)。您可以通过在计算每个段后丢弃旧坐标并仅存储当前行驶距离来节省空间。
【讨论】:
【参考方案6】:Android :: how to calculate distance while walking in android?
有不同的方法可以做到这一点:
1.GPS:每 X 秒(比如 10 秒)不断增加 2 个点之间的 GPS 距离。检查 Android Location.distanceTo 或 distanceBetween。查看 My Tracks 应用程序,它是开源的。 GPS 在室内不可用,并且 如果用户非常频繁地改变方向会有错误(阅读 每 1-2 秒) 2.Accelerometer:使用加速度计寻找步数检测的代码/库。距离来自加速度的双重积分, 错误在这里会很快累积起来。 3.Step检测器:内置在Nexus 5中。Google必须尽可能地处理加速度计错误。这是基于硬件的 计算,消耗更少的电池,但在大多数情况下不可用 截至日期的手机。
第二个选项似乎与您的建议非常相似,我认为这是实现它的最佳方法,因为 iOS 和 Android 在代码和功能上有所延迟,因此实现它的最佳方法是保存 currentLocation 和 previousLocation 在一个 while 循环中,该循环将 .sleep() 并将整个循环与行进的距离相加。 更大的问题是这个所谓的应用程序是一个距离总结应用程序?它只是它里面的一个小功能吗?你如何决定何时停止计算距离?
【讨论】:
【参考方案7】:使用 GPS 坐标的一个问题是它们(显然)不准确。如果您沿直线行驶,则 GPS 坐标可能会显示您在曲折路径上行驶,因此返回的行驶距离比真实距离更大。即使具有良好的 GPS 精度,此误差也可能很大。使用较少的坐标可能会导致更准确的计算,也可能不会。
您需要一种方法来平滑绘制的 GPS 路径,同时适当考虑您所需的精度(再次权衡)。
我的第一个想法是将点分组,并将线段拟合到每个组(查找“线性回归”)。然后找到每个连续的线对重叠的位置来定义每个线段。然后简单地将线段长度相加。
您可以对线段进行曲线拟合,但这在数学上要复杂得多,并且可能不会产生更好的结果(以及使用哪个曲线公式?)。可能有更好的数学方法我不知道。
希望这会有所帮助。
【讨论】:
【参考方案8】:如果精度很重要,您可以使用加速度计和陀螺仪的数据。你可以找到非常简单的公式来解决简单的电影任务,这样你就可以在全局轴上获得 acc。比你只需要使用积分两次(首先获得速度,而不是获得位置)。 只是为了展示另一个视角。
【讨论】:
【参考方案9】:使用 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);
【讨论】:
你的方法实际上是Haversine公式。它是在android的Location类中实现的,所以不需要重新编码...【参考方案10】:每 x 秒记录一个点(可能是 2-3 个?),并为记录的每个点使用下面的距离公式。
Distance = sqrt((x2−x1)^2+(y2−y1)^2)
把它们加起来就是距离
【讨论】:
这是欧几里得距离,而不是您从 A 点到 B 点的总距离。对于短路径,它可能会完成这项工作,但对于较长的路径,它并不准确。以上是关于计算手机实际行驶的距离[关闭]的主要内容,如果未能解决你的问题,请参考以下文章