将rgbd数据集制作成rosbag,并发布图片和camera_info消息

2023-05-16

因为最近做的项目需要和别的开源项目做一些对比,比如rgbdslamV2,但是rdgbslamV2使用的输入是rosbag,并且他必须要订阅四个话题才能运行,这四个话题分别是:

/camera/rgb/image_color
/camera/depth/image
/camera/rgb/camera_info
/camera/depth/camera_info

分别表示深度和彩色图片消息,以及对应的相机参数消息。这个camera_info的话题上发布的消息的类型是:

sensor_msgs/CameraInfo

 

她的格式如下(主要包含了时间戳,以及相机内参K,矫正系数D等等):

 

 

下面的程序基于格式类似于TUM数据集格式(比如ICL-NUIM数据集)的数据集来实现的,也就是说,你需要有一个associations文件,这个文件里面记录了对应的一对对rgb和depth图像,他的格式如下:

1341846226.817920 rgb/1341846226.817920.png 1341846226.817948 depth/1341846226.817948.png
1341846226.850323 rgb/1341846226.850323.png 1341846226.850341 depth/1341846226.850341.png
1341846226.881894 rgb/1341846226.881894.png 1341846226.881917 depth/1341846226.881917.png
1341846226.917980 rgb/1341846226.917980.png 1341846226.918015 depth/1341846226.918015.png

每一行有四列,第一列对应着rgb图像的时间戳,第二列是rgb图像的相对路径,第三列是depth图像的时间戳,第四列是depth图像的相对路径。我在程序里面是通过这个文件来确定rgb和depth图像的对应关系,来一轮一轮地发送消息到话题上。

ros里面提供了一个包可以实现相关功能,我们首先安装一下,执行下面指令:

$ mkdir -p ~/image_transport_ws/src
$ cd ~/image_transport_ws/src
$ source /opt/ros/kinetic/setup.bash  #notice 看你安装的是什么版本的ros,我的是kinetic
$ catkin_create_pkg learning_image_transport image_transport cv_bridge #生成一个包
$ cd ~/image_transport_ws  #或者 cd ..
$ rosdep install --from-paths src -i -y --rosdistro kinetic #这里也需要改成自己的安装
$ catkin_make
$ source devel/setup.bash
$ git clone https://github.com/ros-perception/image_common.git
$ ln -s `pwd`/image_common/image_transport/tutorial/ ./src/image_transport_tutorial
$catkin_make #编译源文件

然后在/image_transport_ws 这个路径下的,运行:roscore
然后发布一个照片:
source devel/setup.bash
rosrun image_transport_tutorial my_publisher path/to/some/image.jpg
订阅这个
节点并显示照片:rosrun image_transport_tutorial my_subscriber

上面的指令会创建一个工作空间,然后这个工作空间里面的代码是通过软链接来链接到外面的clone的文件。而我们接下来要实现的功能就根据刚才运行的这个my_publisher的节点,修改my_publisher.cpp里面程序来实现的,具体是:发布rgbd图像的数据,以及对应的rgb和depth对应的camera_info消息。我们将my_publisher.cpp修改为如下:

 

#include <camera_info_manager/camera_info_manager.h>
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <iostream>
#include <vector>
#include <glob.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;

int parseInfoFile(
        std::string &strAssociation_Path,
        vector<pair<int,pair<string,string> > > &vec_info)//vec_info保存rgb和depth的路径信息
{
    char * line = NULL;
    size_t len = 0;
    ssize_t read;
    FILE *pFile = fopen(strAssociation_Path.c_str(), "r");
    if(!pFile) {
        return -1;
    }
    while ((read = getline(&line, &len, pFile)) != -1) {

        std::istringstream is(line);//istringstream对象可以绑定一行字符串,然后以空格为分隔符把该行分隔开来。
        std::string part;//保存以空格分开的每一部分
        int iIdxToken = 0;
        while (getline(is, part))
        {
            if('#' == part[0])/// Skip file comment '#"
            {
                continue;
            }

            int timeSeq = 0;
            std::string strDepthPath;
            std::string strRgbPath;

            std::istringstream iss(part);
            std::string token;

            while (getline(iss, token, ' '))
            {
                if(2 == iIdxToken) //Time rgb
                {//first token which is time
                    //什么都不干
                }
                else if(1 == iIdxToken)//rgb path,fr1,fr2和fr3的第2列和第四列相反,可能需要修改这里iIdxToken为3
                {
                    strRgbPath = token;
                    // std::cout<<strRgbPath<<endl;
                }
                else if(0 == iIdxToken)//Time depth
                {
                    timeSeq=atoi(token.c_str());
                }
                else if(3 == iIdxToken)//depth path fr1,fr2和fr3的第2列和第四列相反,可能需要修改这里iIdxToken为1
                {
                    strDepthPath = token;
                    // std::cout<<strDepthPath<<endl;
                }
                iIdxToken++;
            }

            vec_info.push_back(make_pair(timeSeq,make_pair(strRgbPath,strDepthPath)));
        }
    }
    fclose(pFile);
    return 0;
}

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

    if(argc !=2)
    {
        cerr << endl << "path_to_depth_error"<< endl;
        return 1;
    }
    char new_name[20];
    string basedir=string(argv[1])+'/';
    string input_associatiations=basedir+"/associations.txt";
    vector<pair<int,pair<string,string> > > picInfo;
    if(parseInfoFile(input_associatiations,picInfo))
        cerr<<" Can‘t read file! "<<endl;
    cout<<"There is "<<picInfo.size()<<" picture pair in all!!"<<endl;

    ros::init(argc, argv, "image_publisher");
    ros::NodeHandle nh;

    image_transport::ImageTransport it(nh);
    //分别将深度图和彩色图发送到两个不同的话题上,准备被录制
    image_transport::Publisher pubrgb = it.advertise("/camera/rgb/image_color", 30);
    image_transport::Publisher pubdepth = it.advertise("/camera/depth/image", 30);
    //分别将rgb和深度图对应的info信息发送到不同的话题上
    ros::Publisher pub_rgb_info = nh.advertise<sensor_msgs::CameraInfo>("/camera/rgb/camera_info", 30);
    ros::Publisher pub_depth_info = nh.advertise<sensor_msgs::CameraInfo>("/camera/depth/camera_info", 30);
    const string camurl = "file:///home/wei/Documents/project/tools/image_transport/calib.yaml";//保存图像参数的yaml文件的位置
    camera_info_manager::CameraInfoManager caminfo(nh, "rgb", camurl);

    sensor_msgs::CameraInfo ci;


    //the argv is the url of the image,may we can use that for all images
    ros::Rate loop_rate(16);
    std::cout<<"Progress: "<<endl;
    for(unsigned int i = 0; i < picInfo.size(); ++i)//开始处理每个图片
    {
        if(!nh.ok())
            break;

        cv::Mat rgb,depth;
       // int timestamp=picInfo[i].first;
        string rgbpath=picInfo[i].second.second;
        rgbpath=basedir+rgbpath;
        string depthpath=picInfo[i].second.first;
        depthpath=basedir+depthpath;


        rgb = cv::imread(rgbpath,-1);
        depth=cv::imread(depthpath,-1);
        //cv::imshow("have a look",depth);
        //cv::waitKey(1);
        if(rgb.empty()||depth.empty())
        {
            cerr << endl << "Failed to load image at: "
                 << rgbpath << "   or   "<< depthpath<< endl;
            return 1;
        }

        std::cout << '\r'
                  << std::setw(4) << std::setfill('0') << i << " / "
                  << std::setw(4) << std::setfill('0') << picInfo.size()
                  << std::flush;


        sensor_msgs::ImagePtr rgbmsg = cv_bridge::CvImage(std_msgs::Header(), "rgb8", rgb).toImageMsg();
        ros::Time begin = ros::Time::now();
        rgbmsg->header.stamp = begin;//这里的时间戳换成你自己的,需要自己再写一个读取时间戳的函数,注意和image进行对应.一般时间戳文件也包含在图片的文件夹中.
        pubrgb.publish(rgbmsg);//发布rgb图像

        sensor_msgs::ImagePtr depthmsg = cv_bridge::CvImage(std_msgs::Header(), "mono16", depth).toImageMsg();
        depthmsg->header.stamp=begin;
        pubdepth.publish(depthmsg);//发布深度图像

        ci=caminfo.getCameraInfo();
        ci.header.frame_id = "/openni_rgb_optical_frame";
        ci.header.stamp=begin;
        pub_rgb_info.publish(ci);//发布rgbinfo

        ci.header.frame_id = "/openni_depth_optical_frame";
        pub_depth_info.publish(ci);//发布深度depth

        ros::spinOnce();
        loop_rate.sleep();
    }
}

简单来说上面的代码分为以下几步:

  1. 指定需要发布的信息的话题,并创建一个ros::Publisher用于发布相机info消息
  2. 创建一个camera_info_manager::CameraInfoManager类型的caminfo对象,并用他从指定的url里面(其实就是保存这上面的相机数据的url)读取相机的info
  3. 再创建一个消息:sensor_msgs::CameraInfo,这个消息在一个循环里面不断更新,首先读取caminfo.getCameraInfo();,然后更新info消息的时间戳等消息
  4. 最后发布即可

 

另外,修改CMakeLists.txt,将第4行和第12行修改为:

find_package(catkin REQUIRED COMPONENTS cv_bridge image_transport camera_info_manager message_generation sensor_msgs)
catkin_package(CATKIN_DEPENDS cv_bridge image_transport camera_info_manager message_runtime sensor_msgs)

实际上就是添加了一个camera_info_manager包。然后把整个工作空间重新catkin_make一下,然后执行:

rosrun image_transport_tutorial my_publisher  /path/to/your/dataset

在执行rostopic list,就可以查看到很多的话题正在发布,包括我开头提到的需要的四个话题,然后我们对需要的话题开始进行录制:

rosbag record -O /path/to/save/ros.bag /camera/rgb/image_color /camera/depth/image /camera/rgb/camera_info /camera/depth/camera_info

遇到的问题

  • 第一个问题是自己如何创建这个camera_info话题上的sensor_msgs/CameraInfo消息,网上的教程非常少,找了好久才找到一个:

    https://answers.ros.org/question/211240/publishing-camera_info-messages/

这里并没有在代码里面直接设置相机的相关参数,比如之前图片里面展示的K,P,D,R(没找到直接设置的代码案例),这里采用的方法是写一个yaml文件,从yaml文件里面读取相关参数,但是这个yaml文件如何写?找了好久网上根本没人给出这个yaml文件的内容,感觉应该就是通过ros的标定程序获得的参数文件,这里直接给出这个yaml文件的内容,大家把里面的参数修改一下换成呢个自己的就可以了,不用重新标定了。(你看,帮你省了多大力,还不快给我点个赞!!!)

image_width: 640
image_height: 480
camera_name: rgb
camera_matrix:
  rows: 3
  cols: 3
  data: [481.2, 0.0, 319.5, 0.0, -480.0,239.5, 0.0, 0.0, 1.0]
distortion_model: plumb_bob
distortion_coefficients:
  rows: 1
  cols: 5
  data: [0.0, 0.0, 0.0, 0.0, 0.0]
rectification_matrix:
  rows: 3
  cols: 3
  data: [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000]
projection_matrix:
  rows: 3
  cols: 4
  data: [481.2, 0.0,  319.5, 0.0, 0.0,-480.0, 239.5, 0.0, 0.0, 0.0, 1.0, 0.0]
  • 程序写完之后,在rviz里面读取指定的话题上的图片数据之后,rviz读取不出来,显示下面的错误:
[ WARN] [1607503757.824458468]: OGRE EXCEPTION(2:InvalidParametersException): Stream size does not match calculated image size in Image::loadRawData at /build/ogre-1.9-mqY1wq/ogre-1.9-1.9.0+dfsg1/OgreMain/src/OgreImage.cpp (line 283)
[ERROR] [1607503757.824565432]: Error loading image: OGRE EXCEPTION(2:InvalidParametersException): Stream size does not match calculated image size in Image::loadRawData at /build/ogre-1.9-mqY1wq/ogre-1.9-1.9.0+dfsg1/OgreMain/src/OgreImage.cpp (line 283)

原因是因为将opencv图像转化为rosmsg的时候,设定的编码方式出了问题,如下:

sensor_msgs::ImagePtr rgbmsg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", rgb).toImageMsg();

比如你rgb里面放的如果不是rgb图像,而是灰度图,那么就会出现上面的 问题。这个编码方式有以下几种:

mono8: CV_8UC1, grayscale image

mono16:CV_16UC1, 16-bit grayscale image

bgr8: CV_8UC3, color image with blue-green-red color order

rgb8: CV_8UC3, color image with red-green-blue color order

bgra8: CV_8UC4, BGR color image with an alpha channel

rgba8: CV_8UC4, RGB color image with an alpha channel

如果这个不行就换个试试,比如同样是灰度图,我使用mono8就会报错,使用mono16就可以。这可能因为原本的灰度图就是CV_16UC1格式的。

  • 遇到错误
ERROR:Tried to advertise a service that is already advertised in this node

原因就是发送消息的话题名字重复了,或者是在while(ros::ok())将advertise包含进去了,这样就会导致重复地向主节点注册主题,故报错。据wiki上解释,有时候自己编写的节点可能与系统本身所有的节点发送的主题起冲突,此时只需修改你自己的主题名即可。


以上就是这个小小的脚本编写过程中遇到的问题,虽然是个很小的程序,但是还是费了不少力气搜索资料的,我想这个程序应该有不少人也需要,因此在这里和大家分享一下。别忘了点个赞哟!!!!!

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将rgbd数据集制作成rosbag,并发布图片和camera_info消息 的相关文章

  • 通过VScode进行git的版本管理

    前言 xff1a 作为测试 xff0c 我们写的自动化脚本和产品手册也是需要使用git进行版本管理起来的 xff0c 本次我们介绍怎么通过git进行版本管理 目录 xff08 一 xff09 搭建本地仓库 xff08 二 xff09 将服务
  • 教你使用stm32接收串口的一帧数据!

    stm32支持接受单个数据或者一帧数据 xff0c 若配置单个数据接收中断的话 xff0c 会出现接收包丢包 xff0c 数据不完整的情况 xff01 因此在stm32的串口中断中 xff0c 还有一个IDLE中断 xff0c 用来产生串口
  • APM-3.5.2-EKF2笔记(未完待续)

    20180704 xff1a 一 EKF2 InitialiseFilter 全过程 1 记录开始时间 xff0c 预期步长时间 frameTimeUsec 61 2500 xff0c 每次融合读取IMU次数 framesPerPredic
  • 在K8s上部署Go服务

    目标 镜像名 xff1a foxliang go v 镜像内容 xff1a 二进制文件 xff0c 跑起来是个http服务 xff0c 监听8080端口 xff0c 接到请求会打印 This is version v running in
  • Java中可以直接调用类中静态方法,不用实例化

    先说结论 xff1a 可以不实例化一个类的情况 xff0c 使用一个类中的静态方法静态方法里 xff0c 只能调用静态方法 先通俗的分析下 xff0c 我们把类看作是一个房子 房子里面有家具 xff0c 桌椅板凳之类的 xff0c 房子里面
  • 【Linux】深入理解线程(线程同步、互斥量mutex、死锁、读写锁、条件变量、信号量)

    一 同步概念 1 线程同步 xff1a 同步即协同步调 xff0c 按预定的先后次序运行 线程同步 xff0c 只一个线程发出某一功能调用时 xff0c 在没有得到结果之前 xff0c 该调用不返回 同时 xff0c 其他线程为保证数据一致
  • pytorch得到模型的计算量和参数量

    文章目录 方法1 自带方法2 编写代码方法3 thop方法4 torchstat方法5 ptflops方法6 torchsummary 方法1 自带 pytorch自带方法 xff0c 计算模型参数总量 total span class t
  • slam、高精地图、定位之间的关系

    高精度地图一般都是指slam 43 卫惯共同制作的区域地图 xff0c 只有卫惯只能得到位置信息 xff0c 没办法得到地物信息 卫惯给绝对位置 xff0c slam给地物 地形信息和相对距离 xff0c 然后融合制作等 2 使用激光雷达或
  • 慕课《如何写好科研论文》期末考试题及答案

    多选 论文写作前的积累包括哪些 实验细节 Idea 专业知识 讲座学术论文质量标准包括 形式标准 内容标准和学术期刊打交道的最大好处是 编辑部聘请的审稿人的专业意见 编辑部提出的技术方面的建议什么情况下 xff0c 应果断放弃一些题目 已经
  • docker学习笔记(七)docker-swarm

    目录 搭建Swarm环境 swarm基本操作 swarm实战 docker swarm服务发布模式 docker stack 官网 https docs docker com swarm overview Docker Swarm is n
  • 【前端】ajax 接口返回图片文件流,将图片保存至自己服务器,并展示该图片

    一 解决前 1 1 问题描述 ajax 调用第三方接口 xff0c 接口没有返回图片链接 xff0c 直接返回的图片 现在要将文件保存至服务器 xff0c 并返回自身的链接 span class token comment 解决前的代码 s
  • http请求带用户名和密码验证

    发送http请求往往需要带用户名和密码 xff0c 服务端进行授权验证 实现方式是将将用户名和密码放到请求头里面 xff0c 采用Basic Authentication Scheme xff0c 译为基本授权方案 xff0c 想要了解的可
  • 【TPM2.0原理及应用指南】 1-3章

    码字不易 xff0c 求求点个赞呗 第一章 TPM的历史 可信平台模块 xff08 TPM xff09 是一种加密协处理器 可信计算组织 xff08 TCG xff09 直接匿名认证 DAA 认证可迁移密钥 xff08 Certified
  • QGC通过网络连接飞控(树莓派+ROS桥接MavLink)

    1 为树莓派刷ubuntu 因为无界面的ubuntu在连接无线 设置自动登录等方面的设置比较复杂 我经过各种百度尝试后 均没有成功 所以我放弃了 转而又刷了ubuntu mate 带界面 然后连接了无线 设置了自动登录 静态IP 自此树莓派
  • 大厂大数据岗位面试随笔

    大厂面试简要记录 1 腾讯2 阿里 1 腾讯 腾讯PCG事业部 大数据开发岗 问题回忆 xff1a spark数据分发机制Hadoop集群高可用机制阐述Spark Streaming给个具体视频应用场景阐述开发思路及任务架构 xff08 期
  • 南京邮电大学C++实验三(多态性实验)

    文章目录 一 实验目的和要求二 实验环境 实验设备 三 实验原理及内容 xff08 一 xff09 实验题目1 xff1a 1 题目2 代码3 程序运行结果 4 实验解答过程 xff1a 1 类Point的构造函数 xff1a 2 用成员函
  • ROS package.xml教程

    文章目录 总览标准格式2 xff08 推荐格式 xff09 基本结构必要标签依赖元包其他标签 标准格式1 xff08 遗留格式 xff09 总览 ROS的package包使用package xml文件来描述 xff0c 该描述文件必须放置在
  • 如何从论文中实现算法复现(译)

    原文地址 xff1a http xff1a codecapsule com 2012 01 18 how to implement a paper 作者 xff1a Emmanuel Goossaert 翻译 xff1a Joseph Ar
  • CMakeList.txt

    一个视频讲解 http v youku com v show id XMjc1MjE0MjEwNA 61 61 html cmake 语法设置路径 xff0c 配置库 xff0c 编译器标记 xff1a https www cnblogs
  • GPS ROS包

    NMEA GPS数据读取 span class hljs label http span wiki span class hljs preprocessor ros span span class hljs preprocessor org

随机推荐

  • Arduino Atmega328P烧写bootloader及熔丝

    Arduino Atmega328P烧写bootloader及熔丝 Cc1924的博客 CSDN博客 亲测成功
  • 云服务器 搭建 AWTRIX 服务器

    Java 环境 首先检查 java 版本 如果没有 安装 openjdk 后再执行 sh脚本 yum list java 1 8 yum install java 1 8 0 openjdk y wget N https blueforce
  • esp8266对接天猫精灵(1)前言

    本系列文章小狂决定一步步来完成其他智能设备与天猫精灵的对接 xff0c 简单粗暴的目的就是使用ESP8266或者其他的wifi设备制造一个智能设备 xff0c 完成一次天猫精灵智能音箱对我们自己制造的智能设备的控制 xff0c 以来验证天猫
  • 牢记公式,ardupilot EKF2就是纸老虎(二)!

    版权声明 xff1a 本文为博主原创文章 xff0c 转载请附上博文链接 xff01 二 扩展卡尔曼滤波器 因为卡尔曼滤波器针对的是线性系统 xff0c 状态转移模型 xff08 说的白话一点就是知道上一时刻被估计量的值 xff0c 通过状
  • esp8266对接天猫精灵(3)原理

    这一篇文章主要讲解服务器端的设置 xff0c 这里我使用的是腾讯云 xff0c 当时学生价1块钱一个月买的 xff0c 现在的学生价涨到了10块 xff0c 为我当时的机智点赞 为什么一定要使用服务器呢 xff0c 这个是因为天猫精灵协议的
  • esp8266对接天猫精灵(8)开发者网关地址

    洋洋洒洒六七千字已经搭进去了 xff0c 终于把服务器篇写的差不多了 xff0c 当然小狂不是专业的写手 xff0c 有些东西写的凑合看吧 xff0c 只是说明过程 xff0c 并不修饰言辞 xff0c 看的舒服就点个赞 xff0c 不舒服
  • esp8266对接天猫精灵(10)nodumcu固件编译

    一 下载编译器 进入这个网站 xff0c https esp8266 ru esplorer xff0c 找到这个地方 xff0c 可以直接下载 xff0c 下载完成后双击红框中的内容就能打开 打开后的截图如下图所示 xff0c 左边为代码
  • esp8266对接天猫精灵(11)终端编程

    一 编写lua脚本获取控制信息 xff08 8266 xff09 前边也说过 xff0c 这个脚本要实现的步骤可以分三步 xff0c 第一步是联网 xff0c 第二步是使用http get到数据 xff0c 然后控制要控制的设备 我们的lu
  • Altium Designer -- 精心总结

    如需转载请注明出处 xff1a http blog csdn net qq 29350001 article details 52199356 以前是使用DXP2004来画图的 xff0c 后来转行 想来已经有一年半的时间没有画过了 突然转
  • Arduino点亮ws2812

    先加载ws2812库文件 span style color rgb 68 68 68 font family none font size 14px background color rgb 255 255 255 a target bla
  • Arduino 旋转编码器ky-040

    int pinA 61 3 Connected to CLK on KY 040 CLK接 pin3 int pinB 61 4 Connected to DT on KY 040 DT接pin4 SW是按键 xff0c 不用接 int e
  • Dockerfile

    Dockerfile文件 xff0c 自创镜像 一 概念 xff1a 二 案例 xff1a 1 先创建一个Dockerfile文件2 编写内容3 构建镜像4 运行 三 指令 xff1a FROM xff1a MAINTAINER xff1a
  • 关于嵌入式无人机之模型创建-使用3D打印装配体01

    做嵌入式的同学离不开硬件的支撑 那么无人机作为一套综合性工程 span class token punctuation span 涉及软件 span class token punctuation span 嵌入式 span class t
  • 牢记公式,ardupilot EKF2就是纸老虎(三)!

    版权声明 xff1a 本文为博主原创文章 xff0c 转载请附上博文链接 xff01 三 掀开EKF2的神秘面纱 EKF2是EKF算法在ardupilot上的代码实现 读到这里你也许已经忘了 xff0c EKF的5大公式 虽然下面是7个公式
  • ROS节点 报错process has died [pid 3322522, exit code -11

    偶尔出现 我的情况是两个节点 ros span class token double colon punctuation span span class token function init span span class token p
  • JS的冒泡函数

    今天下午学习了冒泡函数的加载和运行 一 var a 61 20 30 40 20 15 5 25 for var i 61 0 i lt a length i 43 43 for var j 61 1 j lt a length j 43
  • ubuntu server 版安装桌面

    安装xfce4 xff08 或其他桌面 xff09 amp xinit sudo apt install xfce4 xinit安装Display Manager 安装xdm xff0c 虽然有着古早的界面 xff0c 但是不会安装任何依赖
  • ubuntu下gazebo加载很慢解决办法

    ubuntu下gazebo加载很慢解决办法 前言 刚安装好 r o s ros r o s 后 xff0c 在终端输入命令 gazebo 启动 g
  • 从用户态是怎么切换到核心态的?

    此文章参考了 Linux 用户态通过中断切换到内核态详解 简答来说 xff0c 用户态和核心态的区别就是 xff1a 两者的操作权限不同 xff0c 用户态的进程能够访问的资源受到了极大的控制 xff0c 而运行在内核态的进程可以 为所欲为
  • 将rgbd数据集制作成rosbag,并发布图片和camera_info消息

    因为最近做的项目需要和别的开源项目做一些对比 xff0c 比如rgbdslamV2 xff0c 但是rdgbslamV2使用的输入是rosbag xff0c 并且他必须要订阅四个话题才能运行 xff0c 这四个话题分别是 xff1a cam