Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于行走速度在2个GPS位置之间插值 问题:_Java_Android_Algorithm_Gps_Interpolation - Fatal编程技术网

Java 基于行走速度在2个GPS位置之间插值 问题:

Java 基于行走速度在2个GPS位置之间插值 问题:,java,android,algorithm,gps,interpolation,Java,Android,Algorithm,Gps,Interpolation,给定两个位置: L1=(latitude1,longitude1,timestamp1),L2=(latitude2,longitude2,timestamp2) 以及可配置但恒定的移动速度: v=1.39米每秒(例如) 当用户从L1移动到L2时,我们如何在这两个位置之间插值以估计用户的位置 我一直在寻找这个问题的解决方案,到目前为止我发现,对于小距离(远离极点)可以使用线性插值。因此,我查阅了维基百科,发现: // Imprecise method which does not guaran

给定两个位置:

L1=(latitude1,longitude1,timestamp1)L2=(latitude2,longitude2,timestamp2)

以及可配置但恒定的移动速度:

v=1.39米每秒(例如)

当用户从L1移动到L2时,我们如何在这两个位置之间插值以估计用户的位置


我一直在寻找这个问题的解决方案,到目前为止我发现,对于小距离(远离极点)可以使用线性插值。因此,我查阅了维基百科,发现:

// Imprecise method which does not guarantee v = v1 when t = 1,
// due to floating-point arithmetic error.
float lerp(float v0, float v1, float t) {
    return v0 + t*(v1-v0);
}
所以我想用这个lerp函数在L1L2之间插值纬度和经度。这是最简单的部分。如何计算t?我猜我必须计算一些时间增量,但是我如何计算移动速度呢


编辑: 我正在测试各种收集GPS位置的方法。为此,我记录了整个行走过程中的航路点位置。我需要使用移动速度在这些航路点之间插值,以估计我在行走中的位置。然后,我可以将我的结果与估计值进行比较,看看它们的表现如何

例如:

仔细看看

它包含几个公式和JavaScript示例,可能会对您有所帮助。我知道它不是Java,但它应该足够简单,可以移植代码。特别给出了公式的详细描述

编辑:

虽然对于较短的距离使用线性插值似乎是可以的,但事实上,它可能非常不合适,特别是当你接近极点时。从你在汉堡的例子来看,这已经产生了一种影响,这种影响在几百米的范围内是可以观察到的。请参阅以获得一个好的解释

问题是:经度1度之间的距离因纬度的不同而变化很大

这是因为地球不是扁平的,而是一个球体——实际上是一个椭球体。因此,二维地图上的直线不是地球上的直线,反之亦然

要解决此问题,可以使用以下方法:

  • 获取从起点坐标(L1)到终点坐标(L2)的轴承
  • 给定计算的方位和指定的距离,从起点坐标(L1)沿大圆路径计算新坐标
  • 重复此过程,但使用新计算的坐标作为起始坐标
  • 我们可以创建一些简单的函数来实现这一点:

    double radius = 6371; // earth's mean radius in km
    
    // Helper function to convert degrees to radians
    double DegToRad(double deg) {
        return (deg * Math.PI / 180);
    }
    
    // Helper function to convert radians to degrees
    double RadToDeg(double rad) {
        return (rad * 180 / Math.PI);
    }
    
    // Calculate the (initial) bearing between two points, in degrees
    double CalculateBearing(Location startPoint, Location endPoint) {
        double lat1 = DegToRad(startPoint.latitude);
        double lat2 = DegToRad(endPoint.latitude);
        double deltaLon = DegToRad(endPoint.longitude - startPoint.longitude);
    
        double y = Math.sin(deltaLon) * Math.cos(lat2);
        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(deltaLon);
        double bearing = Math.atan2(y, x);
    
        // since atan2 returns a value between -180 and +180, we need to convert it to 0 - 360 degrees
        return (RadToDeg(bearing) + 360) % 360;
    }
    
    // Calculate the destination point from given point having travelled the given distance (in km), on the given initial bearing (bearing may vary before destination is reached)
    Location CalculateDestinationLocation(Location point, double bearing, double distance) {
    
        distance = distance / radius; // convert to angular distance in radians
        bearing = DegToRad(bearing); // convert bearing in degrees to radians
    
        double lat1 = DegToRad(point.latitude);
        double lon1 = DegToRad(point.logintude);
    
        double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distance) + Math.cos(lat1) * Math.sin(distance) * Math.cos(bearing));
        double lon2 = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(distance) * Math.cos(lat1), Math.cos(distance) - Math.sin(lat1) * Math.sin(lat2));
        lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180 - + 180 degrees
    
        return new Location(RadToDeg(lat2), RadToDeg(lon2));
    }
    
    // Calculate the distance between two points in km
    double CalculateDistanceBetweenLocations(Location startPoint, Location endPoint) {
    
        double lat1 = DegToRad(startPoint.latitude);
        double lon1 = DegToRad(startPoint.longitude);
    
        double lat2 = DegToRad(endPoint.latitude);
        double lon2 = DegToRad(endPoint.longitude);
    
        double deltaLat = lat2 - lat1;
        double deltaLon = lon2 - lon1;
    
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    
        return (radius * c);
    }
    
    这使用了6371公里的平均地球半径。有关此数字及其准确性的说明,请参阅

    现在可以计算两点之间的新中间位置,给定行驶距离(以km为单位):

    假设速度为每秒v(例如1.39)米,现在可以使用简单的for循环来获得相隔1秒的点:

    List<Location> locations = new ArrayList<Location>();
    
    // assuming duration in full seconds
    for (int i = 0; i < duration; i++){
        double bearing = CalculateBearing(startLocation, endLocation);
        double distanceInKm = v / 1000;
        Location intermediaryLocation = CalculateDestinationLocation(startLocation, bearing, distanceInKm);
    
        // add intermediary location to list
        locations.add(intermediaryLocation);
    
        // set intermediary location as new starting location
        startLocation = intermediaryLocation;
    }
    

    与仅使用坐标增量的简单线性插值相比,这将在任何距离上产生更高的精度。尽管这种方法并不完美,但其误差通常为0.3%或更小,这是可以接受的。如果您需要更好的解决方案,您可能需要研究Vincenty公式。

    是的。线性插值

    L1 = (1, 2, 3)
    L2 = (4, 5, 6)
    desired_number_of_interpolation_points = 9
    interpolation_points = []
    
    lat_step = (L2[0] - L1[0]) / (desired_number_of_interpolation_points + 1)
    lon_step = (L2[1] - L1[1]) / (desired_number_of_interpolation_points + 1)
    time_step = (L2[2] - L1[2]) / (desired_number_of_interpolation_points + 1) 
    
    for i in range(1, desired_number_of_interpolation_points + 1)
        interpolation_points.append((lat_step * i, lon_step * i, time_step * i))
    
    我猜我必须计算一些时间增量,但我该如何计算呢 运动速度的因素

    在线性插值中,在案例m中,使用迭代变量t在两个时间点之间迭代,该变量从开始时间t1运行到结束时间t2,具有预定义的步长。 Asume step=1秒,这对您的应用程序非常有用

    long t1 = location1.getTimeStamp(); // in milliseconds;
    long t2 = location2.getTimeStamp();
    double deltaLat = location2.latitude - location1.latitude;
    doule deltaLon =  location2.longitude- location1.longtude;
    // remove this line if you don't have measured speed:
    double deltaSpeed =  location2.speed - location1.speed;
    
    long step = 1 * 1000; // 1 second in millis 
    for (long t = t1; t1 < t2; t+= step) {
    
       // t0_1 shall run from 0.0 to (nearly) 1.0 in that loop
      double t0_1 = (t - t1) / (t2 - t1);
      double latInter = lat1 + deltaLat  * t0_1;
      double lonInter = lon1 + deltaLon  * t0_1;
      // remove the line below if you dont have speed
      double speedInter = speed1 + deltaSpeed  * t0_1;
      Location interPolLocation = new Location(latInter, lonInter, speedInter);
      // add interPolLocation to list or plot.
    }
    
    long t1=location1.getTimeStamp();//以毫秒为单位;
    long t2=location2.getTimeStamp();
    双三角=位置2.纬度-位置1.纬度;
    双三角洲=位置2.经度-位置1.经度;
    //如果没有测得的速度,请删除此行:
    双deltaSpeed=位置2.speed-位置1.speed;
    长步长=1*1000;//1毫秒
    对于(长t=t1;t1
    还有一些其他插值策略的性能优于线性插值,包括运动学插值,它将锚点的初始和最终速度作为输入。例如,参见最近一篇论文(Long JA(2015)运动数据的运动学插值。Int J Geogr Inf Sci 8816:1–15。doi:10.1080/13658816.2015.1081909)中的比较:


    运动学插值有多种方法和实现。编写Java版本应该很容易。

    如果首先将lat/long转换为n向量(),这样的计算实际上非常简单。转换后,可以使用标准插值,还可以避免长距离、极点或日期线的任何问题


    如果你检查维基百科页面上的“外部链接”,有一个页面()解决了十个问题,该页面上的问题6(插入位置)应该与你的问题相同。正如您所见,该解决方案适用于任何距离,也适用于任何地球位置,如磁极。

    因此,您是说设备在固定时间内从A点移动到B点,但其总体速度可能完全无关?我实施了不同的收集gps位置的策略,例如,更新之间的最小距离,最小
    L1 = (1, 2, 3)
    L2 = (4, 5, 6)
    desired_number_of_interpolation_points = 9
    interpolation_points = []
    
    lat_step = (L2[0] - L1[0]) / (desired_number_of_interpolation_points + 1)
    lon_step = (L2[1] - L1[1]) / (desired_number_of_interpolation_points + 1)
    time_step = (L2[2] - L1[2]) / (desired_number_of_interpolation_points + 1) 
    
    for i in range(1, desired_number_of_interpolation_points + 1)
        interpolation_points.append((lat_step * i, lon_step * i, time_step * i))
    
    long t1 = location1.getTimeStamp(); // in milliseconds;
    long t2 = location2.getTimeStamp();
    double deltaLat = location2.latitude - location1.latitude;
    doule deltaLon =  location2.longitude- location1.longtude;
    // remove this line if you don't have measured speed:
    double deltaSpeed =  location2.speed - location1.speed;
    
    long step = 1 * 1000; // 1 second in millis 
    for (long t = t1; t1 < t2; t+= step) {
    
       // t0_1 shall run from 0.0 to (nearly) 1.0 in that loop
      double t0_1 = (t - t1) / (t2 - t1);
      double latInter = lat1 + deltaLat  * t0_1;
      double lonInter = lon1 + deltaLon  * t0_1;
      // remove the line below if you dont have speed
      double speedInter = speed1 + deltaSpeed  * t0_1;
      Location interPolLocation = new Location(latInter, lonInter, speedInter);
      // add interPolLocation to list or plot.
    }