ROS面试题汇总

2023-05-16

1、ROS中订阅(Subscribe)最新消息以及消息队列相关问题

        机器人应用中难免会遇到运算起来很费时间的操作,比如图像的特征提取、点云的匹配等等。有时候,不可避免地,我们需要在ROS的Subscriber的Callback回调函数中进行这些费时的操作。Subscriber所订阅的消息的发布频率可能是很高的,而这些操作的运算速度肯定达不到消息发布的速度。所以,如果我们要是没有取舍的对于每个消息都调用一次回调函数,那么势必会导致计算越来越不实时,很有可能当下在处理的还是几十秒以前的数据。所以,我们希望每次回调函数都处理当前时刻最新的一个消息,这就是我们的目标。

        要达到这个目标有三点,第一点是要设置Publisher的queue_size等于1;第二点是要设置Subscriber的queue_size(消息队列大小)等于1;第三点非常重要,要设置Subscriber的buff_size(缓冲区大小)足够大,大于一个消息的大小。像这样:

# ROS Python
pcdpub = rospy.Publisher("lidardata", PointCloud, queue_size=1)
rospy.Subscriber("lidardata", PointCloud, self.pcd_resolve_callback,queue_size=1,buff_size=52428800)

1.1 Subscriber和Publisher的消息队列起什么作用,队列的大小有什么影响? 

        简单描述一下,Publisher的消息队列是为了缓存发布节点发布的消息,一旦队列中消息的数量超过了queue_size,那么最先进入队列的(最老的)消息被舍弃。Subscriber的消息队列是为了缓存节点接收到的信息,一旦自己处理的速度过慢,接收到的消息数量超过了queue_size,那么最先进入队列的(最老的)消息会被舍弃。所以,我们想只处理最新的消息,实际上只需要把两个queue_size都设置成1,那么系统不会缓存数据,自然处理的就是最新的消息。

1.2 Subscriber有消息队列缓存消息了,为什么Publisher还要有消息队列?

        在我看来,Publisher的消息队列是一定要有的,因为ROS中发布节点往外发送消息是基于Topic发送,而不是直接向Subscriber订阅者发送,所以必须要有一个消息队列来存放发布的消息,以供订阅者来获取。而且这个消息队列的好处是在网络差、带宽小、延时高的时候,保证数据不容易丢失。
 

1.3 既然Publisher有消息队列了,为什么Subscriber还要有消息队列?

        这个问题比较难一点。我的理解是,由于ROS毕竟是分布式系统,Publisher和Subscriber不一定在同一台主机上,因此消息需要通过网络来交换。但是网络的性能时好时坏,如果Subscriber没有消息队列,那么每次运行Callback函数前都要先通过网络取回消息,然后才能处理。当网络很差时,就会让系统堵塞。而有消息队列的话,Subscriber就可以一边处理队列中的消息,一边通过网络缓存新的消息,而不用每次处理消息前都要临时去读一个回来。这样就增加了系统的可靠性。

1.4 为什么要设置缓冲区的大小?

        这个缓冲区的大小是指消息队列使用的缓冲区物理内存空间大小。如果这个空间小于一个消息所需要的空间,比如消息是一副图片或者一帧点云,数据量超过了缓冲区的大小。这个时候为了保证通信不发生错误,就会触发网络通信的保护机制,TCP的Buffer会为你缓存消息。这种机制就会导致每一帧消息都被完整的缓存下来,没有消息被丢弃,感觉上就像queue_size被设置成了无穷大。详细说明请参考:
Ros subscriber not up to date
rospy subscriber queue_size acting strange when buff_size is too small

1.5 消息队列的运行机制

  • 这里只能说是我的理解了,因为没有看过源代码。
  • 首先,发布节点把消息发布,消息进入Publisher的消息队列,同时通知订阅了该话题消息的Subscriber来取消息。
  • 其次,Subscriber来Publisher的消息队列里取消息,但取走的也是最老的消息,因为毕竟这是先入先出的队列。这也是为什么Publisher的消息队列的大小也要设置为1。
  • 最后,被取走的消息存放入了Subscriber的消息队列中,等待被Callback执行。如果Callback执行很慢,消息越堆越多,最老的消息会逐渐被顶替。
  • 当然,这里究竟是Subscriber来取消息,还是Publisher直接把消息推给Subscriber,我只是猜测,反正这里交换的消息肯定不是最新的消息,而是队列里最老的消息。

2、launch文件的写法

<launch>

    <!-- 启动mbot -->
    <node name="robot_bringup" pkg="robot_bringup" type="robot_bringup" output="screen" />

    <!-- 加载机器人模型参数 -->
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find robot_description)/xacro/robot_with_laser.xacro'" />

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态 -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
    <!-- 运行robot_state_publisher节点,发布tf -->
    <node name="state_publisher" pkg="robot_state_publisher" type="robot_state_publisher">
        <param name="publish_frequency" type="double" value="50.0" />
    </node>

    <!-- 运行激光雷达驱动 -->
    <include file="$(find robot_bringup)/launch/rplidar.launch" />

</launch>

3、ros::spin()和ros::spinonce()的区别

        以ros消息发布器和订阅器的教程: http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber(c++)为例。

        

        消息发布器(ros::Publisher)在一个while循环里一直循环发布消息(“hello world”)到话题(“chatter”)上。

        消息订阅器(ros::Subscriber)一直监视话题,一旦知道话题上有数据,就会将该话题上的数据(message)作为参数传入到对应的回调函数(callback)中,但是这时候回调函数还没有被执行,而是把callback函数放到了回调函数队列中。所以当消息发布器不断发送message到该话题上时,就会有相应的callback函数存入队列中,它们函数名一样,只是实参内容不一样。(其实,是将传入的message存入到队列中,这里说是将callback函数存入到队列中,应该是为了便于理解)。

        那什么时候会执行callback函数呢?那就是ros::spin()和ros::spinOnce()的事情了。

        当spinOnce()函数被调用时,spinOnce()会调用回调函数队列中第一个callback函数,此时callback函数才被执行,然后等到下次spinOnce函数又被调用时,回调函数队列中第二个callback函数就会被调用,以此类推。

        所以,这会有一个问题。因为回调函数队列的长度是有限的,如果发布器发送数据的速度太快,spinOnce函数调用的频率太少,就会导致队列溢出,一些callback函数就会被挤掉,导致没被执行到。

        而对于spin函数,一旦进入spin函数,它就不会返回了,相当于它在自己的函数里面死循环了。只要回调函数队列里面有callback函数在,它就会马上去执行callback函数。如果没有的话,它就会阻塞,不会占用CPU。

3.1 spin()和spinOnce()函数意义

        首先要知道,这俩兄弟学名叫ROS消息回调处理函数。它俩通常会出现在ROS的主循环中,程序需要不断调用ros::spin() 或ros::spinOnce(),两者区别在于前者调用后不会再返回,也就是你的主程序到这儿就不往下执行了,而后者在调用后还可以继续执行之后的程序。

如果你的程序写了相关的消息订阅函数,那么程序在执行过程中,除了主程序以外,ROS还会自动在后台按照你规定的格式,接受订阅的消息,但是所接到的消息并不是立刻就被处理,而是必须要等到ros::spin()或ros::spinOnce()执行的时候才被调用,这就是消息回调函数的原理。

3.2 spin()和spinOnce()的区别

        就像上面说的,ros::spin() 在调用后不会再返回,也就是你的主程序到这儿就不往下执行了,而 ros::spinOnce() 后者在调用后还可以继续执行之后的程序。

        其实看函数名也能理解个差不多,一个是一直调用;另一个是只调用一次,如果还想再调用,就需要加上循环了。

这里一定要记住,

  • ros::spin()函数一般不会出现在循环中,因为程序执行到spin()后就不调用其他语句了,也就是说该循环没有任何意义。
  • spin()函数后面一定不能有其他语句(return 0 除外),有也是白搭,不会执行的。
  • ros::spinOnce()的用法相对来说很灵活,但往往需要考虑调用消息的时机,调用频率,以及消息池的大小,这些都要根据现实情况协调好,不然会造成数据丢包或者延迟的错误。

3.3 spin()和spinOnce()常见使用方法

        如果你的程序写了相关的消息订阅函数,那千万千万千万不要忘了在相应位置加上ros::spin()或者ros::spinOnce()函数,不然你是永远都得不到另一边发出的数据或消息的。

3.3.1 ros::spin()        

        ros::spin()函数用起来比较简单,一般都在主程序的最后,加入该语句就可。例子如下:

// 发送端
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
 
int main(int argc, char **argv)
{
    ros::init(argc, argv, "talker");
    ros::NodeHandle n;
    ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
    ros::Rate loop_rate(10);
 
    int count = 0;
    while (ros::ok())
    {
        std_msgs::String msg;
        std::stringstream ss;
        ss << "hello world " << count;
        msg.data = ss.str();
        ROS_INFO("%s", msg.data.c_str());
 
        /**
         * 向 Topic: chatter 发送消息, 发送频率为10Hz(1秒发10次);消息池最大容量1000。
         */
        chatter_pub.publish(msg);
 
        loop_rate.sleep();
        ++count;
    }
    return 0;
}

接收端代码中用到spin()函数:

// 接收端
#include "ros/ros.h"
#include "std_msgs/String.h"
 
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
    ROS_INFO("I heard: [%s]", msg->data.c_str());
}
 
int main(int argc, char **argv)
{
    ros::init(argc, argv, "listener");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
 
    /**
     * ros::spin() 将会进入循环, 一直调用回调函数chatterCallback(),每次调用1000个数据。
     * 当用户输入Ctrl+C或者ROS主进程关闭时退出,
     */
    ros::spin();
    return 0;
}

3.3.2 ros::spinOnce()

        对于ros::spinOnce()的使用,虽说比ros::spin()更自由,可以出现在程序的各个部位,但是需要注意的因素也更多。比如:

        1. 对于有些传输特别快的消息,尤其需要注意合理控制消息池大小和ros::spinOnce()执行频率; 比如消息送达频率为10Hz, ros::spinOnce()的调用频率为5Hz,那么消息池的大小就一定要大于2,才能保证数据不丢失,无延迟。

// 接收端

#include "ros/ros.h"
#include "std_msgs/String.h"
  
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
    /*...TODO...*/ 
}
  
int main(int argc, char **argv)
{
    ros::init(argc, argv, "listener");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("chatter", 2, chatterCallback);
  
    ros::Rate loop_rate(5);
    while (ros::ok())
    {
        /*...TODO...*/ 
 
        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

        2. ros::spinOnce()用法很灵活,也很广泛,具体情况需要具体分析。但是对于用户自定义的周期性的函数,最好和ros::spinOnce并列执行,不太建议放在回调函数中;

/*...TODO...*/
ros::Rate loop_rate(100);
  
while (ros::ok())
{
    /*...TODO...*/
    user_handle_events_timeout(...);
 
    ros::spinOnce();                 
    loop_rate.sleep();
}

4、ros命名空间NodeHandle相关问题

4.1 NodeHandle的定义    

        NodeHandles节点类,ros::NodeHandle类有两个作用:

  • 首先,在roscpp程序的内部,它提供了RAII方式启动和关闭。
  • 其次,它提供了一个额外的层命令空间解决方案,可以使组件更容易写。

4.2 NodeHandle的自动启动节点和关闭节点

        自动启动和关闭

  • ros::NodeHandle管理内部的引用计数
  • 开始节点:

ros::NodeHandle nh;
  • 创建时候,如果内部节点没有开始,ros::NodeHandle会开始节点,ros::NodeHandle实例销毁,节点就会关闭。

4.3 NodeHandle的命名空间

1、句柄可以让你通过构造函数指定命名空间

  • 查阅ROS命名空间文档
  • NodeHandle可以指定命名空间给构造器:
ros::NodeHandle nh("my_namespace");
  • 这使得使用该句柄的任何相对名字都是相对<node_namespace>/my_namespace,而不只是相对<node_namespace>。
  • 也可以指定父NodeHandle和命名空间:
ros::NodeHandle nh1("ns1");
ros::NodeHandle nh2(nh1, "ns2");
  • 这个放nh2 进入<node_namespace>/ns1/ns2 命名空间。

2、也可以指定全局名字

ros::NodeHandle nh("/my_global_namespace");

这种做法并不推荐,因为这样会使得节点无法被放入别的命名空间。只是有时在代码中使用全局名字有用。

  • 你可以指定全局名,如:
ros::NodeHandle nh("/my_global_namespace");
  • 这通常不鼓励,因为它阻止了节点被推为命名空间(如roslaunch)。然而,有时在代码中使用全局名称可能是有用的。

3、私有名字

        使用私有名字比直接调用有私有名的句柄方法更有技巧,你可以在一个私有命名空间中直接创建一个新的句柄。

ros::NodeHandle nh("~my_private_namespace"); ros::Subscriber sub = nh.subscribe("my_private_topic",....);

以上例子会订阅<node_name>/my_private_namespace/my_private_topic === (node_namespace/nodename/my_private_namespace/my_private_topic)

注意:理解的重点上文中红色标注的部分,node_namespacenode_name是两回事!

node_name = node_namespace + node name

// launch 文件中 ns=="node_namespace" 
ros::init(argc, argv, "node_name"); // node name 

ros::NodeHandle n; //n 命名空间为/node_namespace 


ros::NodeHandle n1("sub"); // n1命名空间为/node_namespace/sub 
ros::NodeHandle n2(n1,"sub2");// n2命名空间为/node_namespace/sub/sub2 


ros::NodeHandle pn1("~"); //pn1 命名空间为/node_namespace/node_name 
ros::NodeHandle pn2("~sub"); //pn2 命名空间为/node_namespace/node_name/sub 
ros::NodeHandle pn3("~/sub"); //pn3 命名空间为/node_namespace/node_name/sub 
ros::NodeHandle gn("/global"); // gn 命名空间为/global

综上,只要不是明确指定,就会用节点名node_name来指定命名空间。

5、ros1通信模型

  • talker注册
  • listener注册
  • ROS Master进行信息匹配
  • listener 发送链接请求
  • talker确认请求
  • 建立连接
  • talker给listener发数据

在这里插入图片描述

6、ROS基础

 
6.1 ROS的总体设计目标

 

6.2 ROS的应用框架是怎样的? 

        

总结:ROS就是一个为了提高机器人开发的软件复用率,开发的一款具有独特的通信机制、丰富的开发工具、海量的应用功能、良好的生态系统集的工具。

        

6.3 如何新建一个工作空间?

        最基础的功能包都不会写,怎么意思说学过ROS:

cd ~/catkin_test_ws/src                                        #进入存放功能包的地方
catkin_create_pkg test_package std_msgs roscpp rospy           #创建名字为test_package的功能包,添加std_msgs roscpp rospy依赖
cd ~/catkin_test_ws                                            
catkin_make                                                    #编译
source devel/setup.bash              						   #新建功能包刷新环境变量,才能找到功能包
rospack profile                                                #如果还是找不到功能包,使用该命令刷新功能包路径

        需要注意一点,同一个工作空间下不能存在同名功能包,不同的工作空间下可以存在同名功能包。但是要注意一个问题,ROS运行时会优先选择最前端工作空间的同名功能包。为了避免出现想不到的问题,所有工作空间尽量不使用同名功能包。

        功能包的名称尽量按照a_b_c的格式书写,否则,编译过程将会出现警告。

6.4 如何新建一个功能包?

        这也是需要每个人都要会的,连个最基础的功能包都不会写,怎么好意思说学过ROS?

cd ~/catkin_test_ws/src                                        #进入存放功能包的地方
catkin_create_pkg test_package std_msgs roscpp rospy           #创建名字为test_package的功能包,添加std_msgs roscpp rospy依赖
cd ~/catkin_test_ws                                            
catkin_make                                                    #编译
source devel/setup.bash              						   #新建功能包刷新环境变量,才能找到功能包
rospack profile                                                #如果还是找不到功能包,使用该命令刷新功能包路径

        这里需要注意一点,同一个工作空间下不能存在同名功能包,不同的工作空间下可以存在同名功能包。但是要注意一个问题,ROS运行时会优先选择最前端工作空间的同名功能包。为了避免出现意想不到的问题,所以工作空间尽量不使用同名功能包。

        功能包的名称尽量按照a_b_c的格式书写,否则,编译过程将会出现警告。

6.5 如何新建一个ROS节点?

        接着上面的测试功能包,我们在功能包的src文件下新建test.cpp文件:

cd ~/catkin_test_ws/src/test_package/src/
vim test.cpp

然后就是ROS节点的模板程序,都是在模板程序之上做的修改。

#include "ros/ros.h"                    //引入ROS头文件

int main(int argc,char **argv)
{
	ros::init(argc,argv,"test");        //初始化ROS节点
	
	ros::NodeHandle nh;                 //创建ROS句柄

	ros::Rate loop_rate(10);            //定义循环频率 10HZ

	while(ros::ok())
	{
		std::cout<< "hello ros" <<std::endl;
		loop_rate.sleep();             //按照循环速率延时
	}
	return 0;
}

        到这里,然后编译就可以了?这个功能包的编译还需要修改对应的CMakeLIsts.txt文件,一般为三步。

        设置需要编译的代码和生成的可执行文件;

        设置链接库;

        设置依赖;

        所以我们修改功能包下的CMakeLIsts.txt文件,一般功能包会自动生成CMakeLists.txt文件内容,我们进行修改即可。

add_executable(${PROJECT_NAME}_node src/test.cpp)                             #这里注意自动生成的源文件名字一般不对,一定要修改成对的名字
target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

这里因为我们没有自定义的消息或者服务类型,所以其他的地方不做更改,如果使用了自定义的消息或者服务类型,注意修改其他的地方。

cd ~/catkin_test_ws                                            
catkin_make                                                    #编译
此时~/catkin_test_ws/devel/lib/test_package目录下生成了test_package_node的可执行文件

        执行功能包,在使用rosrun执行功能包之前,使用roscore启动rosmaster。启动rosmaster是启动一切ros节点的前提。

roscore            #启动rosmaster

打开一个新终端启动,test_package功能包下的test_package_node节点。

rosrun test_package test_package_node

终端循环打印hello ros,一个新的ros节点就创建完成了。

6.6 如何在一个ros节点文件中调用其他的源文件?

        这个问题很常见,但是他不应该是个问题,但是发现一些小伙伴还是不太会操作。我们在开发的过程中,随着程序的不断扩大,模块化编程肯定必不可少。有时,我们要调用别人写好的特定功能的源文件,这个时候我们应该怎么做吗?

        首先,将你需要的源文件复制到你需要编写的功能包的src文件夹下,规范地讲,.hpp文件应该放到include文件下,如果文件比较少,也没有必要,和.cpp文件放在一起也可以。

        ros节点源文件只需要添加你复制的头文件下就行了,函数自己调用就行了。

        CMakeLists.txt文件需要做相应的修改,添加你添加的文件名字,放在ros节点文件后面,如下所示:

add_executable(${PROJECT_NAME}_node src/test.cpp src/test2.cpp src/test3.cpp)  
#这里注意自动生成的源文件名字一般不对,一定要修改成对的名字

然后,编译就行了。

6.7 如何设置两台机器的分布式通信?

        ROS是一种分布式软件框架,节点之间通过松耦合的方式进行组合。

        如何设置两台机器的分布式通信呢?

        首先,确保两台机器在同一局域网下,查看各自的ip地址。

ifconfig

然后,各自安装ssh,确保ssh服务,开机自启动。

sudo apt-get install openssh-server                  #安装ssh服务端
sudo service ssh start                               #开启ssh服务
ssh服务开机不会自动启动,需要设置开机自启动
在开机自启动脚本/etc/rc.local加入下面这条命令,注意加入位置是在exit 0这一句之前,加上service ssh start

        然后,在两台机器的/etc/hosts文件中,添加对方的ip地址,通过ping命令,互相测试是否连通。比如在hosts添加,对方机器IP对方机器名。

192.168.1.5   对方机器名
ping 对方机器名或者对方机器ip        #ping测试

然后,在从机端的~/.bashrc文件末尾设置ROS_MASTER_URI,确保从机可以找到主机。

export ROS_MASTER_URI=http://主机名称:11311

最后,在从机端使用ssh用户名@IP地址,输入密码,连接远程终端。 

6.8 ROS开发常用的工具

        launch文件,可以同时启动多个ros节点,可自动启动rosmaster。关于launch的细节,自己学习就好。

        TF坐标变换,用来描述机器人系统中繁杂的坐标系。

        QT工具箱,用来可视化各个ros节点之间的订阅或者请求关系或者可视化各种话题的数据。常用命令,rqt_graph、rqt_plot,而且还可以动态修改部分参数。

        rqt_reconfigure(不常用)。

        rviz可视化平台,机器人可视化平台,几乎是最常用的工具。使用rviz命令启动。

Gazebo物理仿真环境,可对机器人进行三维物理仿真。需要仿真的同学常用。

6.9 ROS的常用命令

#最常用
roscore                    #启动rosmaster
rosrun  pkg_name node_name #启动ros节点
roslaunch pkg_name launch_files_name #启动launch文件
catkin_make                #编译工作空间
rospack profile            #刷新功能包路径

#环境变量
echo $ROS_PACKAGE_PATH     #打印ros环境变量
export | grep ROS          #确认环境变量已经设置正确
source devel/setup.bash    #刷新环境变量
echo "source ~/catkin_test_ws/devel/setup.bash" >> ~/.bashrc    #刷新环境变量,永久有效
source ~/.bashrc                                                #生效上一句

#功能包
catkin_create_pkg test_package std_msgs roscpp rospy            #创建名字为test_package的功能包,添加std_msgs roscpp rospy依赖
rospack list               #查看软件包列表
rospack find package-name  #定位软件包
roscd package-name         #切换到指定功能包目录

#话题
rostopic list              #输出当前运行的topic列表
rostopic info topic-name   #查看话题信息
rostopic echo topic-name   #输出话题数据
rostopic hz topic-name     #每秒发布的消息数量
rostopic bw topic-name     #每秒发布信息所占的字节量

#工具
rviz                       #启动rviz
rqt_graph                  #可视化节点关系
rqt_plot                   #可视化话题数据
rosrun rqt_tf_tree rqt_tf_tree #查看tf树

#数据记录与播放
rosbag record -a           #录制所有topic到bag文件
rosbag play bag_files_name #播放bag文件

 

 

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

ROS面试题汇总 的相关文章

  • Python 实现 Dijkstar 路径规划算法

    Dijstar 最短路径算法 用于计算起始点到最终点的最短路径 一般采用的是贪心算法策略 原理可以参考 图解 Open list 和 close list 环境 Terminal 需要预先安装两个库 matplotlib 和 math pi
  • ros+arduino学习(六):重构ros_lib库文件

    前言 ros lib是arduino程序和ros连接的库文件 通过使用这些库文件和相关函数 可以在arduino上通过编程使得arduino硬件开ros节点程序 这样arduino硬件就可以与上位机通过话题进行通讯 从而把arduino从传
  • 无人飞行器智能感知竞赛--模拟器安装

    开发环境 win11 wsl2 注意事项 请配合视频使用 如果不看视频会对下面的配置过程迷惑 因为一开始我是想安装在ubuntu18 04的 中途发现ubuntu18 04没有ros noetic 所以转入ubuntu20 04配置 视频链
  • 无人驾驶论坛

    1 百度Apollo论坛 http www 51apollo com 2 人工智能中文资讯网 http www ailab cn
  • 关于相机与激光雷达数据采集与标定

    最近在做一个关于车路协同的项目 需要做一个路侧系统 传感器有摄像头和激光雷达 相机和激光雷达联合标定费了老半天劲 在此记录一下 雷达时间戳不对 导致摄像头和雷达的数据无法对齐 解决办法 修改雷达驱动发布点云消息时的时间戳 相机内参标定可以使
  • rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题

    rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题 rospack Warning error while crawling home sun boost filesystem status Permission de
  • 线速度和角速度

    转自 https baike baidu com item E7 BA BF E9 80 9F E5 BA A6 1532652 fr aladdin https baike baidu com item E8 A7 92 E9 80 9F
  • GG-CNN代码学习

    文章目录 1 源码网址 https github com dougsm ggcnn 2 数据集格式转化 下载后的康奈尔数据集 解压完之后里面的格式 里面的 tiff图像通过 txt文件转化得到 python m utils dataset
  • ModuleNotFoundError: No module named ‘rosbag‘

    1 ModuleNotFoundError No module named rosbag File opt ros kinetic lib python2 7 dist packages roslib launcher py line 42
  • Ubuntu安装ROS

    原文链接 https blog csdn net qq 44830040 article details 106049992 这也是我在ubuntu里面安装ROS的第N次 以前每次安装过程都忘记总结了 导致每次安装ROS都浪费了很多的时间用
  • 树莓派配置wifi做热点方法

    http wiki jikexueyuan com project raspberry pi wifi html
  • 《学习篇》学会这18个常用ROS命令集合就能入门ROS了

    常用ROS命令概述 ROS常用命令可以按照其使用场景分为ROSshell命令 ROS执行命令 ROS信息命令 ROS catkin命令与ROS功能包命令 虽然很难从一开始就很熟练地使用所有的命令 但是随着使用的次数增多 你会发现常用的几个R
  • 如何将从 rospy.Subscriber 数据获得的数据输入到变量中?

    我写了一个示例订阅者 我想将从 rospy Subscriber 获得的数据提供给另一个变量 以便稍后在程序中使用它进行处理 目前 我可以看到订阅者正在运行 因为当我使用 rospy loginfo 函数时 我可以看到打印的订阅值 虽然我不
  • 在 CLion 中设置 ROS 包

    我正在使用 CLion C IDE 来编辑 ROS 包 我可以通过打开CMakeLists txt文件 但是 我收到一个错误 FATAL ERROR find package catkin 失败 在工作区和 CMAKE PREFIX PAT
  • 无法加载 LZ4 支持的 Python 扩展。 LZ4 压缩将不可用

    我是 ROS 新手 我刚刚打开终端并输入roscore和另一个终端并键入rostopic node我收到这个错误 上面写着 无法加载 LZ4 支持的 Python 扩展 LZ4 压缩将不可用 我搜索并去了https pypi org pro
  • 在 Python 3 中导入 Rosbag

    我正在尝试从 Python 3 读取 rosbag 文件 我安装了 ROS2 Eloquent Elusor 它应该支持 Python 3 当我跑步时 import rosbag bag rosbag Bag test bag 从Pytho
  • 将 CUDA 添加到 ROS 包

    我想在 ros 包中使用 cuda 有人给我一个简单的例子吗 我尝试使用 cuda 函数构建一个静态库并将该库添加到我的包中 但总是出现链接错误 未定义的引用 cuda 我已经构建了一个可执行文件而不是库并且它可以工作 请帮忙 我自己找到了
  • Caught exception in launch(see debug for traceback)

    Caught exception in launch see debug for traceback Caught exception when trying to load file of format xml Caught except
  • 在 Ubuntu 18.10 上安装 ROS Melodic

    I can t是唯一对 Cosmic 与 Wayland 和 Melodic 的组合感兴趣的人 我会坦白说 我似乎已经在 XPS 13 9370 上成功管理了此操作 或者至少安装脚本 最终 成功完成 然而 有一个非常棘手的解决方法 无论结果
  • 如何使用 PyQT5 连接和分离外部应用程序或对接外部应用程序?

    我正在使用 ROS 为多机器人系统开发 GUI 但我对界面中最不想做的事情感到困惑 在我的应用程序中嵌入 RVIZ GMAPPING 或其他屏幕 我已经在界面中放置了一个终端 但我无法解决如何向我的应用程序添加外部应用程序窗口的问题 我知道

随机推荐

  • AD学习之旅(1)— Altium Designer 16 软件下载与安装

    AD学习之旅 xff08 1 xff09 Altium Designer 16 软件下载与安装 一 前言 Altium Designer是目前EDA行业中使用最方便 xff0c 操作最快捷 xff0c 人性化界面最好的辅助工具 本次软件安装
  • AD学习之旅(16)— 差分线规则的设置及走线

    AD学习之旅 xff08 16 xff09 差分线规则的设置及走线 一 前言 差分线的定义 xff1a 两条存在耦合且平行等长的两根传输线 xff0c 用来传输相位差180度的信号 差分线从理论上说 xff0c 可以是任意两根普通的传输线
  • SystemVerilog学习之路(8)— QuestaSim里覆盖率的查看

    SystemVerilog学习之路 xff08 8 xff09 QuestaSim里覆盖率的查看 一 前言 覆盖率 是衡量设计验证完成程度的一个通用词 xff0c 随着测试逐步覆盖各种合理的组合 xff0c 仿真过程会慢慢勾画出你的设计情况
  • Verilog学习之路(1)— Quartus II 13.0下载安装和HelloWorld

    Verilog学习之路 xff08 1 xff09 Quartus II 13 0下载安装和HelloWorld 一 前言 Quartus II是Altera的FPGA设计工具 xff0c 二 安装包下载 百度云链接地址 xff1a htt
  • Verdi使用方法(1)— 打开user guide和加载波形

    Verdi使用方法 xff08 1 xff09 打开user guide和加载波形 一 在linux上快速打开user guide 在安装有Verdi的Linux服务器上输入如下命令即可快速的打开Verdi的user guide verdi
  • Verdi使用方法(2)— 高效对比两个波形

    Verdi使用方法 xff08 2 xff09 高效对比两个波形 一 打开第一个波形 直接使用如下命令打开一个波形 xff1a verdi tb1 fsdb 加载需要的信号 二 新建一个容器 点击 Window gt Dock to gt
  • C++ 实现 发送HTTP Get/Post请求

    1 简述 最近简单看了一下关于HTTP请求方面的知识 xff0c 之前一直用Qt来实现 xff0c 有专门HTTP请求的QNetworkAccessManager类来处理 xff0c 实现也比较简单 xff0c 这里主要讲解一下用C 43
  • Python学习之路(4)— 正则表达式(一)

    Python学习之路 xff08 4 xff09 正则表达式 一 一 前言 参考文章 xff1a 爬虫要讲武德 xff0c 你却用正则 一篇文章搞定正则表达式 xff01 参考视频 xff1a 硬核Python进阶篇 一小时掌握正则表达式
  • vs code 远程连接服务器(超详细,图文说明)

    工作中需要使用vs code远程连接服务器 xff0c 网上找了好多教程 xff0c 发现没有完善的说明 xff0c 对我这种小白来说真是耗时耗力 xff0c 完成连接后 xff0c 特地把搭建过程图文分享出来 1 安装完vs code后
  • Jetson TX2 --GPIO 库使用(点亮一个LED灯)

    项目介绍 Jetson GPIO Jetson TX2 J21有40个引脚 xff0c 类似于树莓派的40个引脚 xff0c 可以通过Jetson GPIO samples包中提供的python库控制输入输出 该库与Raspberry Pi
  • 机械键盘改热插拔

    所需原料 电烙铁 大概就十几块而已 我计算机系的 不常用 贵了浪费焊锡丝 大概20g就足够挥霍也就几块钱 松香 买的时候让卖家送一点 这个很便宜鸡心眼m1 3买大概250个把 每个按键需要两个 还有一种m1 0的是改灯的 当初买了一千个才十
  • ROS知识

    按规范学习 直接开始学习ROS文件目录结构 转载 https zhuanlan zhihu com p 139405796 常用操作 xff1a 启动测试和订阅服务和话题 小白先熟悉ROS和M300的操作 xff1a ubuntu18 04
  • Ubuntu18.04 ,安装opencv4.5.4

    背景 手眼标定时候 xff0c 需要用到opencv4的findChessboardCornersSB 所以需要下载opencv4 5 4 安装 Ubuntu 18 04 安装opencv4 2 0 遇到的问题 安装结束后 xff0c 出现
  • ubuntu播放文件需要MPEG-4 AAC解码器

    即可
  • 类模板成员函数定义问题

    span class token macro property span class token directive keyword include span span class token string 34 pch h 34 span
  • 视觉SLAM面试题汇总(三)

    北京某自动驾驶公司 xff1a 1 点云的聚类 xff1b 求法向量 xff1b 多个点集 xff0c 求点集的法向量 xff1b 2 LM算法里面lamda的作用 xff1b 3 KD Tree 4 描述子距离的匹配的方法 xff1f 除
  • ORB-SLAM2中关键知识点总结

    目录 1 ORB SLAM2的总体框架是怎样的 xff1f 2 ORB SLAM2是怎样完成初始化的 xff1f 3 ORB SLAM2是如何进行Tracking的 xff1f 4 ORB SLAM2是如何选取关键帧的 xff1f 5 OR
  • RS485知识点

    为什么RS485空闲时的电平要求大于 43 200mv 这不是很容易被接收端接收吗 xff1f a 其实 xff0c 如果RS485的AB线空闲电平如果小于 43 200mv xff0c 485芯片的输出不定 xff0c 有些芯片会输出高
  • 两种点云地面去除方法

    目录 1 基于角度分割的地面 非地面分割 1 1 PCL基本入门 1 1 1 在ROS项目中引入PCL库 1 2 编写节点进行Voxel Grid Filter 1 2 1 验证效果 1 3 点云地面过滤 1 3 1 点云剪裁和过滤 去除过
  • ROS面试题汇总

    1 ROS中订阅 xff08 Subscribe xff09 最新消息以及消息队列相关问题 机器人应用中难免会遇到运算起来很费时间的操作 xff0c 比如图像的特征提取 点云的匹配等等 有时候 xff0c 不可避免地 xff0c 我们需要在