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:
- Finds every
package.xml(the workspace graph) - Parses Python and C++ source files (the communication graph)
- Reads
.msg,.srv,.actionfiles (the interface definitions) - 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:
| Type | Build system |
|---|---|
ament_cmake | CMake-based C++ package |
ament_python | Python package |
cmake | Plain CMake |
meta | Metapackage (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.NodeorNode - C++: classes inheriting from
rclcpp::Nodeorrclcpp_lifecycle::LifecycleNode
Each detected node carries:
| Field | Description |
|---|---|
name | Node class name |
package | Package it belongs to |
language | "python" or "cpp" |
publishers | List of topic names it publishes to |
subscriptions | List of topic names it subscribes to |
services | Service names it provides |
clients | Service names it calls |
has_dynamic_names | true 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:
| Type | Represents |
|---|---|
Package | A ROS2 package |
Node | A node executable |
Topic | A message topic |
Service | A service interface |
Action | An action server/client |
Interface | A .msg/.srv/.action definition |
Edge types:
| Edge | From → To | Meaning |
|---|---|---|
depends_on | Package → Package | Declared dependency |
publishes | Node → Topic | Node publishes messages |
subscribes | Node → Topic | Node subscribes |
provides | Node → Service | Node provides a service |
calls | Node → Service | Node calls a service |
defined_in | Node → Package | Node lives in this package |
Health Score
Each package gets a 0–100 health score based on eleven checks:
| Check | Points | What is checked |
|---|---|---|
| Has description | 8 | <description> in package.xml is non-trivial |
| Has license | 8 | <license> field is declared |
| Has maintainer | 5 | At least one <maintainer> entry |
| Has maintainer email | 4 | Maintainer entry includes an @-address |
| Version not default | 5 | Version ≠ 0.0.0 |
| README present | 10 | README.md, README.rst, or similar file exists |
| No self-dependency | 15 | Package does not list itself as a dependency |
| No circular deps | 10 | Package is not part of any dependency cycle |
| Has test directory | 15 | test/ directory exists and is non-empty |
| Test deps declared | 10 | At least one <test_depend> in package.xml |
| Has launch files | 10 | launch/ 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.