找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1621|回复: 0
收起左侧

ROS中激光雷达数据处理之特征提取 源程序

[复制链接]
ID:393178 发表于 2022-3-3 11:10 | 显示全部楼层 |阅读模式
   ROS中激光雷达的数据就是一串距离值,每隔1度一个距离值(具体情况得看激光雷达的参数),通过实测激光雷达的数据提取关键特征,直线,圆弧

  1. // 进行多边形拟合: Points : 轮廓上的点      n -- 轮廓点数目  Eps -- 拟合精度
  2. // 返回值: 若该轮廓段需要分段,则返回分段点在该轮廓点列中的索引,否则,返回 0 表示不需要分段
  3. // 这里是整个算法计算复杂性最大的一个地方
  4. // 为了提高程序运行效率,对点到直线的距离计算进行改进:
  5. // 多边形拟合中的直线是由点列中的点决定的
  6. // 为了计算点到直线的距离,
  7. // 采用坐标系旋转,将直线旋转到x轴方向,这样点到直线的距离即为各个点
  8. // 在坐标旋转后的y值的绝对值
  9. // 同时,坐标旋转矩阵在该次运算中为定值,只需一次计算,不需要多次的开方或三角计算
  10. int OpenRadar::PolyContourFit( int* X, int* Y, int n , float Eps ) // 根据轮廓点,用多边形拟合该轮廓点   
  11. {
  12.     double dis = sqrt((double)(((X[0] - X[n - 1])*(X[0] - X[n - 1])) +  
  13.                      ((Y[0] - Y[n - 1])* (Y[0] - Y[n - 1]))));
  14.     double cosTheta = (X[n- 1] - X[0]) / dis;
  15.     double sinTheta = - ( Y[n- 1] - Y[0] )/dis;
  16.     double MaxDis = 0;
  17.     int i ;
  18.     int MaxDisInd = -1;
  19.     double dbDis;
  20.     for(i = 1 ; i < n - 1 ; i++)
  21.     {
  22.         // 进行坐标旋转,求旋转后的点到x轴的距离
  23.         dbDis = abs( (Y[i] - Y[0]) * cosTheta + (X[i] - X[0])* sinTheta);
  24.         if( dbDis > MaxDis)
  25.         {
  26.             MaxDis = dbDis;
  27.             MaxDisInd = i;
  28.         }
  29.     }
  30.     if(MaxDis > Eps)
  31.     {
  32.         return MaxDisInd;
  33.         //        cout << "Line 1 : " << endl;
  34.         //        cout << "Start :" << Points[0].x << "  " << Points[0].y  << " --- " << Points[MaxDisInd].x << "  " << Points[MaxDisInd].y << endl;
  35.         //        cout << "角度: "<<180 * atan2(Points[0].y - Points[MaxDisInd].y , Points[0].x - Points[MaxDisInd].x ) / 3.1415926;
  36.         //        cout << "Line 2 :" << endl;
  37.         //        cout << "Start :" << Points[MaxDisInd].x << "  " << Points[MaxDisInd].y  << " --- " << Points[n - 1].x << "  " << Points[n - 1].y << endl;
  38.         //        cout << "角度: "<< 180 * atan2(Points[n - 1].y - Points[MaxDisInd].y , Points[n - 1].x - Points[MaxDisInd].x ) / 3.1415926;
  39.     }
  40.     //    else{
  41.     //        cout << "Line 1 : " << endl;
  42.     //        cout << "Start :" << Points[0].x << "  " << Points[0].y  << " --- " << Points[n - 1].x << "  " << Points[n - 1].y << endl;
  43.     //        cout << "角度: "<<180 * atan2(Points[n - 1].y - Points[0].y , Points[n - 1].x - Points[0].x ) / 3.1415926;

  44.     //    }
  45.     return 0;
  46. }

  47. //将折线拆成两段
  48. int OpenRadar::BreakPolyLine(vector<int>& BreakedRadarRho,
  49.                              vector<double>& BreakedRadarTheta,
  50.                              vector<int>& SepRadarRho ,   
  51.                              vector<double>&SepRadarTheta)
  52. {
  53.     int rho = 0;
  54.     double theta = 0.0;
  55.     int X[1200] = {0};
  56.     int Y[1200] = {0};
  57.     int rhoCopy[1200] = {0};
  58.     double thetaCopy[1200] = {0};
  59.     int pointCnt = 0;
  60.     int lineCnt = 0;
  61.     int N = 0;
  62.     SepRadarRho.clear();
  63.     SepRadarTheta.clear();
  64.     Corners.clear();

  65.     //进行多次迭代,将所有的折线都拆分成直线段
  66.    
  67.    vector<int>CornerIndex;
  68.    int CornerCnt = 0;
  69.    int tempIndex = 0;
  70.     for (int i = 0; i < static_cast<int>(BreakedRadarRho.size());i++)
  71.     {
  72.         rho   = BreakedRadarRho.at(i);
  73.         theta = BreakedRadarTheta.at(i);

  74.         if (rho < 0)
  75.         {
  76.             if (pointCnt > 200)//数目比较少的点直接抛弃
  77.             {
  78.                 CornerIndex.clear();
  79.                 CornerCnt = FindCorners(CornerIndex,X,Y,0,pointCnt,200);

  80.                 if (CornerIndex.size() == 0)
  81.                 {
  82.                     for (int k = 0 ; k < pointCnt;k++)
  83.                     {
  84.                         SepRadarRho.push_back(rhoCopy[k]);
  85.                         SepRadarTheta.push_back(thetaCopy[k]);
  86.                     }
  87.                     SepRadarRho.push_back(-1);
  88.                     SepRadarTheta.push_back(1000.0);
  89.                     lineCnt++;
  90.                 }else
  91.                 {
  92.                     tempIndex = 0;
  93.                     for (int k = 0 ; k < pointCnt;k++)
  94.                     {
  95.                         SepRadarRho.push_back(rhoCopy[k]);
  96.                         SepRadarTheta.push_back(thetaCopy[k]);
  97.                         if (k == CornerIndex.at(tempIndex))
  98.                         {
  99.                             SepRadarRho.push_back(-1);
  100.                             SepRadarTheta.push_back(1000.0);
  101.                             lineCnt++;
  102.                             if (tempIndex < static_cast<int>(CornerIndex.size()) -1)
  103.                             {
  104.                                 tempIndex++;
  105.                             }  
  106.                         }
  107.                     }
  108.                     SepRadarRho.push_back(-1);
  109.                     SepRadarTheta.push_back(1000.0);
  110.                     lineCnt++;
  111.                 }
  112.             }
  113.             pointCnt = 0;
  114.             continue;
  115.         }
  116.         X[pointCnt] = static_cast<int>(rho*cos(theta));
  117.         Y[pointCnt] = static_cast<int>(rho*sin(theta));
  118.         rhoCopy[pointCnt]   = rho;
  119.         thetaCopy[pointCnt] = theta;
  120.         pointCnt++;
  121.     }
  122.    
  123.     //cout<<"lineCnt: "<<lineCnt<<endl;
  124.     return lineCnt;
  125. }

  126. //进行直线拟合
  127. void OpenRadar::FitLine(vector<LinePara>& FittedLine,vector<int>& RadarRho,vector<double>& RadarTheta){

  128.     int rho = 0;
  129.     double theta = 0.0;
  130.     int X[1200] = {0};
  131.     int Y[1200] = {0};
  132.     int pointCnt = 0;
  133.     LinePara tmpLinePara;
  134.     FittedLine.clear();
  135.     for (int i = 0 ; i < static_cast<int>(RadarRho.size());i++)
  136.     {
  137.         rho = RadarRho.at(i);
  138.         theta = RadarTheta.at(i);

  139.         if (rho < 0)
  140.         {
  141.             if (pointCnt > 100 )//点数目足够多的点列才进行直线拟合
  142.             {
  143.                 WeightedFit(X ,Y ,pointCnt,&tmpLinePara);
  144.                 FittedLine.push_back(tmpLinePara);

  145.                 //存储拟合的数据和拟合结果
  146.        /*         FILE* pF = fopen("line.txt","w");
  147.                 fprintf(pF,"[a]\n");
  148.                 fprintf(pF,"%f\n",tmpLinePara.a);
  149.                 fprintf(pF,"[b]\n");
  150.                 fprintf(pF,"%f\n",tmpLinePara.b);
  151.                 fprintf(pF,"[x]\n");
  152.                 for (int j = 0; j < pointCnt ;j++)
  153.                 {
  154.                     fprintf(pF,"%d,",X[j]);
  155.                 }
  156.                 fprintf(pF,"\n[y]\n");
  157.                 for (int j = 0; j < pointCnt ;j++)
  158.                 {
  159.                     fprintf(pF,"%d,",Y[j]);
  160.                 }
  161.                 fclose(pF);*/

  162.                 pointCnt = 0;
  163.                 continue;
  164.             }else {
  165.                 pointCnt = 0;
  166.                 continue;
  167.             }   
  168.         }

  169.         X[pointCnt] = static_cast<int>(rho*cos(theta));
  170.         Y[pointCnt] = static_cast<int>(rho*sin(theta));
  171.         pointCnt++;
  172.     }
  173.    /* for (int i = 0; i < FittedLine.size();i++)
  174.     {
  175.         cout<<"a: "<<FittedLine.at(i).a<<"  b: "<<FittedLine.at(i).b<<" ";
  176.         cout<<"x1: "<<FittedLine.at(i).startPoint.x<<" "
  177.             <<"y1: "<<FittedLine.at(i).startPoint.y<<" "
  178.             <<"x1: "<<FittedLine.at(i).endPoint.x<<" "
  179.             <<"y1: "<<FittedLine.at(i).endPoint.y<<endl;
  180.     }*/

  181. }
复制代码
51hei.png

以上代码: OpenRadar7.0.zip (25.96 KB, 下载次数: 13)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表