UP | HOME

The ROS API and Python

Client Libraries

ROS client libraries allow programs to interact with other ROS processes. There are three primarily supported client libraries:

  • rcl is the C client library, upon which the other client libraries are built.
  • rclcpp is the C++ client library.
  • rclpy is the Python client library.

Documentation

  • As of 9/2024, the rclpy documentation is not properly deployed on the ROS 2 website https://github.com/ros-infrastructure/rosdoc2/issues/68
  • As a result, the links on this website point to the foxy documentation
  • You can build the documentation locally using python3-rosdoc2 as follows:

    git clone -b jazzy https://github.com/ros2/rclpy
    rosdoc2 build --package-path rclpy/rclpy
    
  • The documentation is in docs_output/rclpy/index.html.
  • You can also use import rclpy in the python interpreter and use help()

rclpy

rclpy is a python library that allows a python program to become a ROS 2 node.

  1. import rclpy to use the client library.
  2. rclpy.node defines the Node class
    • One way to make nodes in ROS 2 is to sub-class rclpy.node
    • We focus on this method because it is the most flexible and makes it easier to combine nodes within the same python process.
    • It is also possible to instantiate an rclpy.node.Node object and call it's methods.
  3. Each python ROS 2 node has an entry_point function that is called when the node is started.
    • The entrypoint function can have any name, and it is registered in the setup.py.
    • The def entry_point_name(args=None) function is passed command line arguments.
    • Call rclpy.init(args=args) to have the node parse its ROS command line arguments
  4. The Node class has methods that enable
  5. There are many other ROS functions and classes available in rclpy, look at the documentation.
  6. An example of some ROS API functions is available at https://github.com/m-elwin/me495_demo

Interfaces

To use interfaces from a ROS node you must import the corresponding package. This will expose an object that contains the elements in that interface.

# import for a package/msg/MessageType
from package.msg import MessageType

# import for a package/srv/ServiceType
from package.srv import  ServiceType

# The request type:
ServiceType.Request()

# The response Type:
ServiceType.Response()

# Each object has the same field names as set in the IDL file
# These types can also be constructed by providing keyword arguments to the constructor
# Which in turn contains the field names of the type

Naming in ROS

Understanding Names

  1. Every item in the ROS Computation Graph has a Graph Resource Name
    • The link is for ROS 1 as I have not yet found equivalent documentation for ROS 2 and it is substantially similar.
    • When using rclpy functions to create nodes, subscribers, clients, and services, each of these entities is provided a name as one of the arguments.
    • The name is used by rclpy to register the python object with the appropriate entity in the ROS graph (e.g., publisher/subscriber with a topic).
    • Names are best thought of as placeholder default values: they can be changed by users when the node runs.
  2. Every ROS 2 node exists within a =/namespace/
    • Namespaces are like directories on Linux: they start from the global namespace (called /) and can be nested (e.g., /ns1/ns2/ns3).
  3. Just like paths on Linux, ROS names can be relative or absolute
    • An absolute name is any name that starts with a /
    • A relative name is any name that does not start with a /. This name will be interpreted relative to a context
      • For example, topics that do not start with a / become relative to the namespace the node is in.
    • The base name is the name of the entity without any preceding namespaces.
    • A ~ symbol makes a name private.
      • The ~ gets expanded to the full absolute name of the node (including the base name).
      • Private is enforced by convention and just means that the node namespace and name are prepended.
    • Suppose we have a node called /this/is/mynode:
      • The base name of the node is mynode
  4. Names should start with a lower case letter, and then can contain letters, or underscores.

Example

Suppose we have a node called /this/is/mynode

  1. The base name of the node is mynode.
  2. The namespace of the node is /this/is.
  3. The is namespace is nested under the /this namespace

Suppose /this/is/mynode creates a publisher on the hello topic and a subscriber on the /foo/data topic and a service server called ~/help:

  1. The node (by default) will publish to /this/is/hello.
  2. The node (by default) will subscribe to /foo/data.
  3. The node will offer a service (by default) on /this/is/mynode/help.

Comparison with ROS 1

  1. In ROS 1, parameters were global and followed the same naming conventions as other entities.
  2. In ROS 2, parameters are always associated with a specific node and within that node can optionally have their own parameter namespace.

Manipulating Names

  1. Resources can be remapped to any name that you want using Node Arguments
    • This behavior is like a mv operation in the Linux filesystem
    • It enables multiple copies of a node to run with different names for the topics they subscribe to
    • Any name referred to in the node (including absolute and private names) can be remapped.
    • To remap a specific name use ros2 run package node --ros-args -r old_name:=new_name
      • Multiple -r arguments can be passed after --ros-args to rename multiple entities
    • The node can be renamed using -r __node:=new_node_name in the above
    • The namespace can be changed using -r __ns:=/new_namespace. The namespace must start with a /
  2. When the node's namespace is changed, all entities (e.g., topics) that used relative names will be moved relative to the provided namespace
    • This behavior makes it easy to remap groups of related names
    • Namespaces also allow running multiple groups of nodes simultaneously with the same topics
    • For example, the turtlesim_node supports multiple turtles, each controlled via the same topics. They do not interfere because each turtle is in its own namespace.
  3. In practice, ROS nodes should be written with remapping in mind:
    • Generally, use simple, base names for ROS nodes, the services they offer, and the topics they publish and subscribe to (so do not include the leading /.
      • This way, your node can easily be run under a different namespace without needing to remap each topic individually
      • Using absolute node names makes your node less flexible and harder to use.
    • Users of the node then remap these topics and services as needed

A Node's ROS API

  • The publishers, subscribers, services, parameters, and actions a node declares comprise it's ROS API
    • They determine how other nodes interact with your node, on a ROS level
  • These ROS inter-process communication mechanisms are how you link nodes together, much like how modules, functions, and classes are used from within python.
  • These items should be documented in a docstring at the top of the file that defines your node.

Author: Matthew Elwin.