You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ROS中发布与订阅二维字符串数组/列表?

问题描述

需要编写ROS节点发布如下字符串矩阵:

sherd_1::link goHome0
sherd_2::link goHome0
sherd_3::link goHome0
sherd_5::link goHome0
sherd_6::link goHome1
sherd_9::link goHome1
sherd_10::link goHome2
sherd_11::link goHome1
sherd_12::link goHome0
sherd_13::link goHome2

尝试过程与错误

  1. 首先定义sherd_array.msg:
string[] sherds
string[] homes

该消息可正常发布订阅。

  1. 尝试定义matrix.msg为:
sherd_array[][] data

执行catkin_make时编译错误:

genmsg.base.InvalidMsgSpec: braccio_moveit_gazebo_noetic/custom_msgs/msg/matrix.msg: invalid field: Currently only support 1-dimensional array types: custom_msgs/sherd_array[][]
make[2]: *** [braccio_moveit_gazebo_noetic/custom_msgs/CMakeFiles/_custom_msgs_generate_messages_check_deps_matrix.dir/build.make:70: braccio_moveit_gazebo_noetic/custom_msgs/CMakeFiles/_custom_msgs_generate_messages_check_deps_matrix] Errore 1
make[1]: *** [CMakeFiles/Makefile2:1023: braccio_moveit_gazebo_noetic/custom_msgs/CMakeFiles/_custom_msgs_generate_messages_check_deps_matrix.dir/all] Errore 2
make: *** [Makefile:146: all] Errore 2
Invoking "make -j8 -l8" failed
  1. 修改matrix.msg为:
sherd_array[2] data

发布节点看似正常,但订阅时崩溃,报错:

line 60, in serialize    length = len(val1.sherds)
AttributeError: 'numpy.ndarray' object has no attribute 'sherds'

用rospy.loginfo输出的消息内容是正确的:

[INFO] [1697191139.662418, 201.596000]: data:
  - ['sherd_1::link' 'sherd_2::link' 'sherd_3::link' 'sherd_5::link'
 'sherd_6::link' 'sherd_9::link' 'sherd_10::link' 'sherd_11::link'
 'sherd_12::link' 'sherd_13::link']
  - ['goHome0' 'goHome0' 'goHome0' 'goHome0' 'goHome1' 'goHome1' 'goHome2'
 'goHome1' 'goHome0' 'goHome2']
解决方案

核心问题分析

ROS自定义消息不支持多维数组嵌套自定义消息(即sherd_array[][]这种形式);而修改为固定长度数组后出现的AttributeError,是因为直接将numpy数组赋值给了消息的data字段,但ROS消息期望的是sherd_array类型的对象列表,不是numpy数组。

正确实现方式

方式1:调整消息结构,贴合数据逻辑

如果你的矩阵是每行两个字符串(sherd名称和home目标),可以定义更贴合的基础消息:

# sherd_item.msg
string sherd_name
string home_target

再定义矩阵消息为一维数组:

# sherd_matrix.msg
sherd_item[] items

发布时把每行数据封装成sherd_item对象,再放到数组里即可,完全符合ROS消息规范,无编译或运行问题。

方式2:修复现有消息的赋值逻辑

若坚持使用现有的sherd_array和matrix.msg(sherd_array[2] data),需确保赋值给data的是sherd_array对象,而非numpy数组:

import rospy
from custom_msgs.msg import matrix, sherd_array

def talker():
    pub = rospy.Publisher('sherd_matrix', matrix, queue_size=10)
    rospy.init_node('matrix_publisher', anonymous=True)
    rate = rospy.Rate(10)

    # 原始数据
    sherds = ['sherd_1::link', 'sherd_2::link', 'sherd_3::link', 'sherd_5::link',
              'sherd_6::link', 'sherd_9::link', 'sherd_10::link', 'sherd_11::link',
              'sherd_12::link', 'sherd_13::link']
    homes = ['goHome0', 'goHome0', 'goHome0', 'goHome0',
             'goHome1', 'goHome1', 'goHome2', 'goHome1',
             'goHome0', 'goHome2']

    while not rospy.is_shutdown():
        # 创建matrix消息
        matrix_msg = matrix()
        
        # 创建第一个sherd_array对象,赋值sherds列表
        sa1 = sherd_array()
        sa1.sherds = sherds
        matrix_msg.data[0] = sa1
        
        # 创建第二个sherd_array对象,赋值homes列表
        sa2 = sherd_array()
        sa2.homes = homes
        matrix_msg.data[1] = sa2

        pub.publish(matrix_msg)
        rospy.loginfo(matrix_msg)
        rate.sleep()

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

这样data里的每个元素都是标准的sherd_array消息对象,具备sherds和homes属性,不会出现属性错误。

方式3:用一维字符串数组序列化传输

若不想自定义多层消息,可把每行数据用分隔符拼接成单个字符串,再放到一维数组里发布:

# matrix_string.msg
string[] rows

发布时每行拼接成sherd_1::link,goHome0这样的格式,订阅后用split(',')拆分即可还原二维数据,这种方式最简单,适合快速实现。

关键注意点

  • ROS自定义消息仅支持一维数组,无论基础类型还是自定义消息类型,都不能直接定义多维数组。
  • 赋值消息字段时,必须使用ROS自动生成的消息类对象,不能直接用numpy数组或原生列表(基础类型列表除外)。

内容的提问来源于stack exchange,提问作者caesar753

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:38:20