diff --git a/rviz_default_plugins/CMakeLists.txt b/rviz_default_plugins/CMakeLists.txt index c4f966779..767939b98 100644 --- a/rviz_default_plugins/CMakeLists.txt +++ b/rviz_default_plugins/CMakeLists.txt @@ -205,6 +205,8 @@ set(rviz_default_plugins_source_files src/rviz_default_plugins/displays/pointcloud/transformers/xyz_pc_transformer.cpp src/rviz_default_plugins/displays/pointcloud/get_transport_from_topic.cpp src/rviz_default_plugins/displays/pointcloud/point_cloud_common.cpp + src/rviz_default_plugins/displays/pointcloud/point_cloud_message_type_provider.cpp + src/rviz_default_plugins/displays/pointcloud/point_cloud_transport_discovery.cpp src/rviz_default_plugins/displays/pointcloud/point_cloud_to_point_cloud2.cpp src/rviz_default_plugins/displays/pointcloud/point_cloud_transformer.cpp src/rviz_default_plugins/displays/pointcloud/point_cloud_transformer_factory.cpp @@ -452,6 +454,14 @@ if(BUILD_TESTING) target_link_libraries(image_message_type_provider_test ${TEST_FIXTURE_WITH_MOCK_LIBRARIES} rviz_default_plugins ogre_testing_environment) endif() + ament_add_gmock(point_cloud_message_type_provider_test + test/rviz_default_plugins/displays/pointcloud/point_cloud_message_type_provider_test.cpp + ${TEST_FIXTURE_OBJECTS}) + if(TARGET point_cloud_message_type_provider_test) + target_include_directories(point_cloud_message_type_provider_test PRIVATE test) + target_link_libraries(point_cloud_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/pointcloud/point_cloud_message_type_provider.hpp b/rviz_default_plugins/include/rviz_default_plugins/displays/pointcloud/point_cloud_message_type_provider.hpp new file mode 100644 index 000000000..be033ca72 --- /dev/null +++ b/rviz_default_plugins/include/rviz_default_plugins/displays/pointcloud/point_cloud_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__POINTCLOUD__POINT_CLOUD_MESSAGE_TYPE_PROVIDER_HPP_ +#define RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_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 point_cloud_transport plugins +/// for the PointCloud2 display, so that they are known (e.g. to the +/// "Add display by topic" dialog) before any PointCloud2Display instance +/// exists. +class RVIZ_DEFAULT_PLUGINS_PUBLIC PointCloudMessageTypeProvider + : public rviz_common::MessageTypeProvider +{ +public: + QMap> getMessageTypes() override; +}; + +} // namespace displays +} // namespace rviz_default_plugins + +#endif // RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_MESSAGE_TYPE_PROVIDER_HPP_ diff --git a/rviz_default_plugins/include/rviz_default_plugins/displays/pointcloud/point_cloud_transport_discovery.hpp b/rviz_default_plugins/include/rviz_default_plugins/displays/pointcloud/point_cloud_transport_discovery.hpp new file mode 100644 index 000000000..79242ebdf --- /dev/null +++ b/rviz_default_plugins/include/rviz_default_plugins/displays/pointcloud/point_cloud_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__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISCOVERY_HPP_ +#define RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISCOVERY_HPP_ + +#include +#include + +#include "rviz_default_plugins/visibility_control.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +struct PointCloudTransportPluginInfo +{ + std::string transport_name; + /// Fully qualified message type, empty if the manifest does not declare one. + std::string message_type; +}; + +/// List the installed point_cloud_transport subscriber plugins with their +/// transport names and message types, as declared in their plugin manifests. +RVIZ_DEFAULT_PLUGINS_PUBLIC +std::vector discoverPointCloudTransportSubscriberPlugins(); + +} // namespace displays +} // namespace rviz_default_plugins + +#endif // RVIZ_DEFAULT_PLUGINS__DISPLAYS__POINTCLOUD__POINT_CLOUD_TRANSPORT_DISCOVERY_HPP_ diff --git a/rviz_default_plugins/plugins_description.xml b/rviz_default_plugins/plugins_description.xml index 7bc1e620d..473053e42 100644 --- a/rviz_default_plugins/plugins_description.xml +++ b/rviz_default_plugins/plugins_description.xml @@ -186,6 +186,17 @@ sensor_msgs/msg/PointCloud2 + + + Registers the message types of the installed point_cloud_transport + plugins for the PointCloud2 display. + + + > PointCloudMessageTypeProvider::getMessageTypes() +{ + QSet message_types; + for (const auto & plugin : discoverPointCloudTransportSubscriberPlugins()) { + if (!plugin.message_type.empty()) { + message_types.insert(QString::fromStdString(plugin.message_type)); + } + } + return {{"rviz_default_plugins/PointCloud2", message_types}}; +} + +} // namespace displays +} // namespace rviz_default_plugins + +#include // NOLINT +PLUGINLIB_EXPORT_CLASS( + rviz_default_plugins::displays::PointCloudMessageTypeProvider, + rviz_common::MessageTypeProvider) diff --git a/rviz_default_plugins/src/rviz_default_plugins/displays/pointcloud/point_cloud_transport_discovery.cpp b/rviz_default_plugins/src/rviz_default_plugins/displays/pointcloud/point_cloud_transport_discovery.cpp new file mode 100644 index 000000000..bedeaa51a --- /dev/null +++ b/rviz_default_plugins/src/rviz_default_plugins/displays/pointcloud/point_cloud_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/pointcloud/point_cloud_transport_discovery.hpp" + +#include +#include + +#include "pluginlib/class_loader.hpp" +#include "point_cloud_transport/point_cloud_common.hpp" +#include "point_cloud_transport/subscriber_plugin.hpp" + +namespace rviz_default_plugins +{ +namespace displays +{ + +std::vector discoverPointCloudTransportSubscriberPlugins() +{ + std::vector plugins; + + pluginlib::ClassLoader sub_loader( + "point_cloud_transport", "point_cloud_transport::SubscriberPlugin"); + for (const std::string & plugin_class : sub_loader.getDeclaredClasses()) { + const std::string manifest_path = sub_loader.getPluginManifestPath(plugin_class); + PointCloudTransportPluginInfo info; + info.transport_name = + point_cloud_transport::get_transport_name_from_manifest(manifest_path, plugin_class); + info.message_type = + point_cloud_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/pointcloud/point_cloud_message_type_provider_test.cpp b/rviz_default_plugins/test/rviz_default_plugins/displays/pointcloud/point_cloud_message_type_provider_test.cpp new file mode 100644 index 000000000..1963278f1 --- /dev/null +++ b/rviz_default_plugins/test/rviz_default_plugins/displays/pointcloud/point_cloud_message_type_provider_test.cpp @@ -0,0 +1,45 @@ +// 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/pointcloud/point_cloud_message_type_provider.hpp" + +TEST(PointCloudMessageTypeProviderTest, provides_message_types_for_the_point_cloud2_display) { + rviz_default_plugins::displays::PointCloudMessageTypeProvider provider; + + const auto types_by_class = provider.getMessageTypes(); + + ASSERT_TRUE(types_by_class.contains("rviz_default_plugins/PointCloud2")); + // The 'raw' transport ships with point_cloud_transport itself, so its + // message type is always discoverable. + EXPECT_TRUE( + types_by_class["rviz_default_plugins/PointCloud2"].contains("sensor_msgs/msg/PointCloud2")); +}