来自Haversine轴承计算的不准确结果

时间:2016-03-30 18:36:05

标签: c linux gps haversine

我正在尝试在我正在编写的一个小型GPS程序中实现Haversine公式。距离计算似乎是现场的。但是,我相信轴承是以弧度计算的,我不知道如何将结果正确地转换为罗盘方向(北为0,东为90等)。

任何帮助都将不胜感激,所有关于cosigns和arctangents的讨论让我头疼不已!我是一名程序员,而不是数学家!

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void FindDistance (double latHome, double lonHome, double latDest, double lonDest)
{
    double pi=3.141592653589793;
    int R=6371; //Radius of the Earth in kilometers
    //Keep the parameters passed to the function immutable
    double latHomeTmp=(pi/180)*(latHome);
    double latDestTmp=(pi/180)*(latDest);
    double differenceLon= (pi/180)*(lonDest- lonHome);
    double differenceLat=(pi/180)*(latDest- latHome);
    double a= sin (differenceLat/2.)*sin (differenceLat/2.)+cos   (latHomeTmp)*cos (latDestTmp)*sin (differenceLon/2.)*sin (differenceLon/2.);
    double c=2*atan2 (sqrt (a), sqrt (1-a));
    double Distance=R*c;
    printf ("Distance is %f\n", Distance);

    double RadBearing=atan2 (sin (differenceLon)*cos (latDestTmp), cos   (latHomeTmp)*sin (latDestTmp)-sin (latHomeTmp)*cos (latDestTmp)*cos     (differenceLon));
    double DegBearing=RadBearing*57.2958;
    if (DegBearing<0) DegBearing=360+DegBearing;
    printf ("Bearing is %f\n", DegBearing);
} //Function FindDistance

int main (void) {
    puts ("LA to NY");
    FindDistance (34.052235, -118.243683, 40.748817, -73.985428);
    puts ("NY to LA");
    FindDistance (40.748817, -73.985428, 34.052235, -118.243683);
} //Function main

gcc -o gps -lm gps.c

它从洛杉矶到纽约返回65轴承,从纽约到洛杉矶的轴承为273。

  

如果我们将轴承加在一起,我们得到338这是不对的 - 它不应该等于360吗?   还是我完全出去吃午饭?

无论如何,正如你所看到的,我总是同时计算距离和方位。如果您还可以建议一种方法来清理代码,以便它不执行不必要的计算,那将非常出色!我在一个小型微处理器上运行它,我希望每个循环计数!

1 个答案:

答案 0 :(得分:3)

不是问题。

考虑同一纬度的2个位置,但经度不同。当进入短路大圈路线时,其中一个不在另一个东方(90)。也不是第一次到期(西270)。轴承不一定是互补的。

FindDistance(34.0, -118.0, 34.0, -73.0);
FindDistance(34.0, -73.0, 34.0, -118.0);

Distance is 4113.598081
Bearing is 76.958824
Distance is 4113.598081
Bearing is 283.041176

@user3386109添加了更多有用的信息。

根据site@M Oehm建议您的代码是正确的。

根据OP请求,某些mod可能会略微提高速度。

void FindDistance(double latHome, double lonHome, double latDest,
    double lonDest) {
  // A few extra digits sometimes is worth it - rare is adding more digits a problem
  // double pi=3.141592653589793;
  static const double pi_d180 = 3.1415926535897932384626433832795 / 180;
  static const double d180_pi = 180 / 3.1415926535897932384626433832795;

  // int R=6371; //Radius of the Earth in kilometers
  // (Compiler may do this all ready)
  static const double R = 6371.0; // better to make FP to avoid the need to convert 

  //Keep the parameters passed to the function immutable
  double latHomeTmp = pi_d180 * (latHome);
  double latDestTmp = pi_d180 * (latDest);
  double differenceLon = pi_d180 * (lonDest - lonHome);
  double differenceLat = pi_d180 * (latDest - latHome);

  double a = sin(differenceLat / 2.) * sin(differenceLat / 2.)
      + cos(latHomeTmp) * cos(latDestTmp) * sin(differenceLon / 2.)
          * sin(differenceLon / 2.);

  double c = 2 * atan2(sqrt(a), sqrt(1 - a));
  double Distance = R * c;
  printf("Distance is %f\n", Distance);

  double RadBearing = atan2(sin(differenceLon) * cos(latDestTmp),
      cos(latHomeTmp) * sin(latDestTmp)
          - sin(latHomeTmp) * cos(latDestTmp) * cos(differenceLon));

  // double DegBearing = RadBearing * 57.2958;
  double DegBearing = RadBearing * d180_pi;

  // Why is this even needed?
  if (DegBearing < 0) DegBearing = 360 + DegBearing;

  printf("Bearing is %f\n", DegBearing);
} //Function FindDistance