Creating Packages and Nodes¶
In this exercise, we will create our own ROS package and node.
Motivation¶
The basis of ROS communication is that multiple executables called nodes are running in an environment and communicating with each other in various ways. These nodes exist within a structure called a package. In this module we will create a node inside a newly created package.
Reference Example¶
Further Information and Resources¶
Scan-N-Plan Application: Problem Statement¶
We’ve installed ROS, created a workspace, and even built a few times. Now we want to create our own package and our own node to do what we want to do.
Your goal is to create your first ROS node:
First you need to create a package inside your workspace.
Then you can write your own node
Scan-N-Plan Application: Guidance¶
Create a Package¶
cd into the workspace src directory
Remember that all packages should be created inside a workspace src directory.
cd ~/ros2_ws/src
Use the ROS command to create a package called myworkcell_core with a dependency on rclcpp
ros2 pkg create myworkcell_core --dependencies rclcpp
Run
ros2 pkg create -h
to see more details and options for this command.This command creates a directory and required files for a new ROS package.
The first argument is the name of the new ROS package.
Use the
--dependencies
option to specify packages which the newly created package depends on.
There will now be a folder named myworkcell_core. Change into that folder and edit the package.xml file. Edit the file and change the description, author, etc., as desired.
cd myworkcell_core gedit package.xml &
If you forget to add a dependency when creating a package, you can add additional dependencies in the package.xml file.
STOP! We’ll go through a few more lecture slides before continuing this exercise.¶
Create a Node¶
In the package folder, create the file src/vision_node.cpp (using gedit).
Make sure you know the difference between the workspace
src
directory and the myworkcell_core packagesrc
directory. This node source-file should live at:~/ros2_ws/src/myworkcell_core/src/vision_node.cpp
.
Add the ROS C++ header (include rclcpp.hpp).
/** ** Simple ROS Node **/ #include <rclcpp/rclcpp.hpp>
Add a main function (typical in c++ programs). The rest of our code will go inside this function.
int main(int argc, char* argv[]) { }
Initialize the ROS CPP middleware interface (must be called once per process).
// This must be called before anything else ROS-related rclcpp::init(argc, argv);
Create a ROS node instance.
auto node = std::make_shared<rclcpp::Node>("vision_node");
Print a “Hello World” message using ROS print tools.
RCLCPP_INFO(node->get_logger(), "Hello, World!");
Do not exit the program automatically - keep the node alive.
// Don't exit the program. rclcpp::spin(node);
The complete code should look like this:
/** ** Simple ROS Node **/ #include <rclcpp/rclcpp.hpp> int main(int argc, char* argv[]) { // This must be called before anything else ROS-related rclcpp::init(argc, argv); // Create a ROS node auto node = std::make_shared<rclcpp::Node>("vision_node"); RCLCPP_INFO(node->get_logger(), "Hello, World!"); // Don't exit the program. rclcpp::spin(node); }
RCLCPP_INFO
is one of the many logging methodsIt will print the message to the terminal output, and send it to the /rosout topic for other nodes to monitor.
There are 5 levels of logging: DEBUG, INFO, WARNING, ERROR, & FATAL.
To use a different logging level, replace INFO in
RCLCPP_INFO
orRCLCPP_INFO_STREAM
with the appropriate level.Use
RCLCPP_INFO
for printf-style logging, andRCLCPP_INFO_STREAM
for cout-style logging.
Now that you have created the source code for the node, we need to add instructions for building it into an executable program. In the package folder, edit the CMakeLists.txt file using gedit. Define an executable node named vision_node (add_executable), with the source file vision_node.cpp. Also within the CMakeLists.txt, make sure your new vision_node gets linked to the required dependencies.
add_executable(vision_node src/vision_node.cpp) ament_target_dependencies(vision_node rclcpp)
These lines should be place after the section labeled
# find dependencies
and before theament_package()
call. The flow of a CMakeLists.txt file is almost always to first find all dependencies the current project requires, then to declare the targets the current project is creating, and finally to specify extra information such as how to test the targets and things that projects making use of this one need to know. Note that the term “project” is used here in the context of CMake. Each ROS package acts as a separate CMake project (notice theproject(myworkcell_core)
) line at the very top of the file).
See ament_cmake documentation for more details on common ROS2 CMakeLists rules.
You’re allowed to spread most of the CMakeLists rules across multiple lines, which is often required when a target contains many source files or has many dependencies.
We’ve now told CMake about the vision_node executable and how to build it, but to actually run it, the file must be installed along with all the other workspace outputs. Typically, the installation location will be the
install/
directory alongside thesrc/
directory. Add the following lines afterament_target_dependencies
but beforeament_package
into your CMakeLists.txt to declare an installation rule for the vision_node executable:# Mark executables for installation install(TARGETS vision_node DESTINATION lib/${PROJECT_NAME})
ROS2 installs executables into a package-named subdir in the
lib
directory.A different set of
install
rules are needed if your project builds libraries, which are installed in bot the rootlib
andbin
directories.
Build your program (node), by running
colcon build
in your build terminal windowRemember that you must run
colcon build
from theros2_ws
directory.This will build all of the programs, libraries, etc. in myworkcell_core
In this case, it’s just a single ROS node vision_node
Run a Node¶
Open a terminal to run your node.
Remember to run
source ~/ros2_ws/install/setup.bash
in this new terminal
Run your node.
ros2 run myworkcell_core vision_node
This runs the program we just created. Remember to use TAB to help speed-up typing and reduce errors.
In a second terminal, check what nodes are running.
ros2 node list
You should now see a new /vision_node listed.
To stop the node, input Ctrl+C in the terminal where it is running. The node is running as a completely normal executable file so standard Linux process management tools can also stop it (e.g.,
killall vision_node
).
Challenge¶
Goal: Modify the node so that it prints your name. This will require you to run through the build process again.