ROS 入门 —— 创建工作空间与功能包
ROS 创建工作空间与功能包
工作空间(workspace)是一个存放工程开发相关的文件的文件夹:
- src:代码空间(Source Space)
用于保存我们的源代码程序文件
- build:编译空间(Build Space)
用于保存我们在编译过程中用到的一些中间文件
- devel:开发空间(Development Space)
用于保存我们在编译之后的可执行文件,这里并没有删除我们的编译中间文件
- install:安装空间(Install Space)
用于保存我们编译之后的可执行文件,这里与 devel 是一样的作用,不同的是,这个目录下删去了我们不需要的编译中间文件,我们一般用不到
catkin 编译系统下的工作空间结构如下:

创建工作空间
首先我们来到主目录下,新建一个名为 catkin_ws 的文件夹,然后在目录下创建一个 src 文件夹,并将其初始化为工作空间:
mkdir catkin_ws
cd catkin_ws
mkdir src
cd src
# 初始化工作空间
catkin_init_workspace
显示如下就说明已经成功初始化了工作空间:

然后我们返回到 catkin_ws 路径下,使用如下命令进行编译:
catkin_make
# 这个编译命令一般只会生成 build 和 devel 两个目录,需要 install 目录需要继续执行如下命令:
catkin_make install
编译好了如下:

生成 install 文件如下:

然后我们就需要设置环境变量,这里为了方便,直接添加到系统环境变量中:
gedit ~/.bashrc
# 添加如下内容
source /opt/ros/noetic/setup.bash
source /home/ppqppl/catkin_ws/devel/setup.bash
# 保存后,使用如下命令重载环境变量
source ~/.bashrc
我们使用如下命令检查环境变量是否创建成功:
echo $ROS_PACKEG_PATH
这样我们的名为 catkin_ws 的工作空间就已经创建完成了
创建功能包
在 ROS 中我们可以创建使用自己的功能包,创建功能包命令如下:
catkin_create_pkg <package_name> [depend1] [depend2] …… [depend1]
# 这里直接使用如下命令进行创建
catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
成功创建功能包:

下面我们就可以通过编写程序,发布运行我们自己的功能包中的节点
发布者 publisher 的编程实现

我们已经城建了自己的功能包,我们现在就可以写我们需要发布的控制代码,ROS 的代码主要是 C++ 和 Python
- C++
我们需要进入我们的功能包下的 src 目录下,然后创建一个 velocity_publisher.cpp 文件作为我们的代码源文件,内容如下:
/*
该例程将发布 turtle1/cmd_vel 话题,消息类型 geometry msgs::Twist
*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv){
// ROS 节点初始化
ros::init(argc, argv, "velocity_pulisher");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个 Publisher,发布名为 /turtle1/cmd_vel 的 topic,消息类型为 geometry_msgs::Twist,队列长度 10
ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
// 设置循环频率
ros::Rate loop_rate(10);
int count = 0;
while(ros::ok())
{
// 初始化 geometry_msgs::Twist 类型的消息
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;
vel_msg.angular.z = 0.2;
// 发布消息
turtle_vel_pub.publish(vel_msg);
ROS_INFO("Publish turtle velocity command[%0.2f m/s, %0.2f rad/s]",
vel_msg.linear.x, vel_msg.angular.z);
// 按照循环频率延时
loop_rate.sleep();
}
return 0;
}
- Python
我们需要在功能包下创建一个新的文件夹 scripts ,然后我们的 Python 代码文件就存储在 scripts 文件夹中,这里的代码文件与 c++ 的功能相同的代码文件同名即可,velocity_publisher.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
from geometry_msgs.msg import Twist
def velocity_publisher():
# ROS 节点初始化
rospy.init_node('velocity_publisher', anonymous=True)
# 创建一个 publisher,发布名为 /turtle1/cmd_vel 的 topic.消息类型为 geometry_msgs::Twist, 队列长度 10
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
# 设置循环频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化 geomety_msgs::Twist 类型消息
vel_msg = Twist()
vel_msg.linear.x = 1.5
vel_msg.angular.z = 0.2
# 发布消息
turtle_vel_pub.publish(vel_msg)
rospy.loginfo("Publish turtle velocity command[%0.2f m/s, %0.2f rad/s]",
vel_msg.linear.x, vel_msg.angular.z)
# 按照循环频率延时
rate.sleep()
if __name__ == "__main__":
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
注意:这里在 python 程序的第一行必须要有 #!/usr/bin/env python3
,否则将不能识别当前程序
然后我们需要在功能包目录下的 CMakeLists.txt 中 install 前面添加如下两行:
add_executable(velocity_publisher src/velocity_publisher.cpp)
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})

这两行的作用就是绑定相关环境和头文件,没有这两行就会报错找不到头文件等一系列问题
最后我们就可以回到最初的 catkin_ws 路径下进行编译

出现上面的画面就说明我们已经编译成功了
然后我们就能使用我们发布好的包中的话题了,效果如下:
先运行 ROS-Master

运行小海龟:

最后运行我们自己的发布的包中的话题 c++ 程序:

运行自己发布的包中的话题的 Python 程序:

运行效果如下:
