-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Path trackin conditon node #5602
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
a16f0ee
2425452
a303564
6b4e7f8
7a02bf6
3ea85d8
9e50b94
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,75 @@ | ||
| // Copyright (c) 2025 Berkan Tali | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #ifndef NAV2_BEHAVIOR_TREE__PLUGINS__CONDITION__IS_WITHIN_PATH_TRACKING_BOUNDS_CONDITION_HPP_ | ||
| #define NAV2_BEHAVIOR_TREE__PLUGINS__CONDITION__IS_WITHIN_PATH_TRACKING_BOUNDS_CONDITION_HPP_ | ||
|
|
||
| #include <string> | ||
| #include <memory> | ||
| #include <mutex> | ||
| #include <limits> | ||
|
|
||
| #include "behaviortree_cpp/condition_node.h" | ||
| #include "nav2_ros_common/lifecycle_node.hpp" | ||
| #include "nav2_msgs/msg/tracking_feedback.hpp" | ||
| #include "rclcpp/rclcpp.hpp" | ||
|
|
||
| namespace nav2_behavior_tree | ||
| { | ||
|
|
||
| /** | ||
| * @brief A BT::ConditionNode that subscribes to /tracking_feedback and returns SUCCESS | ||
| * if the error is within the max_error input port, FAILURE otherwise | ||
| */ | ||
| class IsWithinPathTrackingBoundsCondition : public BT::ConditionNode | ||
| { | ||
| public: | ||
| IsWithinPathTrackingBoundsCondition( | ||
| const std::string & condition_name, | ||
| const BT::NodeConfiguration & conf); | ||
|
|
||
| IsWithinPathTrackingBoundsCondition() = delete; | ||
| ~IsWithinPathTrackingBoundsCondition() override = default; | ||
|
|
||
| /** | ||
| * @brief Function to read parameters and initialize class variables | ||
| */ | ||
| void initialize(); | ||
|
|
||
| BT::NodeStatus tick() override; | ||
|
|
||
| static BT::PortsList providedPorts() | ||
| { | ||
| return { | ||
| BT::InputPort<double>("max_error_right", "Maximum allowed tracking error on the right side"), | ||
| BT::InputPort<double>("max_error_left", "Maximum allowed tracking error left side") | ||
| }; | ||
| } | ||
|
|
||
| private: | ||
| rclcpp::Logger logger_{rclcpp::get_logger("is_within_path_tracking_bounds_node")}; | ||
| rclcpp::CallbackGroup::SharedPtr callback_group_; | ||
| rclcpp::executors::SingleThreadedExecutor callback_group_executor_; | ||
| rclcpp::Subscription<nav2_msgs::msg::TrackingFeedback>::SharedPtr tracking_feedback_sub_; | ||
|
Member
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. Use |
||
| double last_error_{0.0}; | ||
| double max_error_right_{1.5}; | ||
| double max_error_left_{1.5}; | ||
| std::chrono::milliseconds bt_loop_duration_; | ||
|
|
||
| void trackingFeedbackCallback(const nav2_msgs::msg::TrackingFeedback::SharedPtr msg); | ||
|
Member
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. Move this before the variables; all methods before all variables please. Also needs doxygen documentation for the API |
||
| }; | ||
|
|
||
| } // namespace nav2_behavior_tree | ||
|
|
||
| #endif // NAV2_BEHAVIOR_TREE__PLUGINS__CONDITION__IS_WITHIN_PATH_TRACKING_BOUNDS_CONDITION_HPP_ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -367,6 +367,11 @@ | |
| <input_port name="battery_topic">Topic for battery info</input_port> | ||
| </Condition> | ||
|
|
||
| <Decorator ID="IsWithinPathTrackingBounds"> | ||
|
Member
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. For docs: this needs to be having its configuration guide page + add to Navigation Plugins table + migration guide with the larger feature description |
||
| <input_port name="max_error_left">Maximum distance robot can go out from path in meters. On left side</input_port> | ||
| <input_port name="max_error_right">Maximum distance robot can go out from path in meters. On right side</input_port> | ||
| </Decorator> | ||
|
|
||
| <Condition ID="DistanceTraveled"> | ||
| <input_port name="distance">Distance to check if passed</input_port> | ||
| <input_port name="global_frame">reference frame to check in</input_port> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| // Copyright (c) 2025 Berkan Tali | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #include "nav2_behavior_tree/plugins/condition/is_within_path_tracking_bounds_condition.hpp" | ||
|
|
||
| namespace nav2_behavior_tree | ||
| { | ||
|
|
||
| IsWithinPathTrackingBoundsCondition::IsWithinPathTrackingBoundsCondition( | ||
| const std::string & condition_name, | ||
| const BT::NodeConfiguration & conf) | ||
| : BT::ConditionNode(condition_name, conf), | ||
| last_error_(std::numeric_limits<double>::max()) | ||
| { | ||
| auto node = config().blackboard->get<nav2::LifecycleNode::SharedPtr>("node"); | ||
|
Member
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. Set |
||
| callback_group_ = node->create_callback_group( | ||
| rclcpp::CallbackGroupType::MutuallyExclusive, | ||
| false); | ||
| callback_group_executor_.add_callback_group(callback_group_, node->get_node_base_interface()); | ||
|
|
||
| tracking_feedback_sub_ = node->create_subscription<nav2_msgs::msg::TrackingFeedback>( | ||
| "tracking_feedback", | ||
| std::bind(&IsWithinPathTrackingBoundsCondition::trackingFeedbackCallback, this, | ||
| std::placeholders::_1), | ||
| rclcpp::SystemDefaultsQoS(), | ||
| callback_group_); | ||
|
|
||
| bt_loop_duration_ = | ||
| config().blackboard->template get<std::chrono::milliseconds>("bt_loop_duration"); | ||
|
|
||
| RCLCPP_INFO(logger_, "Initialized IsWithinPathTrackingBoundsCondition BT node"); | ||
| initialize(); | ||
| } | ||
|
|
||
| void IsWithinPathTrackingBoundsCondition::trackingFeedbackCallback( | ||
| const nav2_msgs::msg::TrackingFeedback::SharedPtr msg) | ||
| { | ||
| last_error_ = msg->tracking_error; | ||
| } | ||
|
|
||
| void IsWithinPathTrackingBoundsCondition::initialize() | ||
| { | ||
| getInput("max_error_left", max_error_left_); | ||
| getInput("max_error_right", max_error_right_); | ||
| } | ||
|
|
||
| BT::NodeStatus IsWithinPathTrackingBoundsCondition::tick() | ||
| { | ||
| if (!BT::isStatusActive(status())) { | ||
| initialize(); | ||
| } | ||
|
|
||
| callback_group_executor_.spin_all(bt_loop_duration_); | ||
|
|
||
| if (!getInput("max_error_left", max_error_left_)) { | ||
| RCLCPP_ERROR(logger_, "max_error_left parameter not provided"); | ||
| return BT::NodeStatus::FAILURE; | ||
| } | ||
|
|
||
| if (max_error_left_ < 0.0) { | ||
| RCLCPP_WARN(logger_, "max_error_left should be positive, using absolute value"); | ||
| max_error_left_ = std::abs(max_error_left_); | ||
| } | ||
|
|
||
SteveMacenski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (!getInput("max_error_right", max_error_right_)) { | ||
| RCLCPP_ERROR(logger_, "max_error_right parameter not provided"); | ||
| return BT::NodeStatus::FAILURE; | ||
| } | ||
|
|
||
| if (max_error_right_ < 0.0) { | ||
| RCLCPP_WARN(logger_, "max_error_right should be positive, using absolute value"); | ||
| max_error_right_ = std::abs(max_error_right_); | ||
| } | ||
|
|
||
| if (last_error_ == std::numeric_limits<double>::max()) { | ||
| RCLCPP_WARN(logger_, "No tracking feedback received yet."); | ||
| return BT::NodeStatus::FAILURE; | ||
| } | ||
|
|
||
| if (last_error_ > 0.0) { // Positive = left side | ||
| if (last_error_ > max_error_left_) { | ||
| return BT::NodeStatus::FAILURE; | ||
| } else { | ||
| return BT::NodeStatus::SUCCESS; | ||
| } | ||
| } else { // Negative = right side | ||
| if (std::abs(last_error_) > max_error_right_) { | ||
| return BT::NodeStatus::FAILURE; | ||
| } else { | ||
| return BT::NodeStatus::SUCCESS; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace nav2_behavior_tree | ||
|
|
||
| #include "behaviortree_cpp/bt_factory.h" | ||
| BT_REGISTER_NODES(factory) | ||
| { | ||
| factory.registerNodeType<nav2_behavior_tree::IsWithinPathTrackingBoundsCondition>( | ||
| "IsWithinPathTrackingBounds"); | ||
| } | ||
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.