6

我正在开发一个应用程序,它更像是您朋友之间的时移竞赛。

我需要计算移动车辆的速度,我不想使用Location.getSpeed()方法。(在底部详细解释了为什么我不想使用它)

我正在尝试借助可用的纬度和经度来计算速度,这就是我需要帮助的地方。

需要的帮助:我想知道的是:

  • 如果算法正确
  • 我应该用厘米而不是米来计算吗
  • 如果有任何可用的代码/库可以做到这一点。

我正在使用以下代码:

这给了我两个 LatLng 点之间的距离:

long getDistanceBetweenPoints(double lat1, double lng1, double lat2, double lng2 ){
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lng2 - lng1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                + Math.cos(Math.toRadians(lat1))
                * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
                * Math.sin(dLon / 2);
        double c = 2 * Math.asin(Math.sqrt(a));
        long distanceInMeters = Math.round(6371000 * c);
        return distanceInMeters;
    }

以下代码是它的使用方式:

if(lastLat == -1 && lastLng == -1){
    lastLat = location.getLatitude();
    lastLng = location.getLongitude();
    lastTimeStamp = location.getTime();
    return;
}
long distanceInMeters = getDistanceBetweenPointsAndSetTotal(lastLat, lastLng, location.getLatitude(), location.getLongitude());
long timeDelta = (location.getTime() - lastTimeStamp)/1000;
long speed = 0;
if(timeDelta > 0){
speed = (distanceInMeters/timeDelta);
}
Log.d("Calculations","Distance: "+distanceInMeters+", TimeDelta: "+timeDelta+" seconds"+",speed: "+speed+" Accuracy: "+location.getAccuracy());

lastLat = location.getLatitude();
lastLng = location.getLongitude();
lastTimeStamp = location.getTime();

当我运行它时,我从该 LogCat 获得以下输出:

Distance: 0, TimeDelta: 0 seconds,speed: 0 Accuracy: 5.0

详细原因
目标消费者不应该拥有带有高质量 GPS 芯片的高质量设备,因此在设备移动时始终获得非常准确的定位是不可能的。

因此我不想依赖这种Location.getSpeed()方法,因为我观察到它仅在精度在 5~8 米范围内时才会给出速度值。

在一般情况下,我得到的正常精度范围是 10-15 米,并且getSpeed()没有给出任何速度。甚至hasSpeed()开始返回错误。

我已经在这件事上琢磨了三天多,对此的任何帮助将不胜感激。

非常感谢提前!

4

4 回答 4

12

我开发了MyTrails,一个 Android 地图和跟踪应用程序,和你一样,我一开始在谷歌认为适合包含在 Android 中的非常粗糙的位置 API 上苦苦挣扎。

当 GPS 芯片没有足够好的修复来根据多普勒效应计算速度时,hasSpeed() 为假。即使是这样,如果速度低于 5km/h 左右,我通常也不相信速度。

我处理速度计算的方法是使用粗略的低通滤波器:我每秒记录一个轨迹点(并且至少相隔 5m,基于LocationManager.requestLocationUpdates(),为了计算最近的速度,我返回几个样本以获得一个有足够的距离(但不超过 30 秒),然后执行你正在做的平均。

我正在使用 Location.distanceBetween() 进行实际距离计算。请注意,它在极少数(但不幸)数量的设备上失败,因此您拥有的 hasrsine 方法可能是更好的选择。你可能想检查一下,我所拥有的是

/**
 * Gets distance in meters, coordinates in RADIAN
 */
private static double getDistance(double lat1, double lon1, double lat2, double lon2) {
    double R = 6371000; // for haversine use R = 6372.8 km instead of 6371 km
    double dLat = lat2 - lat1;
    double dLon = lon2 - lon1;
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1) * Math.cos(lat2) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    //double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    // simplify haversine:
    //return 2 * R * 1000 * Math.asin(Math.sqrt(a));
}

(注意 1000 因子)

于 2014-01-28T16:46:52.150 回答
1

我的天啊.....

地点

检查此方法 - 它允许您计算 2 个地理点之间的距离,只需将其除以您的时间。它应该比你的更准确,因为它以更好的近似值计算距离(WGS83 而不是使用 sin、cos 和其他东西)。

好的,一般的想法是将所有数据保存在简单的单位中,例如 m、s、kg 等,并且仅为了向用户显示数据而进行更改。

于 2014-02-01T21:34:38.460 回答
1

如果算法是正确的?

距离计算看起来像正确的半正弦公式。(对于小距离有更快的公式(而且你只使用小距离),但是haversine会起作用)

我应该用厘米而不是米来计算吗?

千万不要使用厘米,保持国际单位制,速度单位是米/秒。只需使用仪表作为浮点数(双精度)。

我正在开发跟踪应用程序的 Ios 似乎与 Location 类中的 getSpeed() 网络更友好。

但我(再次?)警告你使用慢速。如果您的速度无效,则只需停止计算或在您的应用中将其标记为无效。如果 GPS 芯片不能提供有效的速度,它有充分的理由这样做,你是否会做得更好是一个有趣的问题。在低速时,GPS 倾向于在真实位置周围随机跳跃,跳跃距离为 5-30m。您自己计算的速度很可能显示出设备正在(不)移动的速度。尝试修复您的应用程序,使其不需要低速速度。

于 2014-01-28T17:47:06.853 回答
1

我同意皮埃尔的观点,你也在对结果进行四舍五入。如果这些点之间的距离不够远,则四舍五入可能只提供 0。我不知道如何定义舍入公差。我总是以米为单位计算 - 它让事情变得更容易。我建议在您的代码中遵循 SI 标准单位。您的输出还显示 timeDelta 为零,因此实际上没有计算距离。

于 2014-01-28T16:57:12.440 回答