15#include "pyrobosim_msgs/srv/request_world_state.hpp"
19#include "auto_apms_behavior_tree_core/node.hpp"
20#include "auto_apms_simulation/util.hpp"
21#include "pyrobosim_msgs/msg/robot_state.hpp"
23#define INPUT_KEY_TARGET_LOCATION "target_loc"
24#define INPUT_KEY_FILTER_LOCATION "filter_loc"
25#define INPUT_KEY_FILTER_ROBOT "filter_robot"
26#define INPUT_KEY_TARGET_ROBOT "robot"
27#define OUTPUT_KEY_CURRENT_LOCATION "current_loc"
29namespace auto_apms_simulation
32class IsLocationOccupied :
public auto_apms_behavior_tree::core::RosServiceNode<pyrobosim_msgs::srv::RequestWorldState>
34 std::string target_location_;
37 using RosServiceNode::RosServiceNode;
39 static BT::PortsList providedPorts()
42 BT::InputPort<std::string>(INPUT_KEY_FILTER_ROBOT,
".*",
"Regex filter for robots to consider."),
43 BT::InputPort<std::string>(
44 INPUT_KEY_FILTER_LOCATION,
".*",
"Regex filter for locations to match against the target location."),
45 BT::InputPort<std::string>(INPUT_KEY_TARGET_LOCATION,
"Name of the location to test for occupancy.")};
48 bool setRequest(Request::SharedPtr & request)
50 const BT::Expected<std::string> expected_location = getInput<std::string>(INPUT_KEY_TARGET_LOCATION);
51 if (!expected_location || expected_location.value().empty()) {
53 logger_,
"%s - You must provide a non-empty target location name.",
54 context_.getFullyQualifiedTreeNodeName(
this).c_str());
55 RCLCPP_DEBUG_EXPRESSION(
56 logger_, !expected_location,
"%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(
this).c_str(),
57 expected_location.error().c_str());
60 target_location_ = expected_location.value();
65 BT::NodeStatus onResponseReceived(
const Response::SharedPtr & response)
override final
67 std::regex loc_regex(getInput<std::string>(INPUT_KEY_FILTER_LOCATION).value());
68 std::regex robot_regex(getInput<std::string>(INPUT_KEY_FILTER_ROBOT).value());
69 for (
const pyrobosim_msgs::msg::RobotState & robot_state : response->state.robots) {
71 std::regex_match(robot_state.last_visited_location, loc_regex) &&
72 std::regex_match(robot_state.name, robot_regex) && robot_state.last_visited_location == target_location_)
73 return BT::NodeStatus::SUCCESS;
75 return BT::NodeStatus::FAILURE;
79class RobotSharesCurrentLocation
80:
public auto_apms_behavior_tree::core::RosServiceNode<pyrobosim_msgs::srv::RequestWorldState>
82 std::string target_robot_;
85 using RosServiceNode::RosServiceNode;
87 static BT::PortsList providedPorts()
90 BT::OutputPort<std::string>(OUTPUT_KEY_CURRENT_LOCATION,
"{=}",
"Current location name."),
91 BT::InputPort<std::string>(INPUT_KEY_FILTER_LOCATION,
".*",
"Regex filter for locations to consider."),
92 BT::InputPort<std::string>(
93 INPUT_KEY_TARGET_ROBOT,
"Target robot in question to be the first at the given location.")};
96 bool setRequest(Request::SharedPtr & request)
98 const BT::Expected<std::string> expected_robot = getInput<std::string>(INPUT_KEY_TARGET_ROBOT);
99 if (!expected_robot || expected_robot.value().empty()) {
101 logger_,
"%s - You must provide a non-empty target robot name.",
102 context_.getFullyQualifiedTreeNodeName(
this).c_str());
103 RCLCPP_DEBUG_EXPRESSION(
104 logger_, !expected_robot,
"%s - Error message: %s", context_.getFullyQualifiedTreeNodeName(
this).c_str(),
105 expected_robot.error().c_str());
108 target_robot_ = expected_robot.value();
113 BT::NodeStatus onResponseReceived(
const Response::SharedPtr & response)
override final
116 std::string current_loc;
117 for (
const pyrobosim_msgs::msg::RobotState & robot_state : response->state.robots) {
118 if (robot_state.name == target_robot_) {
119 current_loc = robot_state.last_visited_location;
123 if (
const BT::Result res = setOutput(OUTPUT_KEY_CURRENT_LOCATION, current_loc); !res) {
124 throw auto_apms_behavior_tree::exceptions::RosNodeError(
125 context_.getFullyQualifiedTreeNodeName(
this) +
" - Error setting output port '" + OUTPUT_KEY_CURRENT_LOCATION +
126 "': " + res.error());
128 std::regex loc_regex(getInput<std::string>(INPUT_KEY_FILTER_LOCATION).value());
129 for (
const pyrobosim_msgs::msg::RobotState & robot_state : response->state.robots) {
130 if (robot_state.name == target_robot_)
continue;
132 std::regex_match(robot_state.last_visited_location, loc_regex) &&
133 robot_state.last_visited_location == current_loc)
134 return BT::NodeStatus::SUCCESS;
136 return BT::NodeStatus::FAILURE;
#define AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(type)
Macro for registering a behavior tree node plugin.