Difference between ROS and ROS2

24 Sep 2021 - John Z. Li

ROS is sometimes called by the name ROS1, though I believe it is a misnomer. Throughout this post, I will refer to ROS distributions before ROS2 as ROS. The current actively maintained distribution of ROS is “ROS Noetic Ninjemys”.

Workspace and packages

Initialize a workspace

  1. ROS2: After creating a workspace, assuming the workspace contains a sub-directory named “src”. After entering the “src” sub-directory, the workspace can be initialized using the following:
    # CMake project
    ros2 pkg create --build-type ament_cmake <package_name>
    # Python project
    ros2 pkg create --build-type ament_python <package_name>
    # Or use the --node-name option to specify the entry point of the package, that is
    # the package provides an executable named after "node_name"
    ros2 pkg create --build-type ament_cmake --node-name <node_name> <package_name>
    ros2 pkg create --build-type ament_python --node-name <node_name> <package_name>
    
  2. ROS: After creating an empty workspace, execute the following in the workspace directory:
    catkin_make
    

    This command will initialize a CMake project and creating three sub-directories including “build”, “devel” and “src”. To create a package, after entering the “src” subdirectory, execute the following:

    catkin_create_pkg <package_name> <package_dep_1> <package_dep_2> ... <package_dep_k>
    

Build a workspace

  1. ROS2: To build a workspace, execute the following at the root directory of the workspace:
    # ROS2
    colcon build
    

    It is possible to build only a single ROS2 package or a set of selected packages with

    colcon build --packages-select <pkg_1> <pkg_2> ... <pkg_k>
    
  2. ROS: To build a workspace, execute the following at the root directory of the workspace:
    #ROS
    catkin_make
    

    It is impossible to only build a single package of ROS, because all packages in a workspace is managed by a single CMake file.

List all packages in a workspace

  1. ROS2: At the root of the workspace, execute the following: (don’t need to source the workspace first).
    # don't include packages in the underlay.
    colcon list
    

    Use the following to list all the packages that have been sourced: (if the current workspace is not sourced, packages in the current workspace will not be listed.)

    ros2 pkg list
    
  2. ROS: At the root of the workspace, execute the following: (if the current workspace is not sourced, packages in the current workspace will not be listed.)
    rospack list
    

Find information of a package

  1. ROS2: Use the following to get the information of a package, (the package must have been sourced):
    ros2 pkg xml <package_name>
    

    And use the following to get the installing path of the package:

    ros2 pkg prefix <package_name>
    
  2. ROS: Use the following to find the installing path of a package
    rospack find <packge_name>
    

    After getting the installing path, one can manually check the manifest of the package.

Check package dependencies

  1. ROS2:
    # list all packages in the workspace and their dependencies among each other
    colcon graph
    # check dependencies in the package.xml file (only first-order dependencies)
    ros2 pkg xml <package_name>
    
  2. ROS:
    # list the first-order dependencies of a package
    rospack depends1 <package_name>
    # list all dependencies of a package
    rospack depends <package_name>
    # list all dependencies, indent output to show the depth of dependencies.
    rospack depends-indent <package_name>
    

Launch ROS/ROS2 applications

  1. ROS2: Note that once can also write ROS2 launch files using XML or YAML files. But why not use a full-fledged programming language, python in this case. There are certain things that can not be achieved via XML or YAML.
    # launch an executable provided by a package
    ros2 run <package_name> <executable_name>
    # With ROS2, a launch file is a simple python script.
    # with managed nodes of ROS2, it can be guaranteed that nodes are started up
    # with some well-behaved lifecycle constraints.
    ros2 launch launch.py
    

    2 ROS:

    # file.launch is a XML file that specifies what should be launched.
    # But no guarantee in what order will all nodes be started up.
    roslaunch package_name file.launch
    

Diagnosis tools

  1. ROS2:
    # Check ROS2 setup
    ros2 doctor
    # With some nodes running, get a report of your ROS2 application
    ros2 doctor --report
    # check whether the underlying communication mechanism is working
    ros2 doctor hello
    
  2. ROS:
    # check whether ROS is running correctly
    roswtf
    

ROS node versus ROS2 node

Hode nodes find each other

  1. ROS2: ROS2 uses DDS (Data Distribution Service) to do service discovery and message transmission. Because DDS can orchestrate node communication over the same subnetwork, this makes it possible to deploy ROS2 nodes on multiple computers which all belong to the same subnetwork. DDS is a well-established international standard and good implementation of DDS is battle tested. A good DDS implementation usually uses shared memory to exchange information between two nodes when it is detected that both nodes are located in the same localhost.
  2. ROS: With ROS, one has start the roscore first so that other nodes can find each other and start to communicate with each other. Note that roslaunch will automatically detect whether roscore is already running and start it if not.
    • roscore will starts a ROS Master, which provides a naming registration and finding services for nodes, topics and services.
    • roscore will also start a ROS Parameter Server, which is actually runs as a part of above mentioned ROS Master.
    • roscore will also start a “rosout” logging node. After all the other nodes except those included in roscore find each other, they communicate with each other using standard TCP. Because standard TCP is used, with some network configuration, ROS nodes can also be distributed among multiple machines. The problem is that the TCP mechanism can not be short-circuited even if we know in advance that two nodes reside on the same machine. This leads to a sometimes large performance penalty because the overhead of all the serializing, deserializing and TCP transportation. If performance becomes an issue, with ROS, one often needs to rewrite his application using so-called “nodelets” and use shared pointers to pass messages around.

Node-process relations

ROS follows a strict One-Node-Per-Process-Per-Executable model. Each node in ROS is started by an executable creating a new process. Each node-process then communicating with each other concurrently.

This design has some implications:

Note: This does not mean that one can not use multiple threads to improve the performance of a ROS node, or that some functionalities of a node can not be loaded at runtime. It is just that you can not conceptually model them after ROS node. For example, one can use -ros::MultiThreadedSpinner

With ROS2, it is possible to implement multiple nodes in a single process. ROS2 completely decouples the concept of node can how the node is handled through the executor interface. One can add a node into an executor, and specify a thread to run that executor.

Lifecycle management

Because ROS2 completely decouples the concept of Nodes and the threading model that composes different nodes into a robotic system. It becomes necessary to introduce the notion of “lifecycle management” to make sure that:

ROS does not have this issue because its adherence to single-node-per-process model. While this makes ROS systems simpler, it also limit its capability.

Namespace of services and topics

In ROS, topics with the same .msg name, and services with the same .srv name collides with each other. In ROS2, topics and services are grouped by the packages in which they are defined.

Tools specific to ROS

There are two command line tools that currently are only available for ROS.

  1. Use roscd to navigate to the directory of a ROS package. For example, roscd roscpp will make the shell enter the root directory of the “roscpp” package. This Github issue why such a facility is hard to be implemented with ROS2. Please note that roscd log will change the current directory to the directory where log files are saves. This command does not mean that “log” is a ROS package.
  2. Use rosls to view directory layout of a ROS package without leaving the current directory or entering the full path of the package. For example, rosls roscpp will print the directory layout of the “roscpp” package”