Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(diagnostic_graph_aggregator): update tools #6614

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions system/diagnostic_graph_aggregator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions system/diagnostic_graph_aggregator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ You can reuse the graph by making partial edits. For example, disable hardware c
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

- [graph](./doc/format/graph.md)
Expand Down
29 changes: 29 additions & 0 deletions system/diagnostic_graph_aggregator/doc/tool/converter.md
Original file line number Diff line number Diff line change
@@ -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
```

![rqt_runtime_monitor](./images/rqt_runtime_monitor.png)

```bash
ros2 launch diagnostic_graph_aggregator example-main.launch.xml complement:=true
ros2 run rqt_robot_monitor rqt_robot_monitor
```

![rqt_robot_monitor](./images/rqt_robot_monitor.png)
36 changes: 36 additions & 0 deletions system/diagnostic_graph_aggregator/doc/tool/dump.md
Original file line number Diff line number Diff line change
@@ -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 | |
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions system/diagnostic_graph_aggregator/doc/tool/tree.md
Original file line number Diff line number Diff line change
@@ -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 <graph-config-path>
```

## 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)
```
9 changes: 6 additions & 3 deletions system/diagnostic_graph_aggregator/example/dummy-diags.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<launch>
<arg name="complement" default="false"/>
<include file="$(find-pkg-share diagnostic_graph_aggregator)/launch/diagnostic_graph_aggregator.launch.xml">
<arg name="graph_file" value="$(find-pkg-share diagnostic_graph_aggregator)/example/graph/edit.yaml"/>
</include>
<node pkg="diagnostic_graph_aggregator" exec="converter" name="converter"/>
<include file="$(find-pkg-share diagnostic_graph_aggregator)/launch/converter.launch.xml">
<arg name="complement" value="$(var complement)"/>
</include>
<executable cmd="python3 $(find-pkg-share diagnostic_graph_aggregator)/example/dummy-diags.py"/>
</launch>
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<launch>
<include file="$(find-pkg-share diagnostic_graph_aggregator)/launch/diagnostic_graph_aggregator.launch.xml">
<arg name="complement" default="false"/>
<include file="$(find-pkg-share diagnostic_graph_aggregator)/launch/aggregator.launch.xml">
<arg name="graph_file" value="$(find-pkg-share diagnostic_graph_aggregator)/example/graph/main.yaml"/>
</include>
<node pkg="diagnostic_graph_aggregator" exec="converter" name="converter"/>
<include file="$(find-pkg-share diagnostic_graph_aggregator)/launch/converter.launch.xml">
<arg name="complement" value="$(var complement)"/>
</include>
<executable cmd="python3 $(find-pkg-share diagnostic_graph_aggregator)/example/dummy-diags.py"/>
</launch>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<launch>
<arg name="complement"/>
<node pkg="diagnostic_graph_aggregator" exec="converter" name="converter">
<param name="complement_tree" value="$(var complement)"/>
</node>
</launch>
1 change: 0 additions & 1 deletion system/diagnostic_graph_aggregator/script/dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 7 additions & 7 deletions system/diagnostic_graph_aggregator/src/node/aggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
namespace diagnostic_graph_aggregator
{

MainNode::MainNode() : Node("diagnostic_graph_aggregator_aggregator")
AggregatorNode::AggregatorNode() : Node("aggregator")

Check warning on line 23 in system/diagnostic_graph_aggregator/src/node/aggregator.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/aggregator.cpp#L23

Added line #L23 was not covered by tests
{
// Init diagnostics graph.
{
Expand All @@ -39,7 +39,7 @@
const auto qos_input = rclcpp::QoS(declare_parameter<int64_t>("input_qos_depth"));
const auto qos_graph = rclcpp::QoS(declare_parameter<int64_t>("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<DiagnosticArray>("/diagnostics", qos_input, callback);
pub_graph_ = create_publisher<DiagnosticGraph>("/diagnostics_graph", qos_graph);

Expand All @@ -51,20 +51,20 @@
debug_ = declare_parameter<bool>("use_debug_mode");
}

MainNode::~MainNode()
AggregatorNode::~AggregatorNode()

Check warning on line 54 in system/diagnostic_graph_aggregator/src/node/aggregator.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/aggregator.cpp#L54

Added line #L54 was not covered by tests
{
// for unique_ptr
}

void MainNode::on_timer()
void AggregatorNode::on_timer()

Check warning on line 59 in system/diagnostic_graph_aggregator/src/node/aggregator.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/aggregator.cpp#L59

Added line #L59 was not covered by tests
{
const auto stamp = now();
pub_graph_->publish(graph_.report(stamp));
if (debug_) graph_.debug();
if (modes_) modes_->update(stamp);
}

void MainNode::on_diag(const DiagnosticArray::ConstSharedPtr msg)
void AggregatorNode::on_diag(const DiagnosticArray::ConstSharedPtr msg)

Check warning on line 67 in system/diagnostic_graph_aggregator/src/node/aggregator.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/aggregator.cpp#L67

Added line #L67 was not covered by tests
{
graph_.callback(now(), *msg);
}
Expand All @@ -73,10 +73,10 @@

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<MainNode>();
auto node = std::make_shared<AggregatorNode>();
executor.add_node(node);
executor.spin();
executor.remove_node(node);
Expand Down
6 changes: 3 additions & 3 deletions system/diagnostic_graph_aggregator/src/node/aggregator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
68 changes: 60 additions & 8 deletions system/diagnostic_graph_aggregator/src/node/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

#include "converter.hpp"

#include <memory>
#include <string>
#include <algorithm>

namespace diagnostic_graph_aggregator
{
Expand All @@ -35,45 +34,98 @@
return "UNKNOWN";
}

ToolNode::ToolNode() : Node("diagnostic_graph_aggregator_converter")
std::string parent_path(const std::string & path)

Check warning on line 37 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L37

Added line #L37 was not covered by tests
{
return path.substr(0, path.rfind('/'));

Check warning on line 39 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L39

Added line #L39 was not covered by tests
}

auto create_tree(const DiagnosticGraph & graph)

Check warning on line 42 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L42

Added line #L42 was not covered by tests
{
std::map<std::string, std::unique_ptr<TreeNode>, std::greater<std::string>> tree;
for (const auto & node : graph.nodes) {
tree.emplace(node.status.name, std::make_unique<TreeNode>(true));

Check warning on line 46 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L45-L46

Added lines #L45 - L46 were not covered by tests
}
for (const auto & node : graph.nodes) {

Check warning on line 48 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L48

Added line #L48 was not covered by tests
std::string path = node.status.name;
while (path = parent_path(path), !path.empty()) {

Check warning on line 50 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L50

Added line #L50 was not covered by tests
if (tree.count(path)) break;
tree.emplace(path, std::make_unique<TreeNode>(false));

Check warning on line 52 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L52

Added line #L52 was not covered by tests
}
}
for (const auto & [path, node] : tree) {
const auto parent = parent_path(path);
node->parent = parent.empty() ? nullptr : tree[parent].get();

Check warning on line 57 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L55-L57

Added lines #L55 - L57 were not covered by tests
}
return tree;

Check warning on line 59 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L59

Added line #L59 was not covered by tests
}

ConverterNode::ConverterNode() : Node("converter")

Check warning on line 62 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L62

Added line #L62 was not covered by tests
{
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<DiagnosticGraph>("/diagnostics_graph", qos_graph, callback);
pub_array_ = create_publisher<DiagnosticArray>("/diagnostics_array", qos_array);
pub_array_ = create_publisher<DiagnosticArray>("/diagnostics_agg", qos_array);

Check warning on line 70 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L70

Added line #L70 was not covered by tests

initialize_tree_ = false;
complement_tree_ = declare_parameter<bool>("complement_tree");

Check warning on line 73 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L72-L73

Added lines #L72 - L73 were not covered by tests
}

void ToolNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
void ConverterNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)

Check warning on line 76 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L76

Added line #L76 was not covered by tests
{
DiagnosticArray message;
message.header.stamp = msg->stamp;
message.status.reserve(msg->nodes.size());
for (const auto & node : msg->nodes) {
message.status.push_back(node.status);
for (const auto & link : node.links) {
diagnostic_msgs::msg::KeyValue kv;
const auto & status = msg->nodes[link.index].status;
kv.key = status.name;
kv.value = level_to_string(status.level);
if (link.used) {
message.status.back().values.push_back(kv);
}
}
}

if (complement_tree_ && !initialize_tree_) {
initialize_tree_ = true;
tree_ = create_tree(*msg);

Check warning on line 96 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L94-L96

Added lines #L94 - L96 were not covered by tests
}

if (complement_tree_) {
for (const auto & [path, node] : tree_) {
node->level = DiagnosticStatus::OK;

Check warning on line 101 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L99-L101

Added lines #L99 - L101 were not covered by tests
}
for (const auto & node : msg->nodes) {
tree_[node.status.name]->level = node.status.level;

Check warning on line 104 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L103-L104

Added lines #L103 - L104 were not covered by tests
}
for (const auto & [path, node] : tree_) {
if (!node->parent) continue;
node->parent->level = std::max(node->parent->level, node->level);

Check warning on line 108 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L106-L108

Added lines #L106 - L108 were not covered by tests
}
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;

Check warning on line 114 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

Codecov / codecov/patch

system/diagnostic_graph_aggregator/src/node/converter.cpp#L110-L114

Added lines #L110 - L114 were not covered by tests
}
}

Check warning on line 117 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

ConverterNode::on_graph has a cyclomatic complexity of 15, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 117 in system/diagnostic_graph_aggregator/src/node/converter.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Bumpy Road Ahead

ConverterNode::on_graph has 4 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is one single, nested block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.
pub_array_->publish(message);
}

} // namespace diagnostic_graph_aggregator

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<ToolNode>();
auto node = std::make_shared<ConverterNode>();
executor.add_node(node);
executor.spin();
executor.remove_node(node);
Expand Down
Loading
Loading