Skip to content

Commit be37125

Browse files
authored
Merge pull request #38 from bjv-capra/feature/key-value-array
Feature key value array
2 parents 72ab7f8 + 809cdf5 commit be37125

11 files changed

Lines changed: 177 additions & 93 deletions

File tree

micro_ros_diagnostic_bridge/include/micro_ros_diagnostic_bridge/micro_ros_diagnostic_bridge.hpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
#include "rclcpp/rclcpp.hpp"
2525

26-
#include "diagnostic_msgs/msg/diagnostic_status.hpp"
26+
#include "diagnostic_msgs/msg/diagnostic_array.hpp"
2727
#include "micro_ros_diagnostic_msgs/msg/micro_ros_diagnostic_status.hpp"
2828

2929

@@ -33,6 +33,8 @@ static const char UROS_DIAGNOSTICS_BRIDGE_TOPIC_OUT[] = "diagnostics";
3333
namespace uros_diagnostic_msg = micro_ros_diagnostic_msgs::msg;
3434
namespace diagnostic_msg = diagnostic_msgs::msg;
3535

36+
constexpr int UNIQUE_POLYNOM = 4567;
37+
3638
struct MicroROSDiagnosticUpdater
3739
{
3840
std::string name;
@@ -46,7 +48,7 @@ struct MicroROSDiagnosticKey
4648

4749
bool operator<(const MicroROSDiagnosticKey & rhs) const
4850
{
49-
return (updater_id * UINT_MAX + key_id) < (rhs.updater_id * UINT_MAX + rhs.key_id);
51+
return (updater_id * UNIQUE_POLYNOM + key_id) < (rhs.updater_id * UNIQUE_POLYNOM + rhs.key_id);
5052
}
5153
};
5254

@@ -57,8 +59,10 @@ struct MicroROSDiagnosticValue
5759

5860
bool operator<(const MicroROSDiagnosticValue & rhs) const
5961
{
60-
return (task.updater_id * UINT_MAX * UINT_MAX + task.key_id * UINT_MAX + value_id) <
61-
(rhs.task.updater_id * UINT_MAX * UINT_MAX + rhs.task.key_id * UINT_MAX + rhs.value_id);
62+
return (task.updater_id * UNIQUE_POLYNOM * UNIQUE_POLYNOM + task.key_id * UNIQUE_POLYNOM +
63+
value_id) <
64+
(rhs.task.updater_id * UNIQUE_POLYNOM * UNIQUE_POLYNOM + rhs.task.key_id *
65+
UNIQUE_POLYNOM + rhs.value_id);
6266
}
6367
};
6468

@@ -72,25 +76,25 @@ class MicroROSDiagnosticBridge : public rclcpp::Node
7276
public:
7377
explicit MicroROSDiagnosticBridge(const std::string & path = "");
7478

75-
virtual std::string lookup_hardware(
79+
std::string lookup_hardware(
7680
int hardware_id);
77-
virtual const MicroROSDiagnosticUpdater lookup_updater(
81+
const MicroROSDiagnosticUpdater lookup_updater(
7882
int updater_id);
79-
virtual std::string lookup_key(
83+
std::string lookup_key(
8084
int updater_id,
8185
int key);
82-
virtual std::string lookup_value(
86+
std::string lookup_value(
8387
int updater_id,
8488
int key,
8589
int value_id);
8690

87-
protected:
88-
virtual void read_lookup_table(const std::string & path);
91+
private:
92+
void read_lookup_table(const std::string & path);
8993

9094
rclcpp::Logger logger_;
91-
rclcpp::Subscription<uros_diagnostic_msg::MicroROSDiagnosticStatus>::SharedPtr uros_sub_;
92-
rclcpp::Publisher<diagnostic_msg::DiagnosticStatus>::SharedPtr ros2_pub_;
93-
std::unique_ptr<diagnostic_msg::DiagnosticStatus> msg_out_;
95+
rclcpp::Subscription<uros_diagnostic_msg::MicroROSDiagnosticStatus>::SharedPtr
96+
uros_diagnostics_sub_;
97+
rclcpp::Publisher<diagnostic_msg::DiagnosticArray>::SharedPtr ros2_diagnostics_pub_;
9498

9599
HardwareMap hardware_map_;
96100
UpdaterMap updater_map_;

micro_ros_diagnostic_bridge/src/micro_ros_diagnostic_bridge/micro_ros_diagnostic_bridge.cpp

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
#include <rcl_yaml_param_parser/parser.h>
2727

2828
using micro_ros_diagnostic_msgs::msg::MicroROSDiagnosticStatus;
29-
using diagnostic_msgs::msg::DiagnosticStatus;
29+
using diagnostic_msgs::msg::DiagnosticArray;
30+
31+
static inline std::string VALUE_NOT_FOUND = "NOTFOUND";
3032

3133
MicroROSDiagnosticBridge::MicroROSDiagnosticBridge(const std::string & path)
3234
: Node("micro_ros_diagnostic_bridge"),
@@ -40,54 +42,64 @@ MicroROSDiagnosticBridge::MicroROSDiagnosticBridge(const std::string & path)
4042
}
4143
read_lookup_table(lookup_table_path);
4244

45+
rclcpp::QoS qos{rclcpp::KeepLast{10}};
46+
qos.reliable();
47+
48+
ros2_diagnostics_pub_ = create_publisher<DiagnosticArray>(
49+
UROS_DIAGNOSTICS_BRIDGE_TOPIC_OUT,
50+
qos);
51+
4352
auto callback =
4453
[this](const MicroROSDiagnosticStatus::SharedPtr msg_in) -> void
4554
{
4655
RCLCPP_DEBUG(
4756
get_logger(),
4857
"Bridging message from hardware %d, updater %d", msg_in->hardware_id,
4958
msg_in->updater_id);
50-
msg_out_ = std::make_unique<diagnostic_msgs::msg::DiagnosticStatus>();
59+
auto msg_out = std::make_unique<DiagnosticArray>();
60+
diagnostic_msgs::msg::DiagnosticStatus status_msg{};
5161

5262
auto updater = lookup_updater(msg_in->updater_id);
5363
auto hardware = lookup_hardware(msg_in->hardware_id);
54-
msg_out_->hardware_id = hardware;
55-
msg_out_->name = updater.name;
56-
msg_out_->message = updater.description;
57-
msg_out_->level = msg_in->level;
58-
59-
diagnostic_msgs::msg::KeyValue keyvalue;
60-
RCLCPP_DEBUG(get_logger(), "Bridging updater %d, task %d", msg_in->updater_id, msg_in->key);
61-
keyvalue.key = lookup_key(msg_in->updater_id, msg_in->key);
62-
switch (msg_in->value_type) {
63-
case micro_ros_diagnostic_msgs::msg::MicroROSDiagnosticStatus::VALUE_BOOL:
64-
keyvalue.value = std::to_string(msg_in->bool_value);
65-
break;
66-
case micro_ros_diagnostic_msgs::msg::MicroROSDiagnosticStatus::VALUE_INT:
67-
keyvalue.value = std::to_string(msg_in->int_value);
68-
break;
69-
case micro_ros_diagnostic_msgs::msg::MicroROSDiagnosticStatus::VALUE_DOUBLE:
70-
keyvalue.value = std::to_string(msg_in->double_value);
71-
break;
72-
case micro_ros_diagnostic_msgs::msg::MicroROSDiagnosticStatus::VALUE_LOOKUP:
73-
keyvalue.value = lookup_value(msg_in->updater_id, msg_in->key, msg_in->value_id);
74-
break;
64+
status_msg.hardware_id = hardware;
65+
status_msg.name = updater.name;
66+
status_msg.message = updater.description;
67+
status_msg.level = msg_in->level;
68+
RCLCPP_DEBUG(get_logger(), "Updater %s HW %s", updater.name.c_str(), hardware.c_str());
69+
for (size_t value_index = 0; value_index < msg_in->number_of_values; value_index++) {
70+
diagnostic_msgs::msg::KeyValue keyvalue;
71+
RCLCPP_DEBUG(
72+
get_logger(), "Bridging updater %d, key %d", msg_in->updater_id,
73+
msg_in->values[value_index].key);
74+
keyvalue.key = lookup_key(msg_in->updater_id, msg_in->values[value_index].key);
75+
switch (msg_in->values[value_index].value_type) {
76+
case MicroROSDiagnosticStatus::VALUE_BOOL:
77+
keyvalue.value = std::to_string(msg_in->values[value_index].bool_value);
78+
break;
79+
case MicroROSDiagnosticStatus::VALUE_INT:
80+
keyvalue.value = std::to_string(msg_in->values[value_index].int_value);
81+
break;
82+
case MicroROSDiagnosticStatus::VALUE_DOUBLE:
83+
keyvalue.value = std::to_string(msg_in->values[value_index].double_value);
84+
break;
85+
case MicroROSDiagnosticStatus::VALUE_LOOKUP:
86+
keyvalue.value = lookup_value(
87+
msg_in->updater_id, msg_in->values[value_index].key,
88+
msg_in->values[value_index].value_id);
89+
break;
90+
}
91+
status_msg.values.push_back(keyvalue);
92+
RCLCPP_DEBUG(get_logger(), "key %s value %s", keyvalue.key.c_str(), keyvalue.value.c_str());
7593
}
76-
msg_out_->values.push_back(keyvalue);
77-
78-
ros2_pub_->publish(std::move(msg_out_));
94+
msg_out->status.push_back(status_msg);
95+
msg_out->header.stamp = rclcpp::Clock().now();
96+
ros2_diagnostics_pub_->publish(std::move(msg_out));
7997
};
8098

81-
rclcpp::QoS qos{rclcpp::KeepLast{10}};
82-
qos.reliable();
83-
84-
uros_sub_ = create_subscription<MicroROSDiagnosticStatus>(
99+
uros_diagnostics_sub_ = create_subscription<MicroROSDiagnosticStatus>(
85100
UROS_DIAGNOSTICS_BRIDGE_TOPIC_IN,
86101
qos,
87102
callback);
88-
ros2_pub_ = create_publisher<DiagnosticStatus>(
89-
UROS_DIAGNOSTICS_BRIDGE_TOPIC_OUT,
90-
qos);
91103
}
92104

93105
std::string
@@ -102,7 +114,7 @@ MicroROSDiagnosticBridge::lookup_key(
102114
get_logger(),
103115
"Updater %d and key %d, not found in lookup table.",
104116
updater_id, key);
105-
return "NOTFOUND";
117+
return VALUE_NOT_FOUND;
106118
}
107119
}
108120

@@ -119,7 +131,7 @@ MicroROSDiagnosticBridge::lookup_value(
119131
get_logger(),
120132
"Updater %d, key %d, and value id %d, not found in lookup table.",
121133
updater_id, key, value_id);
122-
return "NOTFOUND";
134+
return VALUE_NOT_FOUND;
123135
}
124136
}
125137

@@ -169,6 +181,9 @@ MicroROSDiagnosticBridge::read_lookup_table(const std::string & path)
169181
for (auto & p : it->second) {
170182
try {
171183
hardware_map_[std::stoi(p.get_name())] = p.value_to_string();
184+
RCLCPP_DEBUG(
185+
get_logger(), "FOUND Parameter: %s HW_ID %s",
186+
p.get_name().c_str(), p.value_to_string().c_str());
172187
} catch (const std::invalid_argument &) {
173188
throw std::runtime_error("Failed to parse hardware_id from lookup_table.");
174189
}
@@ -181,28 +196,37 @@ MicroROSDiagnosticBridge::read_lookup_table(const std::string & path)
181196
auto pos = p.get_name().find('.');
182197
if (pos != std::string::npos) {
183198
updater_key = p.get_name().substr(0, pos);
199+
RCLCPP_DEBUG(get_logger(), "Updater key: %s", updater_key.c_str());
184200
} else {
185201
throw std::runtime_error("Failed to load updater key.");
186202
}
187203

188204
// Updater
189205
if (p.get_name().compare(updater_key + ".name") == 0) {
190206
updater_name = p.value_to_string();
207+
RCLCPP_DEBUG(
208+
get_logger(), "Updater Name: %s, Description: %s",
209+
updater_name.c_str(), updater_descr.c_str());
191210
updater_map_[std::stoi(updater_key)] = {updater_name, updater_descr};
192211
}
193212
if (p.get_name().compare(updater_key + ".description") == 0) {
194213
updater_descr = p.value_to_string();
195214
updater_map_[std::stoi(updater_key)] = {updater_name, updater_descr};
215+
RCLCPP_DEBUG(
216+
get_logger(), "Updater Name: %s, Description: %s",
217+
updater_name.c_str(), updater_descr.c_str());
196218
}
197219

198220
// Keys
199221
if (p.get_name().rfind(updater_key + ".keys", 0) == 0) {
200222
auto start = updater_key.length() + 6;
201223
pos = p.get_name().find('.', start);
202224
key = p.get_name().substr(start, pos - start);
225+
RCLCPP_DEBUG(get_logger(), "Updater key position: %ld, key: %s", pos, key.c_str());
203226
}
204227
if (p.get_name().compare(updater_key + ".keys." + key + ".name") == 0) {
205228
key_name = p.value_to_string();
229+
RCLCPP_DEBUG(get_logger(), "Key name: %s", key_name.c_str());
206230
key_map_[{std::stoi(updater_key), std::stoi(key)}] = key_name;
207231
}
208232

@@ -211,8 +235,8 @@ MicroROSDiagnosticBridge::read_lookup_table(const std::string & path)
211235
auto start = updater_key.length() + key.length() + 14;
212236
pos = p.get_name().find('.', start);
213237
auto value_id = std::stoi(p.get_name().substr(start, pos - start));
214-
value_map_[{{std::stoi(updater_key), std::stoi(key)}, value_id}] =
215-
p.value_to_string();
238+
value_map_[{{std::stoi(updater_key), std::stoi(key)}, value_id}] = p.value_to_string();
239+
RCLCPP_DEBUG(get_logger(), "Value ID %d Value %s", value_id, p.value_to_string().c_str());
216240
}
217241
}
218242
}

micro_ros_diagnostic_msgs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ find_package(rosidl_default_generators REQUIRED)
1515
find_package(std_msgs REQUIRED)
1616

1717
set(msg_files
18+
"msg/MicroROSDiagnosticKeyValue.msg"
1819
"msg/MicroROSDiagnosticStatus.msg"
1920
)
2021
set(srv_files
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Possible levels of operations.
2+
byte OK=0
3+
byte WARN=1
4+
byte ERROR=2
5+
byte STALE=3
6+
7+
# Possible value types
8+
byte VALUE_BOOL=1
9+
byte VALUE_INT=2
10+
byte VALUE_DOUBLE=3
11+
byte VALUE_LOOKUP=10
12+
13+
# Level of operation enumerated above.
14+
byte level
15+
16+
# What key, value is transmitted.
17+
uint16 key
18+
19+
byte value_type
20+
bool bool_value
21+
int32 int_value
22+
float32 double_value
23+
uint16 value_id

micro_ros_diagnostic_msgs/msg/MicroROSDiagnosticStatus.msg

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,5 @@ uint16 updater_id
2626
# A hardware unique string.
2727
uint16 hardware_id
2828

29-
# What key, value is transmitted.
30-
uint16 key
31-
32-
byte value_type
33-
bool bool_value
34-
int32 int_value
35-
float32 double_value
36-
uint16 value_id
29+
uint8 number_of_values
30+
micro_ros_diagnostic_msgs/MicroROSDiagnosticKeyValue[] values

micro_ros_diagnostic_updater/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ option(MICRO_ROS_DIAGNOSTIC_UPDATER_EXAMPLES "Build example updaters for the mic
3030
# Configuration
3131
set(MICRO_ROS_DIAGNOSTIC_UPDATER_MAX_TASKS_PER_UPDATER "5" CACHE STRING "Number of tasks preallocated per updater.")
3232
set(MICRO_ROS_DIAGNOSTIC_UPDATER_DIAGNOSTICS_TOPIC_PREFIX "" CACHE STRING "Prefix for micro-ROS diagnostic topic (append slash '/')")
33+
set(MICRO_ROS_DIAGNOSTIC_UPDATER_MAX_VALUES_PER_TASK "4" CACHE STRING "Number of pre allocated key value pairs.")
3334

3435
# Create library
3536
add_library(${PROJECT_NAME}

micro_ros_diagnostic_updater/example/example_processor_updater.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,37 +30,39 @@ static const int16_t PROCESSOR_TEMPERATURE_TASK_ID = 0;
3030
static const int16_t PROCESSOR_LOAD_TASK_ID = 1;
3131

3232
rcl_ret_t
33-
my_diagnostic_temperature(diagnostic_value_t * temp_kv)
33+
my_diagnostic_temperature(diagnostic_value_t * values, uint8_t * number_of_values)
3434
{
35+
*number_of_values = 1;
3536
// Fake a temperature
3637
++my_diagnostic_temp;
3738
if (my_diagnostic_temp > 99) {
3839
my_diagnostic_temp -= 0;
3940
}
40-
rclc_diagnostic_value_set_int(temp_kv, my_diagnostic_temp);
41+
rclc_diagnostic_value_set_int(&values[0], my_diagnostic_temp);
4142

4243
// Calculate the diagnostic level
4344
if (my_diagnostic_temp > 85) {
44-
rclc_diagnostic_value_set_level(temp_kv, 2);
45+
rclc_diagnostic_value_set_level(&values[0], 2);
4546
} else if (my_diagnostic_temp > 75) {
46-
rclc_diagnostic_value_set_level(temp_kv, 1);
47+
rclc_diagnostic_value_set_level(&values[0], 1);
4748
} else {
48-
rclc_diagnostic_value_set_level(temp_kv, 0);
49+
rclc_diagnostic_value_set_level(&values[0], 0);
4950
}
5051
return RCL_RET_OK;
5152
}
5253

5354
rcl_ret_t
54-
my_diagnostic_load(diagnostic_value_t * load_kv)
55+
my_diagnostic_load(diagnostic_value_t * values, uint8_t * number_of_values)
5556
{
57+
*number_of_values = 1;
5658
// Fake a processor load
57-
rclc_diagnostic_value_set_int(load_kv, my_diagnostic_temp / 2);
59+
rclc_diagnostic_value_set_int(&values[0], my_diagnostic_temp / 2);
5860

5961
// Calculate the diagnostic level
6062
if (my_diagnostic_temp > 46) {
61-
rclc_diagnostic_value_set_level(load_kv, 1);
63+
rclc_diagnostic_value_set_level(&values[0], 1);
6264
} else {
63-
rclc_diagnostic_value_set_level(load_kv, 0);
65+
rclc_diagnostic_value_set_level(&values[0], 0);
6466
}
6567
return RCL_RET_OK;
6668
}

0 commit comments

Comments
 (0)