本文记录一下用python编写使用自定义消息的ros订阅者和发布者时存在的一些问题。

声明一下,本文的代码是从自己项目工程截取的,不适合直接使用,只适合作为参照模板

1、首先是如何创建msg文件和编译

文件结构如图:

catkin_ws
├── build
├── devel
└── src
    ├── robot_msgs
    │   ├── CMakeLists.txt
    │   ├── msg
    │   │   └── Controldata.msg
    │   └── package.xml
    └── tcp_ros
        └── script
            └── test.py

catkin_ws工作空间里有两个package,一个只用来存放消息(可自行添加更多消息),一个用于存放代码。

Controldata.msg消息文件如下:

uint32   cmd
float32 param1
float32 param2

在robot_msgs包里的CMakerList.txt:

cmake_minimum_required(VERSION 2.8.3)
project(robot_msgs)
#这里添加依赖message_generation 用于生成消息
find_package(catkin REQUIRED COMPONENTS   
  message_generation 
  std_msgs 
  geometry_msgs
)
#这里添加消息文件Controldata.msg
add_message_files(        
  DIRECTORY msg
  FILES
  Controldata.msg
)

generate_messages(DEPENDENCIES std_msgs geometry_msgs)  
 #这里增加消息生成包message_runtime 
catkin_package(CATKIN_DEPENDS message_runtime std_msgs geometry_msgs)

在robot_msgs包里的package.xml添加如下:

<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>

在tcp_ros包里的CMakerList:

find_package(catkin REQUIRED COMPONENTS   #查找robot_msgs包
  roscpp
  rospy
  std_msgs
  robot_msgs
)
catkin_package(                           #包含robot_msgs包
  INCLUDE_DIRS include
  LIBRARIES tjurobot
  CATKIN_DEPENDS roscpp rospy std_msgs robot_msgs message_runtime    
  DEPENDS system_lib
)

2、python编写的发布者节点

  • 发布者程序: 关键是如何在python节点里导入存在其他package的msg文件!!
#!/usr/bin/env python
# license removed for brevity
import rospy
from robot_msgs.msg import Controldata  #翻译为:从robot_msgs包里的msg文件夹内导入名为Controldata的msg文件!

def talker():
    pub = rospy.Publisher('chatter', Controldata, queue_size=10)  #设置发布话题名为“chatter”,消息类型为Controldata.msg,消息队列最大容量为10帧的对象pub
    rospy.init_node('talker', anonymous=True)   #初始化名为“talker”的节点
    rate = rospy.Rate(10) # 10hz     
    while not rospy.is_shutdown():
        send_msg = Controldata()   #初始化一个消息结构体:直接以该msg文件名作为函数
        send_msg.cmd =0X15      #给send_msg结构体内参数赋值(也就是该msg文件内参数)
        send_msg.param1 = 123
        send_msg.param2 = 0
        pub.publish(send_msg)    #调用pub对象的publish函数发布话题
        rate.sleep()    #在循环中可以用刚刚好的睡眠时间维持期望的速率,适用于需要不停发布的话题

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

3、python编写的订阅者节点

  • 订阅者程序:关键是如何在回调函数里运用话题数据
#!/usr/bin/env python
import rospy
from robot_msgs.msg import Controldata

def callback_fuc(data):      #该data则相当于发布者的send_msg结构体
    rospy.loginfo("I heard %d,%d,%d", data.cmd,data.param1,data.param2)
    
def listener():
    rospy.init_node('listener', anonymous=True)  #初始化名为“listener”的订阅者节点:anonymous=True会为节点生成唯一的名称避免节点重名
    rospy.Subscriber("chatter", Controldata, callback_fuc)  #设置订阅者属性:订阅的话题名“chatter”,话题对应的msg消息文件名,回调函数名
    rospy.spin()     #必须要有,否则无法接收,但会相当于死循环程序会卡在这里
    
if __name__ == '__main__':
    listener()