From 6a00d1b33ef9609e24efe2bd8a0c74784a450b50 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Thu, 23 Jul 2026 12:03:18 +0200 Subject: [PATCH] Fix Add topic camera transport type Signed-off-by: Alejandro Hernandez Cordero --- .../rviz_common/message_type_provider.hpp | 73 +++++++++++++++++++ .../src/rviz_common/display_factory.cpp | 32 ++++++++ .../src/rviz_common/display_factory.hpp | 11 +++ rviz_default_plugins/CMakeLists.txt | 10 +++ .../image/image_message_type_provider.hpp | 59 +++++++++++++++ .../image/image_transport_discovery.hpp | 58 +++++++++++++++ rviz_default_plugins/plugins_description.xml | 11 +++ .../depth_cloud/depth_cloud_display.cpp | 16 ++-- .../displays/image/image_display.cpp | 17 ++--- .../image/image_message_type_provider.cpp | 60 +++++++++++++++ .../image/image_transport_discovery.cpp | 63 ++++++++++++++++ .../image_message_type_provider_test.cpp | 50 +++++++++++++ 12 files changed, 440 insertions(+), 20 deletions(-) create mode 100644 rviz_common/include/rviz_common/message_type_provider.hpp create mode 100644 rviz_default_plugins/include/rviz_default_plugins/displays/image/image_message_type_provider.hpp create mode 100644 rviz_default_plugins/include/rviz_default_plugins/displays/image/image_transport_discovery.hpp create mode 100644 rviz_default_plugins/src/rviz_default_plugins/displays/image/image_message_type_provider.cpp create mode 100644 rviz_default_plugins/src/rviz_default_plugins/displays/image/image_transport_discovery.cpp create mode 100644 rviz_default_plugins/test/rviz_default_plugins/displays/image/image_message_type_provider_test.cpp diff --git a/rviz_common/include/rviz_common/message_type_provider.hpp b/rviz_common/include/rviz_common/message_type_provider.hpp new file mode 100644 index 000000000..b1cab2362 --- /dev/null +++ b/rviz_common/include/rviz_common/message_type_provider.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef RVIZ_COMMON__MESSAGE_TYPE_PROVIDER_HPP_ +#define RVIZ_COMMON__MESSAGE_TYPE_PROVIDER_HPP_ + +#include // NOLINT: cpplint cannot handle include order here +#include // NOLINT: cpplint cannot handle include order here +#include // NOLINT: cpplint cannot handle include order here + +namespace rviz_common +{ + +/// Pluginlib interface to register message types for display classes. +/** + * A display's supported message types are normally declared statically with + * tags in its plugin description xml. Displays whose + * supported types are only known at runtime (e.g. the Image display, which + * discovers them from the installed image_transport plugins) can export a + * MessageTypeProvider plugin instead. The DisplayFactory loads all declared + * providers before the message types are first queried, so that dialogs like + * "Add display by topic" know about these types before any instance of the + * display exists. + * + * Export implementations with + * PLUGINLIB_EXPORT_CLASS(..., rviz_common::MessageTypeProvider) and declare + * them with base_class_type="rviz_common::MessageTypeProvider" in the plugin + * description xml. + */ +class MessageTypeProvider +{ +public: + virtual ~MessageTypeProvider() = default; + + /// Return the supported message types per display class id. + /** + * The map key is the display class id (e.g. "rviz_default_plugins/Image"), + * the value is the set of fully qualified message types + * (e.g. "sensor_msgs/msg/Image") to register for it. The returned types + * are merged with the statically declared ones. + */ + virtual QMap> getMessageTypes() = 0; +}; + +} // namespace rviz_common + +#endif // RVIZ_COMMON__MESSAGE_TYPE_PROVIDER_HPP_ diff --git a/rviz_common/src/rviz_common/display_factory.cpp b/rviz_common/src/rviz_common/display_factory.cpp index cd14400be..882bccffd 100644 --- a/rviz_common/src/rviz_common/display_factory.cpp +++ b/rviz_common/src/rviz_common/display_factory.cpp @@ -31,6 +31,7 @@ #include "display_factory.hpp" +#include #include #include // NOLINT: cpplint is unable to handle the include order here @@ -70,8 +71,39 @@ void DisplayFactory::updatePluginMessageTypes( message_type_cache_[class_id] = message_types; } +void DisplayFactory::loadMessageTypeProviders() +{ + if (message_type_providers_loaded_) { + return; + } + message_type_providers_loaded_ = true; + + try { + message_type_provider_loader_ = std::make_unique>( + "rviz_common", "rviz_common::MessageTypeProvider"); + } catch (const pluginlib::PluginlibException & e) { + RVIZ_COMMON_LOG_ERROR_STREAM("Failed to create MessageTypeProvider loader: " << e.what()); + return; + } + + for (const std::string & lookup_name : message_type_provider_loader_->getDeclaredClasses()) { + try { + auto provider = message_type_provider_loader_->createUniqueInstance(lookup_name); + const QMap> types_by_class = provider->getMessageTypes(); + for (auto it = types_by_class.cbegin(); it != types_by_class.cend(); ++it) { + message_type_cache_[it.key()].unite(it.value()); + } + } catch (const pluginlib::PluginlibException & e) { + RVIZ_COMMON_LOG_ERROR_STREAM( + "Failed to load MessageTypeProvider '" << lookup_name << "': " << e.what()); + } + } +} + QSet DisplayFactory::getMessageTypes(const QString & class_id) { + loadMessageTypeProviders(); + // lookup in cache if (message_type_cache_.contains(class_id)) { return message_type_cache_[class_id]; diff --git a/rviz_common/src/rviz_common/display_factory.hpp b/rviz_common/src/rviz_common/display_factory.hpp index 6106260d2..9def06054 100644 --- a/rviz_common/src/rviz_common/display_factory.hpp +++ b/rviz_common/src/rviz_common/display_factory.hpp @@ -34,14 +34,18 @@ #include +#include #include #include // NOLINT: cpplint cannot handle include order here #include // NOLINT: cpplint cannot handle include order here #include // NOLINT: cpplint cannot handle include order here +#include "pluginlib/class_loader.hpp" + #include "rviz_common/factory/pluginlib_factory.hpp" #include "rviz_common/display.hpp" +#include "rviz_common/message_type_provider.hpp" namespace rviz_common { @@ -65,6 +69,10 @@ class DisplayFactory : public PluginlibFactory QMap> message_type_cache_; private: + /// Load all declared MessageTypeProvider plugins once and merge their + /// message types into the cache. + void loadMessageTypeProviders(); + bool hasRootNode(tinyxml2::XMLElement * root_element, const std::string & xml_file); bool hasLibraryRoot(tinyxml2::XMLElement * root_element, const std::string & xml_file); void fillCacheForAllClassElements(tinyxml2::XMLElement * library); @@ -73,6 +81,9 @@ class DisplayFactory : public PluginlibFactory std::string lookupClassId( const tinyxml2::XMLElement * class_element, const std::string & derived_class) const; std::string lookupDerivedClass(const tinyxml2::XMLElement * class_element) const; + + std::unique_ptr> message_type_provider_loader_; + bool message_type_providers_loaded_ = false; }; } // namespace rviz_common diff --git a/rviz_default_plugins/CMakeLists.txt b/rviz_default_plugins/CMakeLists.txt index 58e508d6f..c4f966779 100644 --- a/rviz_default_plugins/CMakeLists.txt +++ b/rviz_default_plugins/CMakeLists.txt @@ -167,6 +167,8 @@ set(rviz_default_plugins_source_files src/rviz_default_plugins/displays/illuminance/illuminance_display.cpp src/rviz_default_plugins/displays/image/get_transport_from_topic.cpp src/rviz_default_plugins/displays/image/image_display.cpp + src/rviz_default_plugins/displays/image/image_message_type_provider.cpp + src/rviz_default_plugins/displays/image/image_transport_discovery.cpp src/rviz_default_plugins/displays/image/ros_image_texture.cpp src/rviz_default_plugins/displays/interactive_markers/integer_action.cpp src/rviz_default_plugins/displays/interactive_markers/interactive_marker_control.cpp @@ -442,6 +444,14 @@ if(BUILD_TESTING) target_link_libraries(grid_cells_display_test ${TEST_FIXTURE_WITH_MOCK_LIBRARIES} rviz_default_plugins ogre_testing_environment) endif() + ament_add_gmock(image_message_type_provider_test + test/rviz_default_plugins/displays/image/image_message_type_provider_test.cpp + ${TEST_FIXTURE_OBJECTS}) + if(TARGET image_message_type_provider_test) + target_include_directories(image_message_type_provider_test PRIVATE test) + target_link_libraries(image_message_type_provider_test ${TEST_FIXTURE_WITH_MOCK_LIBRARIES} rviz_default_plugins ogre_testing_environment) + endif() + ament_add_gmock(image_display_test test/rviz_default_plugins/displays/image/image_display_test.cpp ${TEST_FIXTURE_OBJECTS} diff --git a/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_message_type_provider.hpp b/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_message_type_provider.hpp new file mode 100644 index 000000000..6569479ae --- /dev/null +++ b/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_message_type_provider.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_MESSAGE_TYPE_PROVIDER_HPP_ +#define RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_MESSAGE_TYPE_PROVIDER_HPP_ + +#include // NOLINT: cpplint cannot handle include order here +#include // NOLINT: cpplint cannot handle include order here +#include // NOLINT: cpplint cannot handle include order here + +#include "rviz_common/message_type_provider.hpp" +#include "rviz_default_plugins/visibility_control.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +/// Registers the message types of the installed image_transport plugins for +/// the image based displays (Image, Camera and DepthCloud), so that they are +/// known (e.g. to the "Add display by topic" dialog) before any instance of +/// these displays exists. +class RVIZ_DEFAULT_PLUGINS_PUBLIC ImageMessageTypeProvider + : public rviz_common::MessageTypeProvider +{ +public: + QMap> getMessageTypes() override; +}; + +} // namespace displays +} // namespace rviz_default_plugins + +#endif // RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_MESSAGE_TYPE_PROVIDER_HPP_ diff --git a/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_transport_discovery.hpp b/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_transport_discovery.hpp new file mode 100644 index 000000000..38bd38f9f --- /dev/null +++ b/rviz_default_plugins/include/rviz_default_plugins/displays/image/image_transport_discovery.hpp @@ -0,0 +1,58 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_TRANSPORT_DISCOVERY_HPP_ +#define RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_TRANSPORT_DISCOVERY_HPP_ + +#include +#include + +#include "rviz_default_plugins/visibility_control.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +struct ImageTransportPluginInfo +{ + std::string transport_name; + /// Fully qualified message type, empty if the manifest does not declare one. + std::string message_type; +}; + +/// List the installed image_transport subscriber plugins with their transport +/// names and message types, as declared in their plugin manifests. +RVIZ_DEFAULT_PLUGINS_PUBLIC +std::vector discoverImageTransportSubscriberPlugins(); + +} // namespace displays +} // namespace rviz_default_plugins + +#endif // RVIZ_DEFAULT_PLUGINS__DISPLAYS__IMAGE__IMAGE_TRANSPORT_DISCOVERY_HPP_ diff --git a/rviz_default_plugins/plugins_description.xml b/rviz_default_plugins/plugins_description.xml index f5259f2f5..7bc1e620d 100644 --- a/rviz_default_plugins/plugins_description.xml +++ b/rviz_default_plugins/plugins_description.xml @@ -121,6 +121,17 @@ sensor_msgs/msg/Image + + + Registers the message types of the installed image_transport plugins + for the Image, Camera and DepthCloud displays. + + + #include +#include "rviz_default_plugins/displays/image/get_transport_from_topic.hpp" + namespace rviz_default_plugins { namespace displays @@ -245,15 +247,11 @@ DepthCloudDisplay::~DepthCloudDisplay() void DepthCloudDisplay::setTopic(const QString & topic, const QString & datatype) { - if (datatype == "sensor_msgs::msgs::Image") { - depth_transport_property_->setStdString("raw"); - depth_topic_property_->setString(topic); - } else { - setStatus( - rviz_common::properties::StatusProperty::Warn, - "Message", - "Expected topic type of 'sensor_msgs/msg/Image', saw topic type '" + datatype + "'"); - } + (void) datatype; + // The topic may be an image_transport subtopic, e.g. /compressedDepth. + const std::string topic_std = topic.toStdString(); + depth_transport_property_->setStdString(getTransportFromTopic(topic_std)); + depth_topic_property_->setString(QString::fromStdString(getBaseTopicFromTopic(topic_std))); } void DepthCloudDisplay::updateQueueSize() diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_display.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_display.cpp index 8737c7a34..41737d548 100644 --- a/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_display.cpp +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_display.cpp @@ -69,6 +69,7 @@ #include "rviz_common/uniform_string_stream.hpp" #include "rviz_common/validate_floats.hpp" #include "rviz_default_plugins/displays/image/get_transport_from_topic.hpp" +#include "rviz_default_plugins/displays/image/image_transport_discovery.hpp" #include "rviz_default_plugins/displays/image/ros_image_texture.hpp" #include "rviz_default_plugins/displays/image/ros_image_texture_iface.hpp" #include "rviz_rendering/material_manager.hpp" @@ -154,21 +155,15 @@ void ImageDisplay::onInitialize() // Populate transport->message type map dynamically from installed image_transport plugins - pluginlib::ClassLoader sub_loader( - "image_transport", "image_transport::SubscriberPlugin"); transport_override_property_->clearOptions(); transport_override_property_->addOptionStd(""); QSet message_types; - for (const std::string & plugin_class : sub_loader.getDeclaredClasses()) { - const std::string message_type = image_transport::get_message_type_from_manifest( - sub_loader.getPluginManifestPath(plugin_class), plugin_class); - const std::string transport_name = image_transport::get_transport_name_from_manifest( - sub_loader.getPluginManifestPath(plugin_class), plugin_class); - if (!message_type.empty()) { - transport_override_property_->addOptionStd(transport_name); - message_types.insert(QString::fromStdString(message_type)); + for (const auto & plugin : discoverImageTransportSubscriberPlugins()) { + if (!plugin.message_type.empty()) { + transport_override_property_->addOptionStd(plugin.transport_name); + message_types.insert(QString::fromStdString(plugin.message_type)); } else { - unknown_transports_.insert(transport_name); + unknown_transports_.insert(plugin.transport_name); } } // Update the message types to allow in the topic_property_ diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_message_type_provider.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_message_type_provider.cpp new file mode 100644 index 000000000..ba8c7594a --- /dev/null +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_message_type_provider.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "rviz_default_plugins/displays/image/image_message_type_provider.hpp" + +#include "rviz_default_plugins/displays/image/image_transport_discovery.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +QMap> ImageMessageTypeProvider::getMessageTypes() +{ + QSet message_types; + for (const auto & plugin : discoverImageTransportSubscriberPlugins()) { + if (!plugin.message_type.empty()) { + message_types.insert(QString::fromStdString(plugin.message_type)); + } + } + return { + {"rviz_default_plugins/Image", message_types}, + {"rviz_default_plugins/Camera", message_types}, + {"rviz_default_plugins/DepthCloud", message_types}, + }; +} + +} // namespace displays +} // namespace rviz_default_plugins + +#include // NOLINT +PLUGINLIB_EXPORT_CLASS( + rviz_default_plugins::displays::ImageMessageTypeProvider, + rviz_common::MessageTypeProvider) diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_transport_discovery.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_transport_discovery.cpp new file mode 100644 index 000000000..d4e41600c --- /dev/null +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/image/image_transport_discovery.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "rviz_default_plugins/displays/image/image_transport_discovery.hpp" + +#include +#include + +#include "image_transport/camera_common.hpp" +#include "image_transport/subscriber_plugin.hpp" +#include "pluginlib/class_loader.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +std::vector discoverImageTransportSubscriberPlugins() +{ + std::vector plugins; + + pluginlib::ClassLoader sub_loader( + "image_transport", "image_transport::SubscriberPlugin"); + for (const std::string & plugin_class : sub_loader.getDeclaredClasses()) { + const std::string manifest_path = sub_loader.getPluginManifestPath(plugin_class); + ImageTransportPluginInfo info; + info.transport_name = + image_transport::get_transport_name_from_manifest(manifest_path, plugin_class); + info.message_type = + image_transport::get_message_type_from_manifest(manifest_path, plugin_class); + plugins.push_back(info); + } + return plugins; +} + +} // namespace displays +} // namespace rviz_default_plugins diff --git a/rviz_default_plugins/test/rviz_default_plugins/displays/image/image_message_type_provider_test.cpp b/rviz_default_plugins/test/rviz_default_plugins/displays/image/image_message_type_provider_test.cpp new file mode 100644 index 000000000..f8fde40ed --- /dev/null +++ b/rviz_default_plugins/test/rviz_default_plugins/displays/image/image_message_type_provider_test.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2026, Open Source Robotics Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + + +#include + +#include "rviz_default_plugins/displays/image/image_message_type_provider.hpp" + +TEST(ImageMessageTypeProviderTest, provides_message_types_for_the_image_based_displays) { + rviz_default_plugins::displays::ImageMessageTypeProvider provider; + + const auto types_by_class = provider.getMessageTypes(); + + for (const QString class_id : + {"rviz_default_plugins/Image", "rviz_default_plugins/Camera", + "rviz_default_plugins/DepthCloud"}) + { + ASSERT_TRUE(types_by_class.contains(class_id)) << class_id.toStdString(); + // The 'raw' transport ships with image_transport itself, so its message + // type is always discoverable. + EXPECT_TRUE(types_by_class[class_id].contains("sensor_msgs/msg/Image")) << + class_id.toStdString(); + } +}