/*********************************************************************
 *
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * 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.
 *   * Neither the name of Willow Garage, Inc. 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 OWNER 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.
 *
 * Author: Eitan Marder-Eppstein
 *********************************************************************/
#ifndef ROBOT_NAV_CORE_BASE_LOCAL_PLANNER_H
#define ROBOT_NAV_CORE_BASE_LOCAL_PLANNER_H

#include <robot_geometry_msgs/PoseStamped.h>
#include <robot_geometry_msgs/Twist.h>
#include <robot_costmap_2d/costmap_2d_robot.h>
#include <tf3/buffer_core.h>
#include <robot_nav_msgs/Odometry.h>
#include <memory>

namespace robot_nav_core
{
  /**
   * @class BaseLocalPlanner
   * @brief Provides an interface for local planners used in navigation. All local planners written as plugins for the navigation stack must adhere to this interface.
   */
  class BaseLocalPlanner
  {
  public:
    using Ptr = std::shared_ptr<BaseLocalPlanner>;  
    /**
     * @brief  Given the current position, orientation, and velocity of the robot, compute velocity commands to send to the base
     * @param velocity The velocity of the robot
     * @param cmd_vel Will be filled with the velocity command to be passed to the robot base
     * @return True if a valid velocity command was found, false otherwise
     */
    virtual bool computeVelocityCommands(const robot_geometry_msgs::Twist &velocity, robot_geometry_msgs::Twist &cmd_vel) = 0;

    /**
     * @brief Swap object will be injected interjace robot_nav_core::BaseLocalPlanner
     * @param  planner_name  The object name 
     * @return True if instance object is successed, False otherwise
     */
    virtual bool swapPlanner(std::string planner_name) { return false; }

    /**
     * @brief Set velocity for x, y asix of the robot
     * @param linear the command velocity
     * @return True if set is done, false otherwise
     */
    virtual bool setTwistLinear(robot_geometry_msgs::Vector3 linear) { return false; }

    /**
     * @brief Get velocity for x, y asix of the robot
     * @param linear The velocity command
     * @return True if set is done, false otherwise
     */
    virtual robot_geometry_msgs::Vector3 getTwistLinear(bool direct) { throw std::runtime_error("Function getTwistLinear is not Support."); }

    /**
     * @brief Set velocity theta for z asix of the robot
     * @param angular the command velocity
     * @return True if set is done, false otherwise
     */
    virtual bool setTwistAngular(robot_geometry_msgs::Vector3 angular) { return false; }

    /**
     * @brief Get velocity theta for z asix of the robot
     * @param direct The velocity command
     * @return True if set is done, false otherwise
     */
    virtual robot_geometry_msgs::Vector3 getTwistAngular(bool direct) { throw std::runtime_error("Function getTwistLinear is not Support."); }

    /**
     * @brief Get velocity for x, y asix of the robot
     * @return The current velocity
     */
    virtual robot_geometry_msgs::Twist getActualTwist() { throw std::runtime_error("Function getActualTwist is not Support."); }

    /**
     * @brief Check if the kinematic parameters are currently locked
     * @return True if the kinematic parameters are locked, false otherwise
     *
     * This function indicates whether the kinematic parameters (e.g., velocities, accelerations, or direction settings) are in a locked state, preventing modifications. If the parameters are locked during in-place rotation, it could prevent updates to the direction or velocity, potentially causing inconsistencies in motion commands that lead to odometry errors and localization jumps in AMCL.
     */
    virtual bool islock() {throw std::runtime_error("Function islock is not Support.");}

    /**
     * @brief  Lock the kinematic parameters to prevent modifications
     */    
    virtual void lock() {throw std::runtime_error("Function lock is not Support.");}

    /**
     * @brief  Unlock the kinematic parameters to allow modifications
     */    
    virtual void unlock() {throw std::runtime_error("Function unlock is not Support.");}
    
    /**
     * @brief  Check if the goal pose has been achieved by the local planner
     * @return True if achieved, false otherwise
     */
    virtual bool isGoalReached() = 0;

    /**
     * @brief  Set the plan that the local planner is following
     * @param plan The plan to pass to the local planner
     * @return True if the plan was updated successfully, false otherwise
     */
    virtual bool setPlan(const std::vector<robot_geometry_msgs::PoseStamped> &plan) = 0;

    /**
     * @brief Gets the global plan for this local planner.
     *
     * @param path The global plan
     */ 
    virtual void getPlan(std::vector<robot_geometry_msgs::PoseStamped> &path) = 0;


    /**
     * @brief Gets the current global plan
     * @param path The global plan
     */
    virtual void getGlobalPlan(std::vector<robot_geometry_msgs::PoseStamped> &path) = 0;

    /**
     * @brief  Constructs the local planner
     * @param name The name to give this instance of the local planner
     * @param tf A pointer to a transform listener
     * @param costmap_robot The cost map to use for assigning costs to local plans
     */
    virtual void initialize(std::string name, tf3::BufferCore *tf, robot_costmap_2d::Costmap2DROBOT *costmap_robot) = 0;

    /**
     * @brief Set the odometry of the robot
     * @param odom The odometry of the robot
     */
    virtual void setOdom(robot_nav_msgs::Odometry *odom) { odom_ = odom; }

    /**
     * @brief  Virtual destructor for the interface
     */
    virtual ~BaseLocalPlanner() {}

  protected:
    BaseLocalPlanner() {}

    /**
     * @brief The odometry of the robot
     */
     robot_nav_msgs::Odometry *odom_;
  };
} // namespace robot_nav_core

#endif // ROBOT_NAV_CORE_BASE_LOCAL_PLANNER_H
