Skip to content

Commit fbbcace

Browse files
joe28965clalancettemaryaB-osr
authored
Created tutorial: Using Parameters In A Class (ros2#582)
* Create tutorial: Using Parameters In A Class (C++) After struggling myself with getting a parameter in a class in C++, I decided to make a tutorial so others wouldn't have to struggle. * Update Using-Parameters-In-A-Class-CPP.rst * Added my tutorial to the beginner tutorials * Update Using-Parameters-In-A-Class-CPP.rst Removed trailing whitespaces * Update source/Tutorials/Using-Parameters-In-A-Class-CPP.rst Commited changes suggested by @chlalancette Co-Authored-By: Chris Lalancette <[email protected]> * Update source/Tutorials/Using-Parameters-In-A-Class-CPP.rst Co-Authored-By: Chris Lalancette <[email protected]> * Added a summary to Using-Parameters-In-A-Class-CPP.rst * Update source/Tutorials/Using-Parameters-In-A-Class-CPP.rst Co-Authored-By: Marya Belanger <[email protected]> * Update source/Tutorials/Using-Parameters-In-A-Class-CPP.rst Co-Authored-By: Marya Belanger <[email protected]> * Update Tutorials.rst * Update Custom-ROS2-Interfaces.rst * Changed Using-Parameters-In-A-Class based on @maryaB-osr suggestions. Co-authored-by: Chris Lalancette <[email protected]> Co-authored-by: Marya Belanger <[email protected]>
1 parent 0001416 commit fbbcace

File tree

3 files changed

+317
-1
lines changed

3 files changed

+317
-1
lines changed

source/Tutorials.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Beginner: Client Libraries
5050
Tutorials/Writing-A-Simple-Cpp-Service-And-Client
5151
Tutorials/Writing-A-Simple-Py-Service-And-Client
5252
Tutorials/Custom-ROS2-Interfaces
53+
Tutorials/Using-Parameters-In-A-Class-CPP
5354
Tutorials/Getting-Started-With-Ros2doctor
5455

5556
Intermediate

source/Tutorials/Custom-ROS2-Interfaces.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,4 +710,5 @@ You can learn about action interfaces :ref:`here <Actions>`.
710710
Next steps
711711
----------
712712

713-
Now that you have some packages and ROS 2 systems of your own, the :ref:`next tutorial <Ros2Doctor>` will show you how to examine issues in your environment and systems in case you have problems.
713+
Next you will create a simple ROS 2 package with a custom parameter that you will learn to set from a launch file.
714+
This tutorial is available in :ref:`C++ <CppParamNode>`.
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
.. _CppParamNode:
2+
3+
Using Parameters In A Class (C++)
4+
=================================
5+
6+
**Goal:** Create and run a class with ROS parameters using C++.
7+
8+
**Tutorial level:** Beginner
9+
10+
**Time:** 20 minutes
11+
12+
.. contents:: Contents
13+
:depth: 2
14+
:local:
15+
16+
Background
17+
----------
18+
19+
When making your own :ref:`nodes <ROS2Nodes>` you will sometimes need to add parameters that can be set from the launch file.
20+
21+
This tutorial will show you how to create those parameters in a C++ class, and how to set them in a launch file.
22+
23+
Prerequisites
24+
-------------
25+
26+
In previous tutorials, you learned how to :ref:`create a workspace <ROS2Workspace>` and :ref:`create a package <CreatePkg>`.
27+
You have also learned about :ref:`parameters <ROS2Params>` and their function in a ROS 2 system.
28+
29+
Tasks
30+
-----
31+
1 Create a package
32+
^^^^^^^^^^^^^^^^^^
33+
34+
Open a new terminal and :ref:`source your ROS 2 installation <ConfigROS2>` so that ``ros2`` commands will work.
35+
36+
Navigate into the ``dev_ws`` directory created in a previous tutorial.
37+
38+
Recall that packages should be created in the ``src`` directory, not the root of the workspace.
39+
Navigate into ``dev_ws/src`` and create a new package:
40+
41+
.. code-block:: console
42+
43+
ros2 pkg create --build-type ament_cmake cpp_parameters --dependencies rclcpp
44+
45+
Your terminal will return a message verifying the creation of your package ``cpp_parameters`` and all its necessary files and folders.
46+
47+
The ``--dependencies`` argument will automatically add the necessary dependency lines to ``package.xml`` and ``CMakeLists.txt``.
48+
49+
1.1 Update ``package.xml``
50+
~~~~~~~~~~~~~~~~~~~~~~~~~~
51+
52+
Because you used the ``--dependencies`` option during package creation, you don’t have to manually add dependencies to ``package.xml`` or ``CMakeLists.txt``.
53+
54+
As always, though, make sure to add the description, maintainer email and name, and license information to ``package.xml``.
55+
56+
.. code-block:: xml
57+
58+
<description>C++ parameter tutorial</description>
59+
<maintainer email="[email protected]">Your Name</maintainer>
60+
<license>Apache License 2.0</license>
61+
62+
2 Write the C++ node
63+
^^^^^^^^^^^^^^^^^^^^
64+
65+
Inside the ``dev_ws/src/cpp_parameters/src`` directory, create a new file called ``cpp_parameters_node.cpp`` and paste the following code within:
66+
67+
.. code-block:: C++
68+
69+
#include <rclcpp/rclcpp.hpp>
70+
#include <chrono>
71+
#include <string>
72+
#include <functional>
73+
74+
using namespace std::chrono_literals;
75+
76+
class ParametersClass: public rclcpp::Node
77+
{
78+
public:
79+
ParametersClass()
80+
: Node("parameter_node")
81+
{
82+
this->declare_parameter<std::string>("my_parameter", "world");
83+
timer_ = this->create_wall_timer(
84+
1000ms, std::bind(&ParametersClass::respond, this));
85+
}
86+
void respond()
87+
{
88+
this->get_parameter("my_parameter", parameter_string_);
89+
RCLCPP_INFO(this->get_logger(), "Hello %s", parameter_string_.c_str());
90+
}
91+
private:
92+
std::string parameter_string_;
93+
rclcpp::TimerBase::SharedPtr timer_;
94+
};
95+
96+
int main(int argc, char** argv)
97+
{
98+
rclcpp::init(argc, argv);
99+
rclcpp::spin(std::make_shared<ParametersClass>());
100+
rclcpp::shutdown();
101+
return 0;
102+
}
103+
104+
2.1 Examine the code
105+
~~~~~~~~~~~~~~~~~~~~
106+
The ``#include`` statements at the top are the package dependencies.
107+
108+
The next piece of code creates the class and the constructor.
109+
The first line of this constructor creates our parameter.
110+
Our parameter has the name ``my_parameter`` and is assigned the default value ``world``.
111+
Next, ``timer_`` is initialized, which causes the ``respond`` function to be executed once a second.
112+
113+
.. code-block:: C++
114+
115+
class ParametersClass: public rclcpp::Node
116+
{
117+
public:
118+
ParametersClass()
119+
: Node("parameter_node")
120+
{
121+
this->declare_parameter<std::string>("my_parameter", "world");
122+
timer_ = this->create_wall_timer(
123+
1000ms, std::bind(&ParametersClass::respond, this));
124+
}
125+
126+
The first line of our ``respond`` function gets the parameter ``my_parameter`` from the node, and stores it in ``parameter_string_``.
127+
The ``RCLCPP_INFO`` function ensures the message is logged.
128+
129+
.. code-block:: C++
130+
131+
void respond()
132+
{
133+
this->get_parameter("my_parameter", parameter_string_);
134+
RCLCPP_INFO(this->get_logger(), "Hello %s", parameter_string_.c_str());
135+
}
136+
137+
Last is the declaration of ``timer_`` and ``parameter_string_``
138+
139+
.. code-block:: C++
140+
141+
private:
142+
std::string parameter_string_;
143+
rclcpp::TimerBase::SharedPtr timer_;
144+
145+
Following our ``ParametersClass`` is our ``main``.
146+
Here ROS 2 is initialized, and ``rclcpp::spin`` starts processing data from the node.
147+
148+
.. code-block:: C++
149+
150+
int main(int argc, char** argv)
151+
{
152+
rclcpp::init(argc, argv);
153+
rclcpp::spin(std::make_shared<ParametersClass>());
154+
rclcpp::shutdown();
155+
return 0;
156+
}
157+
158+
159+
2.2 Add executable
160+
~~~~~~~~~~~~~~~~~~
161+
162+
Now open the ``CMakeLists.txt`` file. Below the dependency ``find_package(rclcpp REQUIRED)`` add the following lines of code.
163+
164+
.. code-block:: console
165+
166+
add_executable(parameter_node src/cpp_parameters_node.cpp)
167+
ament_target_dependencies(parameter_node rclcpp)
168+
169+
install(TARGETS
170+
parameter_node
171+
DESTINATION lib/${PROJECT_NAME}
172+
)
173+
174+
175+
3 Build and run
176+
^^^^^^^^^^^^^^^
177+
178+
It's good practice to run ``rosdep`` in the root of your workspace (``dev_ws``) to check for missing dependencies before building:
179+
180+
.. code-block:: console
181+
182+
sudo rosdep install -i --from-path src --rosdistro <distro> -y
183+
184+
Navigate back to the root of your workspace, ``dev_ws``, and build your new package:
185+
186+
.. code-block:: console
187+
188+
colcon build --packages-select cpp_parameters
189+
190+
Open a new terminal, navigate to ``dev_ws``, and source the setup files:
191+
192+
.. code-block:: console
193+
194+
. install/setup.bash
195+
196+
Now run the node:
197+
198+
.. code-block:: console
199+
200+
ros2 run cpp_parameters parameter_node
201+
202+
The terminal should return the following message every second:
203+
204+
.. code-block:: console
205+
206+
[INFO] [parameter_node]: Hello world
207+
208+
Now you can see the default value of your parameter, but you want to be able to set it yourself.
209+
There are two ways to accomplish this.
210+
211+
3.1 Change via the console
212+
~~~~~~~~~~~~~~~~~~~~~~~~~~
213+
214+
This part will use the knowledge you have gained from the :ref:`tutoral about parameters <ROS2Params>` and apply it to the node you have just created.
215+
216+
Make sure the node is running:
217+
218+
.. code-block:: console
219+
220+
ros2 run cpp_parameters parameter_node
221+
222+
Open another terminal, source the setup files from inside ``dev_ws`` again, and enter the following line:
223+
224+
.. code-block:: console
225+
226+
ros2 param list
227+
228+
There you will see the custom parameter ``my_parameter``.
229+
To change it simply run the following line in the console:
230+
231+
.. code-block:: console
232+
233+
ros2 param set /parameter_node my_parameter earth
234+
235+
You know it went well if you get the output ``Set parameter successful``.
236+
If you look at the other terminal, you should see the output change to ``[INFO] [parameter_node]: Hello earth``
237+
238+
3.2 Change via a launch file
239+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
240+
You can also set the parameter in a launch file, but first you will need to add the launch directory.
241+
Inside the ``dev_ws/src/cpp_parameters/`` directory, create a new directory called ``launch``.
242+
In there, create a new file called ``cpp_parameters_launch.py``
243+
244+
.. code-block:: Python
245+
246+
from launch import LaunchDescription
247+
from launch_ros.actions import Node
248+
249+
def generate_launch_description():
250+
return LaunchDescription([
251+
Node(
252+
package="cpp_parameters",
253+
node_executable="parameter_node",
254+
node_name="custom_parameter_node",
255+
output="screen",
256+
emulate_tty=True,
257+
parameters=[
258+
{"my_parameter": "earth"}
259+
]
260+
)
261+
])
262+
263+
Here you can see that we set ``my_parameter`` to ``earth`` when we launch our node ``parameter_node``.
264+
By adding the two lines below, we ensure our output is printed in our console.
265+
266+
.. code-block:: console
267+
268+
output="screen",
269+
emulate_tty=True,
270+
271+
Now open the ``CMakeLists.txt`` file.
272+
Below the lines you added earlier, add the following lines of code.
273+
274+
.. code-block:: console
275+
276+
install(
277+
DIRECTORY launch
278+
DESTINATION share/${PROJECT_NAME}
279+
)
280+
281+
Open a console and navigate to the root of your workspace, ``dev_ws``, and build your new package:
282+
283+
.. code-block:: console
284+
285+
colcon build --packages-select cpp_parameters
286+
287+
Then source the setup files:
288+
289+
.. code-block:: console
290+
291+
. install/setup.bash
292+
293+
Now run the node using the launch file we have just created:
294+
295+
.. code-block:: console
296+
297+
ros2 launch cpp_parameters cpp_parameters_launch.py
298+
299+
The terminal should return the following message every second:
300+
301+
.. code-block:: console
302+
303+
[parameter_node-1] [INFO] [custom_parameter_node]: Hello earth
304+
305+
Summary
306+
-------
307+
308+
You created a node with a custom parameter, that can be set either from the launch file or the command line.
309+
You added the dependencies, executable, and launch file to the package configuration files so that you could build and run them, and see the parameter in action.
310+
311+
Next steps
312+
----------
313+
314+
Now that you have some packages and ROS 2 systems of your own, the :ref:`next tutorial <Ros2Doctor>` will show you how to examine issues in your environment and systems in case you have problems.

0 commit comments

Comments
 (0)