zoukankan      html  css  js  c++  java
  • C实现简易运动轨迹检测的程序

    2011-4-25

    这几天,XXX的项目让我做了一个运动轨迹检测的程序,主要用来检测汽车和给定路线的偏移问题,和定位汽车主要在什么路段上。

    如下图

    C实现简易运动轨迹检测的程序

     

    下面是一些算法和资料:

    首先,要确定移动的点,也就是汽车和线段之间的距离,不能直接理解成点到直线的距离,因为当出现下面的情况的时候,点PBC和到A的距离都是一样

    C实现简易运动轨迹检测的程序

    的,这样就区分不点到底靠近哪条线上了。很显然,点固然靠近的应该是线段AB,所以我对这种情况进行了一些改进,如果遇到这种情况,那么直接计算P点到B之间的距离。其实这个程序的关键都是算点到线段的距离,而不是点到线段的高,这些要分清楚。

    点到线段距离的计算:

    点到直线的距离可以直接做垂线求取,但线段是有首尾点的,若要求距离则要考虑首尾点。

        点和线段的关系大致可以有下面几种:

    C实现简易运动轨迹检测的程序

        有特殊情况,是P点和AB重合,否则,根据PABPBA的角度可以有图1、图2、图4三种情况(包括点在AB之间,算是零度角)。

        我做的算法可以快速、简洁地判断角度是钝角还是锐角。

        在求垂线距离时,用海伦公式取代三角函数,使得程序看起来很简洁。

    1.      double GetPointDistance(CPoint p1, CPoint p2)   

    2.      {  

    3.       return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));  

    4.      }  

    5.      float GetNearestDistance(CPoint PA, CPoint PB, CPoint P3)  

    6.      {  

    7.        

    8.      //----------2--------------------  

    9.       float a,b,c;  

    10.    a=GetPointDistance(PB,P3);  

    11.    if(a<=0.00001)  

    12.     return 0.0f;  

    13.    b=GetPointDistance(PA,P3);  

    14.    if(b<=0.00001)  

    15.     return 0.0f;  

    16.    c=GetPointDistance(PA,PB);  

    17.    if(c<=0.00001)  

    18.     return a;//如果PAPB坐标相同,则退出函数,并返回距离  

    19.   //------------------------------  

    20.      

    21.    if(a*a>=b*b+c*c)//--------3--------  

    22.     return b;      //如果是钝角返回b  

    23.    if(b*b>=a*a+c*c)//--------4-------  

    24.     return a;      //如果是钝角返回a  

    25.      

    26.   //1  

    27.    float l=(a+b+c)/2;     //周长的一半  

    28.    float s=sqrt(l*(l-a)*(l-b)*(l-c));  //海伦公式求面积,也可以用矢量求  

    29.    return 2*s/c;  

    30.   }  

     

    下面的程序虽然没用上,还是用经纬度来判断偏移的,不过也贴上,怕以后用到哈。

    根据经纬度坐标计算实际距离

    C实现简易运动轨迹检测的程序double hypot(double x, double y) {
    C实现简易运动轨迹检测的程序       
    return sqrt(x * x + y * y);
    C实现简易运动轨迹检测的程序}
    C实现简易运动轨迹检测的程序
    C实现简易运动轨迹检测的程序
    double distance(double wd1, double jd1, double wd2, double jd2) {// 根据经纬度坐标计算实际距离
    C实现简易运动轨迹检测的程序
          double x, y, out;
    C实现简易运动轨迹检测的程序       
    double PI = 3.1415926535898;
    C实现简易运动轨迹检测的程序       
    double R = 6.371229 * 1e6;
    C实现简易运动轨迹检测的程序        x = (jd2 - jd1) * PI * R * cos( ( (wd1 + wd2) / 2) * PI / 180) / 180;
    C实现简易运动轨迹检测的程序        y = (wd2 - wd1) * PI * R / 180;
    C实现简易运动轨迹检测的程序        
    out = hypot(x, y);
    C实现简易运动轨迹检测的程序        
    return out;
    C实现简易运动轨迹检测的程序   }

     

    判断汽车轨迹是否偏离的算法其实不难,因为通过计算点到每个线段的距离,找出最小的距离,判断是否小于门限0.0001度(就是50)就好了。然后返回一个0或者1。嘿嘿,简单吧。

    举个例子,比如有8个点,必然有7个线段,依次计算7个线段的长度,然后计算点到7个线段的距离,找出最小的距离,再拿来和门限比较就OK了。

    最近我程序构架思想大改,虽然是C语言,但是我引入C++的面向对象思想,运用封装和抽象的思想,大量使用指针和结构体。我用结构体封装了私有变量和函数,同时也提供公共变量和函数。我尽量给用户最简单的和最傻瓜的使用方法,也方便以后自己。

    测试平台:Eclipse  CDT

    三个文件,.h .c 还有个test.c(主要用来演示)

    下面是程序:

     

    //Track_Detect.h

     

    #ifndef TRACK_DETECT_H_

    #define TRACK_DETECT_H_

     

    #include <stdio.h>

    #include <stdlib.h>

    #include <math.h>

    #include <stdint.h>

     

    #define THRESHOLD_MILES 50

    #define THRESHOLD_DEGREE 0.0001

     

    struct Road_coordinate

    {

           double x;

           double y;

    };

     

     

     

    struct GetNearestDistance_Private

    {

           double TempA,TempB,TempC;

           double perimeter;

           double area;

           double (*GetPointDistance)(struct Road_coordinate p1, struct Road_coordinate p2);

    };

     

    struct MinDistance_Of_Roads_Private

    {

           uint32_t Data_Size;

           uint32_t Data_Resolution;

           double *Temp_Data;

           double minTemp;

    };

     

    struct GPS_Track_Detect_Private

    {

           //struct Road_coordinate *RXY;

     

           double (*GetNearestDistance)(struct Road_coordinate PA, struct Road_coordinate PB, struct Road_coordinate PC);

     

           struct MinDistance_Of_Roads_Private MinDistance_Of_Roads;

    };

     

    struct GPS_Track_Detect_Public

    {

           struct Road_coordinate *set_p;

           uint32_t num;

           struct Road_coordinate *move_p;

           uint8_t MinNum;

           double (*MinDistance_Of_Roads)(struct Road_coordinate *set_p, uint32_t num, struct Road_coordinate *move_p, uint8_t *MinNum);

    };

     

     

    //外部函数

    extern double MinDistance_Of_Roads(struct Road_coordinate *set_p, uint32_t num, struct Road_coordinate *move_p, uint8_t *MinNum);

    extern uint32_t GPS_Track_Detect(uint32_t *deviate_flag, double *minValue, struct GPS_Track_Detect_Public *p);

    //注意set_pmove_p是指针

    #define GPS_Track_Detect_MinDistance(set_p, num, move_p, MinNum) MinDistance_Of_Roads(set_p, num, move_p, MinNum)

     

    #endif

     

      

     

    //Track_Detect.c

    //门限是0.0001度,就是50

     

    #include "Track_Detect.h"

     

     

     

    //私有函数声明区

    static double GetPointDistance(struct Road_coordinate p1, struct Road_coordinate p2);

    static double GetNearestDistance(struct Road_coordinate PA, struct Road_coordinate PB, struct Road_coordinate PC);

     

     

    static double GetPointDistance(struct Road_coordinate p1, struct Road_coordinate p2)

    {

           return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));

    }

     

    static double GetNearestDistance(struct Road_coordinate PA, struct Road_coordinate PB, struct Road_coordinate PC)

    {

           struct GetNearestDistance_Private *this = (struct GetNearestDistance_Private *) malloc(sizeof(struct GetNearestDistance_Private));

           this->GetPointDistance = GetPointDistance;

     

           this->TempA = this->GetPointDistance(PB,PC);

           double return_value = 0.0;

           if(this->TempA <= 0.00001)

           {

                  free(this);

                  return 0.0f;

           }

           this->TempB = this->GetPointDistance(PA,PC);

           if(this->TempB <=0.00001 )

           {

                  //return_value = this->TempB;

                  free(this);

                  return 0.0f;

           }

           this->TempC = this->GetPointDistance(PA,PB);

     

           if(this->TempC <= 0.00001)

           {

                  return_value = this->TempA;

                  free(this);

                  return return_value;//如果PAPB坐标相同,则退出函数,并返回距离

     

           }

           if(this->TempA * this->TempA >= this->TempB * this->TempB + this->TempC * this->TempC)

           {

                  return_value = this->TempB;      //如果是钝角返回TempB

                  free(this);

                  return return_value;

     

           }

           if(this->TempB * this->TempB >= this->TempA * this->TempA + this->TempC * this->TempC)

           {

                  return_value = this->TempA;

                  free(this);

                  return return_value;      //如果是钝角返回TempA

           }

           this->perimeter = (this->TempA + this->TempB + this->TempC) / 2;     //周长的一半

           this->area = sqrt(this->perimeter * (this->perimeter - this->TempA) * (this->perimeter - this->TempB) * (this->perimeter - this->TempC));  //海伦公式求面积,也可以用矢量求

           return_value =  2 * this->area / this->TempC;

           free(this);

           return return_value;

    }

     

     

    double MinDistance_Of_Roads(struct Road_coordinate *set_p, uint32_t num, struct Road_coordinate *move_p, uint8_t *MinNum)

    {

     

           uint32_t i = 0;

           double return_value = 0.0;

           struct GPS_Track_Detect_Private *this = (struct GPS_Track_Detect_Private *) malloc(sizeof(struct GPS_Track_Detect_Private));

           this->GetNearestDistance = GetNearestDistance;

     

     

           this->MinDistance_Of_Roads.Data_Resolution = sizeof(set_p[0]);

           this->MinDistance_Of_Roads.Data_Size = this->MinDistance_Of_Roads.Data_Resolution * num;//动态分配数据空间

           this->MinDistance_Of_Roads.Temp_Data = (double *)malloc(this->MinDistance_Of_Roads.Data_Size);

     

           //printf("%d\n", this->MinDistance_Of_Roads.Data_Size);

           //printf("%d\n", this->MinDistance_Of_Roads.Data_Resolution);

     

           for(i = 0; i < (this->MinDistance_Of_Roads.Data_Size / this->MinDistance_Of_Roads.Data_Resolution - 1 ); i++)

           {

                  *(this->MinDistance_Of_Roads.Temp_Data + i) = this->GetNearestDistance(set_p[i], set_p[i + 1], *move_p);

                  //printf("%f\n",*(this->MinDistance_Of_Roads.Temp_Data + i));

           }

           this->MinDistance_Of_Roads.minTemp = *(this->MinDistance_Of_Roads.Temp_Data + 0);

           for(i = 1; i < (this->MinDistance_Of_Roads.Data_Size / this->MinDistance_Of_Roads.Data_Resolution - 1 ); i++)

           {

                  if(*(this->MinDistance_Of_Roads.Temp_Data + i) < this->MinDistance_Of_Roads.minTemp)

                  {

                         this->MinDistance_Of_Roads.minTemp = *(this->MinDistance_Of_Roads.Temp_Data + i);

                         if(MinNum != NULL)

                         *MinNum = i;

                  }

           }

           free(this->MinDistance_Of_Roads.Temp_Data);

           return_value = this->MinDistance_Of_Roads.minTemp;

           free(this);

           //printf("\n\n\n");

           return return_value;

    }

     

     

    //deviate_flag 0 表示不偏移   1表示偏移

    uint32_t GPS_Track_Detect(uint32_t *deviate_flag, double *minValue, struct GPS_Track_Detect_Public *p)

    {

           p->MinDistance_Of_Roads = MinDistance_Of_Roads;

           *minValue = p->MinDistance_Of_Roads(p->set_p, p->num, p->move_p, &p->MinNum);

           *deviate_flag = THRESHOLD_DEGREE >= *minValue ? 0 : 1;

           return 0;

    }

     

     

     

     

    // 测试文件,使用范例Track_Detect_test.c

     

    #include "Track_Detect.h"

     

    struct Road_coordinate RoadXY[] = {

                  {25.037936,98.431538},

                  {25.035104,98.429070},

                  {25.046580,98.411377},

                  {25.049696,98.409866},

                  {25.050273,98.407812},

                  {25.053200,98.406574},

                  {25.056470,98.406300},

                  {25.056452,98.404327}

    };

     

    int main(void) {

     

           struct Road_coordinate test_dat = {.x = 25.050273, .y = 98.407712};

           struct GPS_Track_Detect_Public GTDtest_dat;

           GTDtest_dat.move_p = &test_dat;

           GTDtest_dat.num = 8;

           GTDtest_dat.set_p = RoadXY;

     

           double minValue;

           uint32_t deviate_flag;

     

           GPS_Track_Detect(&deviate_flag, &minValue, &GTDtest_dat);

           printf("%d\n",GTDtest_dat.MinNum);

     

     

     

           printf("\n\n");

           printf("%f\n",minValue);

           printf("%d\n",deviate_flag);

           printf("\n\n");

           uint8_t num;

           printf("%f\n", GPS_Track_Detect_MinDistance(RoadXY, 8, &test_dat, &num));

           printf("%d\n",num);

     

     

     

           return EXIT_SUCCESS;

    }

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    结对编程2
    结对编程总结:简单的四则运算生成程序
    我的结对项目心得与代码规范
    一个团队和他们的调查表-----("调查表与调查结果分析"心得体会)
    目标?我定好了!(我的软件工程课目标)
    Jmeter响应数据为乱码的处理
    软件工程课程建议
    结对编程之Fault、Error、Failure
    我的结对项目编程感想
    调查问卷后的心得
  • 原文地址:https://www.cnblogs.com/nickchan/p/3104536.html
Copyright © 2011-2022 走看看