Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
python_controller.cpp 3.30 KiB

#include <algorithm>
#include <string>
#include <memory>
#include <iostream>

#include "Python.h"

#include "nav2_util/node_utils.hpp"
#include "air_navigation/python_controller.h"
#include "air_navigation/py_interface.h"
#include "nav2_util/geometry_utils.hpp"

#include "air_navigation/python_interpreter.h"

using namespace air_navigation;

void PythonController::configure(
  const rclcpp_lifecycle::LifecycleNode::WeakPtr & parent,
  std::string name, const std::shared_ptr<tf2_ros::Buffer> &,
  const std::shared_ptr<nav2_costmap_2d::Costmap2DROS> &)
{
  auto node = parent.lock();
  RCLCPP_ERROR_STREAM(node->get_logger(), "Configuring Python controller");

  nav2_util::declare_parameter_if_not_declared(node, name + ".module", rclcpp::ParameterValue(""));
  nav2_util::declare_parameter_if_not_declared(node, name + ".class", rclcpp::ParameterValue(""));

  std::string module_name, class_name;

  node->get_parameter(name + ".module", module_name);
  node->get_parameter(name + ".class", class_name);

  RCLCPP_INFO_STREAM(node->get_logger(), "Python controller will use: " << module_name << "." << class_name);
  m_python_controller_interface = air_navigation::python_interpreter::instance()->create_controller(module_name, class_name);;
  if(not m_python_controller_interface)
  {
    RCLCPP_ERROR_STREAM(node->get_logger(), "Failed to construct controller!");
  } else {
    python_lock pl;
    m_python_controller_interface->configure(name);
  }
}

void PythonController::cleanup()
{
  python_lock pl;
  if(m_python_controller_interface) m_python_controller_interface->cleanup();
}

void PythonController::activate()
{
  python_lock pl;
  if(m_python_controller_interface) m_python_controller_interface->activate();
}

void PythonController::deactivate()
{
  python_lock pl;
  if(m_python_controller_interface) m_python_controller_interface->deactivate();
}


geometry_msgs::msg::TwistStamped PythonController::computeVelocityCommands(
  const geometry_msgs::msg::PoseStamped & pose,
  const geometry_msgs::msg::Twist & twist,
    nav2_core::GoalChecker * )
{
  python_lock pl;
  if(m_python_controller_interface)
  {
    py_interface::PoseStamped py_pose;
    py_interface::copy_pose_stamped(pose, &py_pose);
    py_interface::Twist py_twis;
    py_interface::copy_twist(twist, &py_twis);
    py_interface::TwistStamped py_twis_stamped = m_python_controller_interface->computeVelocityCommands(py_pose, py_twis);
    geometry_msgs::msg::TwistStamped twist_stamped;
    py_interface::copy_header(py_twis_stamped.header, &twist_stamped.header);
    py_interface::copy_twist(py_twis_stamped.twist, &twist_stamped.twist);

    return twist_stamped;
  } else {
    return geometry_msgs::msg::TwistStamped();
  }
}

void PythonController::setPlan(const nav_msgs::msg::Path & path)
{
  python_lock pl;
  if(m_python_controller_interface)
  {
    py_interface::Path py_path;
    py_interface::copy_path<py_interface::PoseStamped>(path, &py_path);
    m_python_controller_interface->setPlan(py_path);
  }
}

void PythonController::setSpeedLimit(const double & speed_limit, const bool & percentage)
{
  python_lock pl;
  if(m_python_controller_interface)
  {
    m_python_controller_interface->setSpeedLimit(speed_limit, percentage);
  }
}

// Register this controller as a nav2_core plugin
PLUGINLIB_EXPORT_CLASS(air_navigation::PythonController, nav2_core::Controller)