Skip to content

Commit a4fbaa7

Browse files
committed
Add type registry file
Signed-off-by: Mohamed Abdelaziz <[email protected]>
1 parent 1427288 commit a4fbaa7

File tree

5 files changed

+117
-94
lines changed

5 files changed

+117
-94
lines changed

greenwave_monitor/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ ament_target_dependencies(greenwave_monitor
3636
diagnostic_msgs
3737
greenwave_monitor_interfaces
3838
yaml_cpp_vendor
39+
ament_index_cpp
3940
)
4041
target_link_libraries(greenwave_monitor message_diagnostics)
4142

@@ -61,7 +62,7 @@ install(TARGETS minimal_publisher_node
6162
DESTINATION lib/${PROJECT_NAME})
6263

6364
install(
64-
DIRECTORY launch examples
65+
DIRECTORY launch examples config
6566
DESTINATION share/${PROJECT_NAME}
6667
)
6768

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,2 @@
11
has_header:
2-
# sensor_msgs
3-
- sensor_msgs/msg/Image
4-
- sensor_msgs/msg/CompressedImage
5-
- sensor_msgs/msg/CameraInfo
6-
- sensor_msgs/msg/PointCloud2
7-
- sensor_msgs/msg/LaserScan
8-
- sensor_msgs/msg/Imu
9-
- sensor_msgs/msg/NavSatFix
10-
- sensor_msgs/msg/MagneticField
11-
- sensor_msgs/msg/FluidPressure
12-
- sensor_msgs/msg/Illuminance
13-
- sensor_msgs/msg/RelativeHumidity
14-
- sensor_msgs/msg/Temperature
15-
- sensor_msgs/msg/Range
16-
- sensor_msgs/msg/PointCloud
17-
18-
# geometry_msgs
19-
- geometry_msgs/msg/PoseStamped
20-
- geometry_msgs/msg/TwistStamped
21-
- geometry_msgs/msg/AccelStamped
22-
- geometry_msgs/msg/Vector3Stamped
23-
- geometry_msgs/msg/PointStamped
24-
- geometry_msgs/msg/QuaternionStamped
25-
- geometry_msgs/msg/TransformStamped
26-
- geometry_msgs/msg/WrenchStamped
27-
28-
# nav_msgs
29-
- nav_msgs/msg/OccupancyGrid
30-
- nav_msgs/msg/GridCells
31-
- nav_msgs/msg/Path
32-
- nav_msgs/msg/Odometry
33-
34-
# visualization_msgs
35-
- visualization_msgs/msg/Marker
36-
- visualization_msgs/msg/MarkerArray
37-
- visualization_msgs/msg/InteractiveMarker
2+
- stereo_msgs/msg/DisparityImage

greenwave_monitor/include/greenwave_monitor.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,14 @@ class GreenwaveMonitor : public rclcpp::Node
6363

6464
bool has_header_from_type(const std::string & type_name);
6565

66-
bool read_type_registry(const std::string path);
66+
bool has_header_from_type_registry(const std::string & type_name);
6767

6868
std::chrono::time_point<std::chrono::system_clock>
6969
GetTimestampFromSerializedMessage(
7070
std::shared_ptr<rclcpp::SerializedMessage> serialized_message_ptr,
7171
const std::string & type);
7272

7373
std::string type_registry_path_;
74-
std::unordered_map<std::string, bool> known_header_types_;
7574
std::map<std::string,
7675
std::unique_ptr<message_diagnostics::MessageDiagnostics>> message_diagnostics_;
7776
std::vector<std::shared_ptr<rclcpp::GenericSubscription>> subscriptions_;

greenwave_monitor/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<depend>sensor_msgs</depend>
3737
<depend>greenwave_monitor_interfaces</depend>
3838
<depend>rclpy</depend>
39+
<depend>ament_index_cpp</depend>
3940
<depend>yaml_cpp_vendor</depend>
4041

4142
<exec_depend>launch</exec_depend>

greenwave_monitor/src/greenwave_monitor.cpp

Lines changed: 112 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <sys/stat.h>
2525
#include <yaml-cpp/yaml.h>
2626

27+
#include "ament_index_cpp/get_package_share_directory.hpp"
2728
#include "rosidl_typesupport_introspection_cpp/message_introspection.hpp"
2829

2930
using namespace std::chrono_literals;
@@ -49,23 +50,17 @@ GreenwaveMonitor::GreenwaveMonitor(const rclcpp::NodeOptions & options)
4950
auto topics = this->get_parameter("topics").as_string_array();
5051

5152
// Declare and get the type registry path parameter
52-
this->declare_parameter<std::string>("type_registry_path", "/workspace/colcon_ws/src/greenwave_monitor/greenwave_monitor/config/type_registry.yml");
53+
std::string default_type_registry_path = ament_index_cpp::get_package_share_directory("greenwave_monitor") + "/config/type_registry.yml";
54+
this->declare_parameter<std::string>("type_registry_path", default_type_registry_path);
5355
type_registry_path_ = this->get_parameter("type_registry_path").as_string();
5456

5557
// Check if the type registry path is valid
5658
if (!type_registry_path_.empty() && !is_valid_file(type_registry_path_)) {
57-
RCLCPP_ERROR(
58-
this->get_logger(), "Type registry path '%s' is not a valid file",
59-
type_registry_path_.c_str());
60-
type_registry_path_.clear();
61-
return;
62-
}
63-
64-
if(!read_type_registry(type_registry_path_)) {
6559
RCLCPP_WARN(
66-
this->get_logger(), "Failed to read type registry from path '%s'. "
67-
"Assuming no message types have a header. Consider providing a valid type registry.",
60+
this->get_logger(), "Type registry path '%s' is not a valid file."
61+
"Falling back to build-in type registry.",
6862
type_registry_path_.c_str());
63+
type_registry_path_.clear();
6964
}
7065

7166
message_diagnostics::MessageDiagnosticsConfig diagnostics_config;
@@ -123,45 +118,6 @@ void GreenwaveMonitor::topic_callback(
123118
message_diagnostics_[topic]->updateDiagnostics(msg_timestamp.time_since_epoch().count());
124119
}
125120

126-
// Read YAML type registry
127-
bool GreenwaveMonitor::read_type_registry(const std::string path) {
128-
try {
129-
YAML::Node config = YAML::LoadFile(path);
130-
if (config["has_header"]) {
131-
// Check if 'has_header' is a sequence (list)
132-
if (config["has_header"].IsSequence()) {
133-
for (const auto& type_node : config["has_header"]) {
134-
if (type_node.IsScalar()) {
135-
known_header_types_[type_node.as<std::string>()] = true;
136-
} else {
137-
RCLCPP_WARN(
138-
this->get_logger(),
139-
"Found a non-string value in the registry: %s. Skipping.",
140-
type_node.as<std::string>().c_str());
141-
}
142-
}
143-
} else {
144-
RCLCPP_ERROR(
145-
this->get_logger(),
146-
"'has_header' key is not a sequence in the YAML file.");
147-
return false;
148-
}
149-
} else {
150-
RCLCPP_ERROR(
151-
this->get_logger(),
152-
"'has_header' key is not found in the YAML file.");
153-
return false;
154-
}
155-
} catch (const YAML::BadFile& e) {
156-
RCLCPP_ERROR(this->get_logger(), "Error reading YAML file: %s", e.what());
157-
} catch (const YAML::ParserException& e) {
158-
RCLCPP_ERROR(this->get_logger(), "Error parsing YAML string: %s", e.what());
159-
} catch (const std::exception& e) {
160-
RCLCPP_ERROR(this->get_logger(), "An unexpected error occurred: %s", e.what());
161-
}
162-
return true;
163-
}
164-
165121
void GreenwaveMonitor::timer_callback()
166122
{
167123
RCLCPP_INFO(this->get_logger(), "====================================================");
@@ -254,22 +210,123 @@ bool GreenwaveMonitor::has_header_from_type(const std::string & type_name)
254210
return type_has_header_cache[type_name];
255211
}
256212

257-
auto it = known_header_types_.find(type_name);
258-
bool has_header = (it != known_header_types_.end()) ? it->second : false;
259-
260-
type_has_header_cache[type_name] = has_header;
213+
// rosidl typesupport API is unstable across ROS distributions, so we use this
214+
// map as a more robust way to determine if a message type has a header
215+
static const std::unordered_map<std::string, bool> known_header_types = {
216+
// sensor_msgs
217+
{"sensor_msgs/msg/Image", true},
218+
{"sensor_msgs/msg/CompressedImage", true},
219+
{"sensor_msgs/msg/CameraInfo", true},
220+
{"sensor_msgs/msg/PointCloud2", true},
221+
{"sensor_msgs/msg/LaserScan", true},
222+
{"sensor_msgs/msg/Imu", true},
223+
{"sensor_msgs/msg/NavSatFix", true},
224+
{"sensor_msgs/msg/MagneticField", true},
225+
{"sensor_msgs/msg/FluidPressure", true},
226+
{"sensor_msgs/msg/Illuminance", true},
227+
{"sensor_msgs/msg/RelativeHumidity", true},
228+
{"sensor_msgs/msg/Temperature", true},
229+
{"sensor_msgs/msg/Range", true},
230+
{"sensor_msgs/msg/PointCloud", true},
231+
232+
// geometry_msgs
233+
{"geometry_msgs/msg/PoseStamped", true},
234+
{"geometry_msgs/msg/TwistStamped", true},
235+
{"geometry_msgs/msg/AccelStamped", true},
236+
{"geometry_msgs/msg/Vector3Stamped", true},
237+
{"geometry_msgs/msg/PointStamped", true},
238+
{"geometry_msgs/msg/QuaternionStamped", true},
239+
{"geometry_msgs/msg/TransformStamped", true},
240+
{"geometry_msgs/msg/WrenchStamped", true},
241+
242+
// nav_msgs
243+
{"nav_msgs/msg/OccupancyGrid", true},
244+
{"nav_msgs/msg/GridCells", true},
245+
{"nav_msgs/msg/Path", true},
246+
{"nav_msgs/msg/Odometry", true},
247+
248+
// visualization_msgs
249+
{"visualization_msgs/msg/Marker", true},
250+
{"visualization_msgs/msg/MarkerArray", true},
251+
{"visualization_msgs/msg/InteractiveMarker", true},
252+
253+
// std_msgs (no headers)
254+
{"std_msgs/msg/String", false},
255+
{"std_msgs/msg/Int32", false},
256+
{"std_msgs/msg/Float64", false},
257+
{"std_msgs/msg/Bool", false},
258+
{"std_msgs/msg/Empty", false},
259+
{"std_msgs/msg/Header", false}, // Header itself doesn't have a header
260+
261+
// Common message types without headers
262+
{"geometry_msgs/msg/Twist", false},
263+
{"geometry_msgs/msg/Pose", false},
264+
{"geometry_msgs/msg/Point", false},
265+
{"geometry_msgs/msg/Vector3", false},
266+
{"geometry_msgs/msg/Quaternion", false}
267+
};
268+
269+
auto it = known_header_types.find(type_name);
270+
bool has_header = (it != known_header_types.end()) ? it->second : false;
271+
272+
// In case the type is not in the known list, attempt to read from type registry
273+
if (it == known_header_types.end() && !type_registry_path_.empty()) {
274+
has_header = has_header_from_type_registry(type_name);
275+
}
261276

262277
// Fallback of no header in case of unknown type, log for reference
263-
if (it == known_header_types_.end()) {
278+
if (it == known_header_types.end() && !has_header) {
264279
RCLCPP_WARN_ONCE(
265280
this->get_logger(),
266281
"Unknown message type '%s' - assuming no header. Consider adding to registry.",
267282
type_name.c_str());
268283
}
269284

285+
// Cache the result for future lookups
286+
type_has_header_cache[type_name] = has_header;
287+
270288
return has_header;
271289
}
272290

291+
bool GreenwaveMonitor::has_header_from_type_registry(const std::string & type_name) {
292+
try {
293+
YAML::Node config = YAML::LoadFile(type_registry_path_);
294+
if (config["has_header"]) {
295+
// Check if 'has_header' is a sequence (list)
296+
if (config["has_header"].IsSequence()) {
297+
for (const auto& type_node : config["has_header"]) {
298+
if (type_node.IsScalar()) {
299+
// Check if the type matches
300+
if (type_node.as<std::string>() == type_name) {
301+
return true;
302+
}
303+
} else {
304+
RCLCPP_WARN(
305+
this->get_logger(),
306+
"Found a non-string value in the registry: %s. Skipping.",
307+
type_node.as<std::string>().c_str());
308+
}
309+
}
310+
} else {
311+
RCLCPP_ERROR(
312+
this->get_logger(),
313+
"'has_header' key is not a sequence in the YAML file.");
314+
}
315+
} else {
316+
RCLCPP_ERROR(
317+
this->get_logger(),
318+
"'has_header' key is not found in the YAML file.");
319+
}
320+
} catch (const YAML::BadFile& e) {
321+
RCLCPP_ERROR(this->get_logger(), "Error reading YAML file: %s", e.what());
322+
} catch (const YAML::ParserException& e) {
323+
RCLCPP_ERROR(this->get_logger(), "Error parsing YAML string: %s", e.what());
324+
} catch (const std::exception& e) {
325+
RCLCPP_ERROR(this->get_logger(), "An unexpected error occurred: %s", e.what());
326+
}
327+
return false;
328+
}
329+
273330
bool GreenwaveMonitor::add_topic(const std::string & topic, std::string & message)
274331
{
275332
// Check if topic already exists

0 commit comments

Comments
 (0)