text: // Copyright 2019 Open Source Robotics Foundation, Inc.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  #include <memory>
  
  #include "action_tutorials_interfaces/action/fibonacci.hpp"
  #include "rclcpp/rclcpp.hpp"
  // TODO(jacobperron): Remove this once it is included as part of 'rclcpp.hpp'
  #include "rclcpp_action/rclcpp_action.hpp"
  #include "rclcpp_components/register_node_macro.hpp"
  
  #include "action_tutorials_cpp/visibility_control.h"
  
  namespace action_tutorials_cpp
  {
  class FibonacciActionServer : public rclcpp::Node
  {
  public:
    using Fibonacci = action_tutorials_interfaces::action::Fibonacci;
    using GoalHandleFibonacci = rclcpp_action::ServerGoalHandle<Fibonacci>;
  
    ACTION_TUTORIALS_CPP_PUBLIC
    explicit FibonacciActionServer(const rclcpp::NodeOptions & options = rclcpp::NodeOptions())
    : Node("fibonacci_action_server", options)
    {
      using namespace std::placeholders;
  
      this->action_server_ = rclcpp_action::create_server<Fibonacci>(
        this->get_node_base_interface(),
        this->get_node_clock_interface(),
        this->get_node_logging_interface(),
        this->get_node_waitables_interface(),
        "fibonacci",
        std::bind(&FibonacciActionServer::handle_goal, this, _1, _2),
        std::bind(&FibonacciActionServer::handle_cancel, this, _1),
        std::bind(&FibonacciActionServer::handle_accepted, this, _1));
    }
  
  private:
    rclcpp_action::Server<Fibonacci>::SharedPtr action_server_;
  
    ACTION_TUTORIALS_CPP_LOCAL
    rclcpp_action::GoalResponse handle_goal(
      const rclcpp_action::GoalUUID & uuid,
      std::shared_ptr<const Fibonacci::Goal> goal)
    {
      RCLCPP_INFO(this->get_logger(), "Received goal request with order %d", goal->order);
      (void)uuid;
      // Let's reject sequences that are over 9000
      if (goal->order > 9000) {
        return rclcpp_action::GoalResponse::REJECT;
      }
      return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
    }
  
    ACTION_TUTORIALS_CPP_LOCAL
    rclcpp_action::CancelResponse handle_cancel(
      const std::shared_ptr<GoalHandleFibonacci> goal_handle)
    {
      RCLCPP_INFO(this->get_logger(), "Received request to cancel goal");
      (void)goal_handle;
      return rclcpp_action::CancelResponse::ACCEPT;
    }
  
    ACTION_TUTORIALS_CPP_LOCAL
    void handle_accepted(const std::shared_ptr<GoalHandleFibonacci> goal_handle)
    {
      using namespace std::placeholders;
      // this needs to return quickly to avoid blocking the executor, so spin up a new thread
      std::thread{std::bind(&FibonacciActionServer::execute, this, _1), goal_handle}.detach();
    }
  
    ACTION_TUTORIALS_CPP_LOCAL
    void execute(const std::shared_ptr<GoalHandleFibonacci> goal_handle)
    {
      RCLCPP_INFO(this->get_logger(), "Executing goal");
      rclcpp::Rate loop_rate(1);
      const auto goal = goal_handle->get_goal();
      auto feedback = std::make_shared<Fibonacci::Feedback>();
      auto & sequence = feedback->partial_sequence;
      sequence.push_back(0);
      sequence.push_back(1);
      auto result = std::make_shared<Fibonacci::Result>();
  
      for (int i = 1; (i < goal->order) && rclcpp::ok(); ++i) {
        // Check if there is a cancel request
        if (goal_handle->is_canceling()) {
          result->sequence = sequence;
          goal_handle->canceled(result);
          RCLCPP_INFO(this->get_logger(), "Goal canceled");
          return;
        }
        // Update sequence
        sequence.push_back(sequence[i] + sequence[i - 1]);
        // Publish feedback
        goal_handle->publish_feedback(feedback);
        RCLCPP_INFO(this->get_logger(), "Publish feedback");
  
        loop_rate.sleep();
      }
  
      // Check if goal is done
      if (rclcpp::ok()) {
        result->sequence = sequence;
        goal_handle->succeed(result);
        RCLCPP_INFO(this->get_logger(), "Goal succeeded");
      }
    }
  };  // class FibonacciActionServer
  
  }  // namespace action_tutorials_cpp
  
  RCLCPP_COMPONENTS_REGISTER_NODE(action_tutorials_cpp::FibonacciActionServer)
  