// // Created by zx on 23-12-7. // #include "fallModel.h" #include #include FallModel::FallModel(){ } bool FallModel::fall(pcl::PointCloud::Ptr cloud,pcl::PointCloud::Ptr& out, pcl::PointXYZ& tp,float& theta,FallDirect direct){ auto t1=std::chrono::steady_clock::now(); pcl::PointXYZ minp,maxp; pcl::getMinMax3D(*cloud,minp,maxp); float plate=minp.x; if(direct==ePositive) plate=maxp.x; Eigen::Vector4f centroid; //质心 pcl::compute3DCentroid(*cloud,centroid); // 计算质心 pcl::PointXYZ src_center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]); pcl::PointXYZ new_center, force_center; float dtheta=M_PI,dx=1.0,forceLen=1.0; pcl::PointCloud::Ptr t_cl=cloud; int iter=0; while( fabs(dx)>1e-5 || fabs(forceLen)>1e-4) { if(iter==1000){ printf(" iter 1000 Failed\n"); return false; } float gravy, force; computeForce(t_cl, new_center, force_center, gravy, force, plate,direct); float dis = plate - new_center.x; float r = 1 - exp(-100 * dis * dis); if(direct==ePositive) dx = r * (gravy-force) / float(t_cl->size()); else dx = r * (force - gravy) / float(t_cl->size()); dx = 0.02 * (1 / (1. + exp(-81. * dx)) - 0.5); if(direct==ePositive) forceLen = force_center.y - new_center.y; else forceLen = -force_center.y + new_center.y; dtheta = force * forceLen * M_PI / 180.0 * 0.01; float dyaw = 0.05 * (1 / (1. + exp(-81. * dtheta)) - 0.5); t_cl = transformCloud(t_cl, new_center, dx, dyaw); theta += dyaw; /*printf(" gravy:%f force:%f force_len:%f dx :%f dtheta:%f Yaw:%f\n", gravy, force, forceLen, dx, dtheta * 180.0 / M_PI, theta * 180.0 / M_PI);*/ iter++; } auto t2=std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(t2 - t1); double time=double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den; printf("iter:%d time:%f\n",iter,time); tp=pcl::PointXYZ(new_center.x-src_center.x,new_center.y-src_center.y,new_center.z-src_center.z); out= t_cl; return true; } void FallModel::computeForce(pcl::PointCloud::Ptr cloud,pcl::PointXYZ& center, pcl::PointXYZ& force_center,float& gravy,float& force,float plate ,FallDirect direct){ Eigen::Vector4f centroid; //质心 pcl::compute3DCentroid(*cloud,centroid); // 计算质心 center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]); gravy=cloud->size()*1.0; force=0; pcl::PointCloud::Ptr gravy_cl(new pcl::PointCloud); for(int i=0;isize();++i){ float deep=cloud->points[i].x-plate; if(direct==eNagtive) { if (deep < 0) { float t = pow(36 * deep, 4) * 10.0; if (t > 2) { t = 2; } force += t; gravy_cl->push_back(cloud->points[i]); } }else{ if (deep > 0) { float t = pow(36 * deep, 4) * 10.0; if (t > 2) { t = 2; } force += t; gravy_cl->push_back(cloud->points[i]); } } } pcl::compute3DCentroid(*gravy_cl,centroid); // 计算质心 force_center=pcl::PointXYZ(centroid[0],centroid[1],centroid[2]); } pcl::PointCloud::Ptr FallModel::transformCloud(pcl::PointCloud::Ptr cloud, pcl::PointXYZ center,float dx,float theta) { Eigen::Rotation2D rotation(theta); Eigen::Matrix rotation_matrix = rotation.toRotationMatrix(); pcl::PointCloud::Ptr r_cl(new pcl::PointCloud); for (int i = 0; i < cloud->size(); ++i) { const Eigen::Matrix point(cloud->points[i].x, cloud->points[i].y); const Eigen::Matrix tp(center.x, center.y); //减去经过车辆旋转计算的左前中心 const Eigen::Matrix tanslate_point = rotation_matrix * (point - tp) +tp; r_cl->push_back(pcl::PointXYZ(tanslate_point[0]+dx, tanslate_point[1], 0)); } return r_cl; }