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

ROS2自定义Float32MultiArray子类转C时断言失败错误求助

ROS2中继承Float32MultiArray报错的原因及解决方法

问题场景

我尝试为ROS2的Float32MultiArray对象写一个封装类,用来存储物体的x、y、z三维坐标,代码如下:

class LocationMsg(Float32MultiArray):
    def __init__(self, x_c, y_c, z):
        super().__init__()
        self.data = [x_c, y_c, z]

启动ROS2项目时触发了Python到C的数据转换错误,错误信息如下:

python3: /tmp/binarydeb/ros-galactic-std-msgs-2.2.4/obj-aarch64-linux-gnu/rosidl_generator_py/std_msgs/msg/_float32_multi_array_s.c:55: std_msgs__msg__float32_multi_array__convert_from_py: Assertion `strncmp("std_msgs.msg._float32_multi_array.Float32MultiArray", full_classname_dest, 51) == 0' failed.
Stack trace (most recent call last):
#31   Object "/usr/bin/python3", at 0x503667, in _PyEval_EvalFrameDefault
#30   Object "/usr/bin/python3", at 0x5935e3, in _PyObject_MakeTpCall
#29   Object "/usr/bin/python3", at 0x534e87, in
#28   Object "/usr/bin/python3", at 0x59637f, in _PyObject_Call_Prepend
#27   Object "/usr/bin/python3", at 0x5960af, in _PyObject_FastCallDict
#26   Object "/usr/bin/python3", at 0x59684f, in _PyFunction_Vectorcall
#25   Object "/usr/bin/python3", at 0x4feda3, in _PyEval_EvalFrameDefault
#24   Object "/usr/bin/python3", at 0x48bf8f, in
#23   Object "/usr/bin/python3", at 0x487b37, in
#22   Object "/usr/bin/python3", at 0x5002db, in _PyEval_EvalFrameDefault
#21   Object "/usr/bin/python3", at 0x487b37, in
#20   Object "/usr/bin/python3", at 0x5002db, in _PyEval_EvalFrameDefault
#19   Object "/usr/bin/python3", at 0x487b37, in
#18   Object "/usr/bin/python3", at 0x5001c7, in _PyEval_EvalFrameDefault
#17   Object "/usr/bin/python3", at 0x592bb7, in PyObject_Call
#16   Object "/usr/bin/python3", at 0x493e03, in
#15   Object "/usr/bin/python3", at 0x59684f, in _PyFunction_Vectorcall
#14   Object "/usr/bin/python3", at 0x4feda3, in _PyEval_EvalFrameDefault
#13   Object "/usr/bin/python3", at 0x59684f, in _PyFunction_Vectorcall
#12   Object "/usr/bin/python3", at 0x50340f, in _PyEval_EvalFrameDefault
#11   Object "/usr/bin/python3", at 0x49438b, in
#10   Object "/usr/bin/python3", at 0x5935e3, in _PyObject_MakeTpCall
#9    Object "/usr/bin/python3", at 0x593247, in PyCFunction_Call
#8    Object "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/_rclpy_pybind11.cpython-38-aarch64-linux-gnu.so", at 0xffffbbe1ae8f, in
#7    Object "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/_rclpy_pybind11.cpython-38-aarch64-linux-gnu.so", at 0xffffbbddc05f, in
#6    Object "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/_rclpy_pybind11.cpython-38-aarch64-linux-gnu.so", at 0xffffbbde2983, in
#5    Object "/opt/ros/galactic/lib/librclpy_common.so", at 0xffffbbd98d3f, in rclpy_convert_from_py
#4    Object "/opt/ros/galactic/lib/libstd_msgs__python.so", at 0xffffa6dc17c3, in std_msgs__msg__float32_multi_array__convert_from_py
#3    Object "/lib/aarch64-linux-gnu/libc.so.6", at 0xffffbcc1e4f3, in __assert_fail
#2    Object "/lib/aarch64-linux-gnu/libc.so.6", at 0xffffbcc1e48f, in
#1    Object "/lib/aarch64-linux-gnu/libc.so.6", at 0xffffbcc11aab, in abort
#0    Object "/lib/aarch64-linux-gnu/libc.so.6", at 0xffffbcc24d78, in gsignal
Aborted (Signal sent by tkill() 9066 1000)

我使用的是ROS2 Galactic版本,试过用np.float32()转换坐标值但没用,而且发现self.data需要父类转换后的float类型。下面是最小复现代码:

#ROS2 Imports
import rclpy
from rclpy.node import Node
from std_msgs.msg import Float32MultiArray

import numpy as np

#Publisher class for 3 tuple of blob X Y Z coordinates
class LocationMsg(Float32MultiArray):
    def __init__(self, x_c, y_c, z):
        super().__init__()
        self.data = [x_c, y_c, z]
        

class TestNode(Node):

    def __init__(self):
        super().__init__('TestNode')

        self.timer_period = 1/12  # frequency to call timer_callback

        self.publisher_ = self.create_publisher(LocationMsg, "/Location", 10)
        self.timer = self.create_timer(self.timer_period, self.timer_callback)

    def timer_callback(self):
        x_c = 5.0
        y_c = 5.0
        z = 5.0
        msg = LocationMsg(x_c,y_c,z)
        self.LocationPublisher_.publish(msg)


def main(args=None):
    rclpy.init(args=args)
    publisher = TestNode()
    rclpy.spin(publisher)
    publisher.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

错误原因分析

ROS2的Python消息类由代码生成器自动生成,底层与C++实现强绑定。转换函数std_msgs__msg__float32_multi_array__convert_from_py会严格检查传入对象的类名,必须完全匹配std_msgs.msg._float32_multi_array.Float32MultiArray,自定义的LocationMsg类名不符合要求,因此断言失败。

此外,创建Publisher时指定LocationMsg作为消息类型,但ROS2通信系统仅识别官方生成的消息类型,自定义子类无法被正确识别和转换。

解决方案

不要直接继承ROS2的消息类,改用组合模式或静态工厂方法封装坐标创建逻辑:

方案1:静态工厂方法

在自定义类中实现静态方法,返回标准的Float32MultiArray对象:

class LocationMsg:
    @staticmethod
    def create(x_c, y_c, z):
        msg = Float32MultiArray()
        msg.data = [float(x_c), float(y_c), float(z)]
        return msg

使用方式:

msg = LocationMsg.create(x_c, y_c, z)
self.publisher_.publish(msg)

创建Publisher时需指定标准消息类型:

self.publisher_ = self.create_publisher(Float32MultiArray, "/Location", 10)

方案2:组合类

将Float32MultiArray作为实例属性,提供获取消息对象的方法:

class LocationMsg:
    def __init__(self, x_c, y_c, z):
        self._msg = Float32MultiArray()
        self._msg.data = [float(x_c), float(y_c), float(z)]
    
    def get_msg(self):
        return self._msg
    
    # 可选:添加坐标访问与修改方法
    @property
    def x(self):
        return self._msg.data[0]
    
    @x.setter
    def x(self, value):
        self._msg.data[0] = float(value)

使用方式:

msg = LocationMsg(x_c, y_c, z)
self.publisher_.publish(msg.get_msg())

额外修复:复现代码中的拼写错误

TestNode类中self.LocationPublisher_未定义,需改为self.publisher_,否则运行时会触发属性错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:27:03