参考
ROS官方wiki—创建ROS消息和服务
ROS官方wiki—编写简单的发布者和订阅者(C++)
ROS官方wiki—检验简单的发布者和订阅者
消息的定义
首先进入创建的包
$ roscd beginner_tutorials
$ mkdir srv
消息定义文件(*.msg)
定义一个字符串消息
$ echo "int64 num" > msg/Num.msg
设置*.msg
文件的编译信息
在packages.xml
添加配置
<build_depend>message_generation</build_depend> # 编译时依赖库
<exec_depend>message_runtime</exec_depend> # 运行时依赖库
在CMakeLists.txt中作如下设置
# 添加ROS依赖库
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs # 标准信息,系统支持的基础数据,如int,float,...
message_generation # 将*.srv文件转为C++/Python代码
# 在 packages.xml 中添加过
)
# 添加刚编写的*.msg文件
add_message_files( # ROS 定义的cmake命令,告知ROS自定义的文件
FILES
Num.msg
)
# ROS 定义的cmake命令,告知ROS生成(C++/Python)消息类的依赖库
generate_messages(
DEPENDENCIES
std_msgs
)
查看生成的msg信息
# rosmsg show [message type]
$ rosmsg show beginner_tutorials/Num
msg目录中的任何.msg文件都将生成所有支持语言的代码。
- C++消息的头文件将生成在~/catkin_ws/devel/include/beginner_tutorials/
。
- Python脚本将创建在~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg
。
发布者代码
#include "ros/ros.h" // ROS 头文件
#include "std_msgs/String.h" // 系统定义的字符串消息
#include <sstream>
int main(int argc, char **argv)
{
// 前两个命令行参数
// 第三个节点名,节点名不能冲突!!!
ros::init(argc, argv, "talker");
// ROS 系统句柄
// 第一个申请资源,最后一个句柄销毁所有申请的资源
ros::NodeHandle n;
// 第一个参数,Topic的名字,roscore会根据名字把这个发布者分配给对应的订阅者,之后两者点对点交流
// 第二个参数,Topic 的缓存大小,超过数量的会被丢弃
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// 以 10 Hz 频率发布消息
ros::Rate loop_rate(10);
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());
// 发布消息
chatter_pub.publish(msg);
// 用来接收其他发布者的消息,此处可省略
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
订阅者代码
#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::ok()返回false,ros::spin()就会退出
ros::spin();
return 0;
}
构建程序
以下 cmake 脚本的beginner_tutorials_generate_messages_cpp
见
cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)
## 声明为 catkin package
catkin_package()
include_directories(include ${catkin_INCLUDE_DIRS})
# 发布者 talker
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp) # add_dependencies 是ROS定义的命令
# 订阅者 listener
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp) # add_dependencies 是ROS定义的命令
创建的可执行文件talker和listener,默认会被放到软件包目录下的devel
空间中,即~/catkin_ws/devel/lib/<package name>
。
如果你又添加了新的包,可能需要通过指定–force-cmake参数来让catkin强制生成。参见使用工作空间。
检验编译好的程序
$ cd ~/catkin_ws
$ catkin_make # 编译代码
$ roscore # ROS系统
$ source ./devel/setup.bash # 每次 catkin_make 后执行
启动发布者talker
$ rosrun beginner_tutorials talker # (C++)
可看到类似以下消息:
[INFO] [WallTime: 1314931831.774057] hello world 1314931831.77
[INFO] [WallTime: 1314931832.775497] hello world 1314931832.77
启动订阅者 listener
$ rosrun beginner_tutorials listener # (C++)
可看到类似以下消息:
[INFO] [WallTime: 1314931969.258941] /listener_17657_1314931968795I heard hello world 1314931969.26
[INFO] [WallTime: 1314931970.262246] /listener_17657_1314931968795I heard hello world 1314931970.26