From d5ba087ea37fada5cd84105f0e365e4dcec218f0 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Fri, 26 Jun 2026 13:41:16 +0200 Subject: [PATCH 1/4] modernize to cpp20 Signed-off-by: Alejandro Hernandez Cordero --- rqt_gui_cpp/CMakeLists.txt | 9 ++++----- rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp | 6 ++---- rqt_gui_cpp/package.xml | 1 + .../rqt_gui_cpp/nodelet_plugin_provider.cpp | 20 ++++++++----------- .../rqt_gui_cpp/nodelet_plugin_provider.hpp | 18 ++++++++--------- .../rqt_gui_cpp/roscpp_plugin_provider.cpp | 2 +- .../rqt_gui_cpp/roscpp_plugin_provider.hpp | 8 ++++---- 7 files changed, 29 insertions(+), 35 deletions(-) diff --git a/rqt_gui_cpp/CMakeLists.txt b/rqt_gui_cpp/CMakeLists.txt index 998eac1f..e22b48b8 100644 --- a/rqt_gui_cpp/CMakeLists.txt +++ b/rqt_gui_cpp/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.20) project(rqt_gui_cpp) find_package(ament_cmake REQUIRED) +find_package(ament_cmake_ros_core REQUIRED) if(WIN32) message(STATUS "rqt_gui_cpp is not yet supported on Windows. Package will not be built.") @@ -9,11 +10,8 @@ if(WIN32) return() endif() -# Default to C++17 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) - set(CMAKE_CXX_STANDARD_REQUIRED ON) -endif() +# The C++ standard (C++20) is provided by the +# ament_cmake_ros_core::ament_ros_defaults interface target linked below. if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic -fPIC) @@ -59,6 +57,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ) target_link_libraries(${PROJECT_NAME} PRIVATE + ament_cmake_ros_core::ament_ros_defaults pluginlib::pluginlib Qt${QT_VERSION_MAJOR}::Widgets ) diff --git a/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp b/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp index 755ed148..2fc030c4 100644 --- a/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp +++ b/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp @@ -52,15 +52,13 @@ class Plugin : public qt_gui_cpp::Plugin { public: - Plugin() - : qt_gui_cpp::Plugin() - {} + Plugin() = default; /** * Shutdown and clean up the plugin before unloading. * I.e. unregister subscribers and stop timers. */ - virtual void shutdownPlugin() + void shutdownPlugin() override {} virtual void passInNode(std::shared_ptr node) diff --git a/rqt_gui_cpp/package.xml b/rqt_gui_cpp/package.xml index 34b8a3e7..5458ef63 100644 --- a/rqt_gui_cpp/package.xml +++ b/rqt_gui_cpp/package.xml @@ -14,6 +14,7 @@ Michael Jeronimo ament_cmake + ament_cmake_ros_core pluginlib rclcpp diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp index a8d52d79..a8a5279d 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp @@ -33,6 +33,7 @@ #include "nodelet_plugin_provider.hpp" #include +#include #include #include #include @@ -46,17 +47,17 @@ NodeletPluginProvider::NodeletPluginProvider( const QString & base_class_type) : qt_gui_cpp::RosPluginlibPluginProvider(export_tag, base_class_type) , loader_initialized_(false) - , ros_spin_thread_(0) + , ros_spin_thread_(nullptr) {} NodeletPluginProvider::~NodeletPluginProvider() { - if (ros_spin_thread_ != 0) { + if (ros_spin_thread_ != nullptr) { ros_spin_thread_->abort = true; ros_spin_thread_->exec_.remove_node(node_); ros_spin_thread_->wait(); ros_spin_thread_->deleteLater(); - ros_spin_thread_ = 0; + ros_spin_thread_ = nullptr; } } @@ -76,16 +77,13 @@ void NodeletPluginProvider::init_loader() loader_initialized_ = true; // spawn ros spin thread - if (ros_spin_thread_ == 0) { + if (ros_spin_thread_ == nullptr) { ros_spin_thread_ = new RosSpinThread(this); ros_spin_thread_->start(); } - std::stringstream name; - name << "rqt_gui_cpp_node_"; - name << getpid(); // Initialize a node for execution to be shared by cpp plugins - node_ = rclcpp::Node::make_shared(name.str().c_str()); + node_ = rclcpp::Node::make_shared(std::format("rqt_gui_cpp_node_{}", getpid())); // Add our node to the executor for execution if (ros_spin_thread_) { ros_spin_thread_->exec_.add_node(node_); @@ -101,8 +99,7 @@ std::shared_ptr NodeletPluginProvider::create_plugin( { init_loader(); - std::string nodelet_name = lookup_name + "_" + - QString::number(plugin_context->serialNumber()).toStdString(); + std::string nodelet_name = std::format("{}_{}", lookup_name, plugin_context->serialNumber()); instance_.reset(); instance_ = @@ -137,8 +134,7 @@ NodeletPluginProvider::RosSpinThread::RosSpinThread(QObject * parent) , abort(false) {} -NodeletPluginProvider::RosSpinThread::~RosSpinThread() -{} +NodeletPluginProvider::RosSpinThread::~RosSpinThread() = default; void NodeletPluginProvider::RosSpinThread::run() { diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp index ce4612e9..bf5b3c74 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp @@ -53,20 +53,20 @@ class NodeletPluginProvider public: NodeletPluginProvider(const QString & export_tag, const QString & base_class_type); - virtual ~NodeletPluginProvider(); + ~NodeletPluginProvider() override; - virtual void unload(void * instance); + void unload(void * instance) override; protected: void init_loader(); - virtual std::shared_ptr create_plugin( + std::shared_ptr create_plugin( const std::string & lookup_name, - qt_gui_cpp::PluginContext * plugin_context); + qt_gui_cpp::PluginContext * plugin_context) override; - virtual void init_plugin( + void init_plugin( const QString & plugin_id, qt_gui_cpp::PluginContext * plugin_context, - qt_gui_cpp::Plugin * plugin); + qt_gui_cpp::Plugin * plugin) override; std::shared_ptr instance_; @@ -82,9 +82,9 @@ class NodeletPluginProvider : public QThread { public: - explicit RosSpinThread(QObject * parent = 0); - virtual ~RosSpinThread(); - void run(); + explicit RosSpinThread(QObject * parent = nullptr); + ~RosSpinThread() override; + void run() override; bool abort; // Create an executor that will be responsible for execution of callbacks for a set of nodes. // With this version, all callbacks will be called from within this thread (the main one). diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp index b00036d3..5808cf8f 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp @@ -86,7 +86,7 @@ void RosCppPluginProvider::init_rclcpp() // initialize ROS node once if (!rclcpp_initialized_) { int argc = 0; - char ** argv = 0; + char ** argv = nullptr; // Initialize any global resources needed by the middleware and the client library. // This will also parse command line arguments one day (as of Beta 1 they are not used). diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp index 0725f869..f67a9507 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp @@ -46,13 +46,13 @@ class RosCppPluginProvider public: RosCppPluginProvider(); - virtual ~RosCppPluginProvider(); + ~RosCppPluginProvider() override; - virtual void * load(const QString & plugin_id, qt_gui_cpp::PluginContext * plugin_context); + void * load(const QString & plugin_id, qt_gui_cpp::PluginContext * plugin_context) override; - virtual qt_gui_cpp::Plugin * load_plugin( + qt_gui_cpp::Plugin * load_plugin( const QString & plugin_id, - qt_gui_cpp::PluginContext * plugin_context); + qt_gui_cpp::PluginContext * plugin_context) override; protected: void init_rclcpp(); From 78d0f75765783e5b2c8d769d7a7d74cd51bcc2e9 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Fri, 26 Jun 2026 13:49:17 +0200 Subject: [PATCH 2/4] Move implementation from hpp to cpp Signed-off-by: Alejandro Hernandez Cordero --- rqt_gui_cpp/CMakeLists.txt | 1 + rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp | 10 ++--- rqt_gui_cpp/src/rqt_gui_cpp/plugin.cpp | 50 ++++++++++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 rqt_gui_cpp/src/rqt_gui_cpp/plugin.cpp diff --git a/rqt_gui_cpp/CMakeLists.txt b/rqt_gui_cpp/CMakeLists.txt index e22b48b8..221b85b0 100644 --- a/rqt_gui_cpp/CMakeLists.txt +++ b/rqt_gui_cpp/CMakeLists.txt @@ -41,6 +41,7 @@ ament_export_dependencies( add_library(${PROJECT_NAME} SHARED src/rqt_gui_cpp/nodelet_plugin_provider.cpp + src/rqt_gui_cpp/plugin.cpp src/rqt_gui_cpp/roscpp_plugin_provider.cpp ) target_include_directories(${PROJECT_NAME} PUBLIC diff --git a/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp b/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp index 2fc030c4..aeeec92a 100644 --- a/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp +++ b/rqt_gui_cpp/include/rqt_gui_cpp/plugin.hpp @@ -52,19 +52,15 @@ class Plugin : public qt_gui_cpp::Plugin { public: - Plugin() = default; + Plugin(); /** * Shutdown and clean up the plugin before unloading. * I.e. unregister subscribers and stop timers. */ - void shutdownPlugin() override - {} + void shutdownPlugin() override; - virtual void passInNode(std::shared_ptr node) - { - node_ = node; - } + virtual void passInNode(std::shared_ptr node); protected: rclcpp::Node::SharedPtr node_; diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/plugin.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/plugin.cpp new file mode 100644 index 00000000..1a30f779 --- /dev/null +++ b/rqt_gui_cpp/src/rqt_gui_cpp/plugin.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Dirk Thomas, TU Darmstadt + * 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 TU Darmstadt 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 "rqt_gui_cpp/plugin.hpp" + +#include + +namespace rqt_gui_cpp +{ + +Plugin::Plugin() = default; + +void Plugin::shutdownPlugin() +{} + +void Plugin::passInNode(std::shared_ptr node) +{ + node_ = node; +} + +} // namespace rqt_gui_cpp From 6e8fab9607cf301aa6f621ed2a570cd0f36b84cd Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Fri, 26 Jun 2026 14:08:05 +0200 Subject: [PATCH 3/4] drp redundant instance_ member Signed-off-by: Alejandro Hernandez Cordero --- rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp | 9 +++------ rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp | 2 -- rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp | 2 ++ rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp | 2 -- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp index a8a5279d..bf52b228 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp @@ -100,15 +100,12 @@ std::shared_ptr NodeletPluginProvider::create_plugin( init_loader(); std::string nodelet_name = std::format("{}_{}", lookup_name, plugin_context->serialNumber()); - instance_.reset(); - instance_ = + std::shared_ptr instance = qt_gui_cpp::RosPluginlibPluginProvider::create_plugin(lookup_name); - instance_->passInNode(node_); - instances_[&*instance_] = nodelet_name.c_str(); + instance->passInNode(node_); + instances_[&*instance] = nodelet_name.c_str(); - std::shared_ptr instance = instance_; - instance_.reset(); return instance; } diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp index bf5b3c74..9efab5b0 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.hpp @@ -68,8 +68,6 @@ class NodeletPluginProvider const QString & plugin_id, qt_gui_cpp::PluginContext * plugin_context, qt_gui_cpp::Plugin * plugin) override; - std::shared_ptr instance_; - QMap instances_; bool loader_initialized_; diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp index 5808cf8f..84faa8d3 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp @@ -32,6 +32,8 @@ #include "roscpp_plugin_provider.hpp" +#include + #include "nodelet_plugin_provider.hpp" #include diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp index f67a9507..f5df460b 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.hpp @@ -33,8 +33,6 @@ #ifndef RQT_GUI_CPP__ROSCPP_PLUGIN_PROVIDER_HPP_ #define RQT_GUI_CPP__ROSCPP_PLUGIN_PROVIDER_HPP_ -#include - #include namespace rqt_gui_cpp From bea8f65f92bc522e11dca223a56791f275fab50a Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Fri, 10 Jul 2026 15:41:46 +0200 Subject: [PATCH 4/4] Review feedback Signed-off-by: Alejandro Hernandez Cordero --- rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp index bf52b228..83f8bd2d 100644 --- a/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp +++ b/rqt_gui_cpp/src/rqt_gui_cpp/nodelet_plugin_provider.cpp @@ -104,7 +104,7 @@ std::shared_ptr NodeletPluginProvider::create_plugin( std::shared_ptr instance = qt_gui_cpp::RosPluginlibPluginProvider::create_plugin(lookup_name); instance->passInNode(node_); - instances_[&*instance] = nodelet_name.c_str(); + instances_[instance.get()] = nodelet_name.c_str(); return instance; }