目录
一、新建一个ROS工作空间并创建功能包
二、创建一个msg消息
三、发布话题
四、订阅话题
前言
Ubuntu18.04
ROS Melodic
一、新建一个ROS工作空间并创建功能包
mkdir -p catkin_ws/src
cd ~/catkin_ws/src/
catkin_init_workspace
cd ~/catkin_ws/
catkin_make
echo "source ~/catkin_ws/devel/setup.bash">>~/.bashrc
source ~/.bashrc
cd ~/catkin_ws/src/
catkin_create_pkg topic roscpp rospy std_msgs
执行完毕后建立了工作空间catkin_ws,并创建了功能包topic。
二、创建一个msg消息
在topic包的目录下创建msg文件夹并在msg文件中添加消息成员
cd ~/catkin_ws/src/topic
mkdir msg
cd msg
gedit example.msg
填入以下内容:
std_msgs/Header header
float32 test1
int32 test2
header是消息头,包含了序列号,时间戳,frame_id,一般每个消息都有这个成员,其他的成员可以根据需要随便取。
编辑package.xml文件
gedit ~/catkin_ws/src/topic/package.xml
确保它包含以下两行且没有被注释。如果没有,添加进去:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
修改topic包下面的CMakeLists.txt文件:
gedit ~/catkin_ws/src/topic/CMakeLists.txt
将message_generation添加到COMPONENTS列表中
添加运行时依赖关系CATKIN_DEPENDS message_runtime
添加msg文件
add_message_files(
FILES
example.msg
)
确保generate_messages()函数被调用
generate_messages(
DEPENDENCIES
std_msgs
)
包含消息头文件路径
include_directories(
include
${catkin_INCLUDE_DIRS}
)
添加完后无需编译使用rosmsg show example即可查看是否添加成功
在msg中使用其他msg类型
如果在定义msg时,想用其他的包定义好的msg消息类型
例如在package1中定义消息如下:
std_msgs/Header header
package2/msg2 test
其中test的类型为package2包中的msg2消息类型。则需要确保msg2消息正确定义并生成头文件,同时在package1的CmakeLists.txt中的generate_messages中加入package2,例如:
generate_messages(
DEPENDENCIES
std_msgs
package2
)
如果引用的是当前包package1中定义的消息,则直接定义即可,无需修改generate_messages
如:
std_msgs/Header header
package1/msg1 test
如果修改了msg文件后编译出现报错:
The dependencies of the message/service ‘XXX’ have changed.
Please rerun cmake.
原因是MSG文件通过编译后变成头文件,但是之前的头文件仍然存在导致编译不通过,使用
catkin_make_isolated --force-cmake
直接强制覆盖编译即可
使用catkin_make_isolated --force-cmake编译后会生成下面两个文件夹
这是如果用catkin_make编译提示找不到消息头文件,可以将devel_isolated/package1/include/package1下的几个头文件复制覆盖到devel/package1/include/package1下再用catkin_make编译即可
如果删除devel和build文件夹重新编译时提示找不到定义的msg的头文件,这是由于编译时还没来得及生成,可以多编译几次就可以了
三、发布话题
进入catkin_ws/src/topic/src中新建节点程序
cd ~/catkin_ws/src/topic/src
gedit pub.cpp
一个简单的发布节点程序如下,可以直接复制到pub.cpp中
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
#include"topic/example.h"
int main(int argc, char **argv)
{
ros::init(argc, argv,"pub");
ros::NodeHandle nd;
ros::Publisher publish = nd.advertise<topic::example>("/topic/example", 10);
ros::Rate loop_rate(10);
while (ros::ok())
{
topic::example example;
example.test1 = 1.5;
example.test2 = 2;
publish.publish(example);
loop_rate.sleep();
}
return 0;
}
修改topic包下面的CMakeLists.txt文件:
gedit ~/catkin_ws/src/topic/CMakeLists.txt
在文件的最后加上:
add_executable(pub src/pub.cpp)
target_link_libraries(pub ${catkin_LIBRARIES})
然后编译
cd ~/catkin_ws
catkin_make
. ~/catkin_ws/devel/setup.bash
运行:
roscore
rosrun topic pub
然后执行:
rostopic echo /topic/example
出现下面的信息说明发布成功
四、订阅话题
进入catkin_ws/src/topic/src中新建节点程序
cd ~/catkin_ws/src/topic/src
gedit sub.cpp
一个简单的发布节点程序如下,可以直接复制到sub.cpp中
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
#include"topic/example.h"
void subscriberCallback(const topic::example::ConstPtr& msg)
{
printf("test1=%f,test2=%d\n",msg->test1,msg->test2);
}
int main(int argc, char **argv)
{
ros::Subscriber subscriber;
ros::init(argc, argv,"sub");
ros::NodeHandle nd;
subscriber = nd.subscribe("topic/example", 5, &subscriberCallback);
ros::Rate loop_rate(10);
while (ros::ok())
{
loop_rate.sleep();
ros::spinOnce();
}
return 0;
}
修改topic包下面的CMakeLists.txt文件:
gedit ~/catkin_ws/src/topic/CMakeLists.txt
在文件的最后加上:
add_executable(sub src/sub.cpp)
target_link_libraries(sub ${catkin_LIBRARIES})
然后编译
cd ~/catkin_ws
catkin_make
. ~/catkin_ws/devel/setup.bash
运行:
rosrun sub sub
可以看到打印出了订阅到的话题
运行rqt_graph结果如下: