• 粒子群算法原理


        粒子群算法即PSO是典型的非线性优化算法,之前对这类智能优化算法(粒子群、遗传、退火、鸟群、鱼群、蚁群、各种群。。。)研究过一段时间,这类算法在我看来有个共同的特点——依靠随机产生“可能解”,在迭代的过程中,通过适用度函数fitness function(或称代价函数cost function)在“优良”的“可能解”附近增加随机量,剔除或者减少“劣质”的“可能解”的影响,如此迭代下去,逼近全局最优解,有点达尔文的“优胜劣汰,适者生存”的意思。这类算法的缺点不言而喻,在一定工况下可能陷入局部最优解无法自拔,当然也有各种改进算法,但是我迄今还没遇到,可能是工况都是比较巧的“单峰”的情况吧。同样,对于PSO算法,基础知识不再赘述,只把自己认为重要的点mark下来。(贴一份开源代码:把原本在lidar坐标系下不水平的地面点云,通过PSO求取一个pitch和roll(代码里是一个alpha和beta)将地面点云3D变换后,变成lidar坐标系下水平的,详见paper

    1.PSO_algorithm函数读了几遍后,应该想起来了,整个算法的核心部分就是求取v,,然后用v更新粒子。其中v是所谓的粒子飞行速度,其实就是当前解x与目前的局部(单粒子)最优解personal_best_x和目前的全局(全部粒子)最优解globalbest_x之间的差值error,利用这个error更新当前解x,恨明显就使得x趋向一个“良好”的方向,在趋向的同时(也就是计算v)增加一点随机,保证粒子的多样性,来增加获取最优解的概率。

    2.博主在面试的时候,被问到过,在标定lidar的时候,怎么解决pitch和roll的解耦问题的,一时语塞,没说明白。确实,用欧拉角做3D变换的时候,一方面,旋转的顺序不同会导致不同的结果;另一方面,旋转pitch会影响roll,旋转roll会影响pitch。现在总结一下:

      a.首先3D变换时旋转顺序肯定是固定的因为3D变换的代码只有一个,所以本标定lidar问题只有唯一解。

      b.其次,PSO在任何一次迭代中pitch和roll都是同时计算,同时更新的,也就是说两个参数同时求解,不存在先求pitch后求roll一说,那么问题就类似求最高峰(z最大)的解(x,y)的问题了。

    3.还被问到过,你怎么验证你的标定精度的,现总结下:人为产生一个已知倾斜角度pitch和roll的地面点云,因为产生的时候,是先水平,后倾斜,倾斜时也是固定的3D变换顺序,所以也是唯一解,将此地面点云输入到算法中,求解pitch和roll。

     1 for(uint32_t i=0;i<ParticleSize;i++)
     2 {
     3   for (uint32_t j=0;j<2;j++)
     4   {
     5     v[i][j]=w*v[i][j]+c1*my_rand()*(personalbest_x[i][j]-x[i][j])+
    6 c2*my_rand()*(globalbest_x[j]-x[i][j]); // update the velocity 7 if(v[i][j]>vmax) v[i][j]=vmax; // limit the velocity 8 else if(v[i][j]<-vmax) v[i][j]=-vmax; 9 } 10 x[i][0]=x[i][0]+v[i][0]; // update the position 11 x[i][1]=x[i][1]+v[i][1]; 12 }

    下面就是整个应用的代码了

      1 #include "calculate_alpha_beta.h"
      2 
      3 /*==============================================================================
      4 FileName  : my_min
      5 CreatDate : 2017/4/6
      6 Describe  : calculate the min data in an array
      7 Parameter :
      8 Author    : cgb
      9 ==============================================================================*/
     10 void my_min(double personalbest_faval[],uint32_t num,double *globalbest_faval,uint32_t *index)
     11 {
     12     for(uint32_t i=0;i<num;i++)
     13     {
     14         if(personalbest_faval[i]<*globalbest_faval)
     15         {
     16             *globalbest_faval=personalbest_faval[i];
     17             *index=i;
     18         }
     19     }
     20 }
     21 /*==============================================================================
     22 FileName  : my_rand
     23 CreatDate : 2017/4/6
     24 Describe  : produce a random num 0~1
     25 Parameter :
     26 Author    : cgb
     27 ==============================================================================*/
     28 double my_rand(void)
     29 {
     30     static int flag_once=0;
     31     if(0==flag_once)
     32     {
     33         srand((uint32_t)time(NULL)*65535);
     34         flag_once=1;
     35     }
     36     return ((rand()%100)/99.0);
     37 }
     38 /*==============================================================================
     39 FileName  : fit_plane
     40 CreatDate : 2017/4/6
     41 Describe  : least squares fitting plane equation
     42             plane equation: Z=a*X+b*Y+c
     43 Parameter :
     44 Author    : cgb
     45 ==============================================================================*/
     46 double* fit_plane(pointVector points)
     47 {
     48     double X1=0,Y1=0,Z1=0,X2=0,Y2=0,X1Y1=0,X1Z1=0,Y1Z1=0,C,D,E,G,H;
     49     uint64_t N ,point_num=points.size();
     50     static double para[3];
     51     if (point_num<3)
     52     {
     53         para[0]=-8888;
     54         para[1]=-8888;
     55         para[2]=-8888;
     56     cout<<"****   less than 3 points can't fit the plane   ****"<<endl;
     57     }
     58     else
     59     {
     60         for (uint64_t i=0 ;i<point_num;i++)
     61         {
     62             X1=X1+points[i].x;
     63             Y1=Y1+points[i].y;
     64             Z1=Z1+points[i].z;
     65             X2=X2+points[i].x*points[i].x;
     66             Y2=Y2+points[i].y*points[i].y;
     67             X1Y1=X1Y1+points[i].x*points[i].y;
     68             X1Z1=X1Z1+points[i].x*points[i].z;
     69             Y1Z1=Y1Z1+points[i].y*points[i].z;
     70         }
     71 
     72         N=point_num;
     73         C=N*X2-X1*X1;     // X2!=X1*X1 !!!
     74         D=N*X1Y1-X1*Y1;
     75         E=-(N*X1Z1-X1*Z1);
     76         G=N*Y2-Y1*Y1;
     77         H=-(N*Y1Z1-Y1*Z1);
     78 
     79         para[0]=(H*D-E*G)/(C*G-D*D);
     80         para[1]=(H*C-E*D)/(D*D-G*C);
     81         para[2]=(Z1-para[0]*X1-para[1]*Y1)/N;
     82     }
     83     return para;
     84 }
     85 void trans_cloud(CloudPtr_xyzrgb cloud_hdl, CloudPtr_xyzrgb  cloud_veh_hdl, trans_t trans)
     86 {
     87     /* calibrate horizontal plane to vehicle angle */
     88     Eigen::Matrix4f trans_matrix = Eigen::Matrix4f::Identity();
     89     float alpha = trans.alpha * M_PI / 180.f;
     90     float beta =  trans.beta  * M_PI / 180.f;
     91     float gamma = trans.gamma * M_PI / 180.f;
     92     float x_offset = trans.x_offset;
     93     float y_offset = trans.y_offset;
     94     float z_offset = trans.z_offset;
     95 
     96     trans_matrix(0,0) = (float)(cos(beta) * cos(gamma));
     97     trans_matrix(0,1) = (float)(sin(alpha) * sin(beta) * cos(gamma) -
     98                                     cos(alpha) * sin(gamma));
     99     trans_matrix(0,2) = (float)(cos(alpha) * sin(beta) * cos(gamma) +
    100                                     sin(alpha) * sin(gamma));
    101     trans_matrix(0,3) = (float)x_offset;
    102     trans_matrix(1,0) = (float)(cos(beta) * sin(gamma));
    103     trans_matrix(1,1) = (float)(sin(alpha) * sin(beta) * sin(gamma) +
    104                                     cos(alpha) * cos(gamma));
    105     trans_matrix(1,2) = (float)(cos(alpha) * sin(beta) * sin(gamma) -
    106                                     sin(alpha) * cos(gamma));
    107     trans_matrix(1,3) = (float)y_offset;
    108     trans_matrix(2,0) = -(float)sin(beta);
    109     trans_matrix(2,1) = (float)(sin(alpha) * cos(beta));
    110     trans_matrix(2,2) = (float)(cos(alpha) * cos(beta));
    111     trans_matrix(2,3) = (float)z_offset;
    112     trans_matrix(3,0) = 0;
    113     trans_matrix(3,1) = 0;
    114     trans_matrix(3,2) = 0;
    115     trans_matrix(3,3) = 1.0;
    116     pcl::transformPointCloud(*cloud_hdl, *cloud_veh_hdl, trans_matrix);
    117 }
    118 /*==============================================================================
    119 FileName  : fitness_function
    120 CreatDate : 2017/4/6
    121 Describe  :
    122 Parameter :
    123 Author    : cgb
    124 ==============================================================================*/
    125 double fitness_function(double alpha, double beta, CloudPtr_xyzrgb cloud_in)
    126 {
    127     CloudPtr_xyzrgb cloud_out( new pcl::PointCloud<pcl::PointXYZRGB>() );
    128     double *para,levelness;
    129     trans_t trans;
    130     trans.alpha=alpha;
    131     trans.beta=beta;
    132 
    133     trans_cloud(cloud_in, cloud_out, trans);
    134     para = fit_plane(cloud_out->points);
    135     levelness=fabs(para[0])+fabs(para[1]);
    136     
    137     return levelness;
    138 }
    139 /*==============================================================================
    140 FileName  : PSO_algorithm
    141 CreatDate : 2017/4/6
    142 Describe  : calibrate lidar pitch & roll angle with PSO algorithm
    143 Parameter : Name ----------- Content --------------- Recommend Value
    144             E0 ------------- allowed error --------- 0.001
    145             MaxNum --------- max num of iteration -- 200
    146             narvs ---------- num of x --------------
    147             ParticleSize --- size of particle ------ 30
    148             c1 ------------- personal study para --- 2
    149             c2 ------------- social study para ----- 2
    150             w    ----------- weight ---------------- 0.6
    151             vmax ----------- max flying vel -------- 0.8
    152 Author    : cgb
    153 ==============================================================================*/
    154 pso_out_t PSO_algorithm(CloudPtr_xyzrgb cloud)
    155 {
    156     mtime_test(0);
    157     uint32_t index,iteration_cnt=0,ParticleSize=50;
    158     double MaxNum,c1,c2,vmax,w,E0,x1_range,x2_range,globalbest_faval;
    159     double v[ParticleSize][2],x[ParticleSize][2],personalbest_x[ParticleSize][2],globalbest_x[2];
    160     double f[ParticleSize],personalbest_faval[ParticleSize];
    161     pso_out_t pso_out;
    162     
    163     //PSO parameter
    164     MaxNum       = 200;
    165     c1           = 2;
    166     c2           = 2;
    167     w            = 0.6;
    168     vmax         = 0.8;
    169     E0           = 0.00000001;
    170 
    171     x1_range =45;
    172     x2_range =45;
    173     // init
    174     for (uint32_t i=0;i<ParticleSize;i++)
    175     {
    176         x[i][0]=my_rand()*x1_range*2-x1_range;           // init the position by random
    177         x[i][1]=my_rand()*x2_range*2-x2_range;
    178         v[i][0]=my_rand()*2;                             // init the velocity by random
    179         v[i][1]=my_rand()*2;
    180     }
    181     // first calculation
    182     for (uint32_t i=0;i<ParticleSize;i++)
    183     {
    184         f[i]=fitness_function(x[i][0],x[i][1],cloud);
    185         personalbest_x[i][0]=x[i][0];
    186         personalbest_x[i][1]=x[i][1];
    187         personalbest_faval[i]=f[i];
    188     }
    189 
    190     globalbest_faval=personalbest_faval[0];        //init the globalbest_faval
    191     my_min(personalbest_faval,ParticleSize,&globalbest_faval,&index);
    192     globalbest_x[0]=personalbest_x[index][0];           // get the global best val
    193     globalbest_x[1]=personalbest_x[index][1];
    194 
    195     // loop calculation
    196     while(iteration_cnt<MaxNum)
    197     {
    198         for(uint32_t i=0;i<ParticleSize;i++)            // calculate the best val in local
    199         {
    200             f[i]=fitness_function(x[i][0],x[i][1],cloud);
    201             if (f[i]<personalbest_faval[i])
    202             {
    203                 personalbest_faval[i]=f[i];
    204                 personalbest_x[i][0]=x[i][0];
    205                 personalbest_x[i][1]=x[i][1];
    206             }
    207         }
    208         my_min(personalbest_faval,ParticleSize,
    209                         &globalbest_faval,&index);      // calculate the best val in global
    210         globalbest_x[0]=personalbest_x[index][0];       // get the global best val
    211         globalbest_x[1]=personalbest_x[index][1];
    212 
    213         for(uint32_t i=0;i<ParticleSize;i++)
    214         {
    215              for (uint32_t j=0;j<2;j++)
    216              {
    217                  v[i][j]=w*v[i][j]+c1*my_rand()*(personalbest_x[i][j]-x[i][j])+c2*my_rand()*
    218                          (globalbest_x[j]-x[i][j]);     // update the velocity
    219                  if(v[i][j]>vmax) v[i][j]=vmax;         // limit the velocity
    220                  else if(v[i][j]<-vmax) v[i][j]=-vmax;
    221              }
    222              x[i][0]=x[i][0]+v[i][0];                   // update the position
    223              x[i][1]=x[i][1]+v[i][1];
    224         }
    225         if (fabs(globalbest_faval)<E0)
    226         {
    227           break;
    228         }
    229         iteration_cnt++;
    230     }
    231     
    232     double *para;
    233     CloudPtr_xyzrgb cloud_out( new pcl::PointCloud<pcl::PointXYZRGB>() );
    234     trans_t trans;
    235     trans.alpha=globalbest_x[0];
    236     trans.beta=globalbest_x[1];
    237     trans_cloud(cloud, cloud_out, trans);
    238     para = fit_plane(cloud_out->points);
    239     
    240     pso_out.z_offset      = -para[2];
    241     pso_out.alpha         = globalbest_x[0];
    242     pso_out.beta          = globalbest_x[1];
    243     pso_out.levelness     = globalbest_faval;
    244     pso_out.iteration_cnt = iteration_cnt;
    245     
    246     cout<<"
    ----------------------- END -----------------------
    "<<endl;
    247     cout.precision(5);cout<<setiosflags(ios::showpoint);
    248     cout<<"alpha is      : "<<pso_out.alpha<<" deg"<<endl;
    249     cout<<"beta is       : "<<pso_out.beta<<" deg"<<endl;
    250     cout<<"z_offset is   : "<<pso_out.z_offset<<" m"<<endl;
    251     cout<<"levelness     : "<<pso_out.levelness<<endl;
    252     cout<<"iteration cnt : "<<pso_out.iteration_cnt<<endl;
    253     mtime_test(1);
    254     cout<<"
    ---------------------------------------------------"<<endl;
    255     return pso_out;
    256 }
    257 /*==============================================================================
    258 FileName  : calculate_alpha_beta
    259 CreatDate : 2017/4/6
    260 Describe  :
    261 Parameter : frameID--the PCD file to calculate alpha & beta
    262 Author    : cgb
    263 ==============================================================================*/
    264 void calculate_alpha_beta(uint32_t frameID, scale_t scale)
    265 {
    266     CloudPtr_xyzrgb cloud_final(new pcl::PointCloud<pcl::PointXYZRGB>());
    267     CloudPtr_xyzrgb cloud_raw  (new pcl::PointCloud<pcl::PointXYZRGB>());
    268     trans_t trans;//must use the init trans_t value 
    269     Viewer viewer;
    270     viewer_init(viewer);
    271     
    272     load_PCD(frameID, cloud_final, cloud_raw, scale ,trans);
    273     
    274     pso_out_t pso_put=PSO_algorithm(cloud_final);
    275     
    276     viewer_update(viewer,cloud_final);
    277     viewer_waitstop(viewer);
    278     
    279     uint64_t num_add= plot_plane(cloud_final,255,0,0,30);
    280     viewer_update(viewer,cloud_final);
    281     viewer_waitstop(viewer);
    282     
    283     erase_addpoints(cloud_final,num_add);
    284     trans.alpha    = pso_put.alpha;
    285     trans.beta     = pso_put.beta;
    286     trans.z_offset = pso_put.z_offset;
    287     trans_cloud(cloud_final,cloud_final,trans);
    288     plot_plane(cloud_final,0,255,0,30);
    289     viewer_update(viewer,cloud_final);
    290     viewer_waitstop(viewer);
    291 }
    View Code
  • 相关阅读:
    如何迅速的修改个人信息
    Workflow History List中的字段含义
    Maximum File Size for Crawling Search Services
    SPUtility
    介紹好用元件:Microsoft Chart Controls for .NET 3.5 (转)
    使用Reflector.FileDisassembler反编译DLL
    Webpart开发时注意事项
    SharePoint中的时间问题(转)
    MOSS添加删除导航结点代码示例(SPNavigationNode)
    DbHelper SQL数据操作类【DBHelper.CS】
  • 原文地址:https://www.cnblogs.com/wellp/p/8286984.html
Copyright © 2020-2023  润新知