Skip to content

Commit 5280456

Browse files
committed
Add support for NaN constants and defaults in ROS IDL
* Add nan default example and tests * Add NaN constant example and tests * Test NaNs on float64 and float32 in C++ Signed-off-by: Ryan Friedman <[email protected]>
1 parent 0775e10 commit 5280456

File tree

10 files changed

+52
-5
lines changed

10 files changed

+52
-5
lines changed

rosidl_adapter/test/test_constant.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ def test_constant_constructor():
3030
with pytest.raises(ValueError):
3131
Constant('bool', 'FOO', None)
3232

33+
# NaN is case insensitive in python, so test a few variations.
34+
value = Constant('float32', 'FOO', 'nan')
35+
value = Constant('float32', 'FOO', 'Nan')
36+
value = Constant('float32', 'FOO', 'NaN')
37+
value = Constant('float32', 'FOO', 'NAN')
38+
value = Constant('float64', 'FOO', 'nan')
39+
value = Constant('float64', 'FOO', 'Nan')
40+
value = Constant('float64', 'FOO', 'NaN')
41+
value = Constant('float64', 'FOO', 'NAN')
42+
3343

3444
def test_constant_methods():
3545
assert Constant('bool', 'FOO', '1') != 23

rosidl_generator_c/resource/idl__struct.h.em

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ extern "C"
3232
{
3333
#endif
3434
35+
#include <math.h>
3536
#include <stdbool.h>
3637
#include <stddef.h>
3738
#include <stdint.h>
38-
3939
@#######################################################################
4040
@# Handle message
4141
@#######################################################################

rosidl_generator_c/rosidl_generator_c/__init__.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
from math import isnan
1415

1516
from rosidl_generator_type_description import parse_rihs_string
1617
from rosidl_generator_type_description import RIHS01_HASH_VALUE_SIZE
@@ -209,10 +210,16 @@ def basic_value_to_c(type_, value):
209210
return f'{value}ull'
210211

211212
if 'float' == type_.typename:
212-
return f'{value}f'
213+
if isnan(float(value)):
214+
return 'nanf(\"\")'
215+
else:
216+
return f'{value}f'
213217

214218
if 'double' == type_.typename:
215-
return f'{value}l'
219+
if isnan(float(value)):
220+
return 'nan(\"\")'
221+
else:
222+
return f'{value}l'
216223

217224
assert False, "unknown basic type '%s'" % type_
218225

rosidl_generator_cpp/resource/idl__struct.hpp.em

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ include_directives = set()
2828
2929
#include <algorithm>
3030
#include <array>
31+
#include <limits>
3132
#include <memory>
3233
#include <string>
3334
#include <vector>

rosidl_generator_cpp/resource/msg__struct.hpp.em

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,12 @@ non_defaulted_zero_initialized_members = [
286286
@[ if constant.type.typename in UNSIGNED_INTEGER_TYPES]@
287287
u@
288288
@[ end if]@
289-
@[ elif constant.type.typename == 'float']@
290-
@(constant.value)f@
289+
@[ elif constant.type.typename == 'float' or constant.type.typename == 'double']@
290+
@{
291+
from rosidl_generator_cpp import primitive_value_to_cpp
292+
val = primitive_value_to_cpp(constant.type, constant.value)
293+
}@
294+
@(val)@
291295
@[ else]@
292296
@(constant.value)@
293297
@[ end if];

rosidl_generator_cpp/rosidl_generator_cpp/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from ast import literal_eval
16+
from math import isnan
1617

1718
from rosidl_parser.definition import AbstractGenericString
1819
from rosidl_parser.definition import AbstractNestedType
@@ -195,6 +196,11 @@ def primitive_value_to_cpp(type_, value):
195196
if type_.typename == 'boolean':
196197
return 'true' if value else 'false'
197198

199+
if type_.typename in ['double', 'long double', 'float']:
200+
# Handle special floating types here.
201+
if isnan(float(value)):
202+
return f'std::numeric_limits<{type_.typename}>::quiet_NaN()'
203+
198204
if type_.typename in [
199205
'short', 'unsigned short',
200206
'char', 'wchar',

rosidl_generator_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ if(BUILD_TESTING)
3535
${test_interface_files_MSG_FILES}
3636
${test_interface_files_SRV_FILES}
3737
msg/BasicIdl.idl
38+
msg/NanValueConstant.msg
39+
msg/NanValueDefault.msg
3840
msg/SmallConstant.msg
3941
ADD_LINTER_TESTS
4042
SKIP_INSTALL
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
float32 FLOAT32_NAN=NaN
2+
float64 FLOAT64_NAN=nan
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
float32 float32_nan NaN
2+
float64 float64_nan nan

rosidl_generator_tests/test/rosidl_generator_cpp/test_interfaces.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "rosidl_generator_tests/msg/multi_nested.hpp"
3434
#include "rosidl_generator_tests/msg/nested.hpp"
3535
#include "rosidl_generator_tests/msg/small_constant.hpp"
36+
#include "rosidl_generator_tests/msg/nan_value_constant.hpp"
37+
#include "rosidl_generator_tests/msg/nan_value_default.hpp"
3638
#include "rosidl_generator_tests/msg/strings.hpp"
3739
#include "rosidl_generator_tests/msg/unbounded_sequences.hpp"
3840
#include "rosidl_generator_tests/msg/w_strings.hpp"
@@ -475,6 +477,11 @@ TEST(Test_messages, constants_assign) {
475477
ASSERT_EQ(x, rosidl_generator_tests::msg::SmallConstant::FLOAT32_CONST);
476478
}
477479

480+
TEST(Test_messages, nan_constants) {
481+
ASSERT_TRUE(std::isnan(rosidl_generator_tests::msg::NanValueConstant::FLOAT32_NAN));
482+
ASSERT_TRUE(std::isnan(rosidl_generator_tests::msg::NanValueConstant::FLOAT64_NAN));
483+
}
484+
478485
// Defaults
479486
TEST(Test_messages, defaults) {
480487
rosidl_generator_tests::msg::Defaults message;
@@ -501,6 +508,12 @@ TEST(Test_messages, defaults) {
501508
TEST_BASIC_TYPE_FIELD_ASSIGNMENT(message, uint64_value, 50000000ull, UINT64_MAX);
502509
}
503510

511+
TEST(Test_messages, nan_defaults) {
512+
rosidl_generator_tests::msg::NanValueDefault nan_val_default;
513+
ASSERT_TRUE(std::isnan(nan_val_default.float32_nan));
514+
ASSERT_TRUE(std::isnan(nan_val_default.float64_nan));
515+
}
516+
504517
// String array with default values
505518
TEST(Test_messages, string_arrays_default) {
506519
rosidl_generator_tests::msg::Arrays message;

0 commit comments

Comments
 (0)