fallModel.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //
  2. // Created by zx on 23-12-7.
  3. //
  4. #include "fallModel.h"
  5. #include <pcl/filters/voxel_grid.h>
  6. #include <pcl/common/common.h>
  7. FallModel::FallModel(){
  8. }
  9. bool FallModel::fall(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::PointXYZ>::Ptr& out,
  10. pcl::PointXYZ& tp,float& theta,FallDirect direct){
  11. auto t1=std::chrono::steady_clock::now();
  12. pcl::PointXYZ minp,maxp;
  13. pcl::getMinMax3D(*cloud,minp,maxp);
  14. float plate=minp.x;
  15. if(direct==ePositive)
  16. plate=maxp.x;
  17. Eigen::Vector4f centroid; //质心
  18. pcl::compute3DCentroid(*cloud,centroid); // 计算质心
  19. pcl::PointXYZ src_center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]);
  20. pcl::PointXYZ new_center, force_center;
  21. float dtheta=M_PI,dx=1.0,forceLen=1.0;
  22. pcl::PointCloud<pcl::PointXYZ>::Ptr t_cl=cloud;
  23. int iter=0;
  24. while( fabs(dx)>1e-5 || fabs(forceLen)>1e-4) {
  25. if(iter==1000){
  26. printf(" iter 1000 Failed\n");
  27. return false;
  28. }
  29. float gravy, force;
  30. computeForce(t_cl, new_center, force_center, gravy, force, plate,direct);
  31. float dis = plate - new_center.x;
  32. float r = 1 - exp(-100 * dis * dis);
  33. if(direct==ePositive)
  34. dx = r * (gravy-force) / float(t_cl->size());
  35. else
  36. dx = r * (force - gravy) / float(t_cl->size());
  37. dx = 0.02 * (1 / (1. + exp(-81. * dx)) - 0.5);
  38. if(direct==ePositive)
  39. forceLen = force_center.y - new_center.y;
  40. else
  41. forceLen = -force_center.y + new_center.y;
  42. dtheta = force * forceLen * M_PI / 180.0 * 0.01;
  43. float dyaw = 0.05 * (1 / (1. + exp(-81. * dtheta)) - 0.5);
  44. t_cl = transformCloud(t_cl, new_center, dx, dyaw);
  45. theta += dyaw;
  46. /*printf(" gravy:%f force:%f force_len:%f dx :%f dtheta:%f Yaw:%f\n", gravy, force,
  47. forceLen, dx, dtheta * 180.0 / M_PI, theta * 180.0 / M_PI);*/
  48. iter++;
  49. }
  50. auto t2=std::chrono::steady_clock::now();
  51. auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
  52. double time=double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den;
  53. printf("iter:%d time:%f\n",iter,time);
  54. tp=pcl::PointXYZ(new_center.x-src_center.x,new_center.y-src_center.y,new_center.z-src_center.z);
  55. out= t_cl;
  56. return true;
  57. }
  58. void FallModel::computeForce(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointXYZ& center,
  59. pcl::PointXYZ& force_center,float& gravy,float& force,float plate ,FallDirect direct){
  60. Eigen::Vector4f centroid; //质心
  61. pcl::compute3DCentroid(*cloud,centroid); // 计算质心
  62. center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]);
  63. gravy=cloud->size()*1.0;
  64. force=0;
  65. pcl::PointCloud<pcl::PointXYZ>::Ptr gravy_cl(new pcl::PointCloud<pcl::PointXYZ>);
  66. for(int i=0;i<cloud->size();++i){
  67. float deep=cloud->points[i].x-plate;
  68. if(direct==eNagtive) {
  69. if (deep < 0) {
  70. float t = pow(36 * deep, 4) * 10.0;
  71. if (t > 2) {
  72. t = 2;
  73. }
  74. force += t;
  75. gravy_cl->push_back(cloud->points[i]);
  76. }
  77. }else{
  78. if (deep > 0) {
  79. float t = pow(36 * deep, 4) * 10.0;
  80. if (t > 2) {
  81. t = 2;
  82. }
  83. force += t;
  84. gravy_cl->push_back(cloud->points[i]);
  85. }
  86. }
  87. }
  88. pcl::compute3DCentroid(*gravy_cl,centroid); // 计算质心
  89. force_center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]);
  90. }
  91. pcl::PointCloud<pcl::PointXYZ>::Ptr FallModel::transformCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
  92. pcl::PointXYZ center,float dx,float theta) {
  93. Eigen::Rotation2D<float> rotation(theta);
  94. Eigen::Matrix<float, 2, 2> rotation_matrix = rotation.toRotationMatrix();
  95. pcl::PointCloud<pcl::PointXYZ>::Ptr r_cl(new pcl::PointCloud<pcl::PointXYZ>);
  96. for (int i = 0; i < cloud->size(); ++i) {
  97. const Eigen::Matrix<float, 2, 1> point(cloud->points[i].x, cloud->points[i].y);
  98. const Eigen::Matrix<float, 2, 1> tp(center.x, center.y);
  99. //减去经过车辆旋转计算的左前中心
  100. const Eigen::Matrix<float, 2, 1> tanslate_point = rotation_matrix * (point - tp) +tp;
  101. r_cl->push_back(pcl::PointXYZ(tanslate_point[0]+dx, tanslate_point[1], 0));
  102. }
  103. return r_cl;
  104. }