Skip to content

Commit fc6e38f

Browse files
ct2034ralph-lange
andauthored
Adding READMEs to the repo (#270)
* Adding a repo-level readme * An example aggregation * A readme for the aggregator * Common diagnostics readme * A readme for the diagnostic updater * A readme for the self_test package * Maintainers unified * Skip pep257 while it is unstable Signed-off-by: Christian Henkel <christian.henkel2@de.bosch.com> Co-authored-by: Ralph Lange <ralph-lange@users.noreply.github.com>
1 parent 12ab006 commit fc6e38f

11 files changed

Lines changed: 356 additions & 8 deletions

File tree

.github/workflows/lint.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ jobs:
99
strategy:
1010
fail-fast: false
1111
matrix:
12-
linter: [cppcheck, cpplint, flake8, pep257, uncrustify, xmllint]
12+
linter: [
13+
cppcheck,
14+
cpplint,
15+
flake8,
16+
# pep257,
17+
uncrustify,
18+
xmllint]
1319
steps:
1420
- uses: actions/checkout@v1
1521
- uses: ros-tooling/setup-ros@v0.2

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Overview
2+
The diagnostics system collects information about hardware drivers and robot hardware to make them availaible to users and operators.
3+
The diagnostics system contains tools to collect and analyze this data.
4+
5+
The diagnostics system is build around the `/diagnostics` topic. The topic is used for `diagnostic_msgs/DiagnosticArray` messages.
6+
It contains information about the device names, status, and values.
7+
8+
It contains the following packages:
9+
- [`diagnostic_aggregator`](/diagnostic_aggregator/): Aggregates diagnostic messages from different sources into a single message.
10+
- [`diagnostic_analysis`](/diagnostics/): *Not ported to ROS2 yet* **#contributions-welcome**
11+
- [`diagnostic_common_diagnostics`](/diagnostic_common_diagnostics/): Predefined nodes for monitoring the Linux and ROS system.
12+
- [`diagnostic_updater`](/diagnostic_updater/): Base classes to publishing custom diagnostic messages for Python and C++.
13+
- [`self_test`](/self_test/): Tools to perform self tests on nodes.
14+
15+
## Collecting diagnostic data
16+
At the points of interest, i.e. the hardware drivers, the diagnostic data is collected.
17+
The data must be published on the `/diagnostics` topic.
18+
In the `diagnostic_updater` package, there are base classes to simplify the creation of diagnostic messages.
19+
20+
## Aggregation
21+
The `diagnostic_aggregator` package provides tools to aggregate diagnostic messages from different sources into a single message. It has a plugin system to define the aggregation rules.
22+
23+
## Visualization
24+
Outside of this repository, there is [`rqt_robot_monitor`](https://index.ros.org/p/rqt_robot_monitor/) to visualize diagnostic messages that have been aggregated by the `diagnostic_aggregator`.
25+
26+
Diagnostics messages that are not aggregated can be visualized by [`rqt_runtime_monitor`](https://index.ros.org/p/rqt_runtime_monitor/).
27+
28+
# License
29+
The source code is released under a [BSD 3-Clause license](LICENSE).

diagnostic_aggregator/README.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
General information about this repository, including legal information and known issues/limitations, are given in [README.md](../README.md) in the repository root.
2+
3+
# The diagnostic_aggregator package
4+
This package contains the `aggregator_node`.
5+
It listens to the [`diagnostic_msgs/DiagnosticArray`](https://index.ros.org/p/diagnostic_msgs) messages on the `/diagnostics` topic and aggregates and published them on the `/diagnostics_agg` topic.
6+
7+
One use case for this package is to aggregate the diagnostics of a robot.
8+
Aggregation means that the diagnostics of the robot are grouped by various aspects, like their location on the robot, their type, etc.
9+
This will allow you to easily see which part of the robot is causing problems.
10+
11+
## Example
12+
In our example, we are looking at a robot with arms and legs.
13+
The robot has two of each, one on each side.
14+
The robot also 4 camera sensors, one left and one right and one in the front and one in the back.
15+
These are all the available diagnostic sources:
16+
17+
```
18+
/arms/left/motor
19+
/arms/right/motor
20+
/legs/left/motor
21+
/legs/right/motor
22+
/sensors/left/cam
23+
/sensors/right/cam
24+
/sensors/front/cam
25+
/sensors/rear/cam
26+
```
27+
28+
We want to group the diagnostics by
29+
- all sensors
30+
- all motors
31+
- left side of the robot
32+
- right side of the robot
33+
34+
We can achieve that by creating a configuration file that looks like this (see [example_analyzers.yaml](example/example_analyzers.yaml)):
35+
``` yaml
36+
analyzers:
37+
ros__parameters:
38+
path: Aggregation
39+
arms:
40+
type: diagnostic_aggregator/GenericAnalyzer
41+
path: Arms
42+
startswith: [ '/arms' ]
43+
legs:
44+
type: diagnostic_aggregator/GenericAnalyzer
45+
path: Legs
46+
startswith: [ '/legs' ]
47+
sensors:
48+
type: diagnostic_aggregator/GenericAnalyzer
49+
path: Sensors
50+
startswith: [ '/sensors' ]
51+
motors:
52+
type: diagnostic_aggregator/GenericAnalyzer
53+
path: Motors
54+
contains: [ '/motor' ]
55+
topology:
56+
type: 'diagnostic_aggregator/AnalyzerGroup'
57+
path: Topology
58+
analyzers:
59+
left:
60+
type: diagnostic_aggregator/GenericAnalyzer
61+
path: Left
62+
contains: [ '/left' ]
63+
right:
64+
type: diagnostic_aggregator/GenericAnalyzer
65+
path: Right
66+
contains: [ '/right' ]
67+
```
68+
69+
Based on this configuration, the [rqt_robot_monitor](https://index.ros.org/p/rqt_robot_monitor) will display the diagnostics information in a well-arranged manner as follows:
70+
![doc/rqt_robot_monitor.png](doc/rqt_robot_monitor.png)
71+
72+
Note that it will also display the highest state per group to allow you to see at a glance which part of the robot is not working properly.
73+
For example in the above image, the left side of the robot is not working properly, because the left camera is in the `ERROR` state.
74+
75+
# Analyzers
76+
The `aggregator_node` will load analyzers to process the diagnostics data.
77+
An analyzer is a plugin that inherits from the [`diagnostic_aggregator::Analyzer`](include/diagnostic_aggregator/analyzer.hpp) class.
78+
Analyzers must be implemented in packages that directly depend on [`pluginlib`](https://index.ros.org/p/pluginlib) and `diagnostic_aggregator`.
79+
80+
The [`diagnostic_aggregator::Analyzer`](include/diagnostic_aggregator/analyzer.hpp) class is purely virtual and derived classes must implement the following methods:
81+
82+
- `init()` - Analyzer is initialized with base path and namespace
83+
- `match()` - Returns true if the analyzer is interested in the status message
84+
- `analyze()` - Returns true if the analyzer will analyze the status message
85+
- `report()` - Returns results of analysis as vector of status messages
86+
- `getPath()` - Returns the prefix path of the analyzer (e.g., "/robot/motors/")
87+
- `getName()` - Returns the name of the analyzer (e.g., "Motors")
88+
89+
Analyzers can choose the value of the error level of their output.
90+
Usually, the error level of the output is the highest error level of the input.
91+
The analyzers are responsible for setting the name of each item in the output correctly.
92+
93+
# Using the aggregator_node
94+
95+
## Configuration
96+
97+
The `aggregator_node` can be configured at launch time like in this example:
98+
``` yaml
99+
pub_rate: 1.0 # Optional, defaults to 1.0
100+
base_path: 'PRE' # Optional, defaults to ""
101+
analyzers:
102+
motors:
103+
type: PR2MotorsAnalyzer
104+
joints:
105+
type: GenericAnalyzer
106+
path: 'Joints'
107+
regex: 'Joint*'
108+
```
109+
110+
The `pub_rate` parameter is the rate at which the aggregated diagnostics will be published.
111+
The `base_path` parameter is the prefix that will be added to the name of each item in the output.
112+
113+
Under the `analyzers` key, you can specify the analyzers that you want to use.
114+
Each analyzer must have a unique name.
115+
Under the name, you must specify the type of the analyzer.
116+
This must be the name of the class that implements the analyzer.
117+
Additional parameters depend on the type of the analyzer.
118+
119+
Any diagnostic item that is not matched by any analyzer will be published by an "Other" analyzer.
120+
Items created by the "Other" analyzer will go stale after 5 seconds.
121+
122+
## Launching
123+
You can launch the `aggregator_node` like this (see [example.launch.py.in](example/example.launch.py.in)):
124+
``` python
125+
aggregator = launch_ros.actions.Node(
126+
package='diagnostic_aggregator',
127+
executable='aggregator_node',
128+
output='screen',
129+
parameters=[analyzer_params_filepath])
130+
return launch.LaunchDescription([
131+
aggregator,
132+
])
133+
```
134+
135+
# Basic analyzers
136+
The `diagnostic_aggregator` package provides a few basic analyzers that you can use to aggregate your diagnostics.
137+
138+
## GenericAnalyzer
139+
The [`diagnostic_aggregator::GenericAnalyzer`](include/diagnostic_aggregator/generic_analyzer.hpp) class is a basic analyzer that can be configured to match diagnostics based on their name.
140+
By defining a `path` parameter, you can specify the prefix that will be added to the name of each item in the output.
141+
This way you can group diagnostics by their location or other aspects as demonstrated in the [example](#example).
142+
143+
## AnalyzerGroup
144+
The [`diagnostic_aggregator::AnalyzerGroup`](include/diagnostic_aggregator/analyzer_group.hpp) class is a basic analyzer that can be configured to group other analyzers.
145+
It has itself an `analyzers` parameter that can be filled with other analyzers to group them.
146+
147+
An example of this is (see [example_analyzers.yaml](diagnostic_aggregator/example/example_analyzers.yaml)):
148+
``` yaml
149+
topology:
150+
type: 'diagnostic_aggregator/AnalyzerGroup'
151+
path: Topology
152+
analyzers:
153+
left:
154+
type: diagnostic_aggregator/GenericAnalyzer
155+
path: Left
156+
contains: [ '/left' ]
157+
right:
158+
type: diagnostic_aggregator/GenericAnalyzer
159+
path: Right
160+
contains: [ '/right' ]
161+
```
162+
163+
## DiscardAnalyzer
164+
The [`diagnostic_aggregator::DiscardAnalyzer`](include/diagnostic_aggregator/discard_analyzer.hpp) class is a basic analyzer that discards all diagnostics that match it.
165+
This can be useful if you want to ignore some diagnostics.
166+
167+
## IgnoreAnalyzer
168+
The [`diagnostic_aggregator::IgnoreAnalyzer`](include/diagnostic_aggregator/ignore_analyzer.hpp) will ignore all parameters in its namespace and not match anything.
169+
170+
The difference between the `DiscardAnalyzer` and the `IgnoreAnalyzer` is that the `DiscardAnalyzer` will match diagnostics and discard them, while the `IgnoreAnalyzer` will not match anything.
171+
This means that things that are ignored by the `IgnoreAnalyzer` will still be published in the "Other" analyzer, while things that are discarded by the `DiscardAnalyzer` will not be published at all.
172+
173+
# ROS API
174+
## `aggregator_node`
175+
176+
### Subscribed Topics
177+
- `diagnostics` ([diagnostic_msgs/DiagnosticArray](https://index.ros.org/p/diagnostic_msgs)) - The diagnostics to be aggregated
178+
179+
### Published Topics
180+
- `diagnostics_agg` ([diagnostic_msgs/DiagnosticArray](https://index.ros.org/p/diagnostic_msgs)) - The aggregated diagnostics
181+
- `diagnostics_toplevel_state` ([diagnostic_msgs/DiagnosticStatus](https://index.ros.org/p/diagnostic_msgs)) - The highest state of the aggregated diagnostics
182+
183+
### Parameters
184+
- `pub_rate` (double, default: 1.0) - The rate at which the aggregated diagnostics will be published
185+
- `base_path` (string, default: "") - The prefix that will be added to the name of each item in the output
186+
- `analyzers` (map, default: {}) - The analyzers that will be used to aggregate the diagnostics
187+
188+
# Tutorials
189+
TODO: Port tutorials #contributions-welcome
96.7 KB
Loading

diagnostic_aggregator/example/example_analyzers.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
analyzers:
22
ros__parameters:
3-
path: Analysis
3+
path: Aggregation
44
arms:
55
type: diagnostic_aggregator/GenericAnalyzer
66
path: Arms
@@ -11,7 +11,7 @@ analyzers:
1111
startswith: [ '/legs' ]
1212
sensors:
1313
type: diagnostic_aggregator/GenericAnalyzer
14-
path: Motors
14+
path: Sensors
1515
startswith: [ '/sensors' ]
1616
motors:
1717
type: diagnostic_aggregator/GenericAnalyzer
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
General information about this repository, including legal information, build instructions and known issues/limitations, are given in [README.md](../README.md) in the repository root.
2+
3+
# The diagnostic_common_diagnostics package
4+
This package provides generic nodes to monitor a Linux host.
5+
6+
Currently only the NTP monitor is ported to ROS2.
7+
8+
# Nodes
9+
10+
## ntp_monitor.py
11+
Runs 'ntpdate' to check if the system clock is synchronized with the NTP server.
12+
* If the offset is smaller than `offset-tolerance`, an `OK` status will be published.
13+
* If the offset is larger than the configured `offset-tolerance`, a `WARN` status will be published,
14+
* if it is biggern than `error-offset-tolerance`, an `ERROR` status will be published.
15+
* If there was an error running `ntpdate`, an `ERROR` status will be published.
16+
17+
### Published Topics
18+
#### /diagnostics
19+
diagnostic_msgs/DiagnosticArray
20+
The diagnostics information.
21+
22+
### Parameters
23+
#### ntp_hostname
24+
(default: "pool.ntp.org")
25+
Hostname of NTP server.
26+
27+
#### offset-tolerance"
28+
(default: 500)
29+
Allowed offset from NTP host. Above this is a warning.
30+
31+
#### error-offset-tolerance
32+
(default: 5000000)
33+
If the offset from the NTP host exceeds this value, it is reported as an error instead of warning.
34+
35+
#### self_offset-tolerance
36+
(default: 500)
37+
Offset from self
38+
39+
#### diag-hostname
40+
Computer name in diagnostics output (ex: 'c1')
41+
42+
#### no-self-test
43+
(default: True)
44+
Disable self test.
45+
46+
## hd_monitor.py
47+
**To be ported**
48+
49+
## cpu_monitor.py
50+
**To be ported**
51+
52+
## ram_monitor.py
53+
**To be ported**
54+
55+
## sensors_monitor.py
56+
**To be ported**
57+
58+
## tf_monitor.py
59+
**To be ported**

diagnostic_common_diagnostics/package.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
<name>diagnostic_common_diagnostics</name>
55
<version>1.9.3</version>
66
<description>diagnostic_common_diagnostics</description>
7-
<!-- author -->
8-
<maintainer email="brice.rebsamen@gmail.com">Brice Rebsamen</maintainer>
9-
<!-- maintainers -->
107
<maintainer email="namniart@gmail.com">Austin Hendrix</maintainer>
118
<maintainer email="brice.rebsamen@gmail.com">Brice Rebsamen</maintainer>
129
<maintainer email="ralph.lange@de.bosch.com">Ralph Lange</maintainer>
@@ -15,6 +12,8 @@
1512

1613
<url type="website">http://ros.org/wiki/diagnostic_common_diagnostics</url>
1714

15+
<author email="brice.rebsamen@gmail.com">Brice Rebsamen</author>
16+
1817
<buildtool_depend>ament_cmake</buildtool_depend>
1918
<buildtool_depend>ament_cmake_python</buildtool_depend>
2019

diagnostic_updater/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
General information about this repository, including legal information, build instructions and known issues/limitations, are given in [README.md](../README.md) in the repository root.
2+
# The diagnostic_updater package
3+
4+
This package is used to implement the collection of diagnostics information.
5+
6+
## Overview
7+
It can for example update the state of sensors or actors of the robot.
8+
Common tasks include
9+
* Publish the status of a sensor topic from a device driver
10+
* Report that a hardware device is closed
11+
* Send an error if a value is out bounds (e.g. temperature)
12+
13+
## Example
14+
The file [example.cpp](src/example.cpp) contains an example of how to use the diagnostic_updater.
15+
16+
## C++ and Python API
17+
The main classes are:
18+
19+
### DiagnosticStatusWrapper
20+
This class is used to create a diagnostic message.
21+
It simplifies the creation of the message by providing methods to set the level, name, message and values.
22+
There is also the possibility to merge multiple DiagnosticStatusWrapper into one.
23+
24+
### Updater
25+
This class is used to collect the diagnostic messages and to publish them.
26+
27+
### DiagnosedPublisher
28+
A ROS publisher with included diagnostics.
29+
It diagnoses the frequency of the published messages.
30+

diagnostics/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<name>diagnostics</name>
55
<version>1.9.3</version>
66
<description>diagnostics</description>
7-
<maintainer email="brice.rebsamen@gmail.com">Brice Rebsamen</maintainer>
87
<maintainer email="namniart@gmail.com">Austin Hendrix</maintainer>
8+
<maintainer email="brice.rebsamen@gmail.com">Brice Rebsamen</maintainer>
99
<maintainer email="ralph.lange@de.bosch.com">Ralph Lange</maintainer>
1010

1111
<license>BSD-3-Clause</license>

0 commit comments

Comments
 (0)