Dry-run execution of ROS 2 launch files with structured JSON output.
launch_interface reads a ROS 2 launch file through the real LaunchService pipeline — resolving all substitutions, conditionals, includes, and scoping — without actually starting any nodes or making ROS service calls. The result is a fully-resolved JSON representation of the launch graph, suitable for consumption by dev tools, IDE integrations, linters, and visualizers.
- Resolves the full launch graph including nested includes, conditionals, namespacing, remappings, and parameter files
- Supports all three launch formats: Python (
.launch.py), XML (.launch.xml), and YAML (.launch.yaml) - Handles composable nodes,
OpaqueFunction,OnProcessExithandlers, andCommandSubstitution - Tracks which source file each node originates from
- Merges parameters from YAML files and inline sources with correct override semantics
- Outputs machine-readable JSON (schemas in
schema/)
Given a launch file:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='test_nodes',
executable='node_a',
name='param_node',
namespace='/test_ns',
parameters=[
'/path/to/params.yaml',
{'inline_param': 'hello', 'inline_int': 42},
],
),
])Running launch_interface parse node_with_params.launch.py produces:
{
"launch_file": "/path/to/node_with_params.launch.py",
"launch_arguments": {},
"declared_arguments": {},
"nodes": [
{
"type": "node",
"package": "test_nodes",
"executable": "node_a",
"name": "param_node",
"namespace": "/test_ns",
"fully_qualified_name": "/test_ns/param_node",
"remappings": [],
"parameter_sources": [
{
"type": "file",
"path": "/path/to/params.yaml"
}
],
"parameters": {
"file_param_str": "from_file",
"file_param_int": 100,
"wildcard_param": "applies_to_all",
"inline_param": "hello",
"inline_int": 42
},
"cmd": ["ros2", "run", "test_nodes", "node_a", "--ros-args", ...],
"source_file": "/path/to/node_with_params.launch.py"
}
],
"includes": []
}pip install git+https://github.com/nineyards-robotics/launch_interface.git# Clone into your workspace src/ directory
cd ~/your_ws/src
git clone https://github.com/nineyards-robotics/launch_interface.git
# Build and source
cd ~/your_ws
colcon build --packages-select launch_interface
source install/setup.bashros2launchlaunch_ros
launch_interface parse <launch_file> [key:=value ...]Performs a full dry-run of the launch file and outputs the resolved launch graph as JSON to stdout.
launch_interface parse robot.launch.py use_sim:=true robot_name:=atlaslaunch_interface args <launch_file>Outputs declared launch arguments (with defaults and descriptions) as JSON.
from launch_interface.dry_run import dry_run
from launch_interface.extractor import extract
from launch_interface.parameters import resolve_parameters
from launch_interface.serialise import to_json
result = dry_run("robot.launch.py", launch_arguments={"use_sim": "true"})
model = extract(result)
for node in model.nodes:
node.parameters = resolve_parameters(node)
print(to_json(model))The parse command produces a JSON object with:
| Field | Description |
|---|---|
launch_file |
Absolute path to the launch file |
launch_arguments |
Arguments passed to the launch file |
declared_arguments |
Arguments declared in the launch file with defaults and descriptions |
nodes |
List of resolved nodes (regular nodes and composable node containers) |
includes |
Nested tree of included launch files |
Each node includes its package, executable, fully qualified name, resolved parameters, remappings, full command line, and source file. Composable node containers additionally list their loaded composable nodes with plugin names and resolved parameters.
Full JSON schemas are in schema/parse.schema.json and schema/args.schema.json.
The library uses a three-layer pipeline:
-
Dry-run executor (
dry_run.py) — Runs the launch file through the real ROS 2LaunchService, patchingExecuteLocalandLoadComposableNodesto prevent process spawning and service calls while capturing all resolved entity data. -
Entity extractor (
extractor.py) — Walks the collected entities and builds a structuredLaunchModelwith node info, include trees, and declared arguments. -
Parameter resolver (
parameters.py) — Loads and merges YAML parameter files with inline parameter sources, respecting ROS 2 wildcard (/**) and node-specific namespacing.
Tests require a sourced ROS 2 installation. The test workspace is built automatically by conftest.py on the first run.
# Run all tests
python3 -m pytest tests/ -v
# Schema validation only (no ROS required)
python3 -m pytest tests/test_schema.py -vSee tests/TESTING.md for the full testing guide.
Apache-2.0