-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat(opennav_docking): add on-demand detector client & unit tests for dock plugins (#5015) #5218
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?
feat(opennav_docking): add on-demand detector client & unit tests for dock plugins (#5015) #5218
Conversation
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
f580de2
to
feb37e8
Compare
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.
Good first stab! I have some questions and suggestions, but largely its a good starting point for a couple of hopefully quick iterations. The changes requested in this plugin are the same in both, but I only reviewed the one just to avoid duplicating every comment. Take each comment for both plugin files
nav2_docking/opennav_docking/include/opennav_docking/simple_charging_dock.hpp
Outdated
Show resolved
Hide resolved
nav2_docking/opennav_docking/include/opennav_docking/simple_non_charging_dock.hpp
Outdated
Show resolved
Hide resolved
@@ -133,11 +154,6 @@ void SimpleChargingDock::configure( | |||
|
|||
if (use_external_detection_pose_) { | |||
dock_pose_.header.stamp = rclcpp::Time(0); | |||
dock_pose_sub_ = node_->create_subscription<geometry_msgs::msg::PoseStamped>( |
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.
If !subscribe_toggle_
, I think we should create this, no?
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.
I think the code should move back up here. You also don't need to check !detected_pose_sub_
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.
@bkoensgen this was not completed :-)
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
95ed998
to
dcb62d4
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
@bkoensgen re-request a review from me in the github UX when you're ready for me to take a look again (and CI is building 😉 ) |
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
3 similar comments
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
b6ee1e3
to
e000987
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
1 similar comment
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
118fe82
to
804520a
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
694feb0
to
7153b31
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
49cd52b
to
76b096b
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
8b7d652
to
b3f4910
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
1 similar comment
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
cbf5362
to
e21641e
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
43d42bc
to
4e7de42
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
ccd84ce
to
4b0b1da
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
9750cac
to
5bd06d3
Compare
@bkoensgen, your PR has failed to build. Please check CI outputs and resolve issues. |
dc2325d
to
7c5c042
Compare
Thanks for the detailed review and guidance! I've pushed up the changes addressing your feedback. The biggest change is that I've moved the detector lifecycle management ( Here’s a quick rundown of the other changes:
Should be in good shape for another look now. Let me know what you think! |
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.
Really good job on the tests, thanks for that! Beyond these changes which are mostly superficial, we need to also have the migration guide and configuration guide for docking server updated for these new parameters and capabilities. Please open a PR to include these & I think this is largely ready to go! :-)
All comments I made in the simple charging dock also apply to the implementation of the non-charging plugin too
detected_pose_sub_ = node_->create_subscription<geometry_msgs::msg::PoseStamped>( | ||
"detected_dock_pose", rclcpp::SensorDataQoS(), | ||
[this](const geometry_msgs::msg::PoseStamped::SharedPtr pose) { | ||
detected_dock_pose_ = *pose; |
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.
Should uses of detected_dock_pose_
make sure that detector_state_
is on? Throw otherwise
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 was not completed either
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.
good point. I checked getRefinedPose and it already has a guard clause at the top (if (!detector_enabled_)
) that prevents detected_dock_pose_
from being used improperly.
Returning false there seems like the right behavior for the control loop, so I think we're all set on this one.
"detected_dock_pose", rclcpp::SensorDataQoS(), | ||
[this](const geometry_msgs::msg::PoseStamped::SharedPtr pose) { | ||
detected_dock_pose_ = *pose; | ||
detector_state_ = DetectorState::ON; |
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.
Remove. This is always set anyway on L384 below when we exist the function. It has no impact in the callback (ditto for the subscriber above).
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 was not completed either
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.
You're right, I did remove this initially based on your feedback! But it turned out to cause a subtle race condition that made the tests fail.
What happened was that startDetection(
) would set the detector to "enabled" immediately, but getRefinedPose()
would then be called before the first message from the topic actually arrived. This caused the timestamp check to fail.
The only way I found to make it robustly pass the tests was to put the state update back here, inside the callback. This guarantees the plugin only considers itself 'active' once it has actually received data.
It's a bit counter-intuitive, but it seems necessary to handle that timing issue. Let me know if you have other ideas on how to tackle this!
This change introduces an API to dynamically enable and disable external docking detectors, such as those based on AI, to conserve system resources when not actively docking. Key changes: - Added `startDetectionProcess()` and `stopDetectionProcess()` to the docking plugin interface (`ChargingDock` and `NonChargingDock`). - Implemented this logic in `SimpleChargingDock` and `SimpleNonChargingDock` using a `std_srvs/Trigger` service call and dynamic topic subscription to manage the detector's lifecycle. - The `DockingServer` now ensures `stopDetectionProcess()` is called on all exit paths, including success, failure, and cancellation, to prevent dangling resources. - Added new parameters (`detector_service_name`, `subscribe_toggle`, etc.) to configure this behavior and updated the README documentation. - Added comprehensive C++ unit tests to verify the new detector lifecycle logic, specifically covering service failure cases and proper cleanup on action termination. Closes ros-navigation#5015 Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com> - updtae Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com>
896fa48
to
d88d2df
Compare
15caec9
to
2e6dc99
Compare
Mark this as ready to review again once you'd like me to take a look! |
// Detector control parameters | ||
std::string detector_service_name_; | ||
double detector_service_timeout_{5.0}; | ||
bool subscribe_toggle_{true}; |
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.
bool subscribe_toggle_{true}; | |
bool subscribe_toggle_{false}; |
// Detector control parameters | ||
std::string detector_service_name_; | ||
double detector_service_timeout_{5.0}; | ||
bool subscribe_toggle_{true}; |
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.
bool subscribe_toggle_{true}; | |
bool subscribe_toggle_{false}; |
@@ -133,11 +154,6 @@ void SimpleChargingDock::configure( | |||
|
|||
if (use_external_detection_pose_) { | |||
dock_pose_.header.stamp = rclcpp::Time(0); | |||
dock_pose_sub_ = node_->create_subscription<geometry_msgs::msg::PoseStamped>( |
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.
@bkoensgen this was not completed :-)
/** | ||
* @brief Start external detection process (service call + subscribe). | ||
*/ | ||
void startDetectionProcess() override {startDetection();} |
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.
@bkoensgen this was not completed :-)
rclcpp::Subscription<geometry_msgs::msg::PoseStamped>::SharedPtr detected_pose_sub_; | ||
|
||
// Simple finite-state machine for detector status | ||
enum class DetectorState { OFF, ON }; |
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.
@bkoensgen this was not completed :-)
@@ -133,11 +155,6 @@ void SimpleChargingDock::configure( | |||
|
|||
if (use_external_detection_pose_) { |
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 was not completed either
|
||
void SimpleChargingDock::deactivate() | ||
{ | ||
RCLCPP_DEBUG(node_->get_logger(), "SimpleChargingDock deactivated"); |
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 was not completed either
|
||
void SimpleChargingDock::activate() | ||
{ | ||
RCLCPP_DEBUG(node_->get_logger(), "SimpleChargingDock activated"); |
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 was not completed either
detected_pose_sub_ = node_->create_subscription<geometry_msgs::msg::PoseStamped>( | ||
"detected_dock_pose", rclcpp::SensorDataQoS(), | ||
[this](const geometry_msgs::msg::PoseStamped::SharedPtr pose) { | ||
detected_dock_pose_ = *pose; |
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 was not completed either
"detected_dock_pose", rclcpp::SensorDataQoS(), | ||
[this](const geometry_msgs::msg::PoseStamped::SharedPtr pose) { | ||
detected_dock_pose_ = *pose; | ||
detector_state_ = DetectorState::ON; |
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 was not completed either
@bkoensgen the majority of my review comments were not completed, please see above |
Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com> fix(docking): Change subscribe_toggle default to false Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com> -
2e6dc99
to
2f12cf1
Compare
This commit addresses several code review suggestions to improve the design and robustness of the docking plugins. - Replaced the `DetectorState` enum with a simpler `bool detector_enabled_` for clarity. - Encapsulated the detection process lifecycle within the plugin itself. The `deactivate` method now ensures `stopDetectionProcess` is called, improving encapsulation and simplifying the `DockDatabase`. - Refactored the `configure` method in plugins to group related logic, improving readability. - Cleaned up redundant checks and calls in both the plugins and the `DockingServer` for more robust and intentional code. Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com>
74b8455
to
fc7ae9f
Compare
…back The previous refactoring introduced a race condition where the detector was marked as 'enabled' in startDetection() before a message was actually received. This caused tests to fail because getRefinedPose() would be called with an enabled state but no valid/recent data. This commit fixes the issue by moving the `detector_enabled_ = true` assignment into the subscription callback. This ensures the plugin's state accurately reflects that it has received at least one valid data point before being considered active. Signed-off-by: Koensgen Benjamin <b.koensgen@gmail.com>
3fb99d3
to
96bdb23
Compare
Basic Info
colcon test
)Description of contribution in a few bullet points
detector_service_name
,detector_service_timeout
,subscribe_toggle
std_srvs/Trigger
only when first neededDescription of documentation updates required
nav2_docking/README.md
Description of how this change was tested
colcon test --packages-select opennav_docking
→ all tests passFor Maintainers