ROS
中通过 std_msgs
封装了一些原生的数据类型,比如: String
、Int32
、Int64
、Char
、Bool
、Empty
… 但是,这些数据一般只包含一个 data
字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:激光雷达的信息… std_msgs
由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型。
msgs
只是简单的文本文件,每行具有字段类型和字段名称,可以使用的字段类型有:
ROS
中还有一种特殊类型:Header
,标头包含时间戳和 ROS
中常用的坐标帧信息。会经常看到msg
文件的第一行具有 Header
标头。
我们要实现的话题模型如下:
其中 Message
中的 Person
为我们自定义的消息格式,该消息在订阅者和发布者之间传递。
在功能包 topic_demo
目录下创建一个 msg
文件夹,在该文件夹中创建一个 Person.msg
文件,如下图所示:
Person.msg
中有我们自定义的消息格式
string name
uint8 age
uint8 gender
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
在 package.xml
中添加以下 exec_depend
运行依赖:
<exec_depend>message_generation</exec_depend>
<exec_depend>message_runtime</exec_depend>
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
rospy
std_msgs
turtlesim
message_generation # 新增内容
add_message_files(
FILES
Person.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES topic_demo
CATKIN_DEPENDS geometry_msgs rospy std_msgs turtlesim message_runtime
# DEPENDS system_lib
)
到项目根目录下执行 catkin_make
命令
$ catkin_make
Base path: /home/wohu/project/ros/ros_demo
Source space: /home/wohu/project/ros/ros_demo/src
Build space: /home/wohu/project/ros/ros_demo/build
Devel space: /home/wohu/project/ros/ros_demo/devel
Install space: /home/wohu/project/ros/ros_demo/install
####
#### Running command: "make cmake_check_build_system" in "/home/wohu/project/ros/ros_demo/build"
####
####
#### Running command: "make -j12 -l12" in "/home/wohu/project/ros/ros_demo/build"
####
[ 0%] Built target std_msgs_generate_messages_py
[ 0%] Built target std_msgs_generate_messages_eus
[ 0%] Built target std_msgs_generate_messages_lisp
[ 0%] Built target std_msgs_generate_messages_nodejs
[ 0%] Built target std_msgs_generate_messages_cpp
[ 0%] Built target _topic_demo_generate_messages_check_deps_Person
[ 57%] Built target topic_demo_generate_messages_py
[ 57%] Built target topic_demo_generate_messages_eus
[ 71%] Built target topic_demo_generate_messages_cpp
[ 85%] Built target topic_demo_generate_messages_nodejs
[100%] Built target topic_demo_generate_messages_lisp
[100%] Built target topic_demo_generate_messages
可以看到会生成各种语言的代码文件。其中 Python
相关的代码文件在
/devel/lib/python2.7/dist-packages
目录下
发布者代码 person_publisher.py
:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
import rospy
from topic_demo.msg import Person
def velocity_publisher():
# ROS节点初始化
rospy.init_node('person_publisher', anonymous=True)
# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
#设置循环的频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化learning_topic::Person类型的消息
person_msg = Person()
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.gender = Person.male;
# 发布消息
person_info_pub.publish(person_msg)
rospy.loginfo("Publsh person message[%s, %d, %d]",
person_msg.name, person_msg.age, person_msg.gender)
# 按照循环频率延时
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
订阅者代码 person_subscriber.py
内容:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
import rospy
from topic_demo.msg import Person
def personInfoCallback(msg):
rospy.loginfo("Subcribe Person Info: name:%s age:%d gender:%d",
msg.name, msg.age, msg.gender)
def person_subscriber():
# ROS节点初始化
rospy.init_node('person_subscriber', anonymous=True)
# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
rospy.Subscriber("/person_info", Person, personInfoCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
person_subscriber()
运行代码命令:
$ cd ~/catkin_ws
$ catkin_make
$ source ./devel/setup.bash
$ rescore
$ rosrun topic_demo person_subscriber.py
$ rosrun topic_demo person_publisher.py