-
Notifications
You must be signed in to change notification settings - Fork 434
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add type_description struct conversion utils
Signed-off-by: methylDragon <[email protected]>
- Loading branch information
1 parent
a0a2a06
commit 1ee6c1f
Showing
3 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
215 changes: 215 additions & 0 deletions
215
rclcpp/include/rclcpp/dynamic_typesupport/type_description_conversions.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
// Copyright 2025 Open Source Robotics Foundation, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__TYPE_DESCRIPTION_CONVERSIONS_HPP_ | ||
#define RCLCPP__DYNAMIC_TYPESUPPORT__TYPE_DESCRIPTION_CONVERSIONS_HPP_ | ||
|
||
#include "rosidl_runtime_cpp/type_description/individual_type_description__struct.hpp" | ||
#include "rosidl_runtime_cpp/type_description/type_description__struct.hpp" | ||
#include "rosidl_runtime_cpp/type_description/type_source__struct.hpp" | ||
#include "type_description_interfaces/msg/individual_type_description.hpp" | ||
#include "type_description_interfaces/msg/type_description.hpp" | ||
#include "type_description_interfaces/msg/type_source.hpp" | ||
|
||
namespace rclcpp | ||
{ | ||
namespace dynamic_typesupport | ||
{ | ||
|
||
// IndividualTypeDescription ======================================================================= | ||
|
||
/// Convert a runtime individual type description struct to its corresponding message. | ||
/** | ||
* This function converts a rosidl_runtime_cpp::type_description::IndividualTypeDescription | ||
* struct to the corresponding type_description_interfaces/msg/IndividualTypeDescription | ||
* msg. | ||
* | ||
* \param[in] runtime_individual_description the runtime struct to convert | ||
* \return the converted individual type description msg | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
type_description_interfaces::msg::IndividualTypeDescription_<ToAllocatorT> | ||
convert_individual_type_description_runtime_to_msg( | ||
const rosidl_runtime_cpp::type_description::IndividualTypeDescription_<FromAllocatorT> & | ||
runtime_individual_description, const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
type_description_interfaces::msg::IndividualTypeDescription_<ToAllocatorT> out(alloc); | ||
out.type_name = runtime_individual_description.type_name; | ||
|
||
for (const auto & field : runtime_individual_description.fields) { | ||
out.fields.emplace_back(); | ||
out.fields.back().name = field.name; | ||
out.fields.back().default_value = field.default_value; | ||
|
||
out.fields.back().type.type_id = field.type.type_id; | ||
out.fields.back().type.capacity = field.type.capacity; | ||
out.fields.back().type.string_capacity = field.type.string_capacity; | ||
out.fields.back().type.nested_type_name = field.type.nested_type_name; | ||
} | ||
return out; | ||
} | ||
|
||
/// Convert a individual type description message to its corresponding runtime struct. | ||
/** | ||
* This function converts a type_description_interfaces/msg/IndividualTypeDescription msg | ||
* to the corresponding rosidl_runtime_cpp::type_description::IndividualTypeDescription | ||
* struct. | ||
* | ||
* \param[in] description_msg the message to convert | ||
* \return the converted runtime struct | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
rosidl_runtime_cpp::type_description::IndividualTypeDescription_<ToAllocatorT> | ||
convert_individual_type_description_msg_to_runtime( | ||
const type_description_interfaces::msg::IndividualTypeDescription_<FromAllocatorT> & | ||
individual_description_msg, const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
rosidl_runtime_cpp::type_description::IndividualTypeDescription_<ToAllocatorT> out(alloc); | ||
out.type_name = individual_description_msg.type_name; | ||
|
||
for (const auto & field : individual_description_msg.fields) { | ||
out.fields.emplace_back(); | ||
out.fields.back().name = field.name; | ||
out.fields.back().default_value = field.default_value; | ||
|
||
out.fields.back().type.type_id = field.type.type_id; | ||
out.fields.back().type.capacity = field.type.capacity; | ||
out.fields.back().type.string_capacity = field.type.string_capacity; | ||
out.fields.back().type.nested_type_name = field.type.nested_type_name; | ||
} | ||
return out; | ||
} | ||
|
||
// TypeDescription ================================================================================= | ||
|
||
/// Convert a runtime type description struct to its corresponding message. | ||
/** | ||
* This function converts a rosidl_runtime_cpp::type_description::TypeDescription | ||
* struct to the corresponding type_description_interfaces/msg/TypeDescription | ||
* msg. | ||
* | ||
* \param[in] runtime_description the runtime struct to convert | ||
* \return the converted message | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
type_description_interfaces::msg::TypeDescription_<ToAllocatorT> | ||
convert_type_description_runtime_to_msg( | ||
const rosidl_runtime_cpp::type_description::TypeDescription_<FromAllocatorT> & runtime_description, | ||
const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
type_description_interfaces::msg::TypeDescription_<ToAllocatorT> out(alloc); | ||
out.type_description = | ||
convert_individual_type_description_runtime_to_msg(runtime_description.type_description, alloc); | ||
|
||
for (const auto & referenced_type_description : | ||
runtime_description.referenced_type_descriptions) | ||
{ | ||
out.referenced_type_descriptions.push_back(convert_individual_type_description_runtime_to_msg( | ||
referenced_type_description, alloc)); | ||
} | ||
return out; | ||
} | ||
|
||
/// Convert a type description message to its corresponding runtime struct. | ||
/** | ||
* This function converts a type_description_interfaces/msg/TypeDescription msg | ||
* to the corresponding rosidl_runtime_cpp::type_description::TypeDescription | ||
* struct. | ||
* | ||
* \param[in] description_msg the message to convert | ||
* \return the converted runtime struct | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
rosidl_runtime_cpp::type_description::TypeDescription_<ToAllocatorT> | ||
convert_type_description_msg_to_runtime( | ||
const type_description_interfaces::msg::TypeDescription_<FromAllocatorT> & description_msg, | ||
const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
rosidl_runtime_cpp::type_description::TypeDescription_<ToAllocatorT> out(alloc); | ||
out.type_description = | ||
convert_individual_type_description_msg_to_runtime(description_msg.type_description, alloc); | ||
|
||
for (const auto & referenced_type_description : description_msg.referenced_type_descriptions) { | ||
out.referenced_type_descriptions.push_back(convert_individual_type_description_msg_to_runtime( | ||
referenced_type_description, alloc)); | ||
} | ||
return out; | ||
} | ||
|
||
// TypeSource ====================================================================================== | ||
|
||
/// Convert a runtime type source struct to its corresponding message. | ||
/** | ||
* This function converts a rosidl_runtime_cpp::type_description::TypeSource | ||
* struct to the corresponding type_description_interfaces/msg/TypeSource msg. | ||
* | ||
* \param[in] runtime_type_source the runtime struct to convert | ||
* \return the converted message | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
type_description_interfaces::msg::TypeSource_<ToAllocatorT> | ||
convert_type_source_sequence_runtime_to_msg( | ||
const rosidl_runtime_cpp::type_description::TypeSource_<FromAllocatorT> & runtime_type_source, | ||
const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
type_description_interfaces::msg::TypeSource_<ToAllocatorT> out(alloc); | ||
out.type_name = runtime_type_source.type_name; | ||
out.encoding = runtime_type_source.encoding; | ||
out.raw_file_contents = runtime_type_source.raw_file_contents; | ||
return out; | ||
} | ||
|
||
/// Convert a type source message to its corresponding runtime struct. | ||
/** | ||
* This function converts a type_description_interfaces/msg/TypeSource msg to | ||
* the corresponding rosidl_runtime_cpp::type_description::TypeSource struct. | ||
* | ||
* \param[in] type_source_msg the message to convert | ||
* \return the converted runtime struct | ||
*/ | ||
template< | ||
typename ToAllocatorT = std::allocator<void>, | ||
typename FromAllocatorT | ||
> | ||
rosidl_runtime_cpp::type_description::TypeSource_<ToAllocatorT> | ||
convert_type_source_sequence_msg_to_runtime( | ||
const type_description_interfaces::msg::TypeSource_<FromAllocatorT> & type_source_msg, | ||
const ToAllocatorT & alloc = ToAllocatorT()) | ||
{ | ||
rosidl_runtime_cpp::type_description::TypeSource_<ToAllocatorT> out(alloc); | ||
out.type_name = type_source_msg.type_name; | ||
out.encoding = type_source_msg.encoding; | ||
out.raw_file_contents = type_source_msg.raw_file_contents; | ||
return out; | ||
} | ||
|
||
} // namespace dynamic_typesupport | ||
} // namespace rclcpp | ||
|
||
#endif // RCLCPP__DYNAMIC_TYPESUPPORT__TYPE_DESCRIPTION_CONVERSIONS_HPP_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
rclcpp/test/rclcpp/dynamic_typesupport/test_type_description_conversions.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright 2025 Open Source Robotics Foundation, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include "rclcpp/dynamic_typesupport/type_description_conversions.hpp" | ||
#include "rosidl_runtime_cpp/type_description/individual_type_description__struct.hpp" | ||
#include "rosidl_runtime_cpp/type_description/type_description__struct.hpp" | ||
#include "rosidl_runtime_cpp/type_description/type_source__struct.hpp" | ||
#include "type_description_interfaces/msg/individual_type_description.hpp" | ||
#include "type_description_interfaces/msg/type_description.hpp" | ||
#include "type_description_interfaces/msg/type_source.hpp" | ||
|
||
using rclcpp::dynamic_typesupport:: | ||
convert_individual_type_description_msg_to_runtime; | ||
using rclcpp::dynamic_typesupport:: | ||
convert_individual_type_description_runtime_to_msg; | ||
using rclcpp::dynamic_typesupport::convert_type_description_msg_to_runtime; | ||
using rclcpp::dynamic_typesupport::convert_type_description_runtime_to_msg; | ||
using rclcpp::dynamic_typesupport::convert_type_source_sequence_msg_to_runtime; | ||
using rclcpp::dynamic_typesupport::convert_type_source_sequence_runtime_to_msg; | ||
|
||
TEST(TestTypeDescriptionConversions, individual_type_description_roundtrip) | ||
{ | ||
rosidl_runtime_cpp::type_description::IndividualTypeDescription original; | ||
original.type_name = "test_type_name"; | ||
|
||
original.fields.emplace_back(); | ||
original.fields.back().name = "field1"; | ||
original.fields.back().type.type_id = 1; | ||
|
||
original.fields.emplace_back(); | ||
original.fields.back().name = "field2"; | ||
original.fields.back().type.type_id = 2; | ||
|
||
type_description_interfaces::msg::IndividualTypeDescription msg = | ||
convert_individual_type_description_runtime_to_msg(original); | ||
rosidl_runtime_cpp::type_description::IndividualTypeDescription converted_back | ||
= | ||
convert_individual_type_description_msg_to_runtime(msg); | ||
|
||
EXPECT_EQ(original.type_name, converted_back.type_name); | ||
ASSERT_EQ(original.fields.size(), converted_back.fields.size()); | ||
for (size_t i = 0; i < original.fields.size(); ++i) { | ||
EXPECT_EQ(original.fields[i].name, converted_back.fields[i].name); | ||
EXPECT_EQ(original.fields[i].type, converted_back.fields[i].type); | ||
} | ||
} | ||
|
||
TEST(TestTypeDescriptionConversions, type_description_roundtrip) | ||
{ | ||
rosidl_runtime_cpp::type_description::TypeDescription original; | ||
original.type_description.type_name = "main_type"; | ||
original.type_description.fields.emplace_back(); | ||
original.type_description.fields.back().name = "field1"; | ||
original.type_description.fields.back().type.type_id = 1; | ||
original.type_description.fields.emplace_back(); | ||
original.type_description.fields.back().name = "field2"; | ||
original.type_description.fields.back().type.type_id = 2; | ||
|
||
rosidl_runtime_cpp::type_description::IndividualTypeDescription ref1; | ||
ref1.type_name = "ref_type_1"; | ||
ref1.fields.emplace_back(); | ||
ref1.fields.back().name = "ref_field1"; | ||
ref1.fields.back().type.type_id = 1; | ||
|
||
rosidl_runtime_cpp::type_description::IndividualTypeDescription ref2; | ||
ref2.type_name = "ref_type_2"; | ||
ref2.fields.emplace_back(); | ||
ref2.fields.back().name = "ref_field2"; | ||
ref2.fields.back().type.type_id = 2; | ||
|
||
original.referenced_type_descriptions.push_back(ref1); | ||
original.referenced_type_descriptions.push_back(ref2); | ||
|
||
type_description_interfaces::msg::TypeDescription msg = | ||
convert_type_description_runtime_to_msg(original); | ||
rosidl_runtime_cpp::type_description::TypeDescription converted_back = | ||
convert_type_description_msg_to_runtime(msg); | ||
|
||
EXPECT_EQ(original.type_description.type_name, | ||
converted_back.type_description.type_name); | ||
ASSERT_EQ(original.referenced_type_descriptions.size(), | ||
converted_back.referenced_type_descriptions.size()); | ||
|
||
for (size_t i = 0; i < original.referenced_type_descriptions.size(); ++i) { | ||
EXPECT_EQ(original.referenced_type_descriptions[i].type_name, | ||
converted_back.referenced_type_descriptions[i].type_name); | ||
} | ||
} | ||
|
||
TEST(TestTypeSourceConversions, type_source_roundtrip) | ||
{ | ||
rosidl_runtime_cpp::type_description::TypeSource original; | ||
original.type_name = "test_type_name"; | ||
original.encoding = "test_encoding"; | ||
original.raw_file_contents = "test_contents"; | ||
|
||
type_description_interfaces::msg::TypeSource msg = | ||
convert_type_source_sequence_runtime_to_msg(original); | ||
rosidl_runtime_cpp::type_description::TypeSource converted_back = | ||
convert_type_source_sequence_msg_to_runtime(msg); | ||
|
||
EXPECT_EQ(original.type_name, converted_back.type_name); | ||
EXPECT_EQ(original.encoding, converted_back.encoding); | ||
EXPECT_EQ(original.raw_file_contents, converted_back.raw_file_contents); | ||
} |