-
Notifications
You must be signed in to change notification settings - Fork 11
Type registry file #14
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
base: main
Are you sure you want to change the base?
Changes from all commits
1427288
a4fbaa7
2244b65
19bea93
9e46244
6c81d4b
ac8b0ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| has_header: | ||
| - stereo_msgs/msg/DisparityImage | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,8 @@ | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| #include "greenwave_monitor.hpp" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| #include <sys/stat.h> | ||||||||||||||||||||||
| #include <yaml-cpp/yaml.h> | ||||||||||||||||||||||
| #include <algorithm> | ||||||||||||||||||||||
| #include <cstring> | ||||||||||||||||||||||
| #include <mutex> | ||||||||||||||||||||||
|
|
@@ -26,6 +28,19 @@ | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| using namespace std::chrono_literals; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| namespace | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Check if a file exists and is a regular file | ||||||||||||||||||||||
| bool is_valid_file(const std::string & path) | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| struct stat st; | ||||||||||||||||||||||
| if (stat(path.c_str(), &st) != 0) {return false;} | ||||||||||||||||||||||
| return static_cast<bool>(st.st_mode & S_IFREG); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| } // anonymous namespace | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| GreenwaveMonitor::GreenwaveMonitor(const rclcpp::NodeOptions & options) | ||||||||||||||||||||||
| : Node("greenwave_monitor", options) | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
|
|
@@ -35,6 +50,19 @@ GreenwaveMonitor::GreenwaveMonitor(const rclcpp::NodeOptions & options) | |||||||||||||||||||||
| this->declare_parameter<std::vector<std::string>>("topics", {""}); | ||||||||||||||||||||||
| auto topics = this->get_parameter("topics").as_string_array(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Declare and get the type registry path parameter | ||||||||||||||||||||||
| this->declare_parameter<std::string>("type_registry_path", ""); | ||||||||||||||||||||||
| type_registry_path_ = this->get_parameter("type_registry_path").as_string(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Check if the type registry path is valid | ||||||||||||||||||||||
| if (!type_registry_path_.empty() && !is_valid_file(type_registry_path_)) { | ||||||||||||||||||||||
| RCLCPP_WARN( | ||||||||||||||||||||||
| this->get_logger(), "Type registry path '%s' is not a valid file." | ||||||||||||||||||||||
| "Falling back to build-in type registry.", | ||||||||||||||||||||||
| type_registry_path_.c_str()); | ||||||||||||||||||||||
| type_registry_path_.clear(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| message_diagnostics::MessageDiagnosticsConfig diagnostics_config; | ||||||||||||||||||||||
| diagnostics_config.enable_all_topic_diagnostics = true; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -241,19 +269,65 @@ bool GreenwaveMonitor::has_header_from_type(const std::string & type_name) | |||||||||||||||||||||
| auto it = known_header_types.find(type_name); | ||||||||||||||||||||||
| bool has_header = (it != known_header_types.end()) ? it->second : false; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| type_has_header_cache[type_name] = has_header; | ||||||||||||||||||||||
| // In case the type is not in the known list, attempt to read from type registry | ||||||||||||||||||||||
| if (it == known_header_types.end() && !type_registry_path_.empty()) { | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you feel about using type_registry to update known_header_types and leaving the logic the same?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I initially had implemented, but this has the advantage of being able to add types to the yaml file while it is running. For instance, in case I had an object detection pipeline runnging (v4l2 -> Encoder -> TensorRT -> Decoder) and notice that the detections are coming at 15 Hz while the camera publishes at 30 Hz. It would be practical to be able to add
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to keep this as simple as possible load the YAML file once during initialization and merge it directly into known_header_types. If the user needs to add new types just restart the node. |
||||||||||||||||||||||
| has_header = has_header_from_type_registry(type_name); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Fallback of no header in case of unknown type, log for reference | ||||||||||||||||||||||
| if (it == known_header_types.end()) { | ||||||||||||||||||||||
| if (it == known_header_types.end() && !has_header) { | ||||||||||||||||||||||
| RCLCPP_WARN_ONCE( | ||||||||||||||||||||||
| this->get_logger(), | ||||||||||||||||||||||
| "Unknown message type '%s' - assuming no header. Consider adding to registry.", | ||||||||||||||||||||||
| type_name.c_str()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Cache the result for future lookups | ||||||||||||||||||||||
| type_has_header_cache[type_name] = has_header; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return has_header; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| bool GreenwaveMonitor::has_header_from_type_registry(const std::string & type_name) | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| try { | ||||||||||||||||||||||
| YAML::Node config = YAML::LoadFile(type_registry_path_); | ||||||||||||||||||||||
| if (config["has_header"]) { | ||||||||||||||||||||||
| // Check if 'has_header' is a sequence (list) | ||||||||||||||||||||||
| if (config["has_header"].IsSequence()) { | ||||||||||||||||||||||
| for (const auto & type_node : config["has_header"]) { | ||||||||||||||||||||||
| if (type_node.IsScalar()) { | ||||||||||||||||||||||
| // Check if the type matches | ||||||||||||||||||||||
| if (type_node.as<std::string>() == type_name) { | ||||||||||||||||||||||
| return true; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| RCLCPP_WARN( | ||||||||||||||||||||||
| this->get_logger(), | ||||||||||||||||||||||
| "Found a non-string value in the registry: %s. Skipping.", | ||||||||||||||||||||||
| type_node.as<std::string>().c_str()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+305
to
+309
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Attempting to convert a non-scalar node to string at line 308 will throw an exception. Remove the
Suggested change
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| RCLCPP_ERROR( | ||||||||||||||||||||||
| this->get_logger(), | ||||||||||||||||||||||
| "'has_header' key is not a sequence in the YAML file."); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| RCLCPP_ERROR( | ||||||||||||||||||||||
| this->get_logger(), | ||||||||||||||||||||||
| "'has_header' key is not found in the YAML file."); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } catch (const YAML::BadFile & e) { | ||||||||||||||||||||||
| RCLCPP_ERROR(this->get_logger(), "Error reading YAML file: %s", e.what()); | ||||||||||||||||||||||
| } catch (const YAML::ParserException & e) { | ||||||||||||||||||||||
| RCLCPP_ERROR(this->get_logger(), "Error parsing YAML string: %s", e.what()); | ||||||||||||||||||||||
| } catch (const std::exception & e) { | ||||||||||||||||||||||
| RCLCPP_ERROR(this->get_logger(), "An unexpected error occurred: %s", e.what()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return false; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| bool GreenwaveMonitor::add_topic(const std::string & topic, std::string & message) | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| // Check if topic already exists | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good but actually I'd prefer to have DisparityImage in the default map. Do you want to add that to this PR? else I can do that as a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing! I only had this here as an example and for my local testing. How about PoseWithCovarianceStamped since you have PoseStamped already? In my experience at least, it is very common among both opensource and commerical SLAM systems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both sound great, please add any common types you use to the default known_header_types.