17
17
18
18
#include " utils/test_behavior_tree_fixture.hpp"
19
19
#include " utils/test_dummy_tree_node.hpp"
20
+ #include " utils/get_node_from_tree.hpp"
20
21
#include " nav2_behavior_tree/plugins/control/pause_resume_controller.hpp"
21
22
#include " std_srvs/srv/trigger.hpp"
22
23
23
24
class PauseResumeControllerTestFixture : public nav2_behavior_tree ::BehaviorTreeTestFixture
24
25
{
25
26
public:
26
- void SetUp () override
27
+ static void SetUpTestCase ()
27
28
{
28
29
node_ = std::make_shared<rclcpp::Node>(" pause_resume_controller_test_fixture" );
29
30
executor_ =
@@ -36,49 +37,36 @@ class PauseResumeControllerTestFixture : public nav2_behavior_tree::BehaviorTree
36
37
resume_client_ = node_->create_client <std_srvs::srv::Trigger>(
37
38
" resume" , rclcpp::ServicesQoS (), cb_group_);
38
39
39
- config_-> input_ports [ " pause_service_name " ] = " pause " ;
40
- config_-> input_ports [ " resume_service_name " ] = " resume " ;
40
+ factory_ = std::make_shared<BT::BehaviorTreeFactory>() ;
41
+ config_ = new BT::NodeConfiguration () ;
41
42
config_->blackboard = BT::Blackboard::create ();
42
43
config_->blackboard ->set <rclcpp::Node::SharedPtr>(" node" , node_);
43
44
44
- bt_node_ = std::make_shared<nav2_behavior_tree::PauseResumeController>(
45
- " pause_resume_controller" , *config_);
46
- resumed_child_ = std::make_shared<nav2_behavior_tree::DummyNode>();
47
- paused_child_ = std::make_shared<nav2_behavior_tree::DummyNode>();
48
- on_pause_child_ = std::make_shared<nav2_behavior_tree::DummyNode>();
49
- on_resume_child_ = std::make_shared<nav2_behavior_tree::DummyNode>();
50
- resumed_child_->changeStatus (BT::NodeStatus::SUCCESS);
51
- paused_child_->changeStatus (BT::NodeStatus::SUCCESS);
52
- on_pause_child_->changeStatus (BT::NodeStatus::SUCCESS);
53
- on_resume_child_->changeStatus (BT::NodeStatus::SUCCESS);
54
- bt_node_->addChild (resumed_child_.get ());
55
- bt_node_->addChild (paused_child_.get ());
56
- bt_node_->addChild (on_pause_child_.get ());
57
- bt_node_->addChild (on_resume_child_.get ());
45
+ factory_->registerNodeType <nav2_behavior_tree::PauseResumeController>(" PauseResumeController" );
46
+
47
+ // Register dummy node for testing
48
+ factory_->registerNodeType <nav2_behavior_tree::DummyNode>(" DummyNode" );
49
+ }
50
+
51
+ static void TearDownTestCase ()
52
+ {
53
+ if (config_) {
54
+ delete config_;
55
+ config_ = nullptr ;
56
+ }
57
+ tree_.reset ();
58
58
}
59
59
60
60
protected:
61
- static std::shared_ptr<nav2_behavior_tree::PauseResumeController> bt_node_;
62
- static std::shared_ptr<nav2_behavior_tree::DummyNode> paused_child_;
63
- static std::shared_ptr<nav2_behavior_tree::DummyNode> resumed_child_;
64
- static std::shared_ptr<nav2_behavior_tree::DummyNode> on_pause_child_;
65
- static std::shared_ptr<nav2_behavior_tree::DummyNode> on_resume_child_;
61
+ static BT::NodeConfiguration * config_;
62
+ static std::shared_ptr<BT::BehaviorTreeFactory> factory_;
63
+ static std::shared_ptr<BT::Tree> tree_;
66
64
static rclcpp::executors::SingleThreadedExecutor::SharedPtr executor_;
67
65
static rclcpp::CallbackGroup::SharedPtr cb_group_;
68
66
static rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr pause_client_;
69
67
static rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr resume_client_;
70
68
};
71
69
72
- std::shared_ptr<nav2_behavior_tree::PauseResumeController>
73
- PauseResumeControllerTestFixture::bt_node_ = nullptr ;
74
- std::shared_ptr<nav2_behavior_tree::DummyNode>
75
- PauseResumeControllerTestFixture::paused_child_ = nullptr ;
76
- std::shared_ptr<nav2_behavior_tree::DummyNode>
77
- PauseResumeControllerTestFixture::resumed_child_ = nullptr ;
78
- std::shared_ptr<nav2_behavior_tree::DummyNode>
79
- PauseResumeControllerTestFixture::on_pause_child_ = nullptr ;
80
- std::shared_ptr<nav2_behavior_tree::DummyNode>
81
- PauseResumeControllerTestFixture::on_resume_child_ = nullptr ;
82
70
rclcpp::executors::SingleThreadedExecutor::SharedPtr
83
71
PauseResumeControllerTestFixture::executor_ = nullptr ;
84
72
rclcpp::CallbackGroup::SharedPtr
@@ -87,51 +75,104 @@ rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr
87
75
PauseResumeControllerTestFixture::pause_client_ = nullptr ;
88
76
rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr
89
77
PauseResumeControllerTestFixture::resume_client_ = nullptr ;
78
+ BT::NodeConfiguration * PauseResumeControllerTestFixture::config_ = nullptr ;
79
+ std::shared_ptr<BT::BehaviorTreeFactory> PauseResumeControllerTestFixture::factory_ = nullptr ;
80
+ std::shared_ptr<BT::Tree> PauseResumeControllerTestFixture::tree_ = nullptr ;
90
81
91
82
TEST_F (PauseResumeControllerTestFixture, test_behavior)
92
83
{
93
- resumed_child_->changeStatus (BT::NodeStatus::SUCCESS);
94
- paused_child_->changeStatus (BT::NodeStatus::SUCCESS);
95
- on_pause_child_->changeStatus (BT::NodeStatus::SUCCESS);
96
- on_resume_child_->changeStatus (BT::NodeStatus::SUCCESS);
97
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::SUCCESS);
98
-
99
- // Set on_pause to RUNNING, call pause service, expect RUNNING
100
- on_pause_child_->changeStatus (BT::NodeStatus::RUNNING);
101
- auto res = pause_client_->async_send_request (
84
+ // create tree
85
+ std::string xml_txt =
86
+ R"(
87
+ <root BTCPP_format="4">
88
+ <BehaviorTree ID="MainTree">
89
+ <PauseResumeController
90
+ pause_service_name="pause"
91
+ resume_service_name="resume">
92
+ <DummyNode/> <!-- RESUMED -->
93
+ <DummyNode/> <!-- PAUSED -->
94
+ <DummyNode/> <!-- ON_PAUSE -->
95
+ <DummyNode/> <!-- ON_RESUME -->
96
+ </PauseResumeController>
97
+ </BehaviorTree>
98
+ </root>)" ;
99
+ tree_ = std::make_shared<BT::Tree>(factory_->createTreeFromText (xml_txt, config_->blackboard ));
100
+
101
+ // get pause_resume_controller so we can check state
102
+ auto pause_bt_node =
103
+ nav2_behavior_tree::get_node_from_tree<nav2_behavior_tree::PauseResumeController>(tree_);
104
+ ASSERT_NE (pause_bt_node, nullptr );
105
+ using state_t = nav2_behavior_tree::state_t ;
106
+
107
+ // get dummy nodes so we can change their status
108
+ auto resumed_child =
109
+ nav2_behavior_tree::get_node_from_tree<nav2_behavior_tree::DummyNode>(tree_, 0 );
110
+ auto paused_child =
111
+ nav2_behavior_tree::get_node_from_tree<nav2_behavior_tree::DummyNode>(tree_, 1 );
112
+ auto on_pause_child =
113
+ nav2_behavior_tree::get_node_from_tree<nav2_behavior_tree::DummyNode>(tree_, 2 );
114
+ auto on_resume_child =
115
+ nav2_behavior_tree::get_node_from_tree<nav2_behavior_tree::DummyNode>(tree_, 3 );
116
+ ASSERT_NE (resumed_child, nullptr );
117
+ ASSERT_NE (paused_child, nullptr );
118
+ ASSERT_NE (on_pause_child, nullptr );
119
+ ASSERT_NE (on_resume_child, nullptr );
120
+
121
+ resumed_child->changeStatus (BT::NodeStatus::RUNNING);
122
+ paused_child->changeStatus (BT::NodeStatus::RUNNING);
123
+ on_pause_child->changeStatus (BT::NodeStatus::RUNNING);
124
+ on_resume_child->changeStatus (BT::NodeStatus::RUNNING);
125
+
126
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
127
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::RESUMED);
128
+
129
+ const auto & check_request_succeeded = [](
130
+ rclcpp::Client<std_srvs::srv::Trigger>::FutureAndRequestId & future)
131
+ {
132
+ executor_->spin_until_future_complete (future, std::chrono::seconds (1 ));
133
+ ASSERT_EQ (future.wait_for (std::chrono::seconds (0 )), std::future_status::ready);
134
+ EXPECT_EQ (future.get ()->success , true );
135
+ };
136
+
137
+ // Call pause service, set ON_PAUSE child to RUNNING, expect RUNNING and ON_PAUSE
138
+ auto future = pause_client_->async_send_request (
102
139
std::make_shared<std_srvs::srv::Trigger::Request>());
103
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::RUNNING);
104
- executor_->spin_until_future_complete (res, std::chrono::seconds (1 ));
105
- ASSERT_EQ (res.wait_for (std::chrono::seconds (1 )), std::future_status::ready);
106
- EXPECT_EQ (res.get ()->success , true );
107
-
108
- // Change on_pause to SUCCESS, paused child to FAILURE
109
- // Expect SUCCESS (from on_pause), then FAILURE (from paused child)
110
- on_pause_child_->changeStatus (BT::NodeStatus::SUCCESS);
111
- paused_child_->changeStatus (BT::NodeStatus::FAILURE);
112
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::SUCCESS);
113
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::FAILURE);
114
-
115
- // Set paused to SUCCESS, tick again, expect SUCCESS
116
- paused_child_->changeStatus (BT::NodeStatus::SUCCESS);
117
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::SUCCESS);
118
-
119
- // Set on_resume to SKIPPED, call resume service, expect SUCCESS (treated same as SKIPPED)
120
- on_resume_child_->changeStatus (BT::NodeStatus::SKIPPED);
121
- res = resume_client_->async_send_request (
140
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
141
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::ON_PAUSE);
142
+ check_request_succeeded (future);
143
+
144
+ // Change ON_PAUSE child to SUCCESS, expect RUNNING and PAUSED
145
+ on_pause_child->changeStatus (BT::NodeStatus::SUCCESS);
146
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
147
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::PAUSED);
148
+
149
+ // Set PAUSED child to SUCCESS, expect RUNNING and PAUSED
150
+ // (should keep ticking unless RESUMED branch succeeds)
151
+ paused_child->changeStatus (BT::NodeStatus::SUCCESS);
152
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
153
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::PAUSED);
154
+
155
+ // Set PAUSED child to SKIPPED, expect RUNNING and PAUSED
156
+ paused_child->changeStatus (BT::NodeStatus::SKIPPED);
157
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
158
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::PAUSED);
159
+
160
+ // Call resume service, change ON_RESUME child to FAILURE, expect FAILURE
161
+ future = resume_client_->async_send_request (
122
162
std::make_shared<std_srvs::srv::Trigger::Request>());
123
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::SUCCESS);
124
- executor_->spin_until_future_complete (res, std::chrono::seconds (1 ));
125
- ASSERT_EQ (res.wait_for (std::chrono::seconds (1 )), std::future_status::ready);
126
- EXPECT_EQ (res.get ()->success , true );
127
-
128
- // Set resumed to RUNNING, expect RUNNING
129
- resumed_child_->changeStatus (BT::NodeStatus::RUNNING);
130
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::RUNNING);
131
-
132
- // Change resumed to SUCCESS, expect SUCCESS
133
- resumed_child_->changeStatus (BT::NodeStatus::SUCCESS);
134
- EXPECT_EQ (bt_node_->executeTick (), BT::NodeStatus::SUCCESS);
163
+ on_resume_child->changeStatus (BT::NodeStatus::FAILURE);
164
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::FAILURE);
165
+ check_request_succeeded (future);
166
+
167
+ // Halt the tree, expect RUNNING and RESUMED
168
+ tree_->haltTree ();
169
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::RUNNING);
170
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::RESUMED);
171
+
172
+ // Set resumed child to SUCCESS, expect SUCCESS and RESUMED
173
+ resumed_child->changeStatus (BT::NodeStatus::SUCCESS);
174
+ EXPECT_EQ (tree_->rootNode ()->executeTick (), BT::NodeStatus::SUCCESS);
175
+ EXPECT_EQ (pause_bt_node->getState (), state_t ::RESUMED);
135
176
}
136
177
137
178
int main (int argc, char ** argv)
0 commit comments