From fe028998d8ca61af4e93fbc936e3eb005f5ceb08 Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Wed, 2 Dec 2020 16:04:24 -0800 Subject: [PATCH 1/7] Add a tutorial for monitoring for parameter changes Using the new class, ParameterEventsSubscriber. Signed-off-by: Michael Jeronimo --- source/Tutorials.rst | 1 + .../Monitoring-For-Parameter-Changes-CPP.rst | 348 ++++++++++++++++++ 2 files changed, 349 insertions(+) create mode 100644 source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst diff --git a/source/Tutorials.rst b/source/Tutorials.rst index 63e1795460..3222615520 100644 --- a/source/Tutorials.rst +++ b/source/Tutorials.rst @@ -45,6 +45,7 @@ Beginner: Client Libraries Tutorials/Single-Package-Define-And-Use-Interface Tutorials/Using-Parameters-In-A-Class-CPP Tutorials/Using-Parameters-In-A-Class-Python + Tutorials/Monitoring-For-Parameter-Changes-CPP Tutorials/Getting-Started-With-Ros2doctor Intermediate diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst new file mode 100644 index 0000000000..b0b268a81e --- /dev/null +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -0,0 +1,348 @@ +Monitoring for parameter changes (C++) +====================================== + +**Goal:** Learn to use the ParameterEventsSubscriber class to monitor for parameter changes + +**Tutorial level:** Beginner + +**Time:** 20 minutes + +.. contents:: Contents + :depth: 2 + :local: + +Background +---------- + +Often a node needs to respond to changes to its own parameters or another node's parameters. The ParameterEventsSubscriber class makes it easy to listen for these kinds of parameter changes so that your code can respond to them. This tutorial will show you how to use the C++ version of the ParameterEventsSubscriber class to monitor for changes to a node's own parameters as well as changes to another node's parameters. + +Prerequisites +------------- + +Before starting this tutorial, you should first complete the following tutorials: + +- :ref:`ROS2Params` +- :ref:`CppParamNode` + +Tasks +----- + +The ParameterEventsSubscriber class provides function interfaces to handle parameter events. + +1 Create a package +^^^^^^^^^^^^^^^^^^ + +Open a new terminal and :ref:`source your ROS 2 installation ` so that ``ros2`` commands will work. + +Navigate into the ``dev_ws`` directory created in a previous tutorial (or follow `these instructions `_ if you no longer have the directory and need to create it again). + +Recall that packages should be created in the ``src`` directory, not the root of the workspace. So, navigate into ``dev_ws/src`` and then create a new package there: + +.. code-block:: console + + ros2 pkg create --build-type ament_cmake cpp_parameter_events_subscriber --dependencies rclcpp + +Your terminal will return a message verifying the creation of your package ``cpp_parameter_events_subscriber`` and all its necessary files and folders. + +The ``--dependencies`` argument will automatically add the necessary dependency lines to ``package.xml`` and ``CMakeLists.txt``. + +1.1 Update ``package.xml`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Because you used the ``--dependencies`` option during package creation, you don’t have to manually add dependencies to ``package.xml`` or ``CMakeLists.txt``. As always, though, make sure to add the description, maintainer email and name, and license information to ``package.xml``. + +.. code-block:: xml + + C++ parameter events client tutorial + Your Name + Apache License 2.0 + +2 Write the C++ node +^^^^^^^^^^^^^^^^^^^^ + +Inside the ``dev_ws/src/cpp_parameter_events_subscriber/src`` directory, create a new file called ``parameter_events_subscriber.cpp`` and paste the following code within: + +.. code-block:: C++ + + #include + + #include "rclcpp/rclcpp.hpp" + + class SampleNodeWithParameters : public rclcpp::Node + { + public: + SampleNodeWithParameters() + : Node("node_with_parameters") + { + this->declare_parameter("an_int_param", 0); + + // Create a parameter subscriber that can be used to monitor parameter changes + // (for this node's parameters as well as other nodes' parameters) + param_subscriber_ = std::make_shared(this); + + // Set a callback for this node's integer parameter, "an_int_param" + auto cb = [this](const rclcpp::Parameter & p) { + RCLCPP_INFO( + this->get_logger(), "cb: Received an update to parameter \"%s\" of type %s: \"%ld\"", + p.get_name().c_str(), + p.get_type_name().c_str(), + p.as_int()); + }; + cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); + } + + ~SampleNodeWithParameters() + { + param_subscriber_->remove_parameter_callback(cb_handle_.get()); + } + + private: + std::shared_ptr param_subscriber_; + std::shared_ptr cb_handle_; + }; + + int main(int argc, char ** argv) + { + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + + return 0; + } + +2.1 Examine the code +~~~~~~~~~~~~~~~~~~~~ +The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventsSubscriber class. + +After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventSubscriber`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. + +.. code-block:: C++ + + SampleNodeWithParameters() + : Node("node_with_parameters") + { + this->declare_parameter("an_int_param", 0); + + // Create a parameter subscriber that can be used to monitor parameter changes + // (for this node's parameters as well as other nodes' parameters) + param_subscriber_ = std::make_shared(this); + + // Set a callback for this node's integer parameter, "an_int_param" + auto cb = [this](const rclcpp::Parameter & p) { + RCLCPP_INFO( + this->get_logger(), "cb: Received an update to parameter \"%s\" of type %s: \"%ld\"", + p.get_name().c_str(), + p.get_type_name().c_str(), + p.as_int()); + }; + cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); + } + +The ``ParameterEventSubscriber``'s add_parameter_callback method returns a callback handle that is stored in a member variable. This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. + +.. code-block:: C++ + + ~SampleNodeWithParameters() + { + param_subscriber_->remove_parameter_callback(cb_handle_.get()); + } + +Following the ``SampleNodeWithParameters`` is a typical ``main`` function which initializes ROS, spins the sample node so that it can send and receive messages, and then shuts down after the user enters ^C at the console. + +.. code-block:: C++ + + int main(int argc, char** argv) + { + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + + return 0; + } + + +2.2 Add executable +~~~~~~~~~~~~~~~~~~ + +To build this code, first open the ``CMakeLists.txt`` file and add the following lines of code below the dependency ``find_package(rclcpp REQUIRED)`` + +.. code-block:: console + + add_executable(parameter_events_subscriber src/parameter_events_subscriber.cpp) + ament_target_dependencies(parameter_events_subscriber rclcpp) + + install(TARGETS + parameter_events_subscriber + DESTINATION lib/${PROJECT_NAME} + ) + +3 Build and run +^^^^^^^^^^^^^^^ + +It's good practice to run ``rosdep`` in the root of your workspace (``dev_ws``) to check for missing dependencies before building: + +.. tabs:: + + .. group-tab:: Linux + + .. code-block:: console + + rosdep install -i --from-path src --rosdistro -y + + .. group-tab:: macOS + + rosdep only runs on Linux, so you can skip ahead to next step. + + .. group-tab:: Windows + + rosdep only runs on Linux, so you can skip ahead to next step. + +Navigate back to the root of your workspace, ``dev_ws``, and build your new package: + +.. code-block:: console + + colcon build --packages-select cpp_parameter_events_subscriber + +Open a new terminal, navigate to ``dev_ws``, and source the setup files: + +.. tabs:: + + .. group-tab:: Linux + + .. code-block:: console + + . install/setup.bash + + .. group-tab:: macOS + + .. code-block:: console + + . install/setup.bash + + .. group-tab:: Windows + + .. code-block:: console + + call install/setup.bat + +Now run the node: + +.. code-block:: console + + ros2 run cpp_parameter_events_subscriber parameter_events_subscriber + +The node is now active and has a single parameter and will print a message whenever this parameter is updated. To test this, open up another terminal and source the ROS setup file as before (. install/setup.bash) and execute the following command: + +.. code-block:: console + + ros2 param set node_with_parameters an_int_param 43 + +The terminal running the node will display a message similar to the following: + +.. code-block:: console + + [INFO] [1606950498.422461764] [node_with_parameters]: cb: Received an update to parameter "an_int_param" of type integer: "43" + +The callback we set previously in the node has been invoked and has displayed the new updated value. You can now terminate the running parameter_events_subscriber sample using ^C in the terminal. + +3.1 Monitor changes to another node's parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can also use the ParameterEventsSubscriber to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. + +First update the constructor to add the following code after the existing code: + +.. code-block:: C++ + + // Now, add a callback to monitor any changes to the remote node's parameter. In this + // case, we supply the remote node name. + auto cb2 = [this](const rclcpp::Parameter & p) { + RCLCPP_INFO( + this->get_logger(), "cb2: Received an update to parameter \"%s\" of type: %s: \"%.02lf\"", + p.get_name().c_str(), + p.get_type_name().c_str(), + p.as_double()); + }; + auto remote_node_name = std::string("parameter_blackboard"); + auto remote_param_name = std::string("a_double_param"); + cb_handle2_ = param_subscriber_->add_parameter_callback(remote_param_name, cb2, remote_node_name); + + +The destructor and member variables need to be updated as well to account for the new ``cb_handle2`` member variable: + +.. code-block:: C++ + + ~SampleNodeWithParameters() + { + param_subscriber_->remove_parameter_callback(cb_handle_.get()); + param_subscriber_->remove_parameter_callback(cb_handle2_.get()); // Add this + } + + private: + std::shared_ptr param_subscriber_; + std::shared_ptr cb_handle_; + std::shared_ptr cb_handle2_; // Add this + }; + + +In a terminal, navigate back to the root of your workspace, ``dev_ws``, and build your updated package as before: + +.. code-block:: console + + colcon build --packages-select cpp_parameter_events_subscriber + +Then source the setup files: + +.. tabs:: + + .. group-tab:: Linux + + .. code-block:: console + + . install/setup.bash + + .. group-tab:: macOS + + .. code-block:: console + + . install/setup.bash + + .. group-tab:: Windows + + .. code-block:: console + + call install/setup.bat + +Now, to test monitoring of remote parameters, first run the newly-built parameter_events_subscriber code: + +.. code-block:: console + + ros2 run cpp_parameter_events_subscriber parameter_events_subscriber + +Next, from another teminal (with ROS initialized), run the parameter_blackboard demo application, as follows: + +.. code-block:: console + + ros2 run demo_nodes_cpp parameter_blackboard + +Finally, from a third terminal (with ROS initialized), let's set a parameter on the parameter_blackboard node: + +.. code-block:: console + + ros2 param set parameter_blackboard a_double_param 3.45 + +Upon executing this command, you should see output in the parameter_events_subscriber window, indicating that the callback function was invoked upon the parameter update: + +.. code-block:: console + + [INFO] [1606952588.237531933] [node_with_parameters]: cb2: Received an update to parameter "a_double_param" of type: double: "3.45" + +Summary +------- + +You created a node with a parameter and used the ParameterEventsSubscriber class to set a callback to monitor changes to that parameter. You also used the same class to monitor changes to a remote node. The ParameterEventsSubscriber is a convenient way to monitor for parameter changes so that you can then respond to the updated values. + +Next steps +---------- + +Now that you have examined parameters and have some packages and ROS 2 systems of your own, the :ref:`next tutorial ` will show you how to examine issues in your environment and systems in case you have problems. From c995b741b7389c09572b944e3759f611e9613fdf Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Tue, 16 Feb 2021 15:10:37 -0800 Subject: [PATCH 2/7] Update class name per code review Signed-off-by: Michael Jeronimo --- .../Monitoring-For-Parameter-Changes-CPP.rst | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index b0b268a81e..7f06de5370 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -1,7 +1,7 @@ Monitoring for parameter changes (C++) ====================================== -**Goal:** Learn to use the ParameterEventsSubscriber class to monitor for parameter changes +**Goal:** Learn to use the ParameterEventHandler class to monitor and respond to parameter changes. **Tutorial level:** Beginner @@ -14,7 +14,7 @@ Monitoring for parameter changes (C++) Background ---------- -Often a node needs to respond to changes to its own parameters or another node's parameters. The ParameterEventsSubscriber class makes it easy to listen for these kinds of parameter changes so that your code can respond to them. This tutorial will show you how to use the C++ version of the ParameterEventsSubscriber class to monitor for changes to a node's own parameters as well as changes to another node's parameters. +Often a node needs to respond to changes to its own parameters or another node's parameters. The ParameterEventHandler class makes it easy to listen for parameter changes so that your code can respond to them. This tutorial will show you how to use the C++ version of the ParameterEventHandler class to monitor for changes to a node's own parameters as well as changes to another node's parameters. Prerequisites ------------- @@ -27,12 +27,13 @@ Before starting this tutorial, you should first complete the following tutorials Tasks ----- -The ParameterEventsSubscriber class provides function interfaces to handle parameter events. +In this tutorial, you will create a new package to contain some sample code, write some C++ code to use the ParameterEventHandler class, and test the resulting code. + 1 Create a package ^^^^^^^^^^^^^^^^^^ -Open a new terminal and :ref:`source your ROS 2 installation ` so that ``ros2`` commands will work. +First, open a new terminal and :ref:`source your ROS 2 installation ` so that ``ros2`` commands will work. Navigate into the ``dev_ws`` directory created in a previous tutorial (or follow `these instructions `_ if you no longer have the directory and need to create it again). @@ -40,9 +41,9 @@ Recall that packages should be created in the ``src`` directory, not the root of .. code-block:: console - ros2 pkg create --build-type ament_cmake cpp_parameter_events_subscriber --dependencies rclcpp + ros2 pkg create --build-type ament_cmake cpp_parameter_event_handler --dependencies rclcpp -Your terminal will return a message verifying the creation of your package ``cpp_parameter_events_subscriber`` and all its necessary files and folders. +Your terminal will return a message verifying the creation of your package ``cpp_parameter_event_handler`` and all its necessary files and folders. The ``--dependencies`` argument will automatically add the necessary dependency lines to ``package.xml`` and ``CMakeLists.txt``. @@ -60,7 +61,7 @@ Because you used the ``--dependencies`` option during package creation, you don 2 Write the C++ node ^^^^^^^^^^^^^^^^^^^^ -Inside the ``dev_ws/src/cpp_parameter_events_subscriber/src`` directory, create a new file called ``parameter_events_subscriber.cpp`` and paste the following code within: +Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a new file called ``parameter_event_handler.cpp`` and paste the following code within: .. code-block:: C++ @@ -78,7 +79,7 @@ Inside the ``dev_ws/src/cpp_parameter_events_subscriber/src`` directory, create // Create a parameter subscriber that can be used to monitor parameter changes // (for this node's parameters as well as other nodes' parameters) - param_subscriber_ = std::make_shared(this); + param_subscriber_ = std::make_shared(this); // Set a callback for this node's integer parameter, "an_int_param" auto cb = [this](const rclcpp::Parameter & p) { @@ -93,11 +94,11 @@ Inside the ``dev_ws/src/cpp_parameter_events_subscriber/src`` directory, create ~SampleNodeWithParameters() { - param_subscriber_->remove_parameter_callback(cb_handle_.get()); + param_subscriber_->remove_parameter_callback(cb_handle_); } private: - std::shared_ptr param_subscriber_; + std::shared_ptr param_subscriber_; std::shared_ptr cb_handle_; }; @@ -112,9 +113,9 @@ Inside the ``dev_ws/src/cpp_parameter_events_subscriber/src`` directory, create 2.1 Examine the code ~~~~~~~~~~~~~~~~~~~~ -The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventsSubscriber class. +The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class. -After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventSubscriber`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. +After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventHandler`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. .. code-block:: C++ @@ -125,7 +126,7 @@ After the class declaration, the code defines a class, ``SampleNodeWithParameter // Create a parameter subscriber that can be used to monitor parameter changes // (for this node's parameters as well as other nodes' parameters) - param_subscriber_ = std::make_shared(this); + param_subscriber_ = std::make_shared(this); // Set a callback for this node's integer parameter, "an_int_param" auto cb = [this](const rclcpp::Parameter & p) { @@ -138,13 +139,13 @@ After the class declaration, the code defines a class, ``SampleNodeWithParameter cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } -The ``ParameterEventSubscriber``'s add_parameter_callback method returns a callback handle that is stored in a member variable. This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. +The ``ParameterEventHandler``'s add_parameter_callback method returns a callback handle that is stored in a member variable. This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. .. code-block:: C++ ~SampleNodeWithParameters() { - param_subscriber_->remove_parameter_callback(cb_handle_.get()); + param_subscriber_->remove_parameter_callback(cb_handle_); } Following the ``SampleNodeWithParameters`` is a typical ``main`` function which initializes ROS, spins the sample node so that it can send and receive messages, and then shuts down after the user enters ^C at the console. @@ -168,11 +169,11 @@ To build this code, first open the ``CMakeLists.txt`` file and add the following .. code-block:: console - add_executable(parameter_events_subscriber src/parameter_events_subscriber.cpp) - ament_target_dependencies(parameter_events_subscriber rclcpp) + add_executable(parameter_event_handler src/parameter_event_handler.cpp) + ament_target_dependencies(parameter_event_handler rclcpp) install(TARGETS - parameter_events_subscriber + parameter_event_handler DESTINATION lib/${PROJECT_NAME} ) @@ -201,7 +202,7 @@ Navigate back to the root of your workspace, ``dev_ws``, and build your new pack .. code-block:: console - colcon build --packages-select cpp_parameter_events_subscriber + colcon build --packages-select cpp_parameter_event_handler Open a new terminal, navigate to ``dev_ws``, and source the setup files: @@ -229,7 +230,7 @@ Now run the node: .. code-block:: console - ros2 run cpp_parameter_events_subscriber parameter_events_subscriber + ros2 run cpp_parameter_event_handler parameter_event_handler The node is now active and has a single parameter and will print a message whenever this parameter is updated. To test this, open up another terminal and source the ROS setup file as before (. install/setup.bash) and execute the following command: @@ -243,12 +244,12 @@ The terminal running the node will display a message similar to the following: [INFO] [1606950498.422461764] [node_with_parameters]: cb: Received an update to parameter "an_int_param" of type integer: "43" -The callback we set previously in the node has been invoked and has displayed the new updated value. You can now terminate the running parameter_events_subscriber sample using ^C in the terminal. +The callback we set previously in the node has been invoked and has displayed the new updated value. You can now terminate the running parameter_event_handler sample using ^C in the terminal. 3.1 Monitor changes to another node's parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can also use the ParameterEventsSubscriber to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. +You can also use the ParameterEventHandler to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. First update the constructor to add the following code after the existing code: @@ -274,12 +275,12 @@ The destructor and member variables need to be updated as well to account for th ~SampleNodeWithParameters() { - param_subscriber_->remove_parameter_callback(cb_handle_.get()); - param_subscriber_->remove_parameter_callback(cb_handle2_.get()); // Add this + param_subscriber_->remove_parameter_callback(cb_handle_); + param_subscriber_->remove_parameter_callback(cb_handle2_); // Add this } private: - std::shared_ptr param_subscriber_; + std::shared_ptr param_subscriber_; std::shared_ptr cb_handle_; std::shared_ptr cb_handle2_; // Add this }; @@ -289,7 +290,7 @@ In a terminal, navigate back to the root of your workspace, ``dev_ws``, and buil .. code-block:: console - colcon build --packages-select cpp_parameter_events_subscriber + colcon build --packages-select cpp_parameter_event_handler Then source the setup files: @@ -313,11 +314,11 @@ Then source the setup files: call install/setup.bat -Now, to test monitoring of remote parameters, first run the newly-built parameter_events_subscriber code: +Now, to test monitoring of remote parameters, first run the newly-built parameter_event_handler code: .. code-block:: console - ros2 run cpp_parameter_events_subscriber parameter_events_subscriber + ros2 run cpp_parameter_event_handler parameter_event_handler Next, from another teminal (with ROS initialized), run the parameter_blackboard demo application, as follows: @@ -331,7 +332,7 @@ Finally, from a third terminal (with ROS initialized), let's set a parameter on ros2 param set parameter_blackboard a_double_param 3.45 -Upon executing this command, you should see output in the parameter_events_subscriber window, indicating that the callback function was invoked upon the parameter update: +Upon executing this command, you should see output in the parameter_event_handler window, indicating that the callback function was invoked upon the parameter update: .. code-block:: console @@ -340,7 +341,7 @@ Upon executing this command, you should see output in the parameter_events_subsc Summary ------- -You created a node with a parameter and used the ParameterEventsSubscriber class to set a callback to monitor changes to that parameter. You also used the same class to monitor changes to a remote node. The ParameterEventsSubscriber is a convenient way to monitor for parameter changes so that you can then respond to the updated values. +You created a node with a parameter and used the ParameterEventHandler class to set a callback to monitor changes to that parameter. You also used the same class to monitor changes to a remote node. The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values. Next steps ---------- From 99d64189135a8e0bcee8d5e574728d39cdb3b206 Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Thu, 18 Feb 2021 10:53:52 -0800 Subject: [PATCH 3/7] Remove training whitespace and indicate Galactic only Signed-off-by: Michael Jeronimo --- .../Monitoring-For-Parameter-Changes-CPP.rst | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index 7f06de5370..a09e3da7b0 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -1,5 +1,5 @@ -Monitoring for parameter changes (C++) -====================================== +Monitoring for parameter changes (C++) [Galactic] +================================================= **Goal:** Learn to use the ParameterEventHandler class to monitor and respond to parameter changes. @@ -19,7 +19,7 @@ Often a node needs to respond to changes to its own parameters or another node's Prerequisites ------------- -Before starting this tutorial, you should first complete the following tutorials: +Before starting this tutorial, you should first complete the following tutorials: - :ref:`ROS2Params` - :ref:`CppParamNode` @@ -66,9 +66,9 @@ Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a ne .. code-block:: C++ #include - + #include "rclcpp/rclcpp.hpp" - + class SampleNodeWithParameters : public rclcpp::Node { public: @@ -76,11 +76,11 @@ Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a ne : Node("node_with_parameters") { this->declare_parameter("an_int_param", 0); - + // Create a parameter subscriber that can be used to monitor parameter changes // (for this node's parameters as well as other nodes' parameters) param_subscriber_ = std::make_shared(this); - + // Set a callback for this node's integer parameter, "an_int_param" auto cb = [this](const rclcpp::Parameter & p) { RCLCPP_INFO( @@ -91,31 +91,31 @@ Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a ne }; cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } - + ~SampleNodeWithParameters() { param_subscriber_->remove_parameter_callback(cb_handle_); } - + private: std::shared_ptr param_subscriber_; std::shared_ptr cb_handle_; }; - + int main(int argc, char ** argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared()); rclcpp::shutdown(); - + return 0; } 2.1 Examine the code ~~~~~~~~~~~~~~~~~~~~ -The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class. +The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class. -After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventHandler`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. +After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventHandler`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. .. code-block:: C++ @@ -123,11 +123,11 @@ After the class declaration, the code defines a class, ``SampleNodeWithParameter : Node("node_with_parameters") { this->declare_parameter("an_int_param", 0); - + // Create a parameter subscriber that can be used to monitor parameter changes // (for this node's parameters as well as other nodes' parameters) param_subscriber_ = std::make_shared(this); - + // Set a callback for this node's integer parameter, "an_int_param" auto cb = [this](const rclcpp::Parameter & p) { RCLCPP_INFO( @@ -138,7 +138,7 @@ After the class declaration, the code defines a class, ``SampleNodeWithParameter }; cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } - + The ``ParameterEventHandler``'s add_parameter_callback method returns a callback handle that is stored in a member variable. This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. .. code-block:: C++ @@ -165,7 +165,7 @@ Following the ``SampleNodeWithParameters`` is a typical ``main`` function which 2.2 Add executable ~~~~~~~~~~~~~~~~~~ -To build this code, first open the ``CMakeLists.txt`` file and add the following lines of code below the dependency ``find_package(rclcpp REQUIRED)`` +To build this code, first open the ``CMakeLists.txt`` file and add the following lines of code below the dependency ``find_package(rclcpp REQUIRED)`` .. code-block:: console @@ -249,7 +249,7 @@ The callback we set previously in the node has been invoked and has displayed th 3.1 Monitor changes to another node's parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can also use the ParameterEventHandler to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. +You can also use the ParameterEventHandler to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. First update the constructor to add the following code after the existing code: From e73bd46be2ca6bf3ad6d857077a8d6d1876dd05f Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Thu, 18 Feb 2021 11:36:52 -0800 Subject: [PATCH 4/7] Add info about Galactic requirement and remove from title. Signed-off-by: Michael Jeronimo --- source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index a09e3da7b0..765aeaa1e7 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -1,5 +1,5 @@ -Monitoring for parameter changes (C++) [Galactic] -================================================= +Monitoring for parameter changes (C++) +====================================== **Goal:** Learn to use the ParameterEventHandler class to monitor and respond to parameter changes. @@ -7,6 +7,8 @@ Monitoring for parameter changes (C++) [Galactic] **Time:** 20 minutes +**Minimum Platform:** Galactic + .. contents:: Contents :depth: 2 :local: @@ -24,6 +26,8 @@ Before starting this tutorial, you should first complete the following tutorials - :ref:`ROS2Params` - :ref:`CppParamNode` +In addition, you must be running the Galactic distribution of ROS2. + Tasks ----- From 13bc8adc2b30e787f7b434783b3f4fcc38e245db Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Thu, 18 Mar 2021 14:25:55 -0700 Subject: [PATCH 5/7] Address more review feedback Signed-off-by: Michael Jeronimo --- source/Tutorials.rst | 3 +- .../Monitoring-For-Parameter-Changes-CPP.rst | 48 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/source/Tutorials.rst b/source/Tutorials.rst index 3222615520..f8881db201 100644 --- a/source/Tutorials.rst +++ b/source/Tutorials.rst @@ -45,7 +45,6 @@ Beginner: Client Libraries Tutorials/Single-Package-Define-And-Use-Interface Tutorials/Using-Parameters-In-A-Class-CPP Tutorials/Using-Parameters-In-A-Class-Python - Tutorials/Monitoring-For-Parameter-Changes-CPP Tutorials/Getting-Started-With-Ros2doctor Intermediate @@ -60,6 +59,7 @@ Intermediate Tutorials/Launch-system Tutorials/Composition Tutorials/Colcon-Tutorial + Tutorials/Monitoring-For-Parameter-Changes-CPP.rst Advanced -------- @@ -120,3 +120,4 @@ Examples -------- * `Python and C++ minimal examples `__. + diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index 765aeaa1e7..5a0f9214e6 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -16,7 +16,9 @@ Monitoring for parameter changes (C++) Background ---------- -Often a node needs to respond to changes to its own parameters or another node's parameters. The ParameterEventHandler class makes it easy to listen for parameter changes so that your code can respond to them. This tutorial will show you how to use the C++ version of the ParameterEventHandler class to monitor for changes to a node's own parameters as well as changes to another node's parameters. +Often a node needs to respond to changes to its own parameters or another node's parameters. +The ParameterEventHandler class makes it easy to listen for parameter changes so that your code can respond to them. +This tutorial will show you how to use the C++ version of the ParameterEventHandler class to monitor for changes to a node's own parameters as well as changes to another node's parameters. Prerequisites ------------- @@ -39,9 +41,10 @@ In this tutorial, you will create a new package to contain some sample code, wri First, open a new terminal and :ref:`source your ROS 2 installation ` so that ``ros2`` commands will work. -Navigate into the ``dev_ws`` directory created in a previous tutorial (or follow `these instructions `_ if you no longer have the directory and need to create it again). +Navigate into the ``dev_ws`` directory created in a previous tutorial (or follow :ref:`these instructions ` if you no longer have the directory and need to create it again). -Recall that packages should be created in the ``src`` directory, not the root of the workspace. So, navigate into ``dev_ws/src`` and then create a new package there: +Recall that packages should be created in the ``src`` directory, not the root of the workspace. +So, navigate into ``dev_ws/src`` and then create a new package there: .. code-block:: console @@ -54,7 +57,8 @@ The ``--dependencies`` argument will automatically add the necessary dependency 1.1 Update ``package.xml`` ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Because you used the ``--dependencies`` option during package creation, you don’t have to manually add dependencies to ``package.xml`` or ``CMakeLists.txt``. As always, though, make sure to add the description, maintainer email and name, and license information to ``package.xml``. +Because you used the ``--dependencies`` option during package creation, you don’t have to manually add dependencies to ``package.xml`` or ``CMakeLists.txt``. +As always, though, make sure to add the description, maintainer email and name, and license information to ``package.xml``. .. code-block:: xml @@ -117,9 +121,13 @@ Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a ne 2.1 Examine the code ~~~~~~~~~~~~~~~~~~~~ -The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class. +The first statement, ``#include `` is included so that the code can utilize the std::make_shared template. +The next, ``#include "rclcpp/rclcpp.hpp"`` is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class. -After the class declaration, the code defines a class, ``SampleNodeWithParameters``. The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. Next, the code creates a ``ParameterEventHandler`` that will be used to monitor changes to parameters. Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. +After the class declaration, the code defines a class, ``SampleNodeWithParameters``. +The constructor for the class, declares an integer parameter ``an_int_param``, with a default value of 0. +Next, the code creates a ``ParameterEventHandler`` that will be used to monitor changes to parameters. +Finally, the code creates a lambda function and sets it as the callback to invoke whenever ``an_int_param`` is updated. .. code-block:: C++ @@ -143,7 +151,8 @@ After the class declaration, the code defines a class, ``SampleNodeWithParameter cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } -The ``ParameterEventHandler``'s add_parameter_callback method returns a callback handle that is stored in a member variable. This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. +The ``ParameterEventHandler``'s add_parameter_callback method returns a callback handle that is stored in a member variable. +This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. .. code-block:: C++ @@ -192,7 +201,7 @@ It's good practice to run ``rosdep`` in the root of your workspace (``dev_ws``) .. code-block:: console - rosdep install -i --from-path src --rosdistro -y + rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y .. group-tab:: macOS @@ -236,7 +245,8 @@ Now run the node: ros2 run cpp_parameter_event_handler parameter_event_handler -The node is now active and has a single parameter and will print a message whenever this parameter is updated. To test this, open up another terminal and source the ROS setup file as before (. install/setup.bash) and execute the following command: +The node is now active and has a single parameter and will print a message whenever this parameter is updated. +To test this, open up another terminal and source the ROS setup file as before (. install/setup.bash) and execute the following command: .. code-block:: console @@ -248,12 +258,15 @@ The terminal running the node will display a message similar to the following: [INFO] [1606950498.422461764] [node_with_parameters]: cb: Received an update to parameter "an_int_param" of type integer: "43" -The callback we set previously in the node has been invoked and has displayed the new updated value. You can now terminate the running parameter_event_handler sample using ^C in the terminal. +The callback we set previously in the node has been invoked and has displayed the new updated value. +You can now terminate the running parameter_event_handler sample using ^C in the terminal. 3.1 Monitor changes to another node's parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can also use the ParameterEventHandler to monitor parameter changes to another node's parameters. Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. +You can also use the ParameterEventHandler to monitor parameter changes to another node's parameters. +Let's update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. +We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates. First update the constructor to add the following code after the existing code: @@ -345,9 +358,18 @@ Upon executing this command, you should see output in the parameter_event_handle Summary ------- -You created a node with a parameter and used the ParameterEventHandler class to set a callback to monitor changes to that parameter. You also used the same class to monitor changes to a remote node. The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values. +You created a node with a parameter and used the ParameterEventHandler class to set a callback to monitor changes to that parameter. +You also used the same class to monitor changes to a remote node. +The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values. Next steps ---------- -Now that you have examined parameters and have some packages and ROS 2 systems of your own, the :ref:`next tutorial ` will show you how to examine issues in your environment and systems in case you have problems. +You've completed the Intermediate tutorials! + +Related content +--------------- + +To learn how to adapt ROS 1 parameter files for ROS 2, see the :ref:`Migrating YAML parameter files from ROS 1 to ROS2` tutorial. + + From 4231422f3a362698415cbf2a24a593682b7b698d Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Thu, 18 Mar 2021 14:53:01 -0700 Subject: [PATCH 6/7] Remove pedandic remove calls Signed-off-by: Michael Jeronimo --- .../Monitoring-For-Parameter-Changes-CPP.rst | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index 5a0f9214e6..e3a21d3b54 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -100,11 +100,6 @@ Inside the ``dev_ws/src/cpp_parameter_event_handler/src`` directory, create a ne cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } - ~SampleNodeWithParameters() - { - param_subscriber_->remove_parameter_callback(cb_handle_); - } - private: std::shared_ptr param_subscriber_; std::shared_ptr cb_handle_; @@ -151,16 +146,6 @@ Finally, the code creates a lambda function and sets it as the callback to invok cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb); } -The ``ParameterEventHandler``'s add_parameter_callback method returns a callback handle that is stored in a member variable. -This handle is used in the ``~SampleNodeWithParameters`` destructor to remove the callback when the node is destroyed. - -.. code-block:: C++ - - ~SampleNodeWithParameters() - { - param_subscriber_->remove_parameter_callback(cb_handle_); - } - Following the ``SampleNodeWithParameters`` is a typical ``main`` function which initializes ROS, spins the sample node so that it can send and receive messages, and then shuts down after the user enters ^C at the console. .. code-block:: C++ @@ -286,16 +271,10 @@ First update the constructor to add the following code after the existing code: cb_handle2_ = param_subscriber_->add_parameter_callback(remote_param_name, cb2, remote_node_name); -The destructor and member variables need to be updated as well to account for the new ``cb_handle2`` member variable: +Then add another member variable, ``cb_handle2`` for the additional callback handle: .. code-block:: C++ - ~SampleNodeWithParameters() - { - param_subscriber_->remove_parameter_callback(cb_handle_); - param_subscriber_->remove_parameter_callback(cb_handle2_); // Add this - } - private: std::shared_ptr param_subscriber_; std::shared_ptr cb_handle_; From 12604de9fc822b271f14e33943b0a3dac7584295 Mon Sep 17 00:00:00 2001 From: Michael Jeronimo Date: Thu, 18 Mar 2021 16:02:32 -0700 Subject: [PATCH 7/7] Remove the Next Steps section; fix 'ROS2' usage Signed-off-by: Michael Jeronimo --- source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst index e3a21d3b54..618f33a94b 100644 --- a/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst +++ b/source/Tutorials/Monitoring-For-Parameter-Changes-CPP.rst @@ -28,7 +28,7 @@ Before starting this tutorial, you should first complete the following tutorials - :ref:`ROS2Params` - :ref:`CppParamNode` -In addition, you must be running the Galactic distribution of ROS2. +In addition, you must be running the Galactic distribution of ROS 2. Tasks ----- @@ -341,11 +341,6 @@ You created a node with a parameter and used the ParameterEventHandler class to You also used the same class to monitor changes to a remote node. The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values. -Next steps ----------- - -You've completed the Intermediate tutorials! - Related content ---------------