Extend ros2cli with new verbs
rollingros2 CLI by adding new commands and verbs using Python entry points. This allows third-party packages to register their own functionality directly into the ros2 command hierarchy.repository·rolling·Indexed 42 days ago
https://github.com/ros2/ros2cliStandard command-line interface tools for ROS 2, providing the 'ros2' command to interact with nodes, topics, and services. Includes tools like 'ros2 doctor' (aliased as 'ros2 wtf') for system diagnosis and 'ros2 daemon' for background process management. The CLI is extensible via Python entry points using the CommandExtension class and the 'ros2cli.command' group.
ros2 CLI by adding new commands and verbs using Python entry points. This allows third-party packages to register their own functionality directly into the ros2 command hierarchy.The ros2 multicast command is used to verify if multicast UDP packets can be successfully passed between two endpoints on a network. This is useful for troubleshooting network configurations that might be blocking multicast traffic.
To perform a test:
ros2 multicast receiveros2 multicast sendIf the network allows multicast, the first machine will output Hello World!.
# Machine 1: Start receiving
$ ros2 multicast receive
# Machine 2: Send packet
$ ros2 multicast sendThe ros2doctor tool (also accessible via the alias ros2 wtf) examines your ROS 2 environment—including distribution, platform, and network interfaces—to identify potential issues in your system. Use it to verify that your installation and running system are configured correctly.
ros2 doctor
# or
ros2 wtfThe ros2 command-line interface uses a hierarchical help system. You can discover available commands and detailed usage information by following these patterns:
ros2 --help.ros2 <command> --help.ros2 <command> <verb> --help.# See all available commands
ros2 --help
# See usage for a specific command (e.g., topic)
ros2 topic --help
# See usage for a specific verb (e.g., topic echo)
ros2 topic echo --helpThe ros2 command is an extensible tool. It uses entry points (specifically under the ros2cli.command group) to discover and load subcommands (verbs) on demand. When you run ros2 <command>, the CLI identifies the extension associated with that command and executes its main method.
If you are developing a new command for ros2cli, your extension must implement a main(parser, args) method that accepts the argparse.ArgumentParser instance and the parsed arguments.
CommandExtension is the base class for all ROS 2 CLI command plugins. It uses a plugin system to allow the ros2 tool to discover and instantiate commands dynamically.
When a user invokes a command (e.g., ros2 <command>), the system:
add_arguments if it exists to configure the subparser.main with the parsed arguments.Note that CommandExtension enforces a specific version compatibility with the ros2cli plugin system (version ^0.1).
You can extend ros2doctor by adding your own custom checks or report modules using Python entry points in your setup.py. You must register modules under two specific entry point groups:
ros2doctor.checks: For the logic that performs the check.ros2doctor.report: For the logic that formats the report output.Example setup.py configuration:
entry_points={
'ros2doctor.checks': [
'PlatformCheck = ros2doctor.api.platform:PlatformCheck',
'NetworkCheck = ros2doctor.api.network:NetworkCheck',
],
'ros2doctor.report': [
'PlatformReport = ros2doctor.api.platform:PlatformReport',
'NetworkReport = ros2doctor.api.network:NetworkReport',
],
}entry_points={
'ros2doctor.checks': [
'PlatformCheck = ros2doctor.api.platform:PlatformCheck',
'NetworkCheck = ros2doctor.api.network:NetworkCheck',
],
'ros2doctor.report': [
'PlatformReport = ros2doctor.api.platform:PlatformReport',
'NetworkReport = ros2doctor.api.network:NetworkReport',
],
}You can customize how ros2 doctor displays its findings using the following flags:
-r or --report: Show a report of all checked items.-rf or --report-fail: Show a report containing only the failed checks.-iw or --include-warnings: Treat warnings as failed checks. This can be combined with --report-fail to see all warnings and errors.-ep or --exclude-packages: Exclude specific package checks from the report.ros2 doctor -rf -iwThe add_subparsers_on_demand function is used to dynamically build the argparse subparser tree for CLI extensions. This is critical for performance, as it ensures that only the necessary command extensions are instantiated and loaded based on the user's input.
parser: The parent argparse.ArgumentParser.cli_name: The name of the CLI command (used for help titles).dest: The attribute name under which the selected extension instance will be stored in the parsed args namespace.group_name: The entry_point group name used to discover extensions.hide_extensions: (Optional) A list of extension names to skip.required: Whether the command argument is required.argv: The list of command line arguments (defaults to sys.argv).argv, it only loads that specific extension (and its recursive extensions) to minimize overhead.argcomplete requests for shell completion.SuppressUsageOutput to prevent argparse from printing usage/help messages prematurely during the discovery phase.To add a new command (verb) to the ros2 CLI, you must implement the CommandExtension class. This allows your command to be discovered via entry points and integrated into the argparse hierarchy.
NAME: A property that will be automatically set to the entry point name.main(self, *, parser, args): The core logic of your command. This method must be implemented and is called after arguments are parsed.add_arguments(self, parser, cli_name, *, argv=None) (Optional): Use this to define the specific flags and arguments for your command using an argparse.ArgumentParser instance.from ros2cli.command import CommandExtension
class MyCommand(CommandExtension):
def add_arguments(self, parser, cli_name, *, argv=None):
parser.add_argument('--my-flag', help='An example flag')
def main(self, *, parser, args):
if args.my_flag:
print('Flag is set!')
else:
print('Flag is not set.')from ros2cli.command import CommandExtension
class MyCommand(CommandExtension):
def add_arguments(self, parser, cli_name, *, argv=None):
parser.add_argument('--my-flag', help='An example flag')
def main(self, *, parser, args):
if args.my_flag:
print('Flag is set!')
else:
print('Flag is not set.')The ServerProxy class is used to create a client that communicates with an XML-RPC server (such as the ros2cli daemon). It allows you to call remote methods on the server as if they were local methods. This module aliases standard xmlrpc.client objects to ros2cli.xmlrpc to ensure consistent usage within the ros2cli ecosystem.
from ros2cli.xmlrpc import ServerProxy
# Example usage (conceptual):
# proxy = ServerProxy('http://localhost:8000')
# result = proxy.some_remote_method(arg1, arg2)When running ros2 extension-points, you can use the following flags to control the output:
--all, -a: Includes extension points that failed to be imported in the output. Failed points are prefixed with - .--verbose, -v: Provides additional metadata for each extension point, such as the module name, attributes, and the EXTENSION_POINT_VERSION if available.