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:
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 usehelp()
rclpy
rclpy
is a python library that allows a python program to become a ROS 2 node.
import rclpy
to use the client library.rclpy.node
defines theNode
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.
- One way to make nodes in ROS 2 is to sub-class
- 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
- The entrypoint function can have any name, and it is registered in the
- The
Node
class has methods that enable- Creating service servers: create_service
- Creating service clients: create_client
- Creating publishers: create_publisher
- Creating subscribers: create_subscription
- Creating timers: create_timer
- Declaring and using parameters: declare_parameters, get_parameter
- The rcl_interfaces package defines some types that are useful for describing and interacting with parameters.
- For example, there are a few basic data types for parameters, outlined in the ParameterType message
- The ParameterDescriptor message allows setting metadata for parameters
- Logging: Logging
- There are many other ROS functions and classes available in
rclpy
, look at the documentation. - 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
- It is also possible to make Custom Interfaces
Naming in ROS
Understanding Names
- 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.
- 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
).
- Namespaces are like directories on Linux: they start from the global namespace (called
- 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.
- For example, topics that do not start with a
- The base name is the name of the entity without any preceding namespaces.
- A
~
symbol makes a nameprivate
.- 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.
- The
- Suppose we have a node called
/this/is/mynode
:- The base name of the node is
mynode
- The base name of the node is
- An absolute name is any name that starts with a
- 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
- The base name of the node is
mynode
. - The namespace of the node is
/this/is
. - 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
:
- The node (by default) will publish to
/this/is/hello
. - The node (by default) will subscribe to
/foo/data
. - The node will offer a service (by default) on
/this/is/mynode/help
.
Comparison with ROS 1
- In ROS 1, parameters were global and followed the same naming conventions as other entities.
- In ROS 2, parameters are always associated with a specific node and within that node can optionally have their own parameter namespace.
Manipulating Names
- 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
- Multiple
- The node can be renamed using
-r __node:=new_node_name
in the above - The namespace can be changed using
-r __ns:=/new_namespace
. Thenamespace
must start with a/
- This behavior is like a
- 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.
- 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
- 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
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.