原博客地址 https://www.cnblogs.com/xuanxiaochen/p/6013886.html
在安装好ROS后,接着学习如何创建节点和节点之间的通信方式,以一个简单的主题发布节点和主题订阅节点说明。
节点是连接ROS网络等可执行文件,是实现某些功能的软件包,也是一个主要计算执行的进程。
一、创建工作空间
创建新文件夹,名字自定义,路径也根据自己设定。
cd ~
mkdir -p ros_workspace
创建好后,就需要将次路径添加到ROS_PACKAGE_PATH中。
查看目前ROS的工作空间,
echo $ROS_PACKAGE_PATH
一般显示如下:
/opt/ros/kinetic/share
①:下面将路径添加到~/.bashrc中
echo "export ROS_PACKAGE_PATH=~/ros_workspace:${ROS_PACKAGE_PATH}" >> ~/.bashrc
. ~/.bashrc
②:或者 : (添加环境变量,输入命令 gedit ~/.bashrc打开后
末尾添加 source ~/catkin_ws/devel/setup.bash
如果不添加环境变量,每启动一个终端都需要输入
source ~/catkin_ws/devel/setup.bash
每打开一个终端,都会执行环境变量的脚本,对环境变量调试可以在bash代码中加入
echo "here" ,这样打开终端就可以打印“here”,根据错误提示和echo "here" 的位置关系来定位错误位置)
再次查看ROS正在使用的空间,确保路径正确添加。
二、创建ROS功能包
打开ROS工作目录:
cd ~/ros_workspace
在该目录下创建功能包:
roscreate-pkg test1_tutorials std_msgs rospy roscpp
功能包文件夹下一般包括Makefile、manifest.xml、CMakeLists.txt、mainpage.dox等文件。
std_msgs 包含常见等消息类型
rospy py库
roscpp cpp库
运行命令,查看功能包是否创建
rospack find test1_tutorials
三、编写代码
1、主题发布节点
在功能包中创建src/test1_a.cpp,并添加代码:
1 #include "ros/ros.h"
2 #include "std_msgs/String.h"
3 #include <sstream>
4
5
6 int main(int argc, char **argv)
7 {
8 ros::init(argc,argv,"test1_a");
9 ros::NodeHandle n;
10 ros::Publisher chatter_pub = n.advertise<std_msgs::String>("message",1000);
11 ros::Rate loop_rate(10);
12 while(ros::ok()) {
13 std_msgs::String msg;
14 std::stringstream ss;
15 ss << "Hello test1_b! I am test1_a.";
16 msg.data = ss.str();
17 ROS_INFO("%s",msg.data.c_str());
18 chatter_pub.publish(msg);
19 ros::spinOnce();
20 loop_rate.sleep();
21 }
22 return 0;
23 }
第8行: 初始化,其中第三个参数是节点名称,在ROS系统中必须唯一。
第10行:声明主题message上发布一个消息类型为str_msgs::String的消息,并设置消息缓冲区的大小。
第11行:设置发送消息的频率 10HZ,它追踪自从上一次Rate::sleep()被唤醒之后的持续时间,并在到达时间后继续休眠。
第12行:ros::ok()函数返回值,在下列情况返回false。
- SIGINT句柄接收到Ctrl+C命令来结束;
- 被名称相同的节点提出ROS网络;
- ros::shutdown()被应用的另一部分唤醒。
第18行:把消息通过主题发布出去。
第19行:和下面test1_b.cpp程序ros::spin()进行对比,参考http://www.yfworld.com/?p=2318
2、主题订阅节点
在功能包中创建src/test1_b.cpp,并添加代码:
1 #include "ros/ros.h"
2 #include "std_msgs/String.h"
3
4 void chatterCallback(const std_msgs::String::ConstPtr &msg)
5 {
6 ROS_INFO("Hello test1_a! I am test1_b. I heard:[%s]",msg->data.c_str());
7 }
8
9 int main(int argc, char **argv)
10 {
11 ros::init(argc,argv,"test1_b");
12 ros::NodeHandle n;
13 ros::Subscriber sub = n.subscribe("message",1000,chatterCallback);
14 ros::spin();
15
16 return 0;
17 }
第4-7行:回调函数,当一个新消息到达指定主题时即调用。
第17行:第一个参数指定订阅主题;第二个参数设置消息缓冲区的大小;第三个参数指定回调函数。
订阅节点需要做四件事情:
1)初始化;
2)从主题订阅消息;
3)然后等待消息到达;
4)当消息到达时,chatterCallback()被回调。
四、编译节点
编辑CMakeLists.txt文件,在末尾处添加如下代码:
rosbuild_add_executable(test1_a src/test1_a.cpp)
rosbuild_add_executable(test1_b src/test1_b.cpp)
rosmake工具进行编译:
rosmake test1_tutorials
五、运行功能包
在运行功能包前,请确认节点管理器已经打开。使用下面的命令运行:
roscore
说明:roslaunch命令会启动roscore,再启动相应的launch文件,rosrun则不会
在不同的终端窗口分别运行:
rosrun test1_tutorials test1_a
rosrun test1_tutorials test1_b
可以看到以下信息:
六、参考
http://wiki.ros.org/ROS/Tutorials
《ROS机器人程序设计》 刘品杰 译