-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Writing a Composable Node (C++) Tutorial * Add Package.xml note * Add links to demos Signed-off-by: David V. Lu!! <[email protected]> Co-authored-by: Chris Lalancette <[email protected]> (cherry picked from commit 0c79b0f) Co-authored-by: David V. Lu!! <[email protected]>
- Loading branch information
1 parent
fce8c93
commit 93eace5
Showing
5 changed files
with
176 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
source/Tutorials/Intermediate/Writing-a-Composable-Node.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
Writing a Composable Node (C++) | ||
=============================== | ||
|
||
.. contents:: Table of Contents | ||
:depth: 2 | ||
:local: | ||
|
||
Starting Place | ||
-------------- | ||
|
||
Let's assume that you have a regular ``rclcpp::Node`` executable that you want to run in the same process as other nodes to enable more efficient communication. | ||
|
||
We'll start from having a class that directly inherits from ``Node``, and that also has a main method defined. | ||
|
||
.. code-block:: c++ | ||
|
||
namespace palomino | ||
{ | ||
class VincentDriver : public rclcpp::Node | ||
{ | ||
// ... | ||
}; | ||
} | ||
|
||
int main(int argc, char * argv[]) | ||
{ | ||
rclcpp::init(argc, argv); | ||
rclcpp::spin(std::make_shared<palomino::VincentDriver>()); | ||
rclcpp::shutdown(); | ||
return 0; | ||
} | ||
|
||
This will typically be compiled as an executable in your Cmake. | ||
|
||
.. code-block:: cmake | ||
# ... | ||
add_executable(vincent_driver src/vincent_driver.cpp) | ||
# ... | ||
install(TARGETS vincent_driver | ||
DESTINATION lib/${PROJECT_NAME} | ||
) | ||
Code Updates | ||
------------ | ||
|
||
Add the Package Dependency | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Your `package.xml <https://github.com/ros2/demos/tree/{REPOS_FILE_BRANCH}/composition/package.xml>`__ should have a dependency on ``rclcpp_components``, a la | ||
|
||
.. code-block:: xml | ||
<depend>rclcpp_components</depend> | ||
Alternatively, you can independently add a ``build_depend/exec_depend``. | ||
|
||
Class Definition | ||
^^^^^^^^^^^^^^^^ | ||
|
||
The only change to your class definition that you may have to do is ensure that `the constructor for the class <https://github.com/ros2/demos/tree/{REPOS_FILE_BRANCH}/composition/src/talker_component.cpp>`__ takes a ``NodeOptions`` argument. | ||
|
||
.. code-block:: c++ | ||
|
||
VincentDriver(const rclcpp::NodeOptions & options) : Node("vincent_driver", options) | ||
{ | ||
// ... | ||
} | ||
|
||
No More Main Method | ||
^^^^^^^^^^^^^^^^^^^ | ||
|
||
Replace your main method with a ``pluginlib``-style macro invocation. | ||
|
||
.. code-block:: c++ | ||
|
||
#include <rclcpp_components/register_node_macro.hpp> | ||
RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver) | ||
|
||
.. caution:: | ||
If the main method you are replacing contains a ``MultiThreadedExecutor``, be sure to make note and ensure that your container node is multithreaded. | ||
See section below. | ||
|
||
CMake Changes | ||
^^^^^^^^^^^^^ | ||
First, add ``rclcpp_components`` as a dependency in your CMakeLists.txt with: | ||
|
||
.. code-block:: cmake | ||
find_package(rclcpp_components REQUIRED) | ||
Second, we're going to replace our ``add_executable`` with a ``add_library`` with a new target name. | ||
|
||
.. code-block:: cmake | ||
add_library(vincent_driver_component src/vincent_driver.cpp) | ||
Third, replace other build commands that used the old target to act on the new target. | ||
i.e. ``ament_target_dependencies(vincent_driver ...)`` becomes ``ament_target_dependencies(vincent_driver_component ...)`` | ||
|
||
Fourth, add a new command to declare your component. | ||
|
||
.. code-block:: cmake | ||
rclcpp_components_register_node( | ||
vincent_driver_component | ||
PLUGIN "palomino::VincentDriver" | ||
EXECUTABLE vincent_driver | ||
) | ||
Fifth and finally, change any installation commands in the CMake that operated on the old target to install the library version instead. | ||
For instance, do not install either target into ``lib/${PROJECT_NAME}``. | ||
Replace with the library installation. | ||
|
||
.. code-block:: cmake | ||
ament_export_targets(export_vincent_driver_component) | ||
install(TARGETS vincent_driver_component | ||
EXPORT export_vincent_driver_component | ||
ARCHIVE DESTINATION lib | ||
LIBRARY DESTINATION lib | ||
RUNTIME DESTINATION bin | ||
) | ||
Running Your Node | ||
----------------- | ||
|
||
See the :doc:`Composition tutorial <Composition>` for an in-depth look at composing nodes. | ||
The quick and dirty version is that if you had the following in your Python launch file, | ||
|
||
.. code-block:: python | ||
from launch_ros.actions import Node | ||
# .. | ||
ld.add_action(Node( | ||
package='palomino', | ||
executable='vincent_driver', | ||
# .. | ||
)) | ||
you can replace it with | ||
|
||
.. code-block:: python | ||
from launch_ros.actions import ComposableNodeContainer | ||
from launch_ros.descriptions import ComposableNode | ||
# .. | ||
ld.add_action(ComposableNodeContainer( | ||
name='a_buncha_nodes', | ||
namespace='', | ||
package='rclcpp_components', | ||
executable='component_container', | ||
composable_node_descriptions=[ | ||
ComposableNode( | ||
package='palomino', | ||
plugin='palomino::VincentDriver', | ||
name='vincent_driver', | ||
# .. | ||
extra_arguments=[{'use_intra_process_comms': True}], | ||
), | ||
] | ||
)) | ||
.. caution:: | ||
|
||
If you need multi-threading, instead of setting your executable to ``component_container``, set it to ``component_container_mt`` |