feat: add eagleye_result_logger for CSV regression logging#367
feat: add eagleye_result_logger for CSV regression logging#367rsasaki0109 wants to merge 6 commits intomain-ros2from
Conversation
Add devcontainer for ROS2 Humble development
…attern Replace global static variables and free callback functions with encapsulated class-based rclcpp::Node pattern across all 21 nodes. Also fix CMakeLists.txt ROS_DISTRO comparison (quoted env var). - Each node is now a class inheriting rclcpp::Node - Subscribers, publishers, and timers are private member variables - Callbacks are private member functions - GenericTimer replaced with create_wall_timer() - Nodes with argc/argv routing (heading, rtk_heading, heading_interpolate, yaw_rate_offset) pass args through constructor
Global static variables are zero-initialized by C++ before program startup,
but class members with POD types (int, double, bool) are left uninitialized
when default-initialized. After the refactoring from global statics to class
members, all *Status structs had uninitialized fields, causing garbage values
in estimated outputs (e.g. yaw_rate_offset appearing as ~5.6e+79 rad/s).
Add = {} to each status struct member declaration to value-initialize them,
which zero-initializes all POD members and matches the original behavior.
…sion logging Saves /eagleye/fix (NavSatFix) and /eagleye/eagleye/pose (PoseStamped) to timestamped CSV files for before/after comparison. Usage: ros2 launch eagleye_result_logger result_logger.launch.xml output_dir:=/tmp/results
There was a problem hiding this comment.
Other comments (20)
- eagleye_rt/src/heading_node.cpp (31-31) Missing YAML include. The code uses YAML::LoadFile but doesn't include the yaml-cpp header.
- eagleye_rt/src/slip_angle_node.cpp (128-132) The code is missing a subscription to the `velocity_status` topic, but `velocity_status_` is used in the `imuCallback` method when `use_can_less_mode_` is true. This could lead to undefined behavior since `velocity_status_` would never be updated.
-
eagleye_rt/src/velocity_scale_factor_node.cpp (287-287)
The csv_file is created but there's no check if the file was successfully opened before writing to it. This could lead to silent failures when trying to save data.
std::ofstream csv_file(velocity_scale_factor_save_str_); if (!csv_file) { RCLCPP_ERROR(this->get_logger(), "Failed to open file for writing: %s", velocity_scale_factor_save_str_.c_str()); return; } - eagleye_rt/src/rolling_node.cpp (92-92) Consider initializing all member variables properly. While `rolling_status_` is initialized with empty braces, other message objects like `rolling_` are not explicitly initialized, which could lead to undefined behavior if any fields are accessed before being set.
- eagleye_rt/src/yaw_rate_offset_node.cpp (171-171) The `use_can_less_mode_` member variable is initialized to false but never set to true anywhere in the code. If this mode is supposed to be configurable, consider adding a parameter to set it.
- eagleye_rt/src/rtk_dead_reckoning_node.cpp (134-134) The `rtk_dead_reckoning_status_` is initialized with an empty initializer list `= {}`. Consider explicitly initializing all fields or using a constructor to ensure all status fields are properly initialized.
- eagleye_rt/src/rtk_dead_reckoning_node.cpp (177-179) Consider adding error logging in the catch block for TransformException to help with debugging. The original code had a commented RCLCPP_ERROR line that could be restored.
- eagleye_rt/src/yaw_rate_offset_stop_node.cpp (88-88) The `yaw_rate_offset_stop_status_` is initialized with empty braces, but it's not clear if all fields will be properly initialized this way. Consider explicitly initializing any fields that need specific initial values.
- eagleye_rt/src/heading_interpolate_node.cpp (131-131) The heading_interpolate_status_ member is initialized with empty braces, but this might not properly initialize all fields. Consider explicitly initializing it in the constructor instead to ensure all fields are properly set.
- eagleye_rt/src/heading_node.cpp (189-189) Consider initializing HeadingStatus with proper default values instead of empty braces, as some members might need specific initial values.
- eagleye_rt/src/yaw_rate_offset_stop_node.cpp (63-64) There's a mismatch between the log message and the variable name. The log message says 'estimated_minimum_interval' but the variable is named 'estimated_interval'.
- eagleye_rt/src/angular_velocity_offset_stop_node.cpp (82-83) The `angular_velocity_offset_stop_status_` struct is initialized with empty braces, but `angular_velocity_offset_stop_parameter_` is not initialized. Consider initializing it as well to avoid potential undefined behavior.
-
eagleye_rt/src/yaw_rate_offset_node.cpp (87-87)
The error message formatting in the YAML exception catch block is incorrect. The ANSI color code is incomplete - it's missing the color number after the semicolon.
std::cerr << "\033[1;31myaw_rate_offset_1st Node YAML Error: " << e.msg << "\033[0m" -
eagleye_rt/src/yaw_rate_offset_node.cpp (129-129)
The error message formatting in the second YAML exception catch block is also incorrect.
std::cerr << "\033[1;31myaw_rate_offset_2nd Node YAML Error: " << e.msg << "\033[0m" - eagleye_util/result_logger/eagleye_result_logger/result_logger_node.py (38-38) The `sys` module is imported but not used in the code. Consider removing this unused import.
- eagleye_util/result_logger/eagleye_result_logger/result_logger_node.py (31-33) The docstring mentions output files as `fix.csv` and `pose.csv`, but the actual implementation uses timestamped filenames like `fix_YYYYMMDD_HHMMSS.csv`. Please update the docstring to match the actual implementation.
- eagleye_rt/src/height_node.cpp (129-129) Consider explicitly initializing all fields in the HeightStatus struct rather than using empty braces initialization. This ensures all fields have defined values.
-
eagleye_rt/src/velocity_estimator_node.cpp (82-82)
For consistency with the other callback methods, consider using the same multi-line format for this method.
void ggaCallback(const nmea_msgs::msg::Gpgga::ConstSharedPtr msg) { gga_msg_ = *msg; } -
eagleye_rt/src/correction_imu.cpp (103-103)
The condition check for acc_x_scale_factor_.status.enabled_status is missing the explicit `== true` comparison that is used for acc_x_offset_.status.enabled_status. For consistency and to avoid potential issues with non-boolean values, consider adding the explicit comparison.
if (acc_x_offset_.status.enabled_status == true && acc_x_scale_factor_.status.enabled_status == true) - eagleye_rt/src/rtk_heading_node.cpp (167-167) Consider fully initializing the heading_status_ structure with appropriate default values rather than using an empty initializer list. This ensures all fields are properly initialized.
1 file skipped due to size limits:
- eagleye_rt/src/monitor_node.cpp
💡 To request another review, post a new comment with "/windsurf-review".
| if ( | ||
| !velocity_scale_factor_.status.enabled_status && | ||
| saved_vsf_estimater_number_ >= velocity_scale_factor_status_.estimated_number) { | ||
| std::ofstream csv_file(velocity_scale_factor_save_str_); |
There was a problem hiding this comment.
Similar to the issue below, there's no check if the file was successfully opened before proceeding.
| std::ofstream csv_file(velocity_scale_factor_save_str_); | |
| std::ofstream csv_file(velocity_scale_factor_save_str_); | |
| if (!csv_file) { | |
| RCLCPP_ERROR(this->get_logger(), "Failed to open file for writing: %s", velocity_scale_factor_save_str_.c_str()); | |
| } |
|
|
||
| private: | ||
| eagleye_msgs::msg::VelocityScaleFactor velocity_scale_factor_; | ||
| geometry_msgs::msg::TwistStamped velocity_; |
There was a problem hiding this comment.
The velocity_ member variable is declared but never assigned a value. There's no subscription or callback for the velocity topic that was present in the original code. This could lead to undefined behavior when velocity_ is used in the imuCallback method.
| private: | ||
| eagleye_msgs::msg::VelocityScaleFactor velocity_scale_factor_; | ||
| geometry_msgs::msg::TwistStamped velocity_; | ||
| eagleye_msgs::msg::StatusStamped velocity_status_; |
There was a problem hiding this comment.
The velocity_status_ member variable is declared but never assigned a value. There's no subscription or callback for the velocity status topic that was present in the original code. This could cause issues when velocity_status_ is used in the imuCallback method, particularly when use_can_less_mode_ is true.
Summary
/eagleye/fix(NavSatFix) と/eagleye/eagleye/pose(PoseStamped) をタイムスタンプ付き CSV に保存する新パッケージeagleye_result_loggerを追加出力ファイル
fix_YYYYMMDD_HHMMSS.csv/eagleye/fixpose_YYYYMMDD_HHMMSS.csv/eagleye/eagleye/pose使い方