关键术语
消息文件(.msg):消息文件的扩展名是.msg
,本质上是一个txt文件,开发者可以在创建的消息文件中自定义需要的消息格式,由于消息字段中的字段类型是来自其他功能包,因此需要在package.xml文件及CMakeLists.txt文件中包含定义了字段类型的功能包
创建工作空间(workspace)
打开终端(Ctrl + Alt + T),输入如下的命令流:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
cd ..
catkin_make
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
在工作空间中创建功能包(package)
打开终端(Ctrl + Alt + T),输入如下的命令流:
cd ~/catkin_ws/src
catkin_create_pkg custom_msg_topic roscpp std_msgs message_generation message_runtime
cd ..
catkin_make
向功能包添加自定义消息文件(.msg)
打开终端,输入如下的命令流:
roscd custom_msg_topic
mkdir msg && cd msg
gedit custom_msg.msg
在custom_msg.msg
文件中输入如下的内容:
string first_name
string last_name
uint8 age
uint32 score
输入完成后,保存并关闭文件.
修改CMakeLists.txt
文件的内容为:
cmake_minimum_required(VERSION 2.8.3)
project(custom_msg_topic)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation
)
add_message_files(
FILES
custom_msg.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
LIBRARIES custom_msg_topic
CATKIN_DEPENDS roscpp message_runtime
)
include_directories(
${catkin_INCLUDE_DIRS}
)
修改完成CMakeLitst.txt文件之后,保存并退出.
回到功能包所在的工作空间,构建功能包:
cd ~/catkin_ws
catkin_make
检查自定义消息头文件是否生成,以及生成的消息内容是否正确:
rosmsg show custom_msg_topic/custom_msg
输出内容为:
$ rosmsg show custom_msg_topic/custom_msg
string first_name
string last_name
uint8 age
uint32 score
显然,输出结果和前面定义的内容是完全一致的.
生成了自定义的消息头文件之后,我们就可以利用自定义的消息格式来编写节点了.
向功能包添加发布者(publisher)节点源文件
打开终端,输入如下的命令流:
roscd custom_msg_topic/src
gedit custom_msg_publisher.cpp
将如下的内容输入到上述创建的源文件中:
#include "ros/ros.h"
#include "custom_msg_topic/custom_msg.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "custom_msg_publisher");
ros::NodeHandle nh;
ros::Publisher custom_msg_pub = nh.advertise<custom_msg_topic::custom_msg>("student_info", 1000);
ros::Rate loop_rate(10);
while (ros::ok())
{
custom_msg_topic::custom_msg msg;
std::stringstream ss;
ss<<"Zhang San";
ss>>msg.last_name; //将字符串流中以空格隔开的第一个子字符串Zhang插入到msg.last_name中
ss>>msg.first_name; //将字符串流中以空格隔开的第二个子字符串San插入到msg.first_name中
msg.age = 18;
msg.score = 650;
custom_msg_pub.publish(msg);
loop_rate.sleep();
}
return 0;
}
输入完成后,保存并关闭文件.
向功能包添加订阅者(subscriber)节点源文件
打开终端,输入如下的命令流:
roscd custom_msg_topic/src
gedit custom_msg_subscriber.cpp
将如下的内容输入到上述创建的源文件中:
#include "ros/ros.h"
#include "custom_msg_topic/custom_msg.h"
void student_infoCallback(const custom_msg_topic::custom_msgConstPtr &msg)
{
ROS_INFO("I heard: [%s %s]", msg->last_name.c_str(), msg->first_name.c_str());
ROS_INFO("his age is: [%d]; and his score is: [%d]", msg->age, msg->score);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "custom_msg_subscriber");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("student_info", 1000, student_infoCallback);
ros::spin();
return 0;
}
输入完成后,保存文件并退出.
修改功能包的CMakeLists.txt文件
打开终端,输入如下的命令流:
roscd custom_msg_topic
gedit CMakeLists.txt
将上述文件的内容修改成如下所示:
cmake_minimum_required(VERSION 2.8.3)
project(custom_msg_topic)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation
)
add_message_files(
FILES
custom_msg.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
LIBRARIES custom_msg_topic
CATKIN_DEPENDS roscpp message_runtime
)
include_directories(
${catkin_INCLUDE_DIRS}
)
# 下面是需要添加的内容
add_executable(custom_msg_publisher src/custom_msg_publisher.cpp)
add_executable(custom_msg_subscriber src/custom_msg_subscriber.cpp)
add_dependencies(custom_msg_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(custom_msg_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(custom_msg_publisher ${catkin_LIBRARIES})
target_link_libraries(custom_msg_subscriber ${catkin_LIBRARIES})
修改完成后,保存并退出.
构建功能包,运行节点程序
打开终端,输入如下的命令流:
cd ~/catkin_ws
catkin_make
打开一个新的终端,运行发布者节点程序:
rosrun custom_msg_topic custom_msg_publisher
打开一个新的终端,运行订阅者节点程序:
rosrun custom_msg_topic custom_msg_subscriber
至此,创建自定义消息头文件,编写基于话题通信的节点就完成了.
Enjoy It!