Skip to content
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

Adapt GoalUpdater to update goals as well #4771

Merged
merged 71 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
4e878a2
Add IsStoppedBTNode
tonynajjar Nov 25, 2024
9139f9f
add topic name + reformat
tonynajjar Nov 25, 2024
c7ec42e
fix comment
tonynajjar Nov 25, 2024
5a8ea92
fix abs
tonynajjar Nov 25, 2024
9b5a93e
remove log
tonynajjar Nov 25, 2024
89c8d34
add getter functions for raw twist
tonynajjar Nov 26, 2024
c0098c4
remove unused code
tonynajjar Nov 26, 2024
18b8b76
use odomsmoother
tonynajjar Nov 26, 2024
5c0560a
fix formatting
tonynajjar Nov 26, 2024
66ed384
update groot
tonynajjar Nov 26, 2024
91230b2
Add test
tonynajjar Nov 27, 2024
d2c2db3
reset at success
tonynajjar Nov 27, 2024
c40896d
Merge branch 'add-is-stopped-BT-node'
tonynajjar Nov 27, 2024
11920d5
Merge branch 'ros-navigation:main' into main
tonynajjar Nov 28, 2024
e58ddfd
Merge branch 'main' into add-is-stopped-BT-node
tonynajjar Nov 28, 2024
37a5636
FIX velocity_threshold_
tonynajjar Nov 28, 2024
d237785
Fix stopped Node
tonynajjar Nov 28, 2024
5a4204f
Add tests to odometry_utils
tonynajjar Nov 28, 2024
0295ef9
fix linting
tonynajjar Nov 28, 2024
4c4da1a
Merge branch 'add-is-stopped-BT-node'
tonynajjar Nov 28, 2024
e4ef654
Merge branch 'ros-navigation:main' into main
tonynajjar Dec 3, 2024
58dc8bb
Merge branch 'ros-navigation:main' into main
tonynajjar Dec 4, 2024
fec198f
Adapt goalUpdater to modify goals as well
tonynajjar Nov 28, 2024
5a4f61f
fix formatting
tonynajjar Nov 28, 2024
13b47aa
fixes
tonynajjar Nov 28, 2024
0e9ebc4
change name of msg
tonynajjar Dec 3, 2024
db1b59d
Make input goals be Goals again for compatibility
tonynajjar Dec 5, 2024
4cd7ebf
fix
tonynajjar Dec 5, 2024
012a503
Revert "fix"
tonynajjar Dec 5, 2024
81fc608
refactoring
tonynajjar Dec 5, 2024
799045d
ament
tonynajjar Dec 5, 2024
c657a9f
ignore if no timestamps
tonynajjar Dec 9, 2024
f5bc15a
facepalm
tonynajjar Dec 9, 2024
9d2f2b1
update groot nodes
tonynajjar Dec 11, 2024
bdef481
Use PoseStampedArray
tonynajjar Dec 11, 2024
c0ba65d
Merge branch 'ros-navigation:main' into main
tonynajjar Dec 11, 2024
7c082e7
Merge remote-tracking branch 'origin/main' into use_posestampedarray
tonynajjar Dec 11, 2024
038f051
fix
tonynajjar Dec 11, 2024
622e6e1
fixes
tonynajjar Dec 11, 2024
27d0965
fix
tonynajjar Dec 11, 2024
15c1396
fix
tonynajjar Dec 11, 2024
0a5cc27
fix
tonynajjar Dec 11, 2024
cc16480
use geometry_msgs
tonynajjar Jan 7, 2025
fe0da93
fix import
tonynajjar Jan 7, 2025
1305c8e
use geometry_msgs
tonynajjar Jan 7, 2025
d96cd2d
more fixes
tonynajjar Jan 7, 2025
5d0b1e5
.
tonynajjar Jan 7, 2025
7a261b7
revert
tonynajjar Jan 7, 2025
36c21de
.
tonynajjar Jan 7, 2025
f1c4016
Merge branch 'ros-navigation:main' into main
tonynajjar Jan 7, 2025
80e0c17
Merge branch 'main' into use_posestampedarray
tonynajjar Jan 7, 2025
8c6c5c7
Merge branch 'main' into goals-updater-main
tonynajjar Jan 7, 2025
30aed4b
fix
tonynajjar Jan 7, 2025
9f4f804
add common_interfaces
tonynajjar Jan 7, 2025
4b891c1
fix
tonynajjar Jan 7, 2025
3247145
Merge branch 'use_posestampedarray' into goals-updater-main
tonynajjar Jan 7, 2025
bc1d94c
use PoseStampedArray
tonynajjar Jan 7, 2025
d5521f6
reformat
tonynajjar Jan 7, 2025
42bb546
Merge branch 'ros-navigation:main' into main
tonynajjar Jan 10, 2025
c168369
Merge remote-tracking branch 'origin/main' into goals-updater-main
tonynajjar Jan 10, 2025
ec8e188
revert
tonynajjar Jan 10, 2025
b2cc4db
revert
tonynajjar Jan 10, 2025
ed640cc
fix warn msg
tonynajjar Jan 10, 2025
48833bf
fix test
tonynajjar Jan 10, 2025
7db6be9
fix
tonynajjar Jan 10, 2025
c0f1e8b
fix
tonynajjar Jan 10, 2025
1d55e6c
fix
tonynajjar Jan 10, 2025
d6bc88c
fix
tonynajjar Jan 10, 2025
e5b80ba
improve
tonynajjar Jan 10, 2025
c8b6143
fix format
tonynajjar Jan 10, 2025
2bf8b1a
change to info
tonynajjar Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2018 Intel Corporation
// Copyright (c) 2020 Francisco Martin Rico
// Copyright (c) 2024 Angsa Robotics
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,6 +21,7 @@
#include <string>

#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/pose_stamped_array.hpp"

#include "behaviortree_cpp/decorator_node.h"

Expand Down Expand Up @@ -52,9 +54,11 @@ class GoalUpdater : public BT::DecoratorNode
{
return {
BT::InputPort<geometry_msgs::msg::PoseStamped>("input_goal", "Original Goal"),
BT::OutputPort<geometry_msgs::msg::PoseStamped>(
"output_goal",
"Received Goal by subscription"),
BT::InputPort<geometry_msgs::msg::PoseStampedArray>("input_goals", "Original Goals"),
BT::OutputPort<geometry_msgs::msg::PoseStamped>("output_goal",
"Received Goal by subscription"),
BT::OutputPort<geometry_msgs::msg::PoseStampedArray>("output_goals",
"Received Goals by subscription")
};
}

Expand All @@ -71,9 +75,19 @@ class GoalUpdater : public BT::DecoratorNode
*/
void callback_updated_goal(const geometry_msgs::msg::PoseStamped::SharedPtr msg);

/**
* @brief Callback function for goals update topic
* @param msg Shared pointer to geometry_msgs::msg::PoseStampedArray message
*/
void callback_updated_goals(const geometry_msgs::msg::PoseStampedArray::SharedPtr msg);

rclcpp::Subscription<geometry_msgs::msg::PoseStamped>::SharedPtr goal_sub_;
rclcpp::Subscription<geometry_msgs::msg::PoseStampedArray>::SharedPtr goals_sub_;

geometry_msgs::msg::PoseStamped last_goal_received_;
bool last_goal_received_set_{false};
geometry_msgs::msg::PoseStampedArray last_goals_received_;
bool last_goals_received_set_{false};

rclcpp::Node::SharedPtr node_;
rclcpp::CallbackGroup::SharedPtr callback_group_;
Expand Down
2 changes: 2 additions & 0 deletions nav2_behavior_tree/nav2_tree_nodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@

<Decorator ID="GoalUpdater">
<input_port name="input_goal">Original goal in</input_port>
<input_port name="input_goals">Original goals in</input_port>
<output_port name="output_goal">Output goal set by subscription</output_port>
<output_port name="output_goals">Output goals set by subscription</output_port>
</Decorator>

<Decorator ID="SpeedController">
Expand Down
70 changes: 60 additions & 10 deletions nav2_behavior_tree/plugins/decorator/goal_updater_node.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2018 Intel Corporation
// Copyright (c) 2020 Francisco Martin Rico
// Copyright (c) 2024 Angsa Robotics
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,7 +17,6 @@
#include <string>
#include <memory>

#include "geometry_msgs/msg/pose_stamped.hpp"
#include "behaviortree_cpp/decorator_node.h"

#include "nav2_behavior_tree/plugins/decorator/goal_updater_node.hpp"
Expand All @@ -40,7 +40,9 @@ GoalUpdater::GoalUpdater(
callback_group_executor_.add_callback_group(callback_group_, node_->get_node_base_interface());

std::string goal_updater_topic;
std::string goals_updater_topic;
node_->get_parameter_or<std::string>("goal_updater_topic", goal_updater_topic, "goal_update");
node_->get_parameter_or<std::string>("goals_updater_topic", goals_updater_topic, "goals_update");

rclcpp::SubscriptionOptions sub_option;
sub_option.callback_group = callback_group_;
Expand All @@ -49,39 +51,87 @@ GoalUpdater::GoalUpdater(
rclcpp::SystemDefaultsQoS(),
std::bind(&GoalUpdater::callback_updated_goal, this, _1),
sub_option);
goals_sub_ = node_->create_subscription<geometry_msgs::msg::PoseStampedArray>(
goals_updater_topic,
rclcpp::SystemDefaultsQoS(),
std::bind(&GoalUpdater::callback_updated_goals, this, _1),
sub_option);
}

inline BT::NodeStatus GoalUpdater::tick()
{
geometry_msgs::msg::PoseStamped goal;
geometry_msgs::msg::PoseStampedArray goals;

getInput("input_goal", goal);
getInput("input_goals", goals);

// Spin multiple times due to rclcpp regression in Jazzy requiring a 'warm up' spin
callback_group_executor_.spin_all(std::chrono::milliseconds(1));
callback_group_executor_.spin_all(std::chrono::milliseconds(49));

if (last_goal_received_.header.stamp != rclcpp::Time(0)) {
auto last_goal_received_time = rclcpp::Time(last_goal_received_.header.stamp);
auto goal_time = rclcpp::Time(goal.header.stamp);
if (last_goal_received_time > goal_time) {
goal = last_goal_received_;
if (last_goal_received_set_) {
SteveMacenski marked this conversation as resolved.
Show resolved Hide resolved
if (last_goal_received_.header.stamp == rclcpp::Time(0)) {
// if the goal doesn't have a timestamp, we reject it
RCLCPP_WARN(
node_->get_logger(), "The received goal has no timestamp. Ignoring.");
setOutput("output_goal", goal);
} else {
auto last_goal_received_time = rclcpp::Time(last_goal_received_.header.stamp);
auto goal_time = rclcpp::Time(goal.header.stamp);
if (last_goal_received_time >= goal_time) {
setOutput("output_goal", last_goal_received_);
} else {
RCLCPP_INFO(
node_->get_logger(), "The timestamp of the received goal (%f) is older than the "
"current goal (%f). Ignoring the received goal.",
last_goal_received_time.seconds(), goal_time.seconds());
setOutput("output_goal", goal);
}
}
} else {
setOutput("output_goal", goal);
}

if (last_goals_received_set_) {
if (last_goals_received_.poses.empty()) {
setOutput("output_goals", goals);
} else if (last_goals_received_.header.stamp == rclcpp::Time(0)) {
RCLCPP_WARN(
node_->get_logger(), "The timestamp of the received goal (%f) is older than the "
"current goal (%f). Ignoring the received goal.",
last_goal_received_time.seconds(), goal_time.seconds());
node_->get_logger(), "The received goals array has no timestamp. Ignoring.");
setOutput("output_goals", goals);
} else {
auto last_goals_received_time = rclcpp::Time(last_goals_received_.header.stamp);
auto goals_time = rclcpp::Time(goals.header.stamp);
if (last_goals_received_time >= goals_time) {
setOutput("output_goals", last_goals_received_);
} else {
RCLCPP_INFO(
node_->get_logger(), "The timestamp of the received goals (%f) is older than the "
"current goals (%f). Ignoring the received goals.",
last_goals_received_time.seconds(), goals_time.seconds());
setOutput("output_goals", goals);
}
}
} else {
setOutput("output_goals", goals);
}

setOutput("output_goal", goal);
return child_node_->executeTick();
}

void
GoalUpdater::callback_updated_goal(const geometry_msgs::msg::PoseStamped::SharedPtr msg)
{
last_goal_received_ = *msg;
last_goal_received_set_ = true;
}

void
GoalUpdater::callback_updated_goals(const geometry_msgs::msg::PoseStampedArray::SharedPtr msg)
{
last_goals_received_ = *msg;
last_goals_received_set_ = true;
}

} // namespace nav2_behavior_tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,29 @@ TEST_F(GoalUpdaterTestFixture, test_tick)
R"(
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<GoalUpdater input_goal="{goal}" output_goal="{updated_goal}">
<GoalUpdater input_goal="{goal}" input_goals="{goals}" output_goal="{updated_goal}" output_goals="{updated_goals}">
<AlwaysSuccess/>
</GoalUpdater>
</BehaviorTree>
</root>)";

tree_ = std::make_shared<BT::Tree>(factory_->createTreeFromText(xml_txt, config_->blackboard));
auto goal_updater_pub =
node_->create_publisher<geometry_msgs::msg::PoseStamped>("goal_update", 10);

// create new goal and set it on blackboard
geometry_msgs::msg::PoseStamped goal;
geometry_msgs::msg::PoseStampedArray goals;
goal.header.stamp = node_->now();
goal.pose.position.x = 1.0;
goals.poses.push_back(goal);
config_->blackboard->set("goal", goal);
config_->blackboard->set("goals", goals);

// tick tree without publishing updated goal and get updated_goal
tree_->rootNode()->executeTick();
geometry_msgs::msg::PoseStamped updated_goal;
geometry_msgs::msg::PoseStampedArray updated_goals;
EXPECT_TRUE(config_->blackboard->get("updated_goal", updated_goal));
EXPECT_TRUE(config_->blackboard->get("updated_goals", updated_goals));
}

TEST_F(GoalUpdaterTestFixture, test_older_goal_update)
Expand All @@ -117,7 +120,7 @@ TEST_F(GoalUpdaterTestFixture, test_older_goal_update)
R"(
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<GoalUpdater input_goal="{goal}" output_goal="{updated_goal}">
<GoalUpdater input_goal="{goal}" input_goals="{goals}" output_goal="{updated_goal}" output_goals="{updated_goals}">
<AlwaysSuccess/>
</GoalUpdater>
</BehaviorTree>
Expand All @@ -126,26 +129,39 @@ TEST_F(GoalUpdaterTestFixture, test_older_goal_update)
tree_ = std::make_shared<BT::Tree>(factory_->createTreeFromText(xml_txt, config_->blackboard));
auto goal_updater_pub =
node_->create_publisher<geometry_msgs::msg::PoseStamped>("goal_update", 10);
auto goals_updater_pub =
node_->create_publisher<geometry_msgs::msg::PoseStampedArray>("goals_update", 10);

// create new goal and set it on blackboard
geometry_msgs::msg::PoseStamped goal;
geometry_msgs::msg::PoseStampedArray goals;
goal.header.stamp = node_->now();
goal.pose.position.x = 1.0;
goals.header.stamp = goal.header.stamp;
goals.poses.push_back(goal);
config_->blackboard->set("goal", goal);
config_->blackboard->set("goals", goals);

// publish updated_goal older than goal
geometry_msgs::msg::PoseStamped goal_to_update;
geometry_msgs::msg::PoseStampedArray goals_to_update;
goal_to_update.header.stamp = rclcpp::Time(goal.header.stamp) - rclcpp::Duration(1, 0);
goal_to_update.pose.position.x = 2.0;
goals_to_update.header.stamp = goal_to_update.header.stamp;
goals_to_update.poses.push_back(goal_to_update);

goal_updater_pub->publish(goal_to_update);
goals_updater_pub->publish(goals_to_update);
tree_->rootNode()->executeTick();
geometry_msgs::msg::PoseStamped updated_goal;
geometry_msgs::msg::PoseStampedArray updated_goals;
EXPECT_TRUE(config_->blackboard->get("updated_goal", updated_goal));
EXPECT_TRUE(config_->blackboard->get("updated_goals", updated_goals));

// expect to succeed and not update goal
EXPECT_EQ(tree_->rootNode()->status(), BT::NodeStatus::SUCCESS);
EXPECT_EQ(updated_goal, goal);
EXPECT_EQ(updated_goals, goals);
}

TEST_F(GoalUpdaterTestFixture, test_get_latest_goal_update)
Expand All @@ -155,7 +171,7 @@ TEST_F(GoalUpdaterTestFixture, test_get_latest_goal_update)
R"(
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<GoalUpdater input_goal="{goal}" output_goal="{updated_goal}">
<GoalUpdater input_goal="{goal}" input_goals="{goals}" output_goal="{updated_goal}" output_goals="{updated_goals}">
<AlwaysSuccess/>
</GoalUpdater>
</BehaviorTree>
Expand All @@ -164,32 +180,48 @@ TEST_F(GoalUpdaterTestFixture, test_get_latest_goal_update)
tree_ = std::make_shared<BT::Tree>(factory_->createTreeFromText(xml_txt, config_->blackboard));
auto goal_updater_pub =
node_->create_publisher<geometry_msgs::msg::PoseStamped>("goal_update", 10);
auto goals_updater_pub =
node_->create_publisher<geometry_msgs::msg::PoseStampedArray>("goals_update", 10);

// create new goal and set it on blackboard
geometry_msgs::msg::PoseStamped goal;
geometry_msgs::msg::PoseStampedArray goals;
goal.header.stamp = node_->now();
goal.pose.position.x = 1.0;
goals.poses.push_back(goal);
config_->blackboard->set("goal", goal);
config_->blackboard->set("goals", goals);

// publish updated_goal older than goal
geometry_msgs::msg::PoseStamped goal_to_update_1;
geometry_msgs::msg::PoseStampedArray goals_to_update_1;
goal_to_update_1.header.stamp = node_->now();
goal_to_update_1.pose.position.x = 2.0;
goals_to_update_1.header.stamp = goal_to_update_1.header.stamp;
goals_to_update_1.poses.push_back(goal_to_update_1);

geometry_msgs::msg::PoseStamped goal_to_update_2;
geometry_msgs::msg::PoseStampedArray goals_to_update_2;
goal_to_update_2.header.stamp = node_->now();
goal_to_update_2.pose.position.x = 3.0;
goals_to_update_2.header.stamp = goal_to_update_2.header.stamp;
goals_to_update_2.poses.push_back(goal_to_update_2);

goal_updater_pub->publish(goal_to_update_1);
goals_updater_pub->publish(goals_to_update_1);
goal_updater_pub->publish(goal_to_update_2);
goals_updater_pub->publish(goals_to_update_2);
tree_->rootNode()->executeTick();
geometry_msgs::msg::PoseStamped updated_goal;
geometry_msgs::msg::PoseStampedArray updated_goals;
EXPECT_TRUE(config_->blackboard->get("updated_goal", updated_goal));
EXPECT_TRUE(config_->blackboard->get("updated_goals", updated_goals));

// expect to succeed
EXPECT_EQ(tree_->rootNode()->status(), BT::NodeStatus::SUCCESS);
// expect to update goal with latest goal update
EXPECT_EQ(updated_goal, goal_to_update_2);
EXPECT_EQ(updated_goals, goals_to_update_2);
}

int main(int argc, char ** argv)
Expand Down
Loading