激光雷达获取中心线 中位线 中间线 获取两边障碍物的中间线

效果如图:
请添加图片描述

环境如下:
c++
pcl:1.81
opencv:3.2

float hight_min=-0.1;
float hight_max=0.3;
float SAC_max_error=0.2;
int line_points_num_min=50;
float down_size_leaf=0.05;
float line_distance_max=2.0;
float line_angle_max_error = 0.01;


bool get_zxx(PointCloudType_::Ptr cloud, PointCloudType_::Ptr  out ){

    PointCloudType_  cloud_out_line;
    PointCloudType_  cloud_in;
    std::vector<PointCloudType_> pc_line;

    int point_num = cloud->size();
    for(int i=0;i<point_num;i++){
        PointType_ added_pt;
        if(cloud->points[i].z<hight_min||cloud->points[i].z>hight_max)
            continue;
        added_pt.x = cloud->points[i].x;
        added_pt.y = cloud->points[i].y;
        added_pt.z = 0;
        cloud_in.push_back(added_pt);
    }

    pcl::VoxelGrid<PointType_> sor;
    sor.setInputCloud(cloud_in.makeShared());
    sor.setLeafSize(down_size_leaf, down_size_leaf, down_size_leaf);
    sor.filter(cloud_in);

    pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
	pcl::SACSegmentation<PointType_> seg;               // 创建拟合对象
	seg.setOptimizeCoefficients(true);                     // 设置对估计模型参数进行优化处理
	seg.setModelType(pcl::SACMODEL_LINE);                  // 设置拟合模型为直线模型
	seg.setMethodType(pcl::SAC_RANSAC);                    // 设置拟合方法为RANSAC
	seg.setMaxIterations(100);                             // 设置最大迭代次数
	seg.setDistanceThreshold(SAC_max_error);                       // 判断是否为模型内点的距离阀值/设置误差容忍范围

    point_num = cloud_in.size();

    int k=0;
	while (k < 2 && cloud_in.points.size() > 0.2 * point_num){
		pcl::ModelCoefficients coefficients;
		seg.setInputCloud(cloud_in.makeShared());                         // 输入点云						 
		seg.segment(*inliers, coefficients);              // 内点的索引,模型系数

		PointCloudType_::Ptr cloud_line(new PointCloudType_);
		PointCloudType_::Ptr outside(new PointCloudType_);
		if (inliers->indices.size() > line_points_num_min) // 判断提取直线上的点数是否小于20个点,小于的话该直线不合格
		{
			// lineCoff.push_back(coefficients);             // 将参数保存进vector中
			pcl::ExtractIndices<PointType_> extract;   // 创建点云提取对象
			extract.setInputCloud(cloud_in.makeShared());
			extract.setIndices(inliers);
			extract.setNegative(false);                   // 设置为false,表示提取内点
			extract.filter(*cloud_line);

			extract.setNegative(true);                    // true提取外点(该直线之外的点)
			extract.filter(*outside);                     // outside为外点点云
			cloud_in.makeShared() .swap(outside);                          // 将cloud_f中的点云赋值给cloud
            line_point[k]=cloud_line->size();

            pc_line.push_back(*cloud_line);
		}
		else
		{
			break;
		}
		k++;
    }

    if(pc_line.size()!=2){
        pc_line.clear();    
        return 0;
    }


    int i=0;
    float k_[2];
    float dis[2];

    cv::Mat matA1(2, 2, CV_32F, cv::Scalar::all(0));
    cv::Mat matD1(1, 2, CV_32F, cv::Scalar::all(0));
    cv::Mat matV1(2, 2, CV_32F, cv::Scalar::all(0));
    int index=0;
    float x[2];
    float y[2];

    for(i=0;i<pc_line.size();i++){
        float cx = 0, cy = 0, cz = 0;        
        int num = pc_line[i].size();
        for(int j=0;j<num;j++){
            cx += pc_line[i].points[j].x;
            cy += pc_line[i].points[j].y;
        }
        if(pc_line.size()==0) return 0;
        cx/=num;
        cy/=num;        

        float a11 = 0, a12 = 0, a13 = 0, a22 = 0, a23 = 0, a33 = 0;
        for (int j = 0; j < num; j++) {
            float ax = pc_line[i].points[j].x - cx;
            float ay = pc_line[i].points[j].y - cy;
            a11 += ax * ax; 
            a12 += ax * ay; 
            a22 += ay * ay; 
        }
        a11/=num;
        a12/=num;
        a22/=num;
        matA1.at<float>(0, 0) = a11; matA1.at<float>(0, 1) = a12;
        matA1.at<float>(1, 0) = a12; matA1.at<float>(1, 1) = a22; 
        cv::eigen(matA1, matD1, matV1);
        if (matD1.at<float>(0, 0) < 3 * matD1.at<float>(0, 1)) {
            return 0;
        }
        float x1 = cx + 0.1 * matV1.at<float>(0, 0);
        float y1 = cy + 0.1 * matV1.at<float>(0, 1);
        float x2 = cx - 0.1 * matV1.at<float>(0, 0);
        float y2 = cy - 0.1 * matV1.at<float>(0, 1);

        float x0=0;
        float y0=0;

        float a012 = sqrt(abs(((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1)) * ((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1)))) ;
        float l12 = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
        float ld2 = a012 / l12;

        if(ld2>line_distance_max)continue;

        k_[index] = (y2-y1)/(x2-x1);
        dis[index] = ld2;
        x[index] = cx;
        y[index] = cy;

        index++;
    }
    pc_line.clear();    

    if(abs(atan(k_[0])-atan(k_[1]))>line_angle_max_error)
        return 0;

    float angle=(atan(k_[0])+atan(k_[1]))/2;

    float  y_ =(dis[1]-dis[0])*sin(angle);
    float  x_ = (dis[1]-dis[0])*cos(angle);

    for(i=-100;i<100;i++){
        
        PointType_ added_pt;
        added_pt.x = x_+ 0.1*i*cos(angle);
        added_pt.y =  y_+ 0.1*i*sin(angle);
        added_pt.z = 0;
        out->push_back(added_pt);
    }

    return 1;
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值