Skip to content

add payloads to Action #66

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

Merged
merged 3 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Expand Up @@ -66,8 +66,8 @@ class TreeExecutionServer
/// @brief The payload received in the last goal
const std::string& goalPayload() const;

/// @brief Tree being executed, nullptr if it doesn't exist, yet.
BT::Tree* tree();
/// @brief Tree being executed.
const BT::Tree& tree() const;

/// @brief Pointer to the global blackboard
BT::Blackboard::Ptr globalBlackboard();
Expand Down
50 changes: 29 additions & 21 deletions behaviortree_ros2/src/tree_execution_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ struct TreeExecutionServer::Pimpl
{
rclcpp_action::Server<ExecuteTree>::SharedPtr action_server;
std::thread action_thread;
// thread safe bool to keep track of cancel requests
std::atomic<bool> cancel_requested{ false };

std::shared_ptr<bt_server::ParamListener> param_listener;
bt_server::Params params;
Expand All @@ -43,7 +41,7 @@ struct TreeExecutionServer::Pimpl

std::string tree_name;
std::string payload;
std::shared_ptr<BT::Tree> tree;
BT::Tree tree;
BT::Blackboard::Ptr global_blackboard;
bool factory_initialized_ = false;

Expand Down Expand Up @@ -123,7 +121,6 @@ TreeExecutionServer::handle_goal(const rclcpp_action::GoalUUID& /* uuid */,
{
RCLCPP_INFO(kLogger, "Received goal request to execute Behavior Tree: %s",
goal->target_tree.c_str());
p_->cancel_requested = false;
return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
}

Expand All @@ -137,7 +134,6 @@ rclcpp_action::CancelResponse TreeExecutionServer::handle_cancel(
"processing one.");
return rclcpp_action::CancelResponse::REJECT;
}
p_->cancel_requested = true;
return rclcpp_action::CancelResponse::ACCEPT;
}

Expand Down Expand Up @@ -172,30 +168,29 @@ void TreeExecutionServer::execute(
// This blackboard will be owned by "MainTree". It parent is p_->global_blackboard
auto root_blackboard = BT::Blackboard::create(p_->global_blackboard);

p_->tree = std::make_shared<BT::Tree>();
*(p_->tree) = p_->factory.createTree(goal->target_tree, root_blackboard);
p_->tree = p_->factory.createTree(goal->target_tree, root_blackboard);
p_->tree_name = goal->target_tree;
p_->payload = goal->payload;

// call user defined function after the tree has been created
onTreeCreated(*p_->tree);
onTreeCreated(p_->tree);
p_->groot_publisher.reset();
p_->groot_publisher =
std::make_shared<BT::Groot2Publisher>(*(p_->tree), p_->params.groot2_port);
std::make_shared<BT::Groot2Publisher>(p_->tree, p_->params.groot2_port);

// Loop until the tree is done or a cancel is requested
const auto period =
std::chrono::milliseconds(static_cast<int>(1000.0 / p_->params.tick_frequency));
auto loop_deadline = std::chrono::steady_clock::now() + period;

// operations to be done if the tree execution is aborted, either by
// cancel_requested_ or by onLoopAfterTick()
// cancel requested or by onLoopAfterTick()
auto stop_action = [this, &action_result](BT::NodeStatus status,
const std::string& message) {
action_result->node_status = ConvertNodeStatus(status);
action_result->return_message = message;
RCLCPP_WARN(kLogger, action_result->return_message.c_str());
p_->tree->haltTree();
p_->tree.haltTree();
// override the message value if the user defined function returns it
if(auto msg = onTreeExecutionCompleted(status, true))
{
Expand All @@ -205,15 +200,15 @@ void TreeExecutionServer::execute(

while(rclcpp::ok() && status == BT::NodeStatus::RUNNING)
{
if(p_->cancel_requested)
if(goal_handle->is_canceling())
{
stop_action(status, "Action Server canceling and halting Behavior Tree");
goal_handle->canceled(action_result);
return;
}

// tick the tree once and publish the action feedback
status = p_->tree->tickExactlyOnce();
status = p_->tree.tickExactlyOnce();

if(const auto res = onLoopAfterTick(status); res.has_value())
{
Expand All @@ -232,7 +227,7 @@ void TreeExecutionServer::execute(
const auto now = std::chrono::steady_clock::now();
if(now < loop_deadline)
{
p_->tree->sleep(loop_deadline - now);
p_->tree.sleep(loop_deadline - now);
}
loop_deadline += period;
}
Expand All @@ -245,19 +240,32 @@ void TreeExecutionServer::execute(
return;
}

// set the node_status result to the action
action_result->node_status = ConvertNodeStatus(status);

// Call user defined onTreeExecutionCompleted function.
// Override the message value if the user defined function returns it
if(auto msg = onTreeExecutionCompleted(status, false))
{
action_result->return_message = msg.value();
}
else
{
action_result->return_message =
std::string("Tree finished with status: ") + BT::toStr(status);
}

// set the node_status result to the action
action_result->node_status = ConvertNodeStatus(status);

// return success or aborted for the action result
RCLCPP_INFO(kLogger, "BT finished with status: %s", BT::toStr(status).c_str());
goal_handle->succeed(action_result);
if(status == BT::NodeStatus::SUCCESS)
{
RCLCPP_INFO(kLogger, action_result->return_message.c_str());
goal_handle->succeed(action_result);
}
else
{
RCLCPP_ERROR(kLogger, action_result->return_message.c_str());
goal_handle->abort(action_result);
}
}

const std::string& TreeExecutionServer::treeName() const
Expand All @@ -270,9 +278,9 @@ const std::string& TreeExecutionServer::goalPayload() const
return p_->payload;
}

BT::Tree* TreeExecutionServer::tree()
const BT::Tree& TreeExecutionServer::tree() const
{
return p_->tree ? p_->tree.get() : nullptr;
return p_->tree;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any chance of the user accessing the tree and it being outdated or empty? It doesn't seem like there is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically an empty Tree can be recognized.
But in general I don't believe this can happen, this is the reason why I made the change

}

BT::Blackboard::Ptr TreeExecutionServer::globalBlackboard()
Expand Down
Loading