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¶
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 catkin workspace.
- Then you can write your own node
Scan-N-Plan Application: Guidance¶
Create a Package¶
cd into the catkin workspace src directory Note: Remember that all packages should be created inside a workspace src directory.
cd ~/catkin_ws/src
Use the ROS command to create a package called myworkcell_core with a dependency on roscpp
catkin create pkg myworkcell_core --catkin-deps roscpp
See the catkin_tools documentation for more details on 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
--catkin-deps
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, edit the CMakeLists.txt file using gedit. Browse through the example rules, and add an executable(add_executable), node named vision_node, source file named vision_node.cpp. Also within the CMakeLists.txt, make sure your new vision_node gets linked (‘target_link_libraries’) to the catkin libraries.
add_compile_options(-std=c++11) add_executable(vision_node src/vision_node.cpp) target_link_libraries(vision_node ${catkin_LIBRARIES})
These lines can be placed anywhere in
CMakeLists.txt
, but I typically:- Uncomment existing template examples for
add_compile_options
near the top (just belowproject()
) - Uncomment and edit existing template examples for
add_executable
andtarget_link_libraries
near the bottom - This helps make sure these rules are defined in the correct order, and makes it easy to remember the proper syntax.
Note: You’re also allowed to spread most of the CMakeLists rules across multiple lines, as shown in the
target_link_libraries
template code- Uncomment existing template examples for
In the package folder, create the file src/vision_node.cpp (using gedit).
Add the ros header (include ros.h).
/** ** Simple ROS Node **/ #include <ros/ros.h>
Add a main function (typical in c++ programs).
/** ** Simple ROS Node **/ #include <ros/ros.h> int main(int argc, char* argv[]) { }
Initialize your ROS node (within the main).
/** ** Simple ROS Node **/ #include <ros/ros.h> int main(int argc, char* argv[]) { // This must be called before anything else ROS-related ros::init(argc, argv, "vision_node"); }
Create a ROS node handle.
/** ** Simple ROS Node **/ #include <ros/ros.h> int main(int argc, char* argv[]) { // This must be called before anything else ROS-related ros::init(argc, argv, "vision_node"); // Create a ROS node handle ros::NodeHandle nh; }
Print a “Hello World” message using ROS print tools.
/** ** Simple ROS Node **/ #include <ros/ros.h> int main(int argc, char* argv[]) { // This must be called before anything else ROS-related ros::init(argc, argv, "vision_node"); // Create a ROS node handle ros::NodeHandle nh; ROS_INFO("Hello, World!"); }
Do not exit the program automatically - keep the node alive.
/** ** Simple ROS Node **/ #include <ros/ros.h> int main(int argc, char* argv[]) { // This must be called before anything else ROS-related ros::init(argc, argv, "vision_node"); // Create a ROS node handle ros::NodeHandle nh; ROS_INFO("Hello, World!"); // Don't exit the program. ros::spin(); }
ROS_INFO is one of the many logging methods.
- It 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 ROS_INFO or ROS_INFO_STREAM with the appropriate level.
- Use ROS_INFO for printf-style logging, and ROS_INFO_STREAM for cout-style logging.
Build your program (node), by running
catkin build
in a terminal window- Remember that you must run
catkin build
from within yourcatkin_ws
(or any subdirectory) - This will build all of the programs, libraries, etc. in myworkcell_core
- In this case, it’s just a single ROS node vision_node
- Remember that you must run
Run a Node¶
Open a terminal and start the ROS master.
roscore
The ROS Master must be running before any ROS nodes can function.
Open a second terminal to run your node.
In a previous exercise, we added a line to our
.bashrc
to automatically sourcedevel/setup.bash
in new terminal windowsThis will automatically export the results of the build into your new terminal session.
If you’re reusing an existing terminal, you’ll need to manually source the setup files (since we added a new node):
source ~/catkin_ws/devel/setup.bash
Run your node.
rosrun 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 third terminal, check what nodes are running.
rosnode list
In addition to the /rosout node, you should now see a new /vision_node listed.
Enter rosnode kill /vision_node. This will stop the node.
Note: It is more common to use Ctrl+C to stop a running node in the current terminal window.
Challenge¶
Goal: Modify the node so that it prints your name. This will require you to run through the build process again.