diff --git a/system/diagnostic_graph_aggregator/CMakeLists.txt b/system/diagnostic_graph_aggregator/CMakeLists.txt
index c4a67032541b2..574978ec5adce 100644
--- a/system/diagnostic_graph_aggregator/CMakeLists.txt
+++ b/system/diagnostic_graph_aggregator/CMakeLists.txt
@@ -22,10 +22,17 @@ ament_auto_add_executable(converter
)
target_include_directories(converter PRIVATE src/common)
-ament_auto_add_executable(tool
- src/tool/tool.cpp
+ament_auto_add_executable(tree
+ src/tool/tree.cpp
+ src/tool/utils/loader.cpp
)
-target_include_directories(tool PRIVATE src/common)
+target_include_directories(tree PRIVATE src/common)
+
+ament_auto_add_executable(plantuml
+ src/tool/plantuml.cpp
+ src/tool/utils/loader.cpp
+)
+target_include_directories(plantuml PRIVATE src/common)
if(BUILD_TESTING)
get_filename_component(RESOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test/files ABSOLUTE)
diff --git a/system/diagnostic_graph_aggregator/README.md b/system/diagnostic_graph_aggregator/README.md
index 4dc44feaafc33..cc49ed88ba98f 100644
--- a/system/diagnostic_graph_aggregator/README.md
+++ b/system/diagnostic_graph_aggregator/README.md
@@ -53,20 +53,33 @@ This feature breaks the generality of the graph and may be changed to a plugin o
## Examples
-- [example_0.yaml](./example/example_0.yaml)
-- [example_1.yaml](./example/example_1.yaml)
-- [example_2.yaml](./example/example_2.yaml)
+This is an example of a diagnostic graph configuration. The configuration can be split into multiple files.
+
+- [main.yaml](./example/graph/main.yaml)
+- [module1.yaml](./example/graph/module1.yaml)
+- [module2.yaml](./example/graph/module2.yaml)
+
+```bash
+ros2 launch diagnostic_graph_aggregator example-main.launch.xml
+```
+
+You can reuse the graph by making partial edits. For example, disable hardware checks for simulation.
+
+- [edit.yaml](./example/graph/edit.yaml)
```bash
-ros2 launch diagnostic_graph_aggregator example.launch.xml
+ros2 launch diagnostic_graph_aggregator example-edit.launch.xml
```
+## Debug tools
+
+- [dump](./doc/tool/dump.md)
+- [converter](./doc/tool/converter.md)
+- [tree](./doc/tool/tree.md)
+
## Graph file format
-- [GraphFile](./doc/format/graph-file.md)
-- [Path](./doc/format/path.md)
-- [Node](./doc/format/node.md)
- - [Diag](./doc/format/diag.md)
- - [Unit](./doc/format/unit.md)
- - [And](./doc/format/and.md)
- - [Or](./doc/format/or.md)
+- [graph](./doc/format/graph.md)
+- [path](./doc/format/path.md)
+- [node](./doc/format/node.md)
+- [edit](./doc/format/edit.md)
diff --git a/system/diagnostic_graph_aggregator/doc/format/and.md b/system/diagnostic_graph_aggregator/doc/format/and.md
deleted file mode 100644
index a92aa2817832e..0000000000000
--- a/system/diagnostic_graph_aggregator/doc/format/and.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Unit
-
-And is a node that is evaluated as the AND of the input nodes.
-
-## Format
-
-| Name | Type | Required | Description |
-| ---- | ------------------------------------------ | -------- | ------------------------------------- |
-| type | string | yes | Specify `and` when using this object. |
-| name | string | yes | Name of diagnostic status. |
-| list | List<[Diag](./diag.md)\|[Unit](./unit.md)> | yes | List of input node references. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/diag.md b/system/diagnostic_graph_aggregator/doc/format/diag.md
deleted file mode 100644
index 04e850129cbbf..0000000000000
--- a/system/diagnostic_graph_aggregator/doc/format/diag.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Diag
-
-Diag is a node that refers to a source diagnostics.
-
-## Format
-
-| Name | Type | Required | Description |
-| ---- | ------ | -------- | -------------------------------------- |
-| type | string | yes | Specify `diag` when using this object. |
-| diag | string | yes | Name of diagnostic status. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/edit.md b/system/diagnostic_graph_aggregator/doc/format/edit.md
new file mode 100644
index 0000000000000..71ea8a96bc17f
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/edit.md
@@ -0,0 +1,14 @@
+# Edit
+
+The `edit` is a base object that edits the existing diagnostic graph.
+Any derived object can be used where a edit object is required.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | ------------------------------------------------- |
+| `type` | `string` | yes | The string indicating the type of derived object. |
+
+## Derived objects
+
+- [remove](./edit/remove.md)
diff --git a/system/diagnostic_graph_aggregator/doc/format/edit/remove.md b/system/diagnostic_graph_aggregator/doc/format/edit/remove.md
new file mode 100644
index 0000000000000..6cd4b25e98828
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/edit/remove.md
@@ -0,0 +1,10 @@
+# Remove
+
+The `remove` object is a edit that removes other nodes.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | ---------------------------------------- |
+| `type` | `string` | yes | Specify `remove` when using this object. |
+| `path` | `string` | yes | The path of the node to remove. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/graph-file.md b/system/diagnostic_graph_aggregator/doc/format/graph-file.md
deleted file mode 100644
index 3c4cfec996a4a..0000000000000
--- a/system/diagnostic_graph_aggregator/doc/format/graph-file.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# GraphFile
-
-GraphFile is the top level object that makes up the configuration file.
-
-## Format
-
-| Name | Type | Required | Description |
-| ----- | ----------------------- | -------- | ------------------------------ |
-| files | List<[Path](./path.md)> | no | Paths of the files to include. |
-| nodes | List<[Node](./node.md)> | no | Nodes of the diagnostic graph. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/graph.md b/system/diagnostic_graph_aggregator/doc/format/graph.md
new file mode 100644
index 0000000000000..9dace8a2f0e6d
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/graph.md
@@ -0,0 +1,11 @@
+# Graph
+
+The graph object is the top level structure that makes up the configuration file.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------- | -------------------------------------- | -------- | ------------------------------------------------- |
+| `files` | list\[[path](./path.md)\]
| no | List of path objects for importing subgraphs. |
+| `nodes` | list\[[node](./node.md)\]
| no | List of node objects that make up the graph. |
+| `edits` | list\[[edit](./edit.md)\]
| no | List of edit objects to partially edit the graph. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/node.md b/system/diagnostic_graph_aggregator/doc/format/node.md
index da8e8e57b111f..0f4b52b9b8a72 100644
--- a/system/diagnostic_graph_aggregator/doc/format/node.md
+++ b/system/diagnostic_graph_aggregator/doc/format/node.md
@@ -1,9 +1,25 @@
# Node
-Node is a base object that makes up the diagnostic graph.
+The `node` is a base object that makes up the diagnostic graph.
+Any derived object can be used where a node object is required.
## Format
-| Name | Type | Required | Description |
-| ---- | ------ | -------- | ------------------------------------------- |
-| type | string | yes | Node type. See derived objects for details. |
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | ------------------------------------------------- |
+| `type` | `string` | yes | The string indicating the type of derived object. |
+| `path` | `string` | no | Any string to reference from other nodes. |
+
+## Derived objects
+
+- [diag](./node/diag.md)
+- [and](./node/and.md)
+- [or](./node/or.md)
+- [remapping](./node/remap.md)
+ - warn-to-ok
+ - warn-to-error
+- [constant](./node/const.md)
+ - ok
+ - warn
+ - error
+ - stale
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/and.md b/system/diagnostic_graph_aggregator/doc/format/node/and.md
new file mode 100644
index 0000000000000..562018bf0995b
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/and.md
@@ -0,0 +1,17 @@
+# And
+
+The `and` object is a node that is evaluated as the maximum error level of the input nodes.
+Note that error level `stale` is treated as `error`.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------------------------------------- | -------- | ------------------------------------------------------------ |
+| `type` | string
| yes | Specify `and` or `short-circuit-and` when using this object. |
+| `list` | list\[[node](../node.md)]
| yes | List of input node objects. |
+
+## Short-circuit evaluation
+
+!!! warning
+
+ The`short-circuit-and` is work in progress (WIP).
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/const.md b/system/diagnostic_graph_aggregator/doc/format/node/const.md
new file mode 100644
index 0000000000000..13495be6cdbda
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/const.md
@@ -0,0 +1,18 @@
+# Constant
+
+The constant object is a node with a fixed error level.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | ------------------------------------------- |
+| `type` | `string` | yes | Specify error level when using this object. |
+
+## Error levels
+
+The supported error levels are as follows.
+
+- `ok`
+- `warn`
+- `error`
+- `stale`
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/diag.md b/system/diagnostic_graph_aggregator/doc/format/node/diag.md
new file mode 100644
index 0000000000000..beba8ed0df5b4
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/diag.md
@@ -0,0 +1,10 @@
+# Diag
+
+The `diag` object is a node that refers to a specific status within the source diagnostics.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | -------------------------------------- |
+| `type` | `string` | yes | Specify `diag` when using this object. |
+| `diag` | `string` | yes | The name of the diagnostic status. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/link.md b/system/diagnostic_graph_aggregator/doc/format/node/link.md
new file mode 100644
index 0000000000000..c23aa92575e54
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/link.md
@@ -0,0 +1,10 @@
+# Link
+
+The `link` object is a node that refers to other nodes.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | -------------------------------------- |
+| `type` | `string` | yes | Specify `link` when using this object. |
+| `link` | `string` | yes | The path of the node to reference. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/or.md b/system/diagnostic_graph_aggregator/doc/format/node/or.md
new file mode 100644
index 0000000000000..74e94ffd628e3
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/or.md
@@ -0,0 +1,11 @@
+# Or
+
+The `or` object is a node that is evaluated as the minimum error level of the input nodes.
+Note that error level `stale` is treated as `error`.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------------------------------------- | -------- | ------------------------------------ |
+| `type` | string
| yes | Specify `or` when using this object. |
+| `list` | list\[[node](../node.md)]
| yes | List of input node objects. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/node/remap.md b/system/diagnostic_graph_aggregator/doc/format/node/remap.md
new file mode 100644
index 0000000000000..abf0d11fae12d
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/format/node/remap.md
@@ -0,0 +1,21 @@
+# Constant
+
+!!! warning
+
+ This object is under development. It may be removed in the future.
+
+The remapping object is a node that converts error levels.
+
+## Format
+
+| Name | Type | Required | Description |
+| ------ | -------------------------------------- | -------- | ---------------------------------------------------- |
+| `type` | `string` | yes | Specify remapping type when using this object. |
+| `list` | list\[[node](../node.md)]
| yes | List of input node objects. The list size must be 1. |
+
+## Remapping types
+
+The supported remapping types are as follows.
+
+- `warn-to-ok`
+- `warn-to-error`
diff --git a/system/diagnostic_graph_aggregator/doc/format/or.md b/system/diagnostic_graph_aggregator/doc/format/or.md
deleted file mode 100644
index 3e668b686c9e8..0000000000000
--- a/system/diagnostic_graph_aggregator/doc/format/or.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Unit
-
-Or is a node that is evaluated as the OR of the input nodes.
-
-## Format
-
-| Name | Type | Required | Description |
-| ---- | ------------------------------------------ | -------- | ------------------------------------ |
-| type | string | yes | Specify `or` when using this object. |
-| name | string | yes | Name of diagnostic status. |
-| list | List<[Diag](./diag.md)\|[Unit](./unit.md)> | yes | List of input node references. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/path.md b/system/diagnostic_graph_aggregator/doc/format/path.md
index 1f27accefa35a..6ca32a7eaad80 100644
--- a/system/diagnostic_graph_aggregator/doc/format/path.md
+++ b/system/diagnostic_graph_aggregator/doc/format/path.md
@@ -1,10 +1,19 @@
# Path
-Path is an object that indicates the path of the file to include.
+The path object specifies the file path of the subgraph to be imported.
+The structure of the subgraph file should be [graph object](./graph.md).
## Format
-| Name | Type | Required | Description |
-| ------- | ------ | -------- | ----------------------------- |
-| package | string | yes | Package name. |
-| path | string | yes | Relative path in the package. |
+| Name | Type | Required | Description |
+| ------ | -------- | -------- | ------------------------------ |
+| `path` | `string` | yes | The file path of the subgraph. |
+
+## Substitutions
+
+File paths can contain substitutions like ROS 2 launch. The supported substitutions are as follows.
+
+| Substitution | Description |
+| ----------------------------- | -------------------------------- |
+| `$(dirname)` | The path of this file directory. |
+| `$(find-pkg-share )` | The path of the package. |
diff --git a/system/diagnostic_graph_aggregator/doc/format/unit.md b/system/diagnostic_graph_aggregator/doc/format/unit.md
deleted file mode 100644
index 791689aa2d98a..0000000000000
--- a/system/diagnostic_graph_aggregator/doc/format/unit.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Unit
-
-Diag is a node that refers to a functional unit.
-
-## Format
-
-| Name | Type | Required | Description |
-| ---- | ------ | -------- | -------------------------------------- |
-| type | string | yes | Specify `unit` when using this object. |
-| name | string | yes | Name of diagnostic status. |
diff --git a/system/diagnostic_graph_aggregator/doc/tool/converter.md b/system/diagnostic_graph_aggregator/doc/tool/converter.md
new file mode 100644
index 0000000000000..2351bc1e01054
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/tool/converter.md
@@ -0,0 +1,29 @@
+# Converter tool
+
+This tool converts `/diagnostics_graph` to `/diagnostics_agg` so it can be read by tools such as `rqt_runtime_monitor` and `rqt_robot_monitor`.
+
+## Usage
+
+```bash
+ros2 launch diagnostic_graph_aggregator converter.launch.xml complement:=false
+```
+
+The `complement` argument specifies whether to add an intermediate path that does not exist.
+This means that if the graph contains paths `/A/B` and `/A/B/C/D/E`, the intermediate paths `/A`, `/A/B/C` and `/A/B/C/D` will be added.
+This is useful for tree view in `rqt_robot_monitor`. The completed node has an error level of `STALE`.
+
+## Examples
+
+```bash
+ros2 launch diagnostic_graph_aggregator example-main.launch.xml complement:=false
+ros2 run rqt_runtime_monitor rqt_runtime_monitor --ros-args -r diagnostics:=diagnostics_agg
+```
+
+
+
+```bash
+ros2 launch diagnostic_graph_aggregator example-main.launch.xml complement:=true
+ros2 run rqt_robot_monitor rqt_robot_monitor
+```
+
+
diff --git a/system/diagnostic_graph_aggregator/doc/tool/dump.md b/system/diagnostic_graph_aggregator/doc/tool/dump.md
new file mode 100644
index 0000000000000..33f05ff866603
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/tool/dump.md
@@ -0,0 +1,36 @@
+# Dump tool
+
+This tool displays `/diagnostics_graph` in table format.
+
+## Usage
+
+```bash
+ros2 run diagnostic_graph_aggregator dump
+```
+
+## Examples
+
+```bash
+ros2 launch diagnostic_graph_aggregator example-main.launch.xml
+ros2 run diagnostic_graph_aggregator dump
+```
+
+```txt
+| ----- | ----- | -------------------------------- | ----- |
+| index | level | name | links |
+| ----- | ----- | -------------------------------- | ----- |
+| 0 | OK | /sensing/radars/front | |
+| 1 | OK | /sensing/lidars/front | |
+| 2 | ERROR | /sensing/lidars/top | |
+| 3 | OK | /functions/obstacle_detection | 1 0 |
+| 4 | ERROR | /functions/pose_estimation | 2 |
+| 5 | OK | /external/remote_command | |
+| 6 | OK | /external/joystick_command | |
+| 7 | ERROR | /autoware/modes/pull_over | 4 3 |
+| 8 | OK | /autoware/modes/comfortable_stop | 3 |
+| 9 | OK | /autoware/modes/emergency_stop | |
+| 10 | OK | /autoware/modes/remote | 5 |
+| 11 | OK | /autoware/modes/local | 6 |
+| 12 | ERROR | /autoware/modes/autonomous | 4 3 |
+| 13 | OK | /autoware/modes/stop | |
+```
diff --git a/system/diagnostic_graph_aggregator/doc/tool/images/rqt_robot_monitor.png b/system/diagnostic_graph_aggregator/doc/tool/images/rqt_robot_monitor.png
new file mode 100644
index 0000000000000..e4aa169f02add
Binary files /dev/null and b/system/diagnostic_graph_aggregator/doc/tool/images/rqt_robot_monitor.png differ
diff --git a/system/diagnostic_graph_aggregator/doc/tool/images/rqt_runtime_monitor.png b/system/diagnostic_graph_aggregator/doc/tool/images/rqt_runtime_monitor.png
new file mode 100644
index 0000000000000..768fee688f594
Binary files /dev/null and b/system/diagnostic_graph_aggregator/doc/tool/images/rqt_runtime_monitor.png differ
diff --git a/system/diagnostic_graph_aggregator/doc/tool/tree.md b/system/diagnostic_graph_aggregator/doc/tool/tree.md
new file mode 100644
index 0000000000000..79fa61f527038
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/doc/tool/tree.md
@@ -0,0 +1,40 @@
+# Tree tool
+
+This tool displays the graph structure of the configuration file in tree format.
+
+## Usage
+
+```bash
+ros2 run diagnostic_graph_aggregator tree
+```
+
+## Examples
+
+```bash
+ros2 run diagnostic_graph_aggregator tree system/diagnostic_graph_aggregator/example/graph/main.yaml
+```
+
+```txt
+===== root nodes =================================
+- /autoware/modes/local (and)
+ - /external/joystick_command (diag)
+- /autoware/modes/comfortable_stop (and)
+ - /functions/obstacle_detection (or)
+- /autoware/modes/pull_over (and)
+ - /functions/pose_estimation (and)
+ - /functions/obstacle_detection (or)
+- /autoware/modes/autonomous (and)
+ - /functions/pose_estimation (and)
+ - /functions/obstacle_detection (or)
+- /autoware/modes/remote (and)
+ - /external/remote_command (diag)
+===== intermediate nodes =========================
+- /functions/obstacle_detection (or)
+ - /sensing/lidars/front (diag)
+ - /sensing/radars/front (diag)
+- /functions/pose_estimation (and)
+ - /sensing/lidars/top (diag)
+===== isolated nodes =============================
+- /autoware/modes/stop (const)
+- /autoware/modes/emergency_stop (const)
+```
diff --git a/system/diagnostic_graph_aggregator/example/example_diags.py b/system/diagnostic_graph_aggregator/example/dummy-diags.py
similarity index 93%
rename from system/diagnostic_graph_aggregator/example/example_diags.py
rename to system/diagnostic_graph_aggregator/example/dummy-diags.py
index 52d6189a63f30..08f81bcd738ed 100755
--- a/system/diagnostic_graph_aggregator/example/example_diags.py
+++ b/system/diagnostic_graph_aggregator/example/dummy-diags.py
@@ -59,6 +59,9 @@ def create_status(name: str):
"external_command_checker: joystick_command",
"external_command_checker: remote_command",
]
- rclpy.init()
- rclpy.spin(DummyDiagnostics(diags))
- rclpy.shutdown()
+ try:
+ rclpy.init()
+ rclpy.spin(DummyDiagnostics(diags))
+ rclpy.shutdown()
+ except KeyboardInterrupt:
+ pass
diff --git a/system/diagnostic_graph_aggregator/example/example-edit.launch.xml b/system/diagnostic_graph_aggregator/example/example-edit.launch.xml
new file mode 100644
index 0000000000000..c168b76f19c21
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/example/example-edit.launch.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/system/diagnostic_graph_aggregator/example/example-main.launch.xml b/system/diagnostic_graph_aggregator/example/example-main.launch.xml
new file mode 100644
index 0000000000000..cdc1bc8afca53
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/example/example-main.launch.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/system/diagnostic_graph_aggregator/example/example.launch.xml b/system/diagnostic_graph_aggregator/example/example.launch.xml
deleted file mode 100644
index 71e59a1833d6e..0000000000000
--- a/system/diagnostic_graph_aggregator/example/example.launch.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/system/diagnostic_graph_aggregator/example/graph/edit.yaml b/system/diagnostic_graph_aggregator/example/graph/edit.yaml
new file mode 100644
index 0000000000000..2fbdbffca438d
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/example/graph/edit.yaml
@@ -0,0 +1,6 @@
+files:
+ - { path: $(find-pkg-share diagnostic_graph_aggregator)/example/graph/main.yaml }
+
+edits:
+ - path: /functions/obstacle_detection
+ type: remove
diff --git a/system/diagnostic_graph_aggregator/example/example_0.yaml b/system/diagnostic_graph_aggregator/example/graph/main.yaml
similarity index 83%
rename from system/diagnostic_graph_aggregator/example/example_0.yaml
rename to system/diagnostic_graph_aggregator/example/graph/main.yaml
index 7b01883723c76..2bea907d9c119 100644
--- a/system/diagnostic_graph_aggregator/example/example_0.yaml
+++ b/system/diagnostic_graph_aggregator/example/graph/main.yaml
@@ -1,6 +1,6 @@
files:
- - { path: $(find-pkg-share diagnostic_graph_aggregator)/example/example_1.yaml }
- - { path: $(find-pkg-share diagnostic_graph_aggregator)/example/example_2.yaml }
+ - { path: $(dirname)/module1.yaml }
+ - { path: $(dirname)/module2.yaml }
nodes:
- path: /autoware/modes/stop
diff --git a/system/diagnostic_graph_aggregator/example/example_1.yaml b/system/diagnostic_graph_aggregator/example/graph/module1.yaml
similarity index 100%
rename from system/diagnostic_graph_aggregator/example/example_1.yaml
rename to system/diagnostic_graph_aggregator/example/graph/module1.yaml
diff --git a/system/diagnostic_graph_aggregator/example/example_2.yaml b/system/diagnostic_graph_aggregator/example/graph/module2.yaml
similarity index 100%
rename from system/diagnostic_graph_aggregator/example/example_2.yaml
rename to system/diagnostic_graph_aggregator/example/graph/module2.yaml
diff --git a/system/diagnostic_graph_aggregator/launch/diagnostic_graph_aggregator.launch.xml b/system/diagnostic_graph_aggregator/launch/aggregator.launch.xml
similarity index 100%
rename from system/diagnostic_graph_aggregator/launch/diagnostic_graph_aggregator.launch.xml
rename to system/diagnostic_graph_aggregator/launch/aggregator.launch.xml
diff --git a/system/diagnostic_graph_aggregator/launch/converter.launch.xml b/system/diagnostic_graph_aggregator/launch/converter.launch.xml
new file mode 100644
index 0000000000000..9111338bf622a
--- /dev/null
+++ b/system/diagnostic_graph_aggregator/launch/converter.launch.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/system/diagnostic_graph_aggregator/script/dump.py b/system/diagnostic_graph_aggregator/script/dump.py
index 3e639cbce104d..9abcaeb7a080c 100755
--- a/system/diagnostic_graph_aggregator/script/dump.py
+++ b/system/diagnostic_graph_aggregator/script/dump.py
@@ -84,7 +84,6 @@ def callback(self, msg):
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--topic", default="/diagnostics_graph")
- parser.add_argument("--order", default="index")
args, unparsed = parser.parse_known_args()
try:
diff --git a/system/diagnostic_graph_aggregator/src/node/aggregator.cpp b/system/diagnostic_graph_aggregator/src/node/aggregator.cpp
index 48f489c186bdb..cd16ce8e33e59 100644
--- a/system/diagnostic_graph_aggregator/src/node/aggregator.cpp
+++ b/system/diagnostic_graph_aggregator/src/node/aggregator.cpp
@@ -20,7 +20,7 @@
namespace diagnostic_graph_aggregator
{
-MainNode::MainNode() : Node("diagnostic_graph_aggregator_aggregator")
+AggregatorNode::AggregatorNode() : Node("aggregator")
{
// Init diagnostics graph.
{
@@ -39,7 +39,7 @@ MainNode::MainNode() : Node("diagnostic_graph_aggregator_aggregator")
const auto qos_input = rclcpp::QoS(declare_parameter("input_qos_depth"));
const auto qos_graph = rclcpp::QoS(declare_parameter("graph_qos_depth"));
- const auto callback = std::bind(&MainNode::on_diag, this, _1);
+ const auto callback = std::bind(&AggregatorNode::on_diag, this, _1);
sub_input_ = create_subscription("/diagnostics", qos_input, callback);
pub_graph_ = create_publisher("/diagnostics_graph", qos_graph);
@@ -51,12 +51,12 @@ MainNode::MainNode() : Node("diagnostic_graph_aggregator_aggregator")
debug_ = declare_parameter("use_debug_mode");
}
-MainNode::~MainNode()
+AggregatorNode::~AggregatorNode()
{
// for unique_ptr
}
-void MainNode::on_timer()
+void AggregatorNode::on_timer()
{
const auto stamp = now();
pub_graph_->publish(graph_.report(stamp));
@@ -64,7 +64,7 @@ void MainNode::on_timer()
if (modes_) modes_->update(stamp);
}
-void MainNode::on_diag(const DiagnosticArray::ConstSharedPtr msg)
+void AggregatorNode::on_diag(const DiagnosticArray::ConstSharedPtr msg)
{
graph_.callback(now(), *msg);
}
@@ -73,10 +73,10 @@ void MainNode::on_diag(const DiagnosticArray::ConstSharedPtr msg)
int main(int argc, char ** argv)
{
- using diagnostic_graph_aggregator::MainNode;
+ using diagnostic_graph_aggregator::AggregatorNode;
rclcpp::init(argc, argv);
rclcpp::executors::SingleThreadedExecutor executor;
- auto node = std::make_shared();
+ auto node = std::make_shared();
executor.add_node(node);
executor.spin();
executor.remove_node(node);
diff --git a/system/diagnostic_graph_aggregator/src/node/aggregator.hpp b/system/diagnostic_graph_aggregator/src/node/aggregator.hpp
index dd64809e939cc..6bf9aead9754d 100644
--- a/system/diagnostic_graph_aggregator/src/node/aggregator.hpp
+++ b/system/diagnostic_graph_aggregator/src/node/aggregator.hpp
@@ -26,11 +26,11 @@
namespace diagnostic_graph_aggregator
{
-class MainNode : public rclcpp::Node
+class AggregatorNode : public rclcpp::Node
{
public:
- MainNode();
- ~MainNode();
+ AggregatorNode();
+ ~AggregatorNode();
private:
Graph graph_;
diff --git a/system/diagnostic_graph_aggregator/src/node/converter.cpp b/system/diagnostic_graph_aggregator/src/node/converter.cpp
index 89acfce31a5ab..f0b2108374017 100644
--- a/system/diagnostic_graph_aggregator/src/node/converter.cpp
+++ b/system/diagnostic_graph_aggregator/src/node/converter.cpp
@@ -14,8 +14,7 @@
#include "converter.hpp"
-#include
-#include
+#include
namespace diagnostic_graph_aggregator
{
@@ -35,18 +34,46 @@ std::string level_to_string(DiagnosticLevel level)
return "UNKNOWN";
}
-ToolNode::ToolNode() : Node("diagnostic_graph_aggregator_converter")
+std::string parent_path(const std::string & path)
+{
+ return path.substr(0, path.rfind('/'));
+}
+
+auto create_tree(const DiagnosticGraph & graph)
+{
+ std::map, std::greater> tree;
+ for (const auto & node : graph.nodes) {
+ tree.emplace(node.status.name, std::make_unique(true));
+ }
+ for (const auto & node : graph.nodes) {
+ std::string path = node.status.name;
+ while (path = parent_path(path), !path.empty()) {
+ if (tree.count(path)) break;
+ tree.emplace(path, std::make_unique(false));
+ }
+ }
+ for (const auto & [path, node] : tree) {
+ const auto parent = parent_path(path);
+ node->parent = parent.empty() ? nullptr : tree[parent].get();
+ }
+ return tree;
+}
+
+ConverterNode::ConverterNode() : Node("converter")
{
using std::placeholders::_1;
const auto qos_graph = rclcpp::QoS(1);
const auto qos_array = rclcpp::QoS(1);
- const auto callback = std::bind(&ToolNode::on_graph, this, _1);
+ const auto callback = std::bind(&ConverterNode::on_graph, this, _1);
sub_graph_ = create_subscription("/diagnostics_graph", qos_graph, callback);
- pub_array_ = create_publisher("/diagnostics_array", qos_array);
+ pub_array_ = create_publisher("/diagnostics_agg", qos_array);
+
+ initialize_tree_ = false;
+ complement_tree_ = declare_parameter("complement_tree");
}
-void ToolNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
+void ConverterNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
{
DiagnosticArray message;
message.header.stamp = msg->stamp;
@@ -63,6 +90,31 @@ void ToolNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
}
}
}
+
+ if (complement_tree_ && !initialize_tree_) {
+ initialize_tree_ = true;
+ tree_ = create_tree(*msg);
+ }
+
+ if (complement_tree_) {
+ for (const auto & [path, node] : tree_) {
+ node->level = DiagnosticStatus::OK;
+ }
+ for (const auto & node : msg->nodes) {
+ tree_[node.status.name]->level = node.status.level;
+ }
+ for (const auto & [path, node] : tree_) {
+ if (!node->parent) continue;
+ node->parent->level = std::max(node->parent->level, node->level);
+ }
+ for (const auto & [path, node] : tree_) {
+ if (node->leaf) continue;
+ message.status.emplace_back();
+ message.status.back().name = path;
+ message.status.back().level = node->level;
+ }
+ }
+
pub_array_->publish(message);
}
@@ -70,10 +122,10 @@ void ToolNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
int main(int argc, char ** argv)
{
- using diagnostic_graph_aggregator::ToolNode;
+ using diagnostic_graph_aggregator::ConverterNode;
rclcpp::init(argc, argv);
rclcpp::executors::SingleThreadedExecutor executor;
- auto node = std::make_shared();
+ auto node = std::make_shared();
executor.add_node(node);
executor.spin();
executor.remove_node(node);
diff --git a/system/diagnostic_graph_aggregator/src/node/converter.hpp b/system/diagnostic_graph_aggregator/src/node/converter.hpp
index 7a3e8e4e58033..1f98abed4d619 100644
--- a/system/diagnostic_graph_aggregator/src/node/converter.hpp
+++ b/system/diagnostic_graph_aggregator/src/node/converter.hpp
@@ -19,15 +19,32 @@
#include
+#include
+#include