相机雷达时间同步(基于ROS)

news2024/11/8 20:29:08

文章目录

    • 运行环境:
    • 思路:
    • 同步前和同步后效果对比
    • 1.1创建工作空间
    • 1.2创建功能包
    • 2.1编写源文件
    • 2.2编写头文件
    • 2.3编写可执行文件
    • 2.4配置文件
    • 3.1编译运行
    • 4.1录制时间同步后的rosbag
    • 4.2rviz可视化rosbag

运行环境:

ubuntu20.04 noetic
usb_cam
速腾Robosense 16线
宏基暗影骑士笔记本

思路:

软同步:订阅相机和雷达原始数据,然后进行时间同步,最后将同步后的数据发布出去,通过rosbag record进行录制

同步前和同步后效果对比

同步前的话题:
/rslidar_packets
/usb_cam/image_raw

 # 录制命令
 rosbag record -O lidar_camera /usb_cam/image_raw /rslidar_points

在这里插入图片描述

同步后的话题:
/sync/img
/sync/lidar

 # 录制命令
 rosbag record -O lidar_camera_syn_time /sync/img /sync/lidar

在这里插入图片描述

1.1创建工作空间

mkdir -p sys_time_ws/src
cd sys_time_ws
catkin_make
code .

1.2创建功能包

1) 在工作空间src目录下创建功能包

sys_time
roscpp rospy std_msgs

2.1编写源文件

1)在 src 目录下新建文件 sub_and_pub.cpp

代码解释:
this 关键字指向类创建的对象
registerCallback 绑定回调函数,触发回调函数发布同步后的数据

#include "sys_time/sub_and_pub.h"
 
# 重写头文件中的构造函数subscriberANDpublisher()
# main函数初始化对象(subscriberANDpublisher sp)时自动调用构造函数
subscriberANDpublisher::subscriberANDpublisher()
{
    //订阅话题
    lidar_sub.subscribe(nh, "/rslidar_points", 1);
    camera_sub.subscribe(nh, "/usb_cam/image_raw", 1);

    //消息过滤器,使用 ApproximateTime 进行时间同步(允许一定程度的时间误差)
    sync_.reset(new message_filters::Synchronizer<syncpolicy>(syncpolicy(10), camera_sub, lidar_sub));
    sync_->registerCallback(boost::bind(&subscriberANDpublisher::callback, this, _1, _2));

    //发布者
    camera_pub = nh.advertise<sensor_msgs::Image>("sync/img", 10);
    lidar_pub = nh.advertise<sensor_msgs::PointCloud2>("sync/lidar", 10);
}

void subscriberANDpublisher::callback(const sensor_msgs::ImageConstPtr& image, const sensor_msgs::PointCloud2ConstPtr& pointcloud) {
    ROS_INFO("Received synchronized message!");
    camera_pub.publish(image);
    lidar_pub.publish(pointcloud);
}

2.2编写头文件

1)在功能包下的 include/功能包名 目录下新建头文件 sub_and_pub.h
2)配置 includepath 详情见

#ifndef SUB_AND_PUB_H
#define SUB_AND_PUB_H
//ros头文件
#include <ros/ros.h>
//时间同步
#include <message_filters/subscriber.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/synchronizer.h>
//传感器消息
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <sensor_msgs/PointCloud2.h>
 
class subscriberANDpublisher{
public:
    subscriberANDpublisher();
    void callback(const sensor_msgs::ImageConstPtr &image, const sensor_msgs::PointCloud2ConstPtr &pointcloud);
 
private:
    ros::NodeHandle nh;
    ros::Publisher camera_pub;
    ros::Publisher lidar_pub;
    message_filters::Subscriber<sensor_msgs::PointCloud2> lidar_sub;//雷达订阅
    message_filters::Subscriber<sensor_msgs::Image> camera_sub;//相机订阅
 
    typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::PointCloud2> syncpolicy;//时间戳对齐规则
    typedef message_filters::Synchronizer<syncpolicy> Sync;
    boost::shared_ptr<Sync> sync_;//时间同步器
 
};
#endif

2.3编写可执行文件

#include <ros/ros.h>
#include "sys_time/sub_and_pub.h"

 
int main(int argc, char **argv) {
    ros::init(argc, argv, "node");
    subscriberANDpublisher sp;
    ROS_INFO("main done! ");
    ros::spin();
}

2.4配置文件

1)修改CMakeLists.txt

# 添加message_filters ROS包依赖
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_filters
)

# 头文件路径
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

# 新建c++库,将头文件和源文件添加到新库里面
add_library(sys_time_lib
  include/sys_time/sub_and_pub.h
  src/sub_and_pub.cpp
)

# 将src目录下的main.cpp编译成可执行文件
add_executable(main.cpp src/main.cpp)

# 将新库和ros库链接起来
target_link_libraries(sys_time_lib
  ${catkin_LIBRARIES}
)

# 将可执行文件和新库链接起来
target_link_libraries(main.cpp
  sys_time_lib
  ${catkin_LIBRARIES}
)

2)修改package.xml (实际上不修改也可以通过编译)

  <exec_depend>message_filters</exec_depend>

3.1编译运行

1)运行时间同步节点

# 编译
ctrl+shift+b

roscore
source ./devel/setup.bash
rosrun sys_time main.cpp

在这里插入图片描述

2)启动相机

cd usb_cam_ws
source ./devel/setup.bash
roslaunch usb_cam usb_cam-test.launch

3)启动雷达

cd robosense_ws
source ./devel/setup.bash
roslaunch rslidar_sdk start.launch

当相机雷达全部启动后,显示接受到时间同步消息
在这里插入图片描述

4.1录制时间同步后的rosbag

lidar_camera_syn_time 是保存的rosbag名称
/sync/img 和 /sync/lidar 是录制的话题名

rosbag record -O lidar_camera_syn_time /sync/img /sync/lidar
# 查看录制好的rosbag
rosbag info lidar_camera_syn_time.bag

在这里插入图片描述

4.2rviz可视化rosbag

配置文件详细步骤见:Robosense激光雷达录制rosbag

1)打开rviz

rviz

2)导入配置文件 file–open cofig
在这里插入图片描述

3)添加相机话题
在这里插入图片描述

在这里插入图片描述

4)播放rosbag

rosbag play lidar_camera_syn_time.bag

在这里插入图片描述


⭐⭐⭐ 嘟嘟崽 ⭐⭐⭐
⭐⭐⭐ 祝你成功 ⭐⭐⭐

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

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

相关文章

小黑子—Java从入门到入土过程:第七章

Java零基础入门7.0Java系列第七章1. 游戏打包exe2. API2.1 Math2.2 练习2.2.1 判断质数2.2.2 判断水仙花数&#xff08;自幂数&#xff09;2.3 System2.4 Runtime2.5 Object2.5.1 Object 的成员方法(1) toString(2) equals 比较两个对象是否相等(3) clone方法&#xff08;Objec…

投放视频广告时,如何快速与第三方播放器兼容?

新媒体时代&#xff0c;广告样式越来越丰富。相较于传统的图文信息&#xff0c;视频类广告更具有直观性&#xff0c;能够让消费者在了解产品知识和功能的同时加深对产品的印象。 因此在各类网站或App上投放视频类广告是个很好的宣传方式&#xff0c;但广告商们如果想在网站上展…

1.14 从0开始学习Unity游戏开发--物理引擎

上一篇文章我们讲了如何动态创建物体&#xff0c;以及如何用Prefab机制复用我们制作好的物体和逻辑&#xff0c;那么本篇我们将会讲解如何利用这些功能&#xff0c;结合Unity自带的物理引擎&#xff0c;实现一个简单的FPS游戏的效果。 物理组件 首先我们需要先了解如何使用Un…

Linux基础(超级无敌认真好用,万字收藏篇!!!!)

文章目录Linux基础1 Linux概述1.1 Linux特点1.2 Linux和Window区别2 Linux安装2.1 什么是虚拟化2.2 安装虚拟机2.3 配置网络环境3 Linux文件目录4 Linux常用命令4.1 文件与目录操作4.2 查看文件内容4.3 文本内容处理4.4 查询操作4.5 网络相关4.6 其他命令4.7 解压缩命令5 VI/VI…

今天面了个腾讯拿 38K 出来的,让我见识到了基础的天花板

今天上班开早会就是新人见面仪式&#xff0c;听说来了个很厉害的大佬&#xff0c;年纪还不大&#xff0c;是上家公司离职过来的&#xff0c;薪资已经达到中高等水平&#xff0c;很多人都好奇不已&#xff0c;能拿到这个薪资应该人不简单&#xff0c;果然&#xff0c;自我介绍的…

0102加权quick_union和路径压缩-union-find-动态连通性-算法研究

3 union-find算法 3.5 加权quick-union算法 3.5.1 算法实现 quick-union出现最坏情况&#xff0c;因为我们是随意将一棵树链接到另外一棵树上&#xff0c;修改如下&#xff1a; 添加一个数组和一些代码记录树中节点数&#xff1b;链接时将节点数较小的树链接到较大的树上&a…

基础算法-双指针,滑动窗口,位运算,区间离散化

双指针 两种类型 for(int i0,j0;i<n;i) {while(i<j&&check(i,j)) j;// 每道题目具体逻辑}双指针最核心的性质 可以优化 输入一个字符串 把每个单词输出出来 i找到单词开头 j找到空格 vector<string> rs; for(int i0,j0;i<s.size();i) {ji;while(j&…

.Net Forms Resize 12 Crack

.Net Forms Resize 12 Crack 添加了对Microsoft Visual Studio 2022(v17.5.3)及更高版本的支持。 增加了对Microsoft Windows Server 2019和2022的支持。 改进并调整引擎大小(大约快20%)。 更新与受支持的第三方控件的新版本的兼容性。 添加了新的Microsoft Framework 4.8.1库。…

in、not in、between and、基本查询数据库实验三 单表查询(一)(头歌实践教学平台)

文章目的初衷是希望学习笔记分享给更多的伙伴&#xff0c;并无盈利目的&#xff0c;尊重版权&#xff0c;如有侵犯&#xff0c;请官方工作人员联系博主谢谢。 目录 第1关&#xff1a;基本查询语句 任务描述 相关知识 查询数据表中指定字段的内容 查询数据表中的所有内容 …

Ucore lab2

练习一&#xff1a;实现first-fit 连续物理内存分配算法 根据实验指导书中的实验执行流程概述&#xff0c;先了解分析ucore如何对物理内存进行管理&#xff0c;再完成实验练习。 在对物理内存进行管理之前&#xff0c;需要先进行物理内存布局的探测&#xff0c;探测得到的内存…

[LeetCode解题报告] 1157. 子数组中占绝大多数的元素

[LeetCode解题报告] 1157. 子数组中占绝大多数的元素 一、 题目1. 题目描述2. 原题链接二、 解题报告1. 思路分析2. 复杂度分析3. 代码实现三、 本题小结四、 参考链接一、 题目 1. 题目描述 2. 原题链接 链接: 1157. 子数组中占绝大多数的元素 二、 解题报告 1. 思路分析 …

python+requests的接口自动化测试框架实例详解教程

目录 前言 一、环境准备 二、设计框架结构 三、实现框架功能 四、执行测试用例 五、总结 前言 Python是一种简单易学、功能强大的编程语言&#xff0c;广泛应用于各种软件开发和测试场景中。requests是Python中流行的HTTP库&#xff0c;支持发送HTTP请求和处理HTTP响应&a…

【c语言】多维数组原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…

话说~~ HTTP协议请求的工作流程 (Web服务请求过程)最细详解

目录 文章导入 &#xff1a; 概述 &#xff1a; 详解过程 &#xff1a; DNS域名解析 &#xff1a; DNS 域名解析过程分析 &#xff1a; TCP连接搭建 &#xff1a; 等待TCP队列 建立TCP连接 发起 HTTP 请求 &#xff1a; # 哪是如何进行 HTTP 请求的呢 &#…

实验架构的部署

目录 实验要求 实验环境 1、部署静态页面 2、部署负载均衡 3、搭建动态网页 4、 nginx反向代理 5、部署NFS 7、mysql 安装mysql 安装mha 准备主从复制 开启mha 架构的部署 实验要求 完成用户访问时虚拟IP由LVS负责高可用&#xff0c;静态交给nginx处理&#xff0c;…

【工具篇】Spring Boot 整合阿里云短信-SMS

短信服务-SMS 短信服务&#xff08;Short Message Service&#xff09;是广大企业客户快速触达手机用户所优选使用的通信能力&#xff0c;分为国内短信服务和国际/港澳台短信服务。通过 API/SDK、控制台调用短信发送能力&#xff0c;将指定信息发送至国内或境外手机号码。 应…

<数据结构>NO1.算法的时空复杂度

文章目录&#x1f6a9;算法效率算法复杂度&#x1fa85;时间复杂度大O的渐进表示法常见的时间复杂度举例&#x1fa85;空间复杂度大O的渐进表示法常见的空间复杂度举例&#x1f5ef;️常见复杂度对比&#x1f5ef;️&#x1f6a9;算法效率 算法是一个被设计好的&#xff0c;计…

python 读写txt方法

​​​​​​​ 1. Python支持在程序中读写 txt文件。这里有两种方式&#xff1a; 方式一&#xff1a;使用 python内置函数&#xff0c;该函数将一个字符串的长度转换为与这个字符串长度相关的值。 例如&#xff1a;" readme"&#xff08;"r&#xff09;。 prin…

数据结构---递归转化为非递归

递归转化为非递归前言快速排序非递归归并排序的非递归前言 为什么要学习非递归写法呢&#xff1f; 当我们在用递归实现一个程序的时候&#xff0c;要考虑一个问题&#xff0c;这个程序用递归去实现&#xff0c;当数据量庞大的时候&#xff0c;会不会造成栈溢出(STACK OVERFLOW…

学习风`宇blog的websocket模块

文章目录后端代码引入依赖WebSocketConfigWebSocketServiceImpl分析tb_chat_record表WebSocketServiceImplChatConfigurator聊天消息ChatTypeEnumsWebsocketMessageDTO后端 代码 引入依赖 仅需引入以下依赖 <!-- websocket依赖 --> <dependency><groupId>…