FLT_MAX fails when using Python subscriber or publisher with float32 msg type

asked 2022-09-20 20:09:27 -0600

I might find some unexpected behavior with float32 max. ROS2 humble makes error when numeric_limits<float>::max() or np.finfo(np.float32).max are sent in float32 message if we use Python.

When we write a publisher in C++ and a subscriber in Python, it fails in the subscriber:

[test_subscription-2]   File "/opt/ros/humble/rclpy/lib/python3.8/site-packages/rclpy/executors.py", line 336, in _take_subscription
[test_subscription-2]     msg_info = sub.handle.take_message(sub.msg_type, sub.raw)
[test_subscription-2]
RuntimeError: make_tuple(): unable to convert argument of type 'object' to Python object

When we write a publisher in Python, it fails in the publisher.

[test_publisher-1]   File "/app/test/src/install/interfaces/lib/python3.8/site-packages/interfaces/msg/_test.py", line 124, in value
[test_publisher-1]     assert value >= -3.402823e+38 and value <= 3.402823e+38,
[test_publisher-1] AssertionError: The 'value' field must be a float in [-3.402823e+38, 3.402823e+38]

The second Python publisher case must be from this code:

@f.setter
def f(self, value):
    if __debug__:
        assert \
            isinstance(value, float), \
            "The 'f' field must be of type 'float'"
        assert value >= -3.402823e+38 and value <= 3.402823e+38, \
            "The 'f' field must be a float in [-3.402823e+38, 3.402823e+38]"
    self._f = value

the range is defined not using np.finfo(np.float32).max and comparation is done with (double) 3.402823e+38, which is smaller than np.finfo(np.float32).max or FLT_MAX.

Test code is like following:

Msg definition (Test.msg)

float32 f

Publisher in Python

test_info = Test()
float_casted_max = float(np.finfo(np.float32).max)
test_info.f = float_casted_max
self.pub_test_info.publish(test_info)

Publisher in C++

auto test_msg = interfaces::msg::Test();
test_msg.f = std::numeric_limits<float>::max();
test_pub_->publish(test_msg);

Subscriber in Python

class TestSubscription(Node):
    def __init__(self):
        super().__init__("test_subscription")
        self.sub_test = self.create_subscription(Test, "test", self.listener_callback_key, 10)

test_subscription = TestSubscription()
try:
    rclpy.spin(test_subscription)

Probably, this question is related to https://github.com/ros2/rosidl/issues...

edit retag flag offensive close merge delete

Comments

This is probably also related: https://github.com/ros2/rosidl_python...

SETA Takahiro gravatar image SETA Takahiro  ( 2022-09-20 20:22:33 -0600 )edit