Skip to main content

Core Concepts

Understanding what ros2inspector discovers and how it models your workspace.

What ros2inspector does

ros2inspector reads your ROS2 workspace without running any code. It:

  1. Finds every package.xml (the workspace graph)
  2. Parses Python and C++ source files (the communication graph)
  3. Reads .msg, .srv, .action files (the interface definitions)
  4. Combines everything into the Unified Architecture Model

Packages

A ROS2 package is a directory with a package.xml manifest. ros2inspector detects them all via a BFS walk that respects COLCON_IGNORE markers.

Package types:

TypeBuild system
ament_cmakeCMake-based C++ package
ament_pythonPython package
cmakePlain CMake
metaMetapackage (no code, only dependencies)

Nodes

A node is a ROS2 process that communicates via topics, services, and actions.

ros2inspector detects nodes by looking for:

  • Python: classes inheriting from rclpy.node.Node or Node
  • C++: classes inheriting from rclcpp::Node or rclcpp_lifecycle::LifecycleNode

Each detected node carries:

FieldDescription
nameNode class name
packagePackage it belongs to
language"python" or "cpp"
publishersList of topic names it publishes to
subscriptionsList of topic names it subscribes to
servicesService names it provides
clientsService names it calls
has_dynamic_namestrue if any topic name is computed at runtime

Topics

A topic is a named channel for message passing. ros2inspector identifies topics by parsing string arguments in create_publisher() and create_subscription() calls.

For example, this Python node:

class MyNode(Node):
def __init__(self):
super().__init__("my_node")
self.pub = self.create_publisher(String, "/cmd_vel", 10)
self.sub = self.create_subscription(String, "/odom", self.cb, 10)

yields:

publishers: ["/cmd_vel"]
subscriptions: ["/odom"]

Services & Actions

Detected the same way as topics, from create_service(), create_client(), create_action_server(), and create_action_client() calls.

Interfaces

Message, service, and action definitions in .msg, .srv, and .action files. ros2inspector parses these to extract field names and types.

The Unified Architecture Model (UAM)

The UAM is the central data structure — a directed NetworkX graph combining all entities and relationships.

Node types in the graph:

TypeRepresents
PackageA ROS2 package
NodeA node executable
TopicA message topic
ServiceA service interface
ActionAn action server/client
InterfaceA .msg/.srv/.action definition

Edge types:

EdgeFrom → ToMeaning
depends_onPackage → PackageDeclared dependency
publishesNode → TopicNode publishes messages
subscribesNode → TopicNode subscribes
providesNode → ServiceNode provides a service
callsNode → ServiceNode calls a service
defined_inNode → PackageNode lives in this package

Health Score

Each package gets a 0–100 health score based on eleven checks:

CheckPointsWhat is checked
Has description8<description> in package.xml is non-trivial
Has license8<license> field is declared
Has maintainer5At least one <maintainer> entry
Has maintainer email4Maintainer entry includes an @-address
Version not default5Version ≠ 0.0.0
README present10README.md, README.rst, or similar file exists
No self-dependency15Package does not list itself as a dependency
No circular deps10Package is not part of any dependency cycle
Has test directory15test/ directory exists and is non-empty
Test deps declared10At least one <test_depend> in package.xml
Has launch files10launch/ or bringup/launch/ directory exists

The workspace aggregate is the mean of all package scores.

Static Analysis Scope

ros2inspector's default mode is static analysis — no ROS2 environment needed:

  • Works in CI without sourcing setup.bash
  • Works on partial or non-built workspaces
  • Fast (incremental caching)
  • Detects documented direct patterns and reports ambiguous or unresolved constructs

Dynamic topic names (computed at runtime from parameters or environment) are flagged with has_dynamic_names: true but cannot be resolved statically.

v0.1.0 is intentionally scoped to static source analysis and does not inspect a running ROS graph.

Incremental caching

Each package is cached by a SHA-256 fingerprint of its source files. If nothing changed, analysis is skipped. Cache lives at ~/.cache/ros2inspector/.

Pass --no-cache to force a full re-analysis.