Message equality fails with NaN values for floats/doubles
評価
調査の方向性
nan-failed-comparison コミットと、レポートに示されている失敗した test_basic_types ケースから始めます。float フィールドに対して rosidl_generator_py が使用するメッセージ等価性の経路を追跡し、その後、関連するテストを実行して、同じ NaN 内容を持つメッセージが等しいと比較されることを確認します。
索引モデルが issue の本文から書いたものです。
説明
Bug report
Required Info:
- Operating System:
- Ubuntu 22.04
- Installation type:
- Binaries and Source
- Version or commit hash:
- 0.14.4
- DDS implementation:
- N/A
- Client library (if applicable):
- N/A
Steps to reproduce issue
See the commit on equality which causes the tests to fail on branch nan-failed-comparison
Expected behavior
When floating point values are set to NaN, and the == equality operator is used to check messages are equal, it should return true when two messages have the same contents
Actual behavior
NaN's don't equal themselves, and the message equality evaluates as False.
Additional information
See https://github.com/ros2/rosidl/pull/789#issuecomment-2000037932
I have a fix internally, I just need approval to share it open source.
Test Logs
21: =================================== FAILURES ===================================
21: _______________________________ test_basic_types _______________________________
21:
21: def test_basic_types():
21: msg = BasicTypes()
21:
21: # types
21: assert isinstance(msg.bool_value, bool)
21: assert isinstance(msg.byte_value, bytes)
21: assert 1 == len(msg.byte_value)
21: # for legacy reasons, 'char' from a .msg interface maps to 'uint8'
21: assert isinstance(msg.char_value, int)
21: assert isinstance(msg.float32_value, float)
21: assert isinstance(msg.float64_value, float)
21: assert isinstance(msg.int8_value, int)
21: assert isinstance(msg.uint8_value, int)
21: assert isinstance(msg.int16_value, int)
21: assert isinstance(msg.uint16_value, int)
21: assert isinstance(msg.int32_value, int)
21: assert isinstance(msg.uint32_value, int)
21: assert isinstance(msg.int64_value, int)
21: assert isinstance(msg.uint64_value, int)
21:
21: # default values
21: assert msg.bool_value is False
21: assert bytes([0]) == msg.byte_value
21: assert 0 == msg.char_value
21: assert 0.0 == msg.float32_value
21: assert 0.0 == msg.float64_value
21: assert 0 == msg.int8_value
21: assert 0 == msg.uint8_value
21: assert 0 == msg.int16_value
21: assert 0 == msg.uint16_value
21: assert 0 == msg.int32_value
21: assert 0 == msg.uint32_value
21: assert 0 == msg.int64_value
21: assert 0 == msg.uint64_value
21:
21: # assignment
21: msg.bool_value = True
21: assert msg.bool_value is True
21: msg.byte_value = b'2'
21: assert bytes([50]) == msg.byte_value
21: msg.char_value = 42
21: assert 42 == msg.char_value
21: msg.float32_value = 1.125
21: assert 1.125 == msg.float32_value
21: msg.float64_value = 1.125
21: assert 1.125 == msg.float64_value
21: msg.int8_value = -50
21: assert -50 == msg.int8_value
21: msg.uint8_value = 200
21: assert 200 == msg.uint8_value
21: msg.int16_value = -1000
21: assert -1000 == msg.int16_value
21: msg.uint16_value = 2000
21: assert 2000 == msg.uint16_value
21: msg.int32_value = -30000
21: assert -30000 == msg.int32_value
21: msg.uint32_value = 60000
21: assert 60000 == msg.uint32_value
21: msg.int64_value = -40000000
21: assert -40000000 == msg.int64_value
21: msg.uint64_value = 50000000
21: assert 50000000 == msg.uint64_value
21:
21: # out of range
21: with pytest.raises(AssertionError):
21: setattr(msg, 'char_value', '\x80')
21: for i in [8, 16, 32, 64]:
21: with pytest.raises(AssertionError):
21: setattr(msg, 'int%d_value' % i, 2**(i - 1))
21: with pytest.raises(AssertionError):
21: setattr(msg, 'int%d_value' % i, -2**(i - 1) - 1)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'uint%d_value' % i, -1)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'int%d_value' % i, 2**i)
21: float32_ieee_max_next = numpy.nextafter(3.402823466e+38, math.inf)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'float32_value', -float32_ieee_max_next)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'float32_value', float32_ieee_max_next)
21:
21: # Only run bounds test on system with non-compliant IEEE 754 float64.
21: # Otherwise the number is implicitly converted to inf.
21: if sys.float_info.max > 1.7976931348623157e+308:
21: float64_ieee_max_next = numpy.nextafter(1.7976931348623157e+308, math.inf)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'float64_value', -float64_ieee_max_next)
21: with pytest.raises(AssertionError):
21: setattr(msg, 'float64_value', float64_ieee_max_next)
21:
21: # NaN
21: setattr(msg, 'float32_value', math.nan)
21: assert math.isnan(msg.float32_value)
21: > assert msg == msg
21: E AssertionError: assert rosidl_generator_py.msg.BasicTypes(bool_value=True, byte_value=b'2', char_value=42, float32_value=nan, float64_value=1...6_value=-1000, uint16_value=2000, int32_value=-30000, uint32_value=60000, int64_value=-40000000, uint64_value=50000000) == rosidl_generator_py.msg.BasicTypes(bool_value=True, byte_value=b'2', char_value=42, float32_value=nan, float64_value=1...6_value=-1000, uint16_value=2000, int32_value=-30000, uint32_value=60000, int64_value=-40000000, uint64_value=50000000)
- 主要言語
- EmberScript
- スター
- 26
- フォーク
- 68
- 平均マージ
- 1日 9時間
- マージ済み PR(30日)
- 3
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
ros2/rosidl_python のほかの issue
-
Eliminate array resetting loop in _msg_support.c.em対応中かも @Lidang-Jiang が 168 日前に担当しました。 オープンenhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
ros2/rosidl_python#255 · リアクション 1 件 ·
-
bug
難易度 3/5 1〜2日 初心者へのやさしさ 56/100
ros2/rosidl_python#264 · コメント 2 件 ·
-
Message named pkg/Duration with field builtin_interfaces/Duration is invalid対応中かも @Lidang-Jiang が 167 日前に担当しました。 オープンbug
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
ros2/rosidl_python#257 · コメント 8 件 ·
-
enhancement
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
ros2/rosidl_python#242 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 32/100
ros2/rosidl_python#219 · コメント 2 件 ·
ros2/rosidl_python の issue をすべて見る
似ている issue
-
beginner friendly community contributions-welcome data-structures good first issue hacktoberfest help wanted up-for-grabs
難易度 2/5 1〜3時間 初心者へのやさしさ 92/100
メンテナーはふだん 1 日以内に返信
-
Hermes: /ponytail off never reaches the model, the ruleset stays active対応中かも @szsunyuan が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
DietrichGebert/ponytail#1121 ·
メンテナーはふだん 3 日以内に返信
-
[Bug]: Three default prefs with JSON values are never set (override.sh escapes their quotes twice)オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
Floorp-Projects/Floorp#2913 ·
メンテナーはふだん 1 日以内に返信
-
agent/quality hive/hosted-available-lke648397-260827-5q9t needs-kind quality testing
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
cncf/prow-github-actions#466 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
area: ui difficulty: easy enhancement good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 87/100
メンテナーはふだん 1 日以内に返信