ROS学习之基础包创建的详细流程:包括rosnode, rostopic, rosrun,roslaunch等使用[C++版]

本文详细介绍了如何在ROS环境下创建一个工作空间,初始化并创建ROS程序包,编写发布和接收消息的节点,编辑CMakeLists.txt文件,编译程序包,以及使用launch文件同时启动多个节点。通过这些步骤,读者可以学习到ROS基础包的构建过程和基本操作。

0 引言

本文旨在学习ROS基础包的从零开始创建,包括如何创建一个发布消息节点,一个接收消息节点,还有如何使用roslaunch同时启动多个节点,如何编译ROS工程包等操作。

默认已在Ubuntu系统中安装ROS机器人系统,比如Ubuntu18.04-melodic
工程目录tree

# catkin_ws/src 目录下
.
├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake
└── hello_world
    ├── CMakeLists.txt
    ├── include
    │   └── hello_world
    ├── launch
    │   └── talker_listener.launch
    ├── package.xml
    └── src
        ├── listener.cpp
        └── talker.cpp

👉本文代码GitHubhttps://github.com/MRZHUGH/CSDN/tree/main/ROS/catkin_hw/src/hello_world
👉 Python版https://blog.csdn.net/MRZHUGH/article/details/131595683

1 工作空间创建并初始化

# 新开一个终端
# 创建一个名为catkin_ws工作空间,及src子目录
mkdir -p ~/catkin_ws/src
# 进入到src文件夹
cd ~/catkin_ws/src
# 初始化工作空间
catkin_init_workspace
# 回到工作空间根目录 
cd .. 
# 编译工作空间 
catkin_make

2 创建ROS程序包

# 切换到src文件夹
cd ~/catkin_ws/src
# 创建名为hello_world的ROS程序包,以后创建其他的包也是此方法,只需修改包的名称即可
catkin_create_pkg hello_world roscpp rospy std_msgs

执行后,src目录下新建了一个 hello_world文件夹及子目录和子文件

.
├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake
└── hello_world
    ├── CMakeLists.txt
    ├── include
    │   └── hello_world
    ├── package.xml
    └── src

3 创建消息节点

3.1 发布消息节点

在 hello_world/src 代码资源文件夹下新建发布消息节点的talker.cpp文件,详细代码如下:

#include "ros/ros.h" //创建ROS节点必须包含的头文件,固定格式
#include "std_msgs/String.h" //节点中使用某种特定的消息类型
#include <sstream> // c++中用来处理面向流的输入和输出的标准库

int main(int argc,char **argv)
{
	ros::init(argc,argv,"talker"); // 初始化一个名为talker的节点,以后写其他的节点只要修改talker就行
	ros::NodeHandle n; // 创建名为n的节点句柄,自己写程序只要改n这个地方就行
	// ROS节点中发布话题的方式,chatter_pub是发布者实例,发布消息的类型是std_msgs/String的话题,
	// topic话题名称为chatter,队列大小为1000,n为访问实例,要修改的话就改提到的这几个地方
	ros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter", 1000);
	ros::Rate loop_rate(10); // 制定循环的频率,此处为10HZ,固定格式
	int count=0; // 进入节点的主循环,在节点未发生异常的情况下将一直在循环,固定格式
	while(ros::ok()) // 当Ctrl+c按下时,ros::ok()将会返回false,固定格式
	{
		// 初始化std_msgs::String类型的消息
		std_msgs::String msg;
		std::stringstream ss;
		ss<<"hello world"<<count;
		msg.data=ss.str(); // 用data来存储字符串
		// 发布消息
		ROS_INFO("%s",msg.data.c_str()); //ROS_INFO类似于cout和printf
		chatter_pub.publish(msg); // 发布封装完毕的消息msg
		// 循环等待回调函数
		ros::spinOnce(); // 用来处理节点订阅话题的所有回调函数
		// 按照循环频率延时,固定格式
		loop_rate.sleep();
		++count;
	}
	return 0;
}

3.2 接收消息节点

在 hello_world/src 代码资源文件夹下新建接收消息节点的listener.cpp文件,详细代码如下:


#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"); // 初始化一个名为listener的节点
	ros::NodeHandle n; // 创建名为n的节点句柄
	// 创建一个Subscriber的话题,注册回调函数chatterCallback
	ros::Subscriber sub=n.subscribe("chatter", 1000, chatterCallback);
	// 循环等待回调函数
	ros::spin();
	return 0;
}  

4 编辑CMakeLists.txt

执行第2步后,hello_world文件夹下生成了CMakeLists.txt,打开编辑:

# 第一行修改cmake最小版本为 2.8.3
cmake_minimum_required(VERSION 2.8.3)

# 最后添加以下几行
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker hello_world)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener hello_world)

5 编译程序包

# 回到catkin_ws工作空间
cd ~/catkin_ws/src
# 执行catkin_make编译
catkin_make

6 运行消息节点

# 新开终端
roscore
# 新开终端,运行talker节点
source ~/catkin_ws/devel/setup.bash 
rosrun hello_world talker

运行后,可以看到已成功创建发布消息的节点,并持续发布消息:

[ INFO] [1688019211.336438520]: hello world0
[ INFO] [1688019211.436538723]: hello world1
[ INFO] [1688019211.536531392]: hello world2
[ INFO] [1688019211.636536978]: hello world3
[ INFO] [1688019211.736561791]: hello world4
[ INFO] [1688019211.836520559]: hello world5
[ INFO] [1688019211.936556623]: hello world6
[ INFO] [1688019212.036533914]: hello world7
[ INFO] [1688019212.136574843]: hello world8
[ INFO] [1688019212.236534653]: hello world9
[ INFO] [1688019212.336576466]: hello world10
[ INFO] [1688019212.436533892]: hello world11
[ INFO] [1688019212.536543132]: hello world12
...
# 新开终端,运行listener节点
source ~/catkin_ws/devel/setup.bash 
rosrun hello_world listener

运行后,可以看到打印已订阅talker发出的消息:

[ INFO] [1688019425.918466687]: I heard: [hello world4]
[ INFO] [1688019426.018305977]: I heard: [hello world5]
[ INFO] [1688019426.117968093]: I heard: [hello world6]
[ INFO] [1688019426.218154007]: I heard: [hello world7]
[ INFO] [1688019426.318345417]: I heard: [hello world8]
[ INFO] [1688019426.418056486]: I heard: [hello world9]
[ INFO] [1688019426.517999187]: I heard: [hello world10]
[ INFO] [1688019426.618130109]: I heard: [hello world11]
[ INFO] [1688019426.718321709]: I heard: [hello world12]
[ INFO] [1688019426.818094286]: I heard: [hello world13]
[ INFO] [1688019426.917948960]: I heard: [hello world14]
[ INFO] [1688019427.017976226]: I heard: [hello world15]
[ INFO] [1688019427.118302080]: I heard: [hello world16]

7 添加launch启动文件

rosrun只能启动一个消息节点,可以用ROS中launch文件启动多个节点,在hello_world文件夹中新建launch文件夹,并在launch文件夹中新建talker_listener.launch,打开talker_listener.launch,添加如下xml格式的代码:

<launch>
	<node name="listener_node" pkg="hello_world" type="listener" output="screen"/>
	<node name="talker_node" pkg="hello_world" type="talker" output="screen"/>
</launch>

  • node name: 该节点的名字,相当于代码中 ros::init() 中设置的信息,有了它代码中的名称会被覆盖;
  • pkg: 表示该节点的package,相当于 rosrun 命令后面的第一个参数;
  • type: 可执行文件的名字,rosrun 命令的第二个参数;是否可以理解为要执行的节点;
  • output=“screen”: 将标准输出显示在屏幕上而不是记录在日志中

8 重新编译

# 新开终端
# 重新编译前,先给talker_listener.launch可执行权限
sudo chmod +x ~/catkin_ws/src/hello_world/launch/talker_listener.launch

# 回到catkin_ws工作空间
cd ~/catkin_ws
# 重新编译
catkin_make

9 运行launch文件

# 编译后,重新source
source ~/catkin_ws/devel/setup.bash
# 运行talker_listener.launch
roslaunch hello_world talker_listener.launch

运行后,自动启动了roscore, 也启动了talker和listener两个消息节点:

SUMMARY
========

PARAMETERS
 * /rosdistro: melodic
 * /rosversion: 1.14.11

NODES
  /
    listener_node (hello_world/listener)
    talker_node (hello_world/talker)

ROS_MASTER_URI=http://localhost:11311

process[listener_node-1]: started with pid [30875]
process[talker_node-2]: started with pid [30877]
[ INFO] [1688020081.054048128]: hello world0
[ INFO] [1688020081.154174941]: hello world1
[ INFO] [1688020081.254183692]: hello world2
[ INFO] [1688020081.354176431]: hello world3
[ INFO] [1688020081.354852999]: I heard: [hello world3]
[ INFO] [1688020081.454181460]: hello world4
[ INFO] [1688020081.454357334]: I heard: [hello world4]
[ INFO] [1688020081.554196089]: hello world5
[ INFO] [1688020081.554813633]: I heard: [hello world5]
[ INFO] [1688020081.654196695]: hello world6
[ INFO] [1688020081.654732170]: I heard: [hello world6]
...

10 查看节点和topic

查看消息node

rosnode list

输出:

/listener_node
/rosout
/talker_node

查看话题topic

rostopic list

输出:

/chatter
/rosout
/rosout_agg

用rqt_graph查看消息节点node和话题topic的关系

请添加图片描述
至此,成功创建一个ROS基础包,并包含一个发布节点,一个接收节点,一个话题用来传递消息,也学习了基础的ROS包编译等操作。




须知少时凌云志,曾许人间第一流。



⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZPILOTE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值