AutoAPMS
Resilient Robot Mission Management
Loading...
Searching...
No Matches
execute_task_action.cpp
1// Copyright 2024 Robin Müller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "pyrobosim_msgs/action/execute_task_action.hpp"
16
17#include <map>
18
19#include "auto_apms_behavior_tree_core/node.hpp"
20#include "auto_apms_simulation/util.hpp"
21
22#define INPUT_KEY_ROBOT_NAME "robot"
23#define INPUT_KEY_TARGET_LOCATION "target"
24#define INPUT_KEY_OBJECT "object"
25
26namespace auto_apms_simulation
27{
28
29class ExecuteTaskAction : public auto_apms_behavior_tree::core::RosActionNode<pyrobosim_msgs::action::ExecuteTaskAction>
30{
31public:
32 using RosActionNode::RosActionNode;
33
34 virtual bool setGoal(Goal & goal) = 0;
35
36 BT::NodeStatus onResultReceived(const WrappedResult & result) override final
37 {
38 const BT::NodeStatus base_status = RosActionNode::onResultReceived(result);
39 if (base_status != BT::NodeStatus::SUCCESS) return base_status;
40 if (
41 result.result->execution_result.status == ExecutionResultMsg::SUCCESS ||
42 result.result->execution_result.status == ExecutionResultMsg::CANCELED) {
43 RCLCPP_DEBUG(
44 logger_, "%s - SUCCESS: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
45 toStr(result.result->execution_result).c_str());
46 return BT::NodeStatus::SUCCESS;
47 }
48 RCLCPP_ERROR(
49 logger_, "%s - FAILURE: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
50 toStr(result.result->execution_result).c_str());
51 return BT::NodeStatus::FAILURE;
52 }
53};
54
55class NavigateToLocation : public ExecuteTaskAction
56{
57public:
58 using ExecuteTaskAction::ExecuteTaskAction;
59
60 static BT::PortsList providedPorts()
61 {
62 return {
63 BT::InputPort<std::string>(
64 INPUT_KEY_TARGET_LOCATION,
65 "Name of the target to navigate to (Terms for the knowledge query are separated by whitespace)."),
66 BT::InputPort<std::string>(INPUT_KEY_ROBOT_NAME, "Name of the robot.")};
67 }
68
69 bool setGoal(Goal & goal)
70 {
71 const BT::Expected<std::string> expected_robot = getInput<std::string>(INPUT_KEY_ROBOT_NAME);
72 if (!expected_robot || expected_robot.value().empty()) {
73 RCLCPP_ERROR(
74 logger_, "%s - You must provide a non-empty robot name.", context_.getFullyQualifiedTreeNodeName(this).c_str());
75 RCLCPP_DEBUG_EXPRESSION(
76 logger_, !expected_robot, "%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
77 expected_robot.error().c_str());
78 return false;
79 }
80 const BT::Expected<std::string> expected_location = getInput<std::string>(INPUT_KEY_TARGET_LOCATION);
81 if (!expected_location || expected_location.value().empty()) {
82 RCLCPP_ERROR(
83 logger_, "%s - You must provide a non-empty target location name.",
84 context_.getFullyQualifiedTreeNodeName(this).c_str());
85 RCLCPP_DEBUG_EXPRESSION(
86 logger_, !expected_location, "%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
87 expected_location.error().c_str());
88 return false;
89 }
90 goal.action.type = "navigate";
91 goal.action.robot = expected_robot.value();
92 goal.action.target_location = expected_location.value();
93 return true;
94 }
95};
96
97class PickObject : public ExecuteTaskAction
98{
99public:
100 using ExecuteTaskAction::ExecuteTaskAction;
101
102 static BT::PortsList providedPorts()
103 {
104 return {
105 BT::InputPort<std::string>(INPUT_KEY_OBJECT, " ", "Name of the object to pick. Empty for the nearest object."),
106 BT::InputPort<std::string>(INPUT_KEY_ROBOT_NAME, "Name of the robot.")};
107 }
108
109 bool setGoal(Goal & goal)
110 {
111 const BT::Expected<std::string> expected_robot = getInput<std::string>(INPUT_KEY_ROBOT_NAME);
112 if (!expected_robot || expected_robot.value().empty()) {
113 RCLCPP_ERROR(
114 logger_, "%s - You must provide a non-empty robot name.", context_.getFullyQualifiedTreeNodeName(this).c_str());
115 RCLCPP_DEBUG_EXPRESSION(
116 logger_, !expected_robot, "%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
117 expected_robot.error().c_str());
118 return false;
119 }
120 goal.action.type = "pick";
121 goal.action.robot = expected_robot.value();
122 goal.action.object = getInput<std::string>(INPUT_KEY_OBJECT).value();
123 if (goal.action.object.empty()) goal.action.object = " "; // Include a whitespace to indicate 'any object'
124 return true;
125 }
126};
127
128class PlaceObject : public ExecuteTaskAction
129{
130public:
131 using ExecuteTaskAction::ExecuteTaskAction;
132
133 static BT::PortsList providedPorts()
134 {
135 return {BT::InputPort<std::string>(INPUT_KEY_ROBOT_NAME, "Name of the robot.")};
136 }
137
138 bool setGoal(Goal & goal)
139 {
140 const BT::Expected<std::string> expected_robot = getInput<std::string>(INPUT_KEY_ROBOT_NAME);
141 if (!expected_robot || expected_robot.value().empty()) {
142 RCLCPP_ERROR(
143 logger_, "%s - You must provide a non-empty robot name.", context_.getFullyQualifiedTreeNodeName(this).c_str());
144 RCLCPP_DEBUG_EXPRESSION(
145 logger_, !expected_robot, "%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(this).c_str(),
146 expected_robot.error().c_str());
147 return false;
148 }
149 goal.action.type = "place";
150 goal.action.robot = expected_robot.value();
151 return true;
152 }
153};
154
155} // namespace auto_apms_simulation
156
157AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(auto_apms_simulation::NavigateToLocation)
158AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(auto_apms_simulation::PickObject)
159AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(auto_apms_simulation::PlaceObject)
#define AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(type)
Macro for registering a behavior tree node plugin.
Definition node.hpp:40
const char * toStr(const ActionNodeErrorCode &err)
Convert the action error code to string.