Skip to content

Commit 7b762e9

Browse files
committed
added utility function for converting only selected members of a message
Signed-off-by: Dominik Authaler <[email protected]>
1 parent e62c0ed commit 7b762e9

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

dynmsg/include/dynmsg/message_reading.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ namespace cpp
5252
*/
5353
YAML::Node message_to_yaml(const RosMessage_Cpp & message);
5454

55+
/// Variant of dynmsg::cpp::message_to_yaml() for converting only selected members of a message into a YAML format.
56+
/**
57+
* \details In order to decrease the overhead of converting full messages into their corresponding YAML format this
58+
* function uses the type introspection information to convert solely the specified member. This member
59+
* can either be a raw value or a message itself.
60+
*
61+
* \param message ROS message to convert.
62+
* \param member_identifier Identifier of the member, multiple levels within the message are separated by '/'.
63+
* \return YAML representation of the selected member, will be null if the specified member is not part of the
64+
* provided message.
65+
*/
66+
YAML::Node selected_member_to_yaml(const RosMessage_Cpp & message, const std::string &member_identifier);
67+
5568
} // namespace cpp
5669

5770
} // namespace dynmsg

dynmsg/src/message_reading_cpp.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,5 +637,59 @@ message_to_yaml(const RosMessage_Cpp & message)
637637
return yaml_msg;
638638
}
639639

640+
YAML::Node
641+
selected_member_to_yaml(const RosMessage_Cpp & message, const std::string &member_identifier)
642+
{
643+
// in case no member identifier is provided the function defaults to converting the full message
644+
if (member_identifier.empty()) {
645+
return message_to_yaml(message);
646+
}
647+
648+
RosMessage_Cpp tmp_msg = message;
649+
std::size_t start = 0;
650+
std::size_t end = 0;
651+
652+
const MemberInfo_Cpp *member_info = nullptr;
653+
uint8_t * member_data = nullptr;
654+
655+
bool more_sublevels_available = true;
656+
657+
while (more_sublevels_available) {
658+
std::string field_name;
659+
if ((end = member_identifier.find('/', start)) != std::string::npos) {
660+
field_name = member_identifier.substr(start, end - start);
661+
start = end + 1;
662+
} else {
663+
field_name = member_identifier.substr(start);
664+
more_sublevels_available = false;
665+
}
666+
667+
// iterate over message and check whether the field is available
668+
bool found = false;
669+
670+
for (uint32_t idx = 0; idx < tmp_msg.type_info->member_count_; idx++) {
671+
member_info = &tmp_msg.type_info->members_[idx];
672+
member_data = &tmp_msg.data[member_info->offset_];
673+
674+
if (std::string(member_info->name_) == field_name) {
675+
if (member_info->type_id_ == rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE) {
676+
// update temporary message used for processing to the nested member
677+
tmp_msg.type_info = reinterpret_cast<const TypeInfo_Cpp *>(member_info->members_->data);
678+
tmp_msg.data = const_cast<uint8_t *>(member_data);
679+
}
680+
681+
found = true;
682+
break;
683+
}
684+
}
685+
686+
if (!found) {
687+
return YAML::Node();
688+
}
689+
}
690+
691+
return impl::member_to_yaml(*member_info, member_data);
692+
}
693+
640694
} // namespace cpp
641695
} // namespace dynmsg

0 commit comments

Comments
 (0)