计算两帧雷达数据之间的变换矩阵

文章目录

    • package.xml
    • CMakeLists.txt
    • point_cloud_registration.cc
    • 运行结果

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>point_cloud_registration</name>
  <version>0.0.0</version>
  <description>The point_cloud_registration package</description>

  <maintainer email="xiaoqiuslam@qq.com">xiaqiuslam</maintainer>

  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>
  
  <build_depend>pcl_conversions</build_depend>
  <build_depend>pcl_ros</build_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>sensor_msgs</build_depend>

  <build_export_depend>pcl_conversions</build_export_depend>
  <build_export_depend>pcl_ros</build_export_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>sensor_msgs</build_export_depend>
  
  <exec_depend>pcl_conversions</exec_depend>
  <exec_depend>pcl_ros</exec_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>

  <export>
  </export>
</package>

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)

project(point_cloud_registration)

add_compile_options(-std=c++11)

find_package(catkin REQUIRED COMPONENTS
  pcl_conversions
  pcl_ros
  roscpp
  sensor_msgs
)

find_package(PCL REQUIRED QUIET)

catkin_package()

include_directories(
include
  ${catkin_INCLUDE_DIRS}
  ${PCL_INCLUDE_DIRS}
)

add_executable(point_cloud_registration src/point_cloud_registration.cc)
    
target_link_libraries(point_cloud_registration ${catkin_LIBRARIES})

point_cloud_registration.cc

#include <chrono>
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>

void ScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg);
void ConvertScan2PointCloud(const sensor_msgs::LaserScan::ConstPtr &scan_msg);
void ScanMatchWithICP(const sensor_msgs::LaserScan::ConstPtr &scan_msg);

bool is_first_scan_ = true;
pcl::PointCloud<pcl::PointXYZ>::Ptr current_pointcloud_; 
pcl::PointCloud<pcl::PointXYZ>::Ptr last_pointcloud_; 
pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp_;


void ScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
    // 第一帧雷达数据
    if (is_first_scan_ == true)
    {
        // 转换数据类型 并保存到current_pointcloud_
        ConvertScan2PointCloud(scan_msg);
        is_first_scan_ = false;
    }
    // 第二帧雷达数据
    else
    {
        // 数据类型转换
        std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();

        // 将current_pointcloud_赋值到last_pointcloud_进行保存
        *last_pointcloud_ = *current_pointcloud_;   

        // 数据类型转换 
        ConvertScan2PointCloud(scan_msg);

        // 调用ICP进行计算 雷达前后两帧间的坐标变换
        ScanMatchWithICP(scan_msg);
    }
}


void ConvertScan2PointCloud(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_msg = boost::shared_ptr<pcl::PointCloud<pcl::PointXYZ>>(new pcl::PointCloud<pcl::PointXYZ>());
    cloud_msg->points.resize(scan_msg->ranges.size());

    for (unsigned int i = 0; i < scan_msg->ranges.size(); ++i)
    {
        pcl::PointXYZ &point_tmp = cloud_msg->points[i];
        float range = scan_msg->ranges[i];

        if (!std::isfinite(range))
            continue;

        if (range > scan_msg->range_min && range < scan_msg->range_max)
        {
            float angle = scan_msg->angle_min + i * scan_msg->angle_increment;
            point_tmp.x = range * cos(angle);
            point_tmp.y = range * sin(angle);
            point_tmp.z = 0.0;
        }
    }

    cloud_msg->width = scan_msg->ranges.size();
    cloud_msg->height = 1;
    cloud_msg->is_dense = true;

    pcl_conversions::toPCL(scan_msg->header, cloud_msg->header);

    *current_pointcloud_ = *cloud_msg;
}


void ScanMatchWithICP(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
    icp_.setInputSource(last_pointcloud_);
    icp_.setInputTarget(current_pointcloud_);

    pcl::PointCloud<pcl::PointXYZ> unused_result;
    icp_.align(unused_result);

    if (icp_.hasConverged() == false)
    {
        return;
    }
    else
    {
        Eigen::Affine3f transfrom;
        transfrom = icp_.getFinalTransformation();

        float x, y, z, roll, pitch, yaw;
        pcl::getTranslationAndEulerAngles(transfrom, x, y, z, roll, pitch, yaw);
        std::cout << "transfrom: (x: " << x << ", y: " << y << ", yaw: " << yaw * 180 / M_PI << ")" << std::endl;
    }
}


int main(int argc, char **argv)
{

    ros::init(argc, argv, "point_cloud_registration");

    ros::NodeHandle node_handle_; 

    ros::Subscriber laser_scan_subscriber_;

    laser_scan_subscriber_ = node_handle_.subscribe("laser_scan", 1, &ScanCallback);

    current_pointcloud_ = boost::shared_ptr<pcl::PointCloud<pcl::PointXYZ>>(new pcl::PointCloud<pcl::PointXYZ>());
    
    last_pointcloud_ = boost::shared_ptr<pcl::PointCloud<pcl::PointXYZ>>(new pcl::PointCloud<pcl::PointXYZ>());

    ros::spin();
    
    return 0;
}

运行结果

roscore 
source devel/setup.bash && rosrun point_cloud_registration point_cloud_registration
rosbag play 1.bag 

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Dbeaver:Ubuntu Linux 20.04 mysql 驱动损坏或者没有驱动,无法联网更新下载

下载方法&#xff1a; https://blog.csdn.net/wangpaiblog/article/details/112057533 Ubuntu Linux 20.04 (Architecture Independent), DEB Package 下载地址&#xff1a; https://downloads.mysql.com/archives/c-j/ 安装deb&#xff1a; sudo dpkg -i mysql-connector-java…

存储引擎的简介

简介&#xff1a; 1.在mysql存储引擎可以说就是指表的类型&#xff0c;可以称为表处理器&#xff0c;以表的形式存储。 2.他的功能就是接收上层传下来的指令&#xff0c;然后对表中的数据进行提取写入操作。 目的&#xff1a; 为了管理方便&#xff0c;我们把连接管理&#xf…

【Linux】Linux C编程

gcc编译器 gcc [options] [filenames] 其中&#xff0c;options是编译器所需要的选项参数&#xff0c;filenames是文件名。 gcc编译过程 C语言编译过程一般可以分为预处理、编译、汇编、链接四个步骤。 1.预处理阶段 预处理阶段主要处理宏定义和include&#xff0c;并进行语…

List(CS61B学习记录)

问题引入 上图中&#xff0c;赋给b海象的weight会改变a海象的weight&#xff0c;但x的赋值又不会改变y的赋值 Bits 要解释上图的问题&#xff0c;我们应该从Java的底层入手 相同的二进制编码&#xff0c;却因为数据类型不同&#xff0c;输出不同的值 变量的声明 基本类型…

使用Git将代码上传至代码托管平台GitCode

使用像GitLbi、GitHub、Gitee等代码托管平台用于版本控制非常滴方便&#xff0c;能够跟踪代码的变化和历史记录&#xff0c;方便管理和回滚&#xff0c;还允许多个开发者同时在一个项目上进行开发和协作&#xff0c;提高团队协作效率。 这些平台的代码托管和上传方式都大同小异…

MongoDB开启事务

MongoDB开启事务 配置单节点。到路径C:\Program Files\MongoDB\Server\4.0\bin 使用记事本以管理员权限打开文件mongod.cfg添加如下配置&#xff1a; replication:replSetName: rs02. 重启MongoDB服务 3. 重启后执行命令 rs.initiate()

java集合题库详解

1. Arraylist与LinkedList区别 可以从它们的底层数据结构、效率、开销进行阐述哈 ArrayList是数组的数据结构&#xff0c;LinkedList是链表的数据结构。 随机访问的时候&#xff0c;ArrayList的效率比较高&#xff0c;因为LinkedList要移动指针&#xff0c;而ArrayList是基于索…

【嵌入式高级C语言】10:C语言文件

文章目录 1 文件的概述1.1 文件分类&#xff08;存储介质&#xff09;1.2 磁盘文件分类&#xff08;存储方式&#xff09;1.3 二进制文件和文本文件的区别 2 文件缓冲区3 文件指针4 文件的API4.1 打开文件4.2 关闭文件4.3 重新定位流4.3.1 fseek4.3.2 ftell4.3.3 rewind 4.4 字…

基于SpringBoot的快递配送规划系统的设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 Spring Boot框架 3 1.2 Vue框架 4 1.4 Bootstrap框架 4 1.5 JQuery技术 5 1.6 Ajax技术 5 1.7 ECharts 5 1.8 MySQL 6 1.9本章小结 6 2 系统分析 7 2.1 需求分析 7 2.2 非功能需求 10 2.3 本章小结 10 3 系统设计 11 3.1 …

如何发布新华网稿件,新华网报价多少钱?

在当今信息爆炸的时代&#xff0c;媒体的重要性不言而喻。而作为国内最具影响力的媒体之一&#xff0c;新华网更是备受关注。那么&#xff0c;作为一名公关从业者或者自媒体人士&#xff0c;如何能够在媒介多多网成功发布新华网的稿件呢&#xff1f;接下来&#xff0c;我们就来…

基于PSO粒子群算法的三角形采集堆轨道优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 假设一个收集轨道&#xff0c;上面有5个采集堆&#xff0c;这5个采集堆分别被看作一个4*20的矩阵&#xff08;下面只有4*10&#xff09;&#xff0c;每个模块&…

C语言学习--练习3(贪心)

目录 贪心算法 1. 两数对之间的最大乘积差 2.三角形的最大周长 3.数组拆分 4.救生艇 5.发送饼干 6.摆动数组 贪心算法 概念定义 所谓贪心&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上进行考虑&#xff0c;算法得到的是在某种…

300分钟吃透分布式缓存-26讲:如何大幅成倍提升Redis处理性能?

主线程 Redis 自问世以来&#xff0c;广受好评&#xff0c;应用广泛。但相比&#xff0c; Memcached 单实例压测 TPS 可以高达百万&#xff0c;线上可以稳定跑 20~40 万而言&#xff0c;Redis 的单实例压测 TPS 不过 10~12 万&#xff0c;线上一般最高也就 2~4 万&#xff0c;…

Microsoft Copilot 好像能把论文配图看明白了

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ Microsoft Copilot 好像能把论文配图看明白了&#xff0c;下面是两个案例。 请用学术风格详细描述您的研究论文中的这幅配图。在描述时&#xff0c;请尽可能准确地阐述图片的主要元素、颜色、形状、大…

如何在一个pycharm项目中创建jupyter notebook文件,并切换到conda环境中

1、第一步可以直接在pycharm项目中创建jupyter notebook文件 2、假若想要切换成pytorch环境做实验例子&#xff0c;会发现报这个错误 Jupyter server process exited with code 1 C:\Users\12430\.conda\envs\pytorch3.11\python.exe: No module named jupyter在这里&#xff…

推理判断-聂佳-判读4-定义判断

知识点讲解 考点1 快速识别有效信息 考点2 同构选项排除 题目 考点1 快速识别有效信息 考点2 同构选项排除 总结

linuxOPS基础_操作系统概述

计算机发展史 第一台计算机是1946 年2 月14 日诞生日&#xff0c;第一台名称ENIAC。体积一间屋子的大小&#xff0c;重量高达28t。 第一代&#xff1a;1946 – 1958 > 12 年 &#xff08;电子管&#xff09; 第二代&#xff1a;1958 – 1964 > 6 年 &#xff08;晶体管…

kafka(三)springboot集成kafka(1)介绍

基于kafka新版本 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.0.0</version></dependency> </dependencies> 一、kafkaProducer 1、介绍…

HTML 学习笔记(九)颜色值和长度单位

一、颜色 1.通过RGB值来设置颜色 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>table</title&…

【Linux】线程同步与生产消费者问题

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;CP问题&#x1f449;&#x1f3fb;互斥…