Metadata-Version: 2.4
Name: ros2_graph
Version: 0.0.6
Summary: Generate mermaid description of ROS2 graphs to add on your markdown files.
Home-page: https://github.com/kiwicampus/ros2_graph
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: argparse~=1.4.0
Requires-Dist: pyyaml~=6.0
Requires-Dist: argcomplete
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-dist
Dynamic: summary

# ros2_graph
Generate Mermaid descriptions of ROS 2 graphs for your Markdown files.

## Motivation

To improve architectural documentation, visualizations of nodes and topics are needed. However, maintaining or manually creating these graphs is often tedious and error-prone. Therefore, an automated tool is necessary.

The first alternative is [rqt-graph](http://wiki.ros.org/rqt_graph), but it does not include services or actions and may include extraneous information when filtering by node. The typical workflow involves connecting to a terminal where the ROS system is running, launching `rqt-graph`, saving the resulting image, and uploading it to the cloud to include it in the documentation.

To simplify this process and include all relevant information, this tool was created.

## Installation

ROS 2 must be installed beforehand (tested on the Humble distribution).

```bash
pip install ros2-graph
```

To enable tab completion of running node names (like `ros2 node info <tab>`), add this to your `~/.bashrc`:

```bash
eval "$(register-python-argcomplete3 ros2_graph)"
```

Use `register-python-argcomplete` instead if your distribution does not ship the `3` suffixed script.

To export the diagram as an image, install npm and [mermaid-cli](https://github.com/mermaid-js/mermaid-cli) on your computer:

```bash
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install nodejs
npm install -g @mermaid-js/mermaid-cli
```

## How it works

Suppose you want to generate a graph that shows how a node relates to other nodes via topics, services, and actions. Ensure your node is running. Then, run the following command:

```bash
ros2_graph your_node
```

This will print a Mermaid graph description to the console. Copy and paste it into the node's README. 

To export the output to a file, use the `-o` flag:

```bash
ros2_graph /turtlesim -o turtle_diagram.md
```

You can also export the diagram as an image (PNG, SVG, or PDF) by specifying the desired file extension or using the `--outputFormat` flag:

```bash
ros2_graph /turtlesim -o turtle_diagram.png
ros2_graph /turtlesim -o turtle_diagram --outputFormat png
```

**Note:** Make sure to copy everything between ` ```mermaid ` and ` ``` `, including the markers themselves.

Use `--hideTopics`, `--hideServices`, `--hideActions` to hide elements by type.

GitHub supports Mermaid graphs. You can also view them in VS Code by installing the "bierner.markdown-mermaid" extension in your `devcontainer.json`.

What about nodes that are closely related, such as range sensors? Don't worry—you can include as many nodes as you want:

```bash
ros2_graph node_1 node_2 … node_n
```

Example:

```bash
ros2_graph /turtlesim
```
See an example graph:

![](https://github.com/kiwicampus/ros2_graph/raw/main/images/turtle_graph.png)
```
flowchart LR

/clear[/ /clear<br>std_srvs/srv/Empty \]:::bugged
/kill[/ /kill<br>turtlesim/srv/Kill \]:::bugged
/reset[/ /reset<br>std_srvs/srv/Empty \]:::bugged
/spawn[/ /spawn<br>turtlesim/srv/Spawn \]:::bugged
subgraph ns/turtlesim["/turtlesim"]
/turtlesim[ /turtlesim ]:::main
/turtlesim/get_type_description[/ /turtlesim/get_type_description<br>type_description_interfaces/srv/GetTypeDescription \]:::bugged
end
subgraph ns/teleop_turtle["/teleop_turtle"]
/teleop_turtle[ /teleop_turtle ]:::main
/teleop_turtle[ /teleop_turtle ]:::node
/teleop_turtle/get_type_description[/ /teleop_turtle/get_type_description<br>type_description_interfaces/srv/GetTypeDescription \]:::bugged
end
subgraph ns/turtle1["/turtle1"]
/turtle1/cmd_vel([ /turtle1/cmd_vel<br>geometry_msgs/msg/Twist ]):::topic
/turtle1/color_sensor([ /turtle1/color_sensor<br>turtlesim/msg/Color ]):::bugged
/turtle1/pose([ /turtle1/pose<br>turtlesim/msg/Pose ]):::bugged
/turtle1/set_pen[/ /turtle1/set_pen<br>turtlesim/srv/SetPen \]:::bugged
/turtle1/teleport_absolute[/ /turtle1/teleport_absolute<br>turtlesim/srv/TeleportAbsolute \]:::bugged
/turtle1/teleport_relative[/ /turtle1/teleport_relative<br>turtlesim/srv/TeleportRelative \]:::bugged
/turtle1/rotate_absolute{{ /turtle1/rotate_absolute<br>turtlesim/action/RotateAbsolute }}:::action
end
/turtle1/cmd_vel --> /turtlesim
/turtlesim --> /turtle1/color_sensor
/turtlesim --> /turtle1/pose
/teleop_turtle --> /turtle1/cmd_vel
/teleop_turtle --> /turtle1/cmd_vel
/clear o-.-o /turtlesim
/kill o-.-o /turtlesim
/reset o-.-o /turtlesim
/spawn o-.-o /turtlesim
/turtle1/set_pen o-.-o /turtlesim
/turtle1/teleport_absolute o-.-o /turtlesim
/turtle1/teleport_relative o-.-o /turtlesim
/turtlesim/get_type_description o-.-o /turtlesim
/teleop_turtle/get_type_description o-.-o /teleop_turtle

/turtle1/rotate_absolute o==o /turtlesim
/teleop_turtle <==> /turtle1/rotate_absolute
/teleop_turtle <==> /turtle1/rotate_absolute
subgraph keys[<b>Keys<b/>]
subgraph nodes[<b><b/>]
topicb((No connected)):::bugged
main_node[main]:::main
end
subgraph connection[<b><b/>]
node1[node1]:::node
node2[node2]:::node
node1 o-.-o|to server| service[/Service<br>service/Type\]:::service
service <-.->|to client| node2
node1 -->|publish| topic([Topic<br>topic/Type]):::topic
topic -->|subscribe| node2
node1 o==o|to server| action{{/Action<br>action/Type/}}:::action
action <==>|to client| node2
end
end
classDef node opacity:0.9,fill:#2A0,stroke:#391,stroke-width:4px,color:#fff
classDef action opacity:0.9,fill:#66A,stroke:#225,stroke-width:2px,color:#fff
classDef service opacity:0.9,fill:#3B8062,stroke:#3B6062,stroke-width:2px,color:#fff
classDef topic opacity:0.9,fill:#852,stroke:#CCC,stroke-width:2px,color:#fff
classDef main opacity:0.9,fill:#059,stroke:#09F,stroke-width:4px,color:#fff
classDef bugged opacity:0.9,fill:#933,stroke:#800,stroke-width:2px,color:#fff
style keys opacity:0.15,fill:#FFF
style nodes opacity:0.15,fill:#FFF
style connection opacity:0.15,fill:#FFF
linkStyle 14,21 fill:none,stroke:green;
linkStyle 15,16,22 fill:none,stroke:green;
```
## Custom style

For custom Mermaid styles, use the `--styleConfig` flag to load a style `.yaml` file. It should look like this (example uses default values; any omitted field will use its default):

```yaml
shapes:
  main: ["[", "]"]
  node: ["[", "]"]
  topic: ["([", "])"]
  service: ["[/", "\]"]
  action: ["{{", "}}"]
colors:
  main: "opacity:0.9,fill:#059,stroke:#09F,stroke-width:4px,color:#fff"
  node: "opacity:0.9,fill:#2A0,stroke:#391,stroke-width:4px,color:#fff"
  topic: "opacity:0.9,fill:#852,stroke:#CCC,stroke-width:2px,color:#fff"
  service: "opacity:0.9,fill:#3B8062,stroke:#3B6062,stroke-width:2px,color:#fff"
  action: "opacity:0.9,fill:#66A,stroke:#225,stroke-width:2px,color:#fff"
  no_conected: "opacity:0.9,fill:#933,stroke:#800,stroke-width:2px,color:#fff"
links_display:
  topics_publisher: "-->"
  topics_subscriber: "-->"
  services_server: "o-.-o"
  services_client: "<-.->"
  action_server: "o==o"
  action_client: "<==>"
links_style:
  topics_publisher:
  topics_subscriber:
  services_server:
  services_client:
  action_server: fill:none,stroke:green;
  action_client: fill:none,stroke:green;
display_keys: True
group_namespaces: True
ignore:
  nodes:
    - "/Graph_generator"
  topics:
  services:
  actions:
```

Use the `ignore` field to exclude specific nodes, topics, services, or actions from your graph. [Regular expressions](https://docs.python.org/3/library/re.html) are supported.

To hide all topics, services, or actions at once, use the `--hideTopics`, `--hideServices`, or `--hideActions` flags:

```bash
ros2_graph /turtlesim --hideServices --hideActions
```
