固态激光雷达zvision_lidar lio-sam与fast-lio2对比

news2024/10/5 17:18:19

 机械式激光雷达,可以根据ring提取边和面特征,固态式激光雷达实现特征检查需要的工作比较多,可以将降采样的都做为面特征进行处理。lio-sam添加固态雷达代码:

一、imageProjection.cpp

(sensor == SensorType::ZVISION) {
            pcl::moveFromROSMsg(currentCloudMsg, *tmpOusterCloudIn);
            laserCloudIn->points.resize(tmpOusterCloudIn->size());
            laserCloudIn->is_dense = tmpOusterCloudIn->is_dense;
            for (size_t i = 0; i < tmpOusterCloudIn->size(); i++) {
                auto &src = tmpOusterCloudIn->points[i];
                auto &dst = laserCloudIn->points[i];
                dst.x = src.x;
                dst.y = src.y;
                dst.z = src.z;
                dst.intensity = src.intensity;
                //dst.ring = src.ring;
                dst.time = src.t * 1e-9f; //ms
            }
        } 

 取消ring检测

if (ringFlag == 0 && sensor != SensorType::ZVISION) {
            ringFlag = -1;
            for (int i = 0; i < (int)currentCloudMsg.fields.size(); ++i) {
                if (currentCloudMsg.fields[i].name == "ring") {
                    ringFlag = 1;
                    break;
                }
            }
            if (ringFlag == -1) {
                ROS_ERROR("Point cloud ring channel not available, please configure your point cloud data!");
                ros::shutdown();
            }
        }

 取消去畸变

void projectPointCloud() {
        int cloudSize = laserCloudIn->points.size();
        fullCloud->clear();
        // range image projection
        for (int i = 0; i < cloudSize; ++i) {
            PointType thisPoint;
            thisPoint.x = laserCloudIn->points[i].x;
            thisPoint.y = laserCloudIn->points[i].y;
            thisPoint.z = laserCloudIn->points[i].z;
            thisPoint.intensity = laserCloudIn->points[i].intensity;

            float range = pointDistance(thisPoint);
            if (range < lidarMinRange || range > lidarMaxRange)
                continue;
            if (thisPoint.z < lidarLowRange) //去除地面点
                continue;

            if (sensor != SensorType::ZVISION) {
                int rowIdn = laserCloudIn->points[i].ring;
                if (rowIdn < 0 || rowIdn >= N_SCAN)
                    continue;

                if (rowIdn % downsampleRate != 0)
                    continue;

                int columnIdn = -1;
                if (sensor == SensorType::VELODYNE || sensor == SensorType::OUSTER) {
                    float horizonAngle = atan2(thisPoint.x, thisPoint.y) * 180 / M_PI;
                    static float ang_res_x = 360.0 / float(Horizon_SCAN);
                    columnIdn = -round((horizonAngle - 90.0) / ang_res_x) + Horizon_SCAN / 2;
                    if (columnIdn >= Horizon_SCAN)
                        columnIdn -= Horizon_SCAN;
                } else if (sensor == SensorType::LIVOX) {
                    columnIdn = columnIdnCountVec[rowIdn];
                    columnIdnCountVec[rowIdn] += 1;
                }

                if (columnIdn < 0 || columnIdn >= Horizon_SCAN)
                    continue;

                if (rangeMat.at<float>(rowIdn, columnIdn) != FLT_MAX)
                    continue;

                thisPoint = deskewPoint(&thisPoint, laserCloudIn->points[i].time); //去畸变

                rangeMat.at<float>(rowIdn, columnIdn) = range;

                int index = columnIdn + rowIdn * Horizon_SCAN;
            } else {
                if (i % downsampleRate != 0)
                    continue;
            }
            fullCloud->push_back(thisPoint);
        }
    }

 将所有的点广播出去

void publishClouds() {
        cloudInfo.header = cloudHeader;
        if (sensor != SensorType::ZVISION)
            cloudInfo.cloud_deskewed = publishCloud(pubExtractedCloud, extractedCloud, cloudHeader.stamp, lidarFrame);
        else
            cloudInfo.cloud_deskewed = publishCloud(pubExtractedCloud, fullCloud, cloudHeader.stamp, lidarFrame);
        pubLaserCloudInfo.publish(cloudInfo);
    }

 二、mapOptmization.cpp

订阅所有图片

if (sensor != SensorType::ZVISION)
            subCloud = nh.subscribe<lio_sam::cloud_info>("lio_sam/feature/cloud_info", 1, &mapOptimization::laserCloudInfoHandler, this, ros::TransportHints().tcpNoDelay());
        else
            subCloud = nh.subscribe<lio_sam::cloud_info>("lio_sam/deskew/cloud_info", 1, &mapOptimization::laserCloudInfoHandler, this, ros::TransportHints().tcpNoDelay());

 将点云放入面特征

void laserCloudInfoHandler(const lio_sam::cloud_infoConstPtr &msgIn) {
        // extract time stamp
        timeLaserInfoStamp = msgIn->header.stamp;
        timeLaserInfoCur = msgIn->header.stamp.toSec();

        // extract info and feature cloud
        cloudInfo = *msgIn;
        if (sensor != SensorType::ZVISION) {
            pcl::fromROSMsg(msgIn->cloud_corner, *laserCloudCornerLast);
            pcl::fromROSMsg(msgIn->cloud_surface, *laserCloudSurfLast);
        } else {
            pcl::fromROSMsg(msgIn->cloud_deskewed, *laserCloudSurfLast);
        }

 修改特征处理函数

void scan2MapOptimization() {
        if (cloudKeyPoses3D->points.empty())
            return;
        if (sensor != SensorType::ZVISION) {
            if (laserCloudSurfLastDSNum > surfFeatureMinValidNum && laserCloudCornerLastDSNum > edgeFeatureMinValidNum) {
                //kdtreeCornerFromMap->setInputCloud(laserCloudCornerFromMapDS);
                kdtreeSurfFromMap->setInputCloud(laserCloudSurfFromMapDS);

                for (int iterCount = 0; iterCount < 30; iterCount++) {
                    laserCloudOri->clear();
                    coeffSel->clear();

                    //cornerOptimization();
                    surfOptimization();

                    combineOptimizationCoeffs();

                    if (LMOptimization(iterCount) == true)
                        break;
                }

                transformUpdate();
            } else {
                ROS_WARN("Not enough features! Only %d edge and %d planar features available.", laserCloudCornerLastDSNum, laserCloudSurfLastDSNum);
            }
        } else {
            if (laserCloudSurfLastDSNum > surfFeatureMinValidNum) {
                kdtreeSurfFromMap->setInputCloud(laserCloudSurfFromMapDS);

                for (int iterCount = 0; iterCount < 30; iterCount++) {
                    laserCloudOri->clear();
                    coeffSel->clear();

                    cornerOptimization();
                    surfOptimization();

                    combineOptimizationCoeffs();

                    if (LMOptimization(iterCount) == true)
                        break;
                }

                transformUpdate();
            } else {
                ROS_WARN("Not enough features!  %d planar features available.", laserCloudSurfLastDSNum);
            }
        }
    }

 cmakelist.txt

取消特征检测函数

# Feature Association 取消特征检测
if(0)
  add_executable(${PROJECT_NAME}_featureExtraction src/featureExtraction.cpp)
  add_dependencies(${PROJECT_NAME}_featureExtraction ${catkin_EXPORTED_TARGETS} ${PROJECT_NAME}_generate_messages_cpp)
  target_link_libraries(${PROJECT_NAME}_featureExtraction ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})
endif()

 修改launch不需要运行featureExtration

    <!--<node pkg="$(arg project)" type="$(arg project)_featureExtraction"   name="$(arg project)_featureExtraction"    output="screen"     respawn="true"/>-->

 lio-sam将结果反馈到Imu预积分中,如果特征匹配较差会发散,导致imu预积分也发散。

 fast-lio2

在预处理函数中添加zvison_lidar处理函数

void Preprocess::zvision_handler(const sensor_msgs::PointCloud2::ConstPtr &msg) {
    pl_surf.clear();
    pl_corn.clear();
    pl_full.clear();
    // ROS_WARN("size of aaaaaa");
    PointCloudXYZI pl_orig;
    pcl::fromROSMsg(*msg, pl_orig);
    int plsize = pl_orig.points.size();
    // ROS_WARN("size of bbbbbb");
    if (plsize == 0) return;
    pl_surf.reserve(plsize);
    // ROS_WARN("size of cccc%d", plsize);
    for (int i = 0; i < plsize; i++) {
        PointType added_pt;

        added_pt.x = pl_orig.points[i].x;
        added_pt.y = pl_orig.points[i].y;
        added_pt.z = pl_orig.points[i].z;
        added_pt.intensity = pl_orig.points[i].intensity;
        added_pt.curvature = pl_orig.points[i].normal_x; // curvature unit: ms

        /**** 较近距离,以及较远距离点云的去除  ***/
        // ROS_WARN("size of ddd%f", top_height);
        if (added_pt.z > top_height) {
            continue;
        }

        double distance_p = added_pt.x * added_pt.x + added_pt.y * added_pt.y;
        // ROS_WARN("size of eee%f", max_blind);
        if (distance_p > (max_blind)) {
            continue;
        }
        //ROS_WARN("size of fff%f", blind);
        if (distance_p < (blind)) {
            continue;
        }

        all_point_num += 1;
        /**** 点云降采样  地面点采用更大的降采样倍率 且距离近的地面点用更大的降采样倍率 ***/
        //ROS_WARN("size of gggg%f", ground_height);
        if (added_pt.z < ground_height) {
            //ROS_WARN("size of hhhh");
            ground_point_num += 1;
            if ((i / 8) % ground_filter_num == 0) {
                pl_surf.points.push_back(added_pt);
            }

        } else {
            // ROS_WARN("size of iiiii");
            if ((i / 8) % point_filter_num == 0) { //  8个点为一个扫描周期
                pl_surf.points.push_back(added_pt);
            }
        }
    }
    //std::cout << "aaaaaaaaaaaaaaaa" << pl_surf.points.size() << std::endl;
    //ROS_WARN("size of %d", pl_surf.points.size());
}

调用雷达处理函数

void Preprocess::process(const sensor_msgs::PointCloud2::ConstPtr &msg, PointCloudXYZI::Ptr &pcl_out) {
    zvision_handler(msg);
    *pcl_out = pl_surf;
}

 去掉地面删除函数

 Eigen::Matrix3f ground_cov_, all_covariance;
            Eigen::Vector4f ground_pc_mean_, xyz_centroid;
            Eigen::VectorXf ground_singular_values_;

            pcl::PointCloud<pcl::PointXYZINormal>::Ptr ground_cloud_filtered(new pcl::PointCloud<pcl::PointXYZINormal>);
            p_pre->zvision_remove_ground(feats_undistort, ground_cloud_filtered);

            /*pcl::computeMeanAndCovarianceMatrix(*ground_cloud_filtered, ground_cov_, ground_pc_mean_);
            Eigen::JacobiSVD<Eigen::MatrixXf> svd(ground_cov_, Eigen::DecompositionOptions::ComputeFullU);
            ground_singular_values_ = svd.singularValues();
            Eigen::VectorXf normal_ = (svd.matrixU().col(2));
            Eigen::Vector3f seeds_mean = ground_pc_mean_.head<3>();
            double ang_y = acos(normal_(1) / 1.0);
            double ang_x = acos(normal_(0) / 1.0);

            ground_euler_x = ang_y - M_PI / 2.0;
            ground_euler_y = M_PI / 2.0 - ang_x;

            double d_ = (normal_.transpose() * seeds_mean);
            bool is_ground_reliable = true;
            if (abs(d_ - seeds_mean(2)) > 0.03 || seeds_mean(2) > -0.50 || seeds_mean(2) < -0.55) {
                is_ground_reliable = false;
            }

            // publish_ground(pubGround, is_ground_reliable, d_, ground_euler_x, ground_euler_y);

            pcl::compute3DCentroid(*feats_undistort, xyz_centroid);
            pcl::computeCovarianceMatrix(*feats_undistort, xyz_centroid, all_covariance);

            Eigen::EigenSolver<Eigen::Matrix3f> es(all_covariance);
            Eigen::VectorXf eigenvalues = es.eigenvalues().real();
            Eigen::VectorXf sorted_eigen;
            Eigen::VectorXi index;
            sort_vec(eigenvalues, sorted_eigen, index);

            if (sorted_eigen(2) < 1000 && log10(abs(sorted_eigen(1)) / abs(sorted_eigen(2))) > eigen_degen) {
                flag_degen = true;
            }*/

地面处理函数改为

void Preprocess::zvision_remove_ground(PointCloudXYZI::Ptr &input, PointCloudXYZI::Ptr &out_put) {
    pcl::PassThrough<pcl::PointXYZINormal> passX;

    //  直通滤波去除地面
    passX.setInputCloud(input);    //这个参数得是指针,类对象不行
    passX.setFilterFieldName("x"); //设置想在哪个坐标轴上操作
    passX.setFilterLimits(-0.5, 0.5);
    passX.setFilterLimitsNegative(false); //保留(true就是删除,false就是保留而删除此区间外的)
    passX.filter(*out_put);               //输出到结果指针

    passX.setInputCloud(out_put);  //这个参数得是指针,类对象不行
    passX.setFilterFieldName("y"); //设置想在哪个坐标轴上操作
    passX.setFilterLimits(0.3, 1.3);
    passX.setFilterLimitsNegative(false); //保留(true就是删除,false就是保留而删除此区间外的)
    passX.filter(*out_put);               //输出到结果指针

    passX.setInputCloud(out_put);  //这个参数得是指针,类对象不行
    passX.setFilterFieldName("z"); //设置想在哪个坐标轴上操作
    passX.setFilterLimits(-2, -0.0);
    passX.setFilterLimitsNegative(false); //保留(true就是删除,false就是保留而删除此区间外的)
    passX.filter(*out_put);               //输出到结果指针
}

 总结:fast-lio在固态激光雷达处理上更快,鲁棒性更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/857788.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

css冒号对齐

实现后的样式效果 实现方式 html&#xff1a; <el-col v-if"item.showInSingle ! false" :span"6" style"padding: 4px 0"><label>{{ item.label }}&#xff1a;</label><span v-if"singleData[item.prop] ! 0 &…

企业权限管理(四)-订单操作

订单操作 各种表之间的关系 订单查询流程 order-list.jsp界面 创建实体类 订单 package com.itheima.ssm.domain;import com.itheima.ssm.utils.DateUtils;import java.util.Date; import java.util.List;//订单 public class Orders {private String id;private String o…

Vue3 —— ref 全家桶及源码学习

该文章是在学习 小满vue3 课程的随堂记录示例均采用 <script setup>&#xff0c;且包含 typescript 的基础用法 前言 本章 ref 全家桶 主要包括以下几个api 和 对应源码的学习&#xff1a; refisRefshallowReftriggerRefcustomRef 一、api 各自的使用 1、ref 使用 v…

【雕爷学编程】Arduino动手做(04)---震动传感器模块3

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

Word转PDF在线转换如何操作?分享转换技巧

现如今&#xff0c;pdf转换器已成为大家日常办公学习必不可少的工具&#xff0c;市场上的pdf转换器主要有两种类型&#xff0c;一种是需要下载安装的&#xff0c;另一种是网页版&#xff0c;打开就可以使用的&#xff0c;今天小编给大家推荐一个非常好用的网页版pdf转换器&…

【解决问题】手动执行maven命令安装指定jar包到本地仓库

背景&#xff1a; 有一个三方jar从远程仓库始终没有拉下来&#xff0c;没办法只能自己去下载&#xff0c;但是自己下载下来&#xff0c;不能直接建立个目录放到本地仓库&#xff0c;需要执行命令才行 操作 命令&#xff1a; mvn install:install-file -DgroupIdcom.alipay …

Java【Spring】使用类注解和方法注解, 更简单的存储和获取 Bean

文章目录 前言一、存储 Bean1, 配置文件2, 五大类注解Bean 的命名规则 3, 方法注解Bean 的命名规则 二、获取 Bean1, 属性注入2, Setter 注入3, 构造方法注入4, Autowired 和 Resource 的区别5, 同一个类型的多个 Bean 注入问题 总结 前言 各位读者好, 我是小陈, 这是我的个人主…

「2024」预备研究生mem-论证推理强化:评价类

一、论证推理强化&#xff1a;评价类 二、课后题

解决: git拉取报错 git 未能顺利结束 (退出码 1)

拉取代码失败信息 解决方法: 执行一下"git push -f origin master"命令即可 步骤: 1.项目文件夹右击选择"Git Bash Here",打开命令窗口 2. 输入"git push -f origin master"后,回画 执行结束 3.再拉取代码,成功

【数学建模】-- Matlab中图的最短路径

前言&#xff1a; 图的基本概念&#xff1a; 若想简单绘制图可以利用此网站&#xff1a; 左上角Undirected/Directed是无向图/有向图 左边 0-index &#xff0c;1-index为0下标&#xff0c;1下标。 Node Count为节点个数 Graph Data&#xff1a;最初尾节点的名称&#xff…

从初学者的角度来理解指针常量和常量指针

重新理解指针常量&#xff0c;常量指针 应用 我先提一个问题&#xff1a;知道指针常量&#xff0c;常量指针存在的作用是什么吗&#xff1f; 先了解它们存在的作用再去理解它们&#xff0c;或许更轻松些。 比如配置文件读取&#xff1a;在许多工程中&#xff0c;配置文件用于…

linux 下 网卡命名改名

Linux 操作系统的网卡设备的传统命名方式是 eth0、eth1、eth2等&#xff0c;而 CentOS7 提供了不同的命名规则&#xff0c;默认是网卡命名会根据网卡的硬件信息&#xff0c;插槽位置等有关&#xff1b;来分配。这样做的优点是命名全自动的、可预知的&#xff0c;缺点是比 eth0、…

计算机服务器被360后缀勒索病毒攻击怎么办,勒索病毒解密

计算机技术的不断发展&#xff0c;不仅方便了企业的生产生活&#xff0c;也为社会的发展带来了巨大贡献&#xff0c;但随之而来的网络威胁也不断增加&#xff0c;勒索病毒就是其中较为常见的常见的威胁。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的计算机服务器…

volatile,解决内存可见性引起的问题,wait和notify

补充&#xff1a;synchronized&#xff08;务必会读&#xff08;辛可肉耐子&#xff09;会写&#xff09;&#xff0c;要搭配一个对象的时候&#xff0c;不一定非要是访问的this成员 synchronized(锁对象&#xff09;{ 代码块} public synchronized static void func(){} 静态方…

JS+CSS实现内凹导航栏

在移动互联网时代&#xff0c;导航栏是一个非常重要的元素&#xff0c;它能够帮助用户快速找到所需的信息。下面使用JS CSS实现一个内凹导航栏&#xff0c;内凹导航栏则是一种比较流行的设计风格&#xff0c;它能够让导航栏看起来更加立体和美观&#xff0c;视觉效果也非常不错…

vue : 无法加载文件 C:\Users\…\npm\vue.ps1,因为在此系统上禁止运行脚本。

在 PowerShell 中创建 vue 项目时&#xff0c;出现了以下错误导致创建失败&#xff1a;vue : 无法加载文件 C:\Users\…\npm\vue.ps1&#xff0c;因为在此系统上禁止运行脚本。 报错原因 用户权限不足导致无法加载文件&#xff0c;以管理员身份运行终端或者 PowerShell 也可…

使用Three.js制作一个旋转多面体

之前一直对three.js比较好奇&#xff0c;但是一直没有着手学习。今天刷到一篇博客&#xff08;博主&#xff1a;1_bit&#xff09;&#xff0c;觉得挺有意思&#xff0c;就跟着敲了一下。 html: 其中canvas用于添加渲染好的元素&#xff0c;本篇文章通过CDN形式引入three.js,…

2023 Gartner RPA魔力象限报告解读:国产厂商“破纪录”跃升意味着什么?

2023 Gartner RPA魔力象限报告解读&#xff1a;象限跃升彰显国产RPA厂商实力 2023 Gartner RPA魔力象限报告四大行业趋势&#xff0c;国产RPA厂商已在践行 文/王吉伟 8月3日&#xff0c;全球著名咨询调查机构Gartner发布了《2023年全球RPA魔力象限&#xff08;Gartner RPA M…

ceph相关概念和部署

Ceph 可用于向云提供 Ceph 对象存储 平台和 Ceph 可用于提供 Ceph 块设备服务 到云平台。Ceph 可用于部署 Ceph 文件 系统。所有 Ceph 存储集群部署都从设置 每个 Ceph 节点&#xff0c;然后设置网络。 Ceph 存储集群需要满足以下条件&#xff1a;至少一个 Ceph 监控器&#x…

10分钟学会阿里OSS对象存储

一. 前言 最近有很多小伙伴问&#xff0c;如果我们要进行大规模的文件存储该怎么做? 其实实现文件存储的技术有很多&#xff0c;如果我们在网上搜索一下&#xff0c;你会发现实现的技术简直是五花八门&#xff0c;比如有一种技术叫FastDFS就可以实现文件存储&#xff0c;但该…