Program Listing for File as2_behavior_tree_node.cpp

Return to documentation for file (/tmp/ws/src/aerostack2/as2_behavior_tree/src/as2_behavior_tree_node.cpp)

/*!*******************************************************************************************
 *  \file       as2_behavior_tree_node.cpp
 *  \brief      ROS2 entrypoint for launching a node to run a behavior tree
 *  \authors    Pedro Arias Pérez
 *              Miguel Fernández Cortizas
 *              David Pérez Saura
 *              Rafael Pérez Seguí
 *
 *  \copyright  Copyright (c) 2022 Universidad Politécnica de Madrid
 *              All Rights Reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ********************************************************************************/

#include <chrono>
#include <thread>

#include "behaviortree_cpp_v3/bt_factory.h"

#include "as2_behavior_tree/action/arm_service.hpp"
#include "as2_behavior_tree/action/echo.hpp"
#include "as2_behavior_tree/action/follow_path.hpp"
#include "as2_behavior_tree/action/get_origin.hpp"
#include "as2_behavior_tree/action/go_to_action.hpp"
#include "as2_behavior_tree/action/go_to_gps_action.hpp"
#include "as2_behavior_tree/action/gps_to_cartesian.hpp"
#include "as2_behavior_tree/action/land_action.hpp"
#include "as2_behavior_tree/action/offboard_service.hpp"
#include "as2_behavior_tree/action/send_event.hpp"
#include "as2_behavior_tree/action/set_origin.hpp"
#include "as2_behavior_tree/action/takeoff_action.hpp"
#include "as2_behavior_tree/condition/is_flying_condition.hpp"
#include "as2_behavior_tree/decorator/wait_for_alert.hpp"
#include "as2_behavior_tree/decorator/wait_for_event.hpp"

#include "rclcpp/rclcpp.hpp"

// Groot connetion
#include <behaviortree_cpp_v3/loggers/bt_zmq_publisher.h>

#include "behaviortree_cpp_v3/loggers/bt_cout_logger.h"

int main(int argc, char *argv[]) {
  rclcpp::init(argc, argv);
  auto node = std::make_shared<rclcpp::Node>("bt_manager");

  node->declare_parameter<std::string>("tree", "");
  node->declare_parameter<bool>("use_groot", false);
  node->declare_parameter<int>("groot_client_port", 1666);
  node->declare_parameter<int>("groot_server_port", 1667);
  node->declare_parameter<int>("server_timeout", 10000); // miliseconds
  node->declare_parameter<int>("bt_loop_duration", 10);  // miliseconds
  std::string tree_description = node->get_parameter("tree").as_string();
  bool groot_logger = node->get_parameter("use_groot").as_bool();
  int groot_client_port = node->get_parameter("groot_client_port").as_int();
  int groot_server_port = node->get_parameter("groot_server_port").as_int();
  int server_timeout = node->get_parameter("server_timeout").as_int();
  int bt_loop_duration = node->get_parameter("bt_loop_duration").as_int();

  BT::BehaviorTreeFactory factory;

  factory.registerNodeType<as2_behavior_tree::ArmService>("Arm");
  factory.registerNodeType<as2_behavior_tree::DisarmService>("Disarm");
  factory.registerNodeType<as2_behavior_tree::OffboardService>("Offboard");
  factory.registerNodeType<as2_behavior_tree::TakeoffAction>("TakeOff");
  factory.registerNodeType<as2_behavior_tree::GoToAction>("GoTo");
  factory.registerNodeType<as2_behavior_tree::LandAction>("Land");
  factory.registerNodeType<as2_behavior_tree::IsFlyingCondition>("IsFlying");
  factory.registerNodeType<as2_behavior_tree::WaitForEvent>("WaitForEvent");
  factory.registerNodeType<as2_behavior_tree::WaitForAlert>("WaitForAlert");
  factory.registerNodeType<as2_behavior_tree::SendEvent>("SendEvent");
  factory.registerNodeType<as2_behavior_tree::Echo>("Echo");
  factory.registerNodeType<as2_behavior_tree::SetOrigin>("SetOrigin");
  factory.registerNodeType<as2_behavior_tree::GetOrigin>("GetOrigin");
  factory.registerNodeType<as2_behavior_tree::GpsToCartesian>("GpsToCartesian");
  factory.registerNodeType<as2_behavior_tree::GoToGpsAction>("GoToGps");
  factory.registerNodeType<as2_behavior_tree::FollowPathAction>("FollowPath");

  BT::NodeConfiguration *config = new BT::NodeConfiguration();
  // Create the blackboard that will be shared by all of the nodes in the tree
  config->blackboard = BT::Blackboard::create();
  // Put items on the blackboard
  config->blackboard->set<rclcpp::Node::SharedPtr>("node", node);
  config->blackboard->set<std::chrono::milliseconds>(
      "server_timeout", std::chrono::milliseconds(server_timeout));
  config->blackboard->set<std::chrono::milliseconds>(
      "bt_loop_duration", std::chrono::milliseconds(bt_loop_duration));

  auto tree = factory.createTreeFromFile(tree_description, config->blackboard);

  // LOGGERS
  BT::StdCoutLogger logger_cout(tree);
  std::shared_ptr<BT::PublisherZMQ> groot_pub = nullptr;

  if (groot_logger) {
    groot_pub = std::make_shared<BT::PublisherZMQ>(tree, 25U, groot_client_port,
                                                   groot_server_port);
  }

  // to keep track of the number of ticks it took to reach a terminal result
  int ticks = 0;

  BT::NodeStatus result = BT::NodeStatus::RUNNING;

  // BT loop execution rate
  rclcpp::WallRate loopRate(std::chrono::milliseconds((int)(bt_loop_duration)));

  // main BT execution loop
  while (rclcpp::ok() && result == BT::NodeStatus::RUNNING) {
    result = tree.tickRoot();
    ticks++;
    loopRate.sleep();
  }

  rclcpp::shutdown();
  return 0;
}