Program Listing for File behavior_server__impl.hpp

Return to documentation for file (include/as2_behavior/__impl/behavior_server__impl.hpp)

#ifndef __AS2_BEHAVIOR_SERVER__IMPL_HPP__
#define __AS2_BEHAVIOR_SERVER__IMPL_HPP__
#include "as2_behavior/__detail/behavior_server__class.hpp"

namespace as2_behavior {

template <typename actionT>
BehaviorServer<actionT>::BehaviorServer(const std::string& name, const rclcpp::NodeOptions& options)
    : as2::Node(name, options), action_name_(name) {
  register_action();
  register_service_servers();
  register_publishers();
  register_timers();
}

template <typename actionT>
void BehaviorServer<actionT>::register_action() {
  // create a group for the action server
  auto action_server_group =
      this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);

  this->action_server_ = rclcpp_action::create_server<actionT>(
      this, this->generate_global_name(action_name_),
      std::bind(&BehaviorServer::handleGoal, this, std::placeholders::_1, std::placeholders::_2),
      std::bind(&BehaviorServer::handleCancel, this, std::placeholders::_1),
      std::bind(&BehaviorServer::handleAccepted, this, std::placeholders::_1));

  // this->action_server_->
};

template <typename actionT>
rclcpp_action::GoalResponse BehaviorServer<actionT>::handleGoal(
    const rclcpp_action::GoalUUID& uuid,
    std::shared_ptr<const typename actionT::Goal> goal) {
  RCLCPP_DEBUG(this->get_logger(), "Received goal request with UUID: %s", (char*)uuid.data());
  if (this->activate(goal)) {
    return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
  } else {
    return rclcpp_action::GoalResponse::REJECT;
  }
}

template <typename actionT>
rclcpp_action::CancelResponse BehaviorServer<actionT>::handleCancel(
    const std::shared_ptr<GoalHandleAction> goal_handle) {
  RCLCPP_INFO(this->get_logger(), "Request to cancel goal received");
  std_srvs::srv::Trigger::Request::SharedPtr req =
      std::make_shared<std_srvs::srv::Trigger::Request>();
  std_srvs::srv::Trigger::Response::SharedPtr res =
      std::make_shared<std_srvs::srv::Trigger::Response>();
  deactivate(req, res);
  if (res->success) {
    return rclcpp_action::CancelResponse::ACCEPT;
  } else {
    return rclcpp_action::CancelResponse::REJECT;
  }
};

template <typename actionT>
void BehaviorServer<actionT>::handleAccepted(const std::shared_ptr<GoalHandleAction> goal_handle) {
  goal_handle_ = goal_handle;
};

template <typename actionT>
std::string BehaviorServer<actionT>::generate_name(const std::string& name) {
  return std::string(this->get_name()) + "/_behavior/" + name;
}

template <typename actionT>
void BehaviorServer<actionT>::register_service_servers() {
  pause_srv_ = this->create_service<std_srvs::srv::Trigger>(
      generate_name("pause"),
      std::bind(&BehaviorServer::pause, this, std::placeholders::_1, std::placeholders::_2));
  resume_srv_ = this->create_service<std_srvs::srv::Trigger>(
      generate_name("resume"),
      std::bind(&BehaviorServer::resume, this, std::placeholders::_1, std::placeholders::_2));
  stop_srv_ = this->create_service<std_srvs::srv::Trigger>(
      generate_name("stop"),
      std::bind(&BehaviorServer::deactivate, this, std::placeholders::_1, std::placeholders::_2));
}

template <typename actionT>
void BehaviorServer<actionT>::register_publishers() {
  // feedback_pub_    = this->create_publisher<feedback_msg>(generate_name("feedback"), 10);
  // goal_status_pub_ = this->create_publisher<goal_status_msg>(generate_name("goal_status"), 10);
  behavior_status_pub_ =
      this->create_publisher<BehaviorStatus>(generate_name("behavior_status"), 10);
}

template <typename actionT>
void BehaviorServer<actionT>::register_timers() {
  behavior_status_timer_ = this->create_timer(
      std::chrono::milliseconds(100), std::bind(&BehaviorServer::publish_behavior_status, this));
}

template <typename actionT>
void BehaviorServer<actionT>::register_run_timer() {
  run_timer_ = this->create_timer(std::chrono::milliseconds(100),
                                  std::bind(&BehaviorServer::timer_callback, this));
}
template <typename actionT>
void BehaviorServer<actionT>::cleanup_run_timer(const ExecutionStatus& state) {
  on_execution_end(state);
  goal_handle_.reset();
  run_timer_.reset();
}

template <typename actionT>
bool BehaviorServer<actionT>::on_activate(std::shared_ptr<const typename actionT::Goal> goal) {
  return true;
};

template <typename actionT>
bool BehaviorServer<actionT>::on_modify(std::shared_ptr<const typename actionT::Goal> goal) {
  return true;
}

template <typename actionT>
bool BehaviorServer<actionT>::on_deactivate(const std::shared_ptr<std::string>& message) {
  return true;
}
template <typename actionT>
bool BehaviorServer<actionT>::on_pause(const std::shared_ptr<std::string>& message) {
  return true;
}
template <typename actionT>
bool BehaviorServer<actionT>::on_resume(const std::shared_ptr<std::string>& message) {
  return true;
}

/* template <typename actionT>
ExecutionStatus BehaviorServer<actionT>::on_run(typename feedback_msg::SharedPtr& fb) {
  return ExecutionStatus::SUCCESS;
} */

template <typename actionT>
ExecutionStatus BehaviorServer<actionT>::on_run(
    const typename std::shared_ptr<const typename actionT::Goal>& goal,
    typename std::shared_ptr<typename actionT::Feedback>& feedback_msg,
    typename std::shared_ptr<typename actionT::Result>& result_msg) {
  return ExecutionStatus::SUCCESS;
}  // namespace as2_behavior

template <typename actionT>
bool BehaviorServer<actionT>::activate(std::shared_ptr<const typename actionT::Goal> goal) {
  RCLCPP_INFO(this->get_logger(), "START");
  if (on_activate(goal)) {
    register_run_timer();
    behavior_status_.status = BehaviorStatus::RUNNING;
    return true;
  }
  return false;
};
template <typename actionT>
void BehaviorServer<actionT>::deactivate(
    const typename std_srvs::srv::Trigger::Request::SharedPtr goal,
    typename std_srvs::srv::Trigger::Response::SharedPtr result) {
  RCLCPP_INFO(this->get_logger(), "STOP");
  auto msg        = std::make_shared<std::string>();
  result->success = on_deactivate(msg);
  result->message = *msg;
  if (result->success) {
    cleanup_run_timer(ExecutionStatus::ABORTED);
    behavior_status_.status = BehaviorStatus::IDLE;
  }
};
template <typename actionT>

void BehaviorServer<actionT>::modify(std::shared_ptr<const typename actionT::Goal> goal) {
  RCLCPP_INFO(this->get_logger(), "MODIFY");
  on_modify(goal);
};
template <typename actionT>
void BehaviorServer<actionT>::pause(const typename std_srvs::srv::Trigger::Request::SharedPtr goal,
                                    typename std_srvs::srv::Trigger::Response::SharedPtr result) {
  RCLCPP_INFO(this->get_logger(), "PAUSE");
  if (behavior_status_.status != BehaviorStatus::RUNNING) {
    result->success = false;
    result->message = "Behavior is not running";
    return;
  }
  auto msg        = std::make_shared<std::string>();
  result->success = on_pause(msg);
  result->message = *msg;
  if (result->success) {
    behavior_status_.status = BehaviorStatus::PAUSED;
  }
};
template <typename actionT>
void BehaviorServer<actionT>::resume(const typename std_srvs::srv::Trigger::Request::SharedPtr goal,
                                     typename std_srvs::srv::Trigger::Response::SharedPtr result) {
  RCLCPP_INFO(this->get_logger(), "RESUME");
  if (behavior_status_.status != BehaviorStatus::PAUSED) {
    result->success = false;
    result->message = "Behavior is not paused";
    return;
  }
  auto msg        = std::make_shared<std::string>();
  result->success = on_resume(msg);
  result->message = *msg;
  if (result->success) {
    behavior_status_.status = BehaviorStatus::RUNNING;
  }
};

template <typename actionT>
void BehaviorServer<actionT>::run(
    const typename std::shared_ptr<GoalHandleAction>& goal_handle_action) {
  if (behavior_status_.status != BehaviorStatus::RUNNING) {
    return;
  };
  auto goal              = goal_handle_action->get_goal();
  auto feedback          = std::make_shared<typename actionT::Feedback>();
  auto result            = std::make_shared<typename actionT::Result>();
  ExecutionStatus status = on_run(goal, feedback, result);

  switch (status) {
    case ExecutionStatus::SUCCESS: {
      RCLCPP_INFO(this->get_logger(), "SUCCESS");
      behavior_status_.status = BehaviorStatus::IDLE;
      goal_handle_->succeed(result);
    } break;
    case ExecutionStatus::RUNNING: {
      auto clk = this->get_clock();
      RCLCPP_INFO_THROTTLE(this->get_logger(), *clk, 5000, "RUNNING");
      goal_handle_action->publish_feedback(feedback);
      behavior_status_.status = BehaviorStatus::RUNNING;
    } break;
    case ExecutionStatus::FAILURE: {
      RCLCPP_INFO(this->get_logger(), "FAILURE");
      behavior_status_.status = BehaviorStatus::IDLE;
      goal_handle_->abort(result);
    } break;
    case ExecutionStatus::ABORTED: {
      RCLCPP_INFO(this->get_logger(), "ABORTED");
      behavior_status_.status = BehaviorStatus::IDLE;
      goal_handle_->abort(result);
    } break;
  }

  if (behavior_status_.status != BehaviorStatus::RUNNING) {
    cleanup_run_timer(status);
  }
}

template <typename actionT>
void BehaviorServer<actionT>::publish_behavior_status() {
  BehaviorStatus msg;
  msg.status = behavior_status_.status;
  behavior_status_pub_->publish(msg);
}
};  // namespace as2_behavior

#endif  // AS2_BEHAVIOR__BEHAVIOR_SERVER_HPP_