123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- #include <ceres/ceres.h>
- #include <ceres/cubic_interpolation.h>
- #include "car_pose_detector.h"
- struct DiscreteCostFunction {
- std::vector<double> line_;
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_;
- explicit DiscreteCostFunction(std::vector<double> &line,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
- line_ = line;
- cloud_=cloud;
- }
- template<typename JetT>
- bool operator()(const JetT* const x, JetT* residual) const {
- ceres::Grid1D<double> grid(line_.data(), 0, line_.size());
- ceres::CubicInterpolator<ceres::Grid1D<double>> cubic(grid);
- JetT tx=x[0];
- JetT theta=x[1];
- for(int i=0;i<cloud_->size();++i){
- pcl::PointXYZ pt=cloud_->points[i];
- JetT cx= JetT(pt.x) * ceres::cos(theta) - JetT(pt.y) * ceres::sin(theta) + tx + 1.5;
- cubic.Evaluate(cx*100.,&residual[i]);
- residual[i]=JetT(1.0)-residual[i];
- }
- return true;
- }
- };
- Car_pose_detector::Car_pose_detector(){
- float width = 1.8;
- float sigma=25.;
- float solution = 0.01;
- for (int i=-130;i<130;++i) {
- float x=i*solution;
- double y = 1.0 / (1.0 + ceres::exp(-sigma * (x+width/2.))) -
- 1.0 / (1.0 + ceres::exp(-sigma * (x-width/2.)));
- line_.emplace_back(y);
- // printf("---Debug %s %d : [%d %f %f]. \n", __func__, __LINE__, i, x, y);
- }
- }
- // 检测底盘z方向值,去中心,使用mat加速
- bool Car_pose_detector::detect_pose_mat(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr,
- pcl::PointCloud<pcl::PointXYZ>::Ptr out_cloud, float &x,
- float &theta) {
- //离群点过滤
- pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
- sor.setInputCloud(cloud_ptr);
- sor.setMeanK(50); //K近邻搜索点个数
- sor.setStddevMulThresh(0.7); //标准差倍数
- sor.setNegative(false); //保留未滤波点(内点)
- sor.filter(*cloud_ptr); //保存滤波结果到cloud_filter
- double t_vars[2] = {0, 0};
- // 去中心化
- // 构建最小二乘问题
- ceres::Problem problem;
- // tp_trans_mat_cost->debug_img(t_cloud, m_model);
- problem.AddResidualBlock( // 向问题中添加误差项
- // 使用自动求导,模板参数:误差类型,输出维度,输入维度,维数要与前面struct中一致
- new ceres::AutoDiffCostFunction<DiscreteCostFunction, ceres::DYNAMIC, 2>(
- (new DiscreteCostFunction(line_,cloud_ptr)), cloud_ptr->size()),
- nullptr, // 核函数,这里不使用,为空
- t_vars // 待估计参数
- );
- // problem.SetParameterLowerBound(t_vars, 0, -0.1);
- // problem.SetParameterUpperBound(t_vars, 0, 0.1);
- problem.SetParameterLowerBound(t_vars, 1, (-20) * M_PI / 180.0f);
- problem.SetParameterUpperBound(t_vars, 1, (20) * M_PI / 180.0f);
- // 配置求解器
- ceres::Solver::Options options; // 这里有很多配置项可以填
- options.linear_solver_type = ceres::DENSE_QR; // 增量方程如何求解
- options.minimizer_progress_to_stdout = false; // 输出到cout
- options.max_num_iterations = 100;
- ceres::Solver::Summary summary; // 优化信息
- std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
- ceres::Solve(options, &problem, &summary); // 开始优化
- std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
- std::chrono::duration<double> time_used = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
- std::cout << "solve time cost = " << time_used.count() << " seconds. " << std::endl;
- x = t_vars[0];
- theta = t_vars[1] * 180 / M_PI;
- for (auto &point: cloud_ptr->points) {
- pcl::PointXYZ result;
- result.x = - point.y * std::sin(t_vars[1]) + point.x * std::cos(t_vars[1]) + t_vars[0];
- result.y = point.y * std::cos(t_vars[1]) + point.x * std::sin(t_vars[1]);
- result.z = point.z;
- out_cloud->emplace_back(result);
- }
- return true;
- }
|