controller.hpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Marcus Liebhardt, Yujin Robot.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Yujin Robot nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /*****************************************************************************
00031 ** Ifdefs
00032 *****************************************************************************/
00033 
00034 #ifndef YOCS_CONTROLLER_HPP_
00035 #define YOCS_CONTROLLER_HPP_
00036 
00037 /*****************************************************************************
00038 ** Includes
00039 *****************************************************************************/
00040 #include <cmath>
00041 #include <string>
00042 #include <geometry_msgs/Twist.h>
00043 #include <ros/ros.h>
00044 #include <std_msgs/Empty.h>
00045 #include <std_msgs/Float32.h>
00046 #include <tf/transform_listener.h>
00047 #include <yocs_controllers/default_controller.hpp>
00048 
00049 namespace yocs
00050 {
00051 
00077 class DiffDrivePoseController : public Controller
00078 {
00079 public:
00080   DiffDrivePoseController(ros::NodeHandle& nh, std::string& name) : Controller(),
00081                                                                        nh_(nh),
00082                                                                        name_(name){};
00083   virtual ~DiffDrivePoseController(){};
00084 
00089   bool init();
00090 
00094   void spinOnce();
00095 
00096 private:
00100   bool getPoseDiff();
00104   void getControlOutput();
00108   void setControlOutput();
00109 
00114   void controlMaxVelCB(const std_msgs::Float32ConstPtr msg);
00115 
00120   void enableCB(const std_msgs::EmptyConstPtr msg);
00121 
00126   void disableCB(const std_msgs::EmptyConstPtr msg);
00127 
00128   // basics
00129   ros::NodeHandle nh_;
00130   std::string name_;
00131 
00132   // interfaces
00134   ros::Subscriber enable_controller_subscriber_;
00136   ros::Subscriber disable_controller_subscriber_;
00138   ros::Subscriber control_velocity_subscriber_;
00140   ros::Publisher command_velocity_publisher_;
00141 
00142   // variables and constants for the control law
00144   double r_;
00146   double theta_;
00148   double delta_;
00150   double v_;
00152   double v_max_;
00154   double w_;
00156   double w_max_;
00158   double cur_;
00160   double k_1_;
00162   double k_2_;
00167   double beta_;
00172   double lambda_;
00173 
00175   tf::TransformListener tf_listener_;
00177   tf::StampedTransform tf_goal_pose_rel_;
00179   std::string base_frame_name_;
00181   std::string goal_frame_name_;
00182 };
00183 
00184 bool DiffDrivePoseController::init()
00185 {
00186   enable_controller_subscriber_ = nh_.subscribe("enable", 10, &DiffDrivePoseController::enableCB, this);
00187   disable_controller_subscriber_ = nh_.subscribe("disable", 10, &DiffDrivePoseController::disableCB, this);
00188   control_velocity_subscriber_ = nh_.subscribe("control_max_vel", 10, &DiffDrivePoseController::controlMaxVelCB, this);
00189   command_velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>("command_velocity", 10);
00190 
00191   // retrieve configuration parameters
00192   base_frame_name_ = "base_footprint";
00193   if(!nh_.getParam("base_frame_name", base_frame_name_))
00194   {
00195     ROS_WARN_STREAM("Couldn't retrieve parameter 'base_frame_name' from parameter server! Using default '"
00196                     << base_frame_name_ << "'. [" << name_ <<"]");
00197   }
00198   goal_frame_name_ = "base_goal_pose";
00199   if(!nh_.getParam("goal_frame_name", goal_frame_name_))
00200   {
00201     ROS_WARN_STREAM("Couldn't retrieve parameter 'goal_frame_name' from parameter server! Using default '"
00202                     << goal_frame_name_ << "'. [" << name_ <<"]");
00203   }
00204   v_ = 0.0;
00205   v_max_ = 0.5;
00206   if(!nh_.getParam("v_max", v_max_))
00207   {
00208     ROS_WARN_STREAM("Couldn't retrieve parameter 'v_max' from parameter server! Using default '"
00209                     << v_max_ << "'. [" << name_ <<"]");
00210   }
00211   w_max_ = M_PI / 4 * v_max_;
00212   k_1_ = 1.0;
00213   if(!nh_.getParam("k_1", k_1_))
00214   {
00215     ROS_WARN_STREAM("Couldn't retrieve parameter 'k_1' from parameter server! Using default '"
00216                     << k_1_ << "'. [" << name_ <<"]");
00217   }
00218   k_2_ = 3.0;
00219   if(!nh_.getParam("k_2", k_2_))
00220   {
00221     ROS_WARN_STREAM("Couldn't retrieve parameter 'k_2' from parameter server! Using default '"
00222                     << k_2_ << "'. [" << name_ <<"]");
00223   }
00224   beta_ = 0.4;
00225   if(!nh_.getParam("beta", beta_))
00226   {
00227     ROS_WARN_STREAM("Couldn't retrieve parameter 'beta' from parameter server! Using default '"
00228                     << beta_ << "'. [" << name_ <<"]");
00229   }
00230   lambda_ = 2.0;
00231   if(!nh_.getParam("lambda", lambda_))
00232   {
00233     ROS_WARN_STREAM("Couldn't retrieve parameter 'lambda' from parameter server! Using default '"
00234                     << lambda_ << "'. [" << name_ <<"]");
00235   }
00236   ROS_DEBUG_STREAM("Controller initialised with the following parameters: [" << name_ <<"]");
00237   ROS_DEBUG_STREAM("base_frame_name = " << base_frame_name_ <<", goal_frame_name = "
00238                    << goal_frame_name_ << " [" << name_ <<"]");
00239   ROS_DEBUG_STREAM("v_max = " << v_max_ <<", k_1 = " << k_1_ << ", k_2 = " << k_2_
00240                    << ", beta = " << beta_ << ", lambda = " << lambda_ << " [" << name_ <<"]");
00241   return true;
00242 };
00243 
00244 void DiffDrivePoseController::spinOnce()
00245 {
00246   if (this->getState())
00247   {
00248     ROS_INFO_STREAM_THROTTLE(1.0, "Controller spinning. [" << name_ <<"]");
00249     // determine pose difference in polar coordinates
00250     if (!getPoseDiff())
00251     {
00252       ROS_WARN_STREAM_THROTTLE(1.0, "Getting pose difference failed. Skipping control loop. [" << name_ <<"]");
00253       return;
00254     }
00255     // determine controller output (v, w)
00256     getControlOutput();
00257     // set control output (v, w)
00258     setControlOutput();
00259     // Logging
00260     ROS_DEBUG_STREAM_THROTTLE(1.0, "Current state: [" << name_ <<"]");
00261     ROS_DEBUG_STREAM_THROTTLE(1.0, "r = " << r_ << ", theta = " << theta_ << ", delta = " << delta_
00262                                    << " [" << name_ <<"]");
00263     ROS_DEBUG_STREAM_THROTTLE(1.0, "cur = " << cur_ << ", v = " << v_ << ", w = " << w_ << " [" << name_ <<"]");
00264   }
00265   else
00266   {
00267     ROS_WARN_STREAM_THROTTLE(3.0, "Controller is disabled. Idling ... [" << name_ <<"]");
00268   }
00269 };
00270 
00271 bool DiffDrivePoseController::getPoseDiff()
00272 {
00273   // use tf to get information about the goal pose relative to the base
00274   try
00275   {
00276     tf_listener_.lookupTransform(base_frame_name_, goal_frame_name_, ros::Time(0), tf_goal_pose_rel_);
00277   }
00278   catch (tf::TransformException const &ex)
00279   {
00280     ROS_WARN_STREAM_THROTTLE(1.0, "Couldn't get transform from base to goal pose! [" << name_ <<"]");
00281     ROS_DEBUG_STREAM_THROTTLE(1.0, "tf error: " << ex.what());
00282     return false;
00283   }
00284 
00285   // determine distance to goal
00286   r_ = std::sqrt(std::pow(tf_goal_pose_rel_.getOrigin().getX(), 2)
00287                  + std::pow(tf_goal_pose_rel_.getOrigin().getY(), 2));
00288   // determine orientation of r relative to the base frame
00289   delta_ = std::atan2(-tf_goal_pose_rel_.getOrigin().getY(), tf_goal_pose_rel_.getOrigin().getX());
00290   // determine orientation of r relative to the goal frame
00291   // helper: theta = tf's orientation + delta
00292   theta_ = tf::getYaw(tf_goal_pose_rel_.getRotation()) + delta_;
00293 
00294   return true;
00295 };
00296 
00297 void DiffDrivePoseController::getControlOutput()
00298 {
00299   cur_ = (-1 / r_) * (k_2_ * (delta_ - std::atan(-k_1_ * theta_))
00300          + (1 + (k_1_ / (1 + std::pow((k_1_ * theta_), 2)))) * sin(delta_));
00301   v_ = v_max_ / (1 + beta_ * std::pow(std::abs(cur_), lambda_));
00302   w_ = cur_ * v_;
00303   if (w_ > w_max_)
00304   {
00305     w_ = w_max_;
00306   }
00307 };
00308 
00309 void DiffDrivePoseController::setControlOutput()
00310 {
00311   geometry_msgs::TwistPtr cmd_vel(new geometry_msgs::Twist());
00312   cmd_vel->linear.x = v_;
00313   cmd_vel->angular.z = w_;
00314   command_velocity_publisher_.publish(cmd_vel);
00315 };
00316 
00317 void DiffDrivePoseController::controlMaxVelCB(const std_msgs::Float32ConstPtr msg)
00318 {
00319   v_max_ = msg->data;
00320   ROS_INFO_STREAM("Maximum linear control velocity has been set to " << v_max_ << ". [" << name_ << "]");
00321 };
00322 
00323 void DiffDrivePoseController::enableCB(const std_msgs::EmptyConstPtr msg)
00324 {
00325   if (this->enable())
00326   {
00327     ROS_INFO_STREAM("Controller has been enabled. [" << name_ << "]");
00328   }
00329   else
00330   {
00331     ROS_INFO_STREAM("Controller was already enabled. [" << name_ <<"]");
00332   }
00333 };
00334 
00335 void DiffDrivePoseController::disableCB(const std_msgs::EmptyConstPtr msg)
00336 {
00337   if (this->disable())
00338   {
00339     ROS_INFO_STREAM("Controller has been disabled. [" << name_ <<"]");
00340   }
00341   else
00342   {
00343     ROS_INFO_STREAM("Controller was already disabled. [" << name_ <<"]");
00344   }
00345 };
00346 
00347 } // namespace yocs
00348 
00349 #endif /* YOCS_CONTROLLER_HPP_ */


yocs_diff_drive_pose_controller
Author(s): Marcus Liebhardt
autogenerated on Fri Aug 28 2015 13:45:05