00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef YOCS_CONTROLLER_HPP_
00035 #define YOCS_CONTROLLER_HPP_
00036
00037
00038
00039
00040 #include <cmath>
00041 #include <string>
00042 #include <geometry_msgs/Twist.h>
00043 #include <ros/ros.h>
00044 #include <std_msgs/Bool.h>
00045 #include <std_msgs/Empty.h>
00046 #include <std_msgs/Float32.h>
00047 #include <std_msgs/String.h>
00048 #include <tf/transform_listener.h>
00049 #include <yocs_controllers/default_controller.hpp>
00050 #include <yocs_math_toolkit/geometry.hpp>
00051
00052 namespace yocs
00053 {
00054
00080 class DiffDrivePoseController : public Controller
00081 {
00082 public:
00083 DiffDrivePoseController(ros::NodeHandle& nh, std::string& name) : Controller(),
00084 nh_(nh),
00085 name_(name){};
00086 virtual ~DiffDrivePoseController(){};
00087
00092 bool init();
00093
00097 void spinOnce();
00098
00099 private:
00103 bool getPoseDiff();
00107 void getControlOutput();
00111 void setControlOutput();
00112
00117 void controlMaxVelCB(const std_msgs::Float32ConstPtr msg);
00118
00123 void enableCB(const std_msgs::StringConstPtr msg);
00124
00129 void disableCB(const std_msgs::EmptyConstPtr msg);
00130
00138 double boundRange(double v, double min, double max);
00139
00140
00141 ros::NodeHandle nh_;
00142 std::string name_;
00143
00144
00146 ros::Subscriber enable_controller_subscriber_;
00148 ros::Subscriber disable_controller_subscriber_;
00150 ros::Subscriber control_velocity_subscriber_;
00152 ros::Publisher command_velocity_publisher_;
00154 ros::Publisher pose_reached_publisher_;
00155
00156
00158 double r_;
00160 double theta_;
00162 double delta_;
00164 double v_;
00166 double v_min_;
00168 double v_max_;
00170 double w_;
00172 double w_min_;
00174 double w_max_;
00176 double cur_;
00178 double k_1_;
00180 double k_2_;
00185 double beta_;
00190 double lambda_;
00192 double dist_thres_;
00194 double orient_thres_;
00196 bool pose_reached_;
00198 double dist_eps_;
00200 double orient_eps_;
00201
00203 tf::TransformListener tf_listener_;
00205 tf::StampedTransform tf_goal_pose_rel_;
00207 std::string base_frame_name_;
00209 std::string goal_frame_name_;
00210 };
00211
00212 bool DiffDrivePoseController::init()
00213 {
00214 enable_controller_subscriber_ = nh_.subscribe("enable", 10, &DiffDrivePoseController::enableCB, this);
00215 disable_controller_subscriber_ = nh_.subscribe("disable", 10, &DiffDrivePoseController::disableCB, this);
00216 control_velocity_subscriber_ = nh_.subscribe("control_max_vel", 10, &DiffDrivePoseController::controlMaxVelCB, this);
00217 command_velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>("command_velocity", 10);
00218 pose_reached_publisher_ = nh_.advertise<std_msgs::Bool>("pose_reached", 10);
00219
00220
00221 base_frame_name_ = "base_footprint";
00222 if(!nh_.getParam("base_frame_name", base_frame_name_))
00223 {
00224 ROS_WARN_STREAM("Couldn't retrieve parameter 'base_frame_name' from parameter server! Using default '"
00225 << base_frame_name_ << "'. [" << name_ <<"]");
00226 }
00227 goal_frame_name_ = "base_goal_pose";
00228 if(!nh_.getParam("goal_frame_name", goal_frame_name_))
00229 {
00230 ROS_WARN_STREAM("Couldn't retrieve parameter 'goal_frame_name' from parameter server! Using default '"
00231 << goal_frame_name_ << "'. [" << name_ <<"]");
00232 }
00233 v_ = 0.0;
00234 v_min_ = 0.01;
00235 if(!nh_.getParam("v_min", v_min_))
00236 {
00237 ROS_WARN_STREAM("Couldn't retrieve parameter 'v_min' from parameter server! Using default '"
00238 << v_min_ << "'. [" << name_ <<"]");
00239 }
00240 v_max_ = 0.5;
00241 if(!nh_.getParam("v_max", v_max_))
00242 {
00243 ROS_WARN_STREAM("Couldn't retrieve parameter 'v_max' from parameter server! Using default '"
00244 << v_max_ << "'. [" << name_ <<"]");
00245 }
00246 w_min_ = 0.01;
00247 if(!nh_.getParam("w_min", w_min_))
00248 {
00249 ROS_WARN_STREAM("Couldn't retrieve parameter 'w_min' from parameter server! Using default '"
00250 << w_min_ << "'. [" << name_ <<"]");
00251 }
00252 w_max_ = M_PI / 4 * v_max_;
00253 if(!nh_.getParam("w_max", w_max_))
00254 {
00255 ROS_WARN_STREAM("Couldn't retrieve parameter 'w_max' from parameter server! Using default '"
00256 << w_max_ << "'. [" << name_ <<"]");
00257 }
00258 k_1_ = 1.0;
00259 if(!nh_.getParam("k_1", k_1_))
00260 {
00261 ROS_WARN_STREAM("Couldn't retrieve parameter 'k_1' from parameter server! Using default '"
00262 << k_1_ << "'. [" << name_ <<"]");
00263 }
00264 k_2_ = 3.0;
00265 if(!nh_.getParam("k_2", k_2_))
00266 {
00267 ROS_WARN_STREAM("Couldn't retrieve parameter 'k_2' from parameter server! Using default '"
00268 << k_2_ << "'. [" << name_ <<"]");
00269 }
00270 beta_ = 0.4;
00271 if(!nh_.getParam("beta", beta_))
00272 {
00273 ROS_WARN_STREAM("Couldn't retrieve parameter 'beta' from parameter server! Using default '"
00274 << beta_ << "'. [" << name_ <<"]");
00275 }
00276 lambda_ = 2.0;
00277 if(!nh_.getParam("lambda", lambda_))
00278 {
00279 ROS_WARN_STREAM("Couldn't retrieve parameter 'lambda' from parameter server! Using default '"
00280 << lambda_ << "'. [" << name_ <<"]");
00281 }
00282 dist_thres_ = 0.01;
00283 if(!nh_.getParam("dist_thres", dist_thres_))
00284 {
00285 ROS_WARN_STREAM("Couldn't retrieve parameter 'dist_thres' from parameter server! Using default '"
00286 << dist_thres_ << "'. [" << name_ <<"]");
00287 }
00288 orient_thres_ = 0.02;
00289 if(!nh_.getParam("orient_thres", orient_thres_))
00290 {
00291 ROS_WARN_STREAM("Couldn't retrieve parameter 'orient_thres' from parameter server! Using default '"
00292 << orient_thres_ << "'. [" << name_ <<"]");
00293 }
00294 dist_eps_ = dist_eps_ * 0.2;
00295 if(!nh_.getParam("dist_eps", dist_eps_))
00296 {
00297 ROS_WARN_STREAM("Couldn't retrieve parameter 'dist_eps' from parameter server! Using default '"
00298 << dist_eps_ << "'. [" << name_ <<"]");
00299 }
00300 orient_eps_ = orient_thres_ * 0.2;
00301 if(!nh_.getParam("orient_eps", orient_eps_))
00302 {
00303 ROS_WARN_STREAM("Couldn't retrieve parameter 'orient_eps' from parameter server! Using default '"
00304 << orient_eps_ << "'. [" << name_ <<"]");
00305 }
00306 pose_reached_ = false;
00307 ROS_DEBUG_STREAM("Controller initialised with the following parameters: [" << name_ <<"]");
00308 ROS_DEBUG_STREAM("base_frame_name = " << base_frame_name_ <<", goal_frame_name = "
00309 << goal_frame_name_ << " [" << name_ <<"]");
00310 ROS_DEBUG_STREAM("v_max = " << v_max_ <<", k_1 = " << k_1_ << ", k_2 = " << k_2_ << ", beta = " << beta_
00311 << ", lambda = " << lambda_ << ", dist_thres = " << dist_thres_
00312 << ", orient_thres = " << orient_thres_ <<" [" << name_ <<"]");
00313 return true;
00314 };
00315
00316 void DiffDrivePoseController::spinOnce()
00317 {
00318 if (this->getState())
00319 {
00320 ROS_DEBUG_STREAM_THROTTLE(1.0, "Controller spinning. [" << name_ <<"]");
00321
00322 if (!getPoseDiff())
00323 {
00324 ROS_WARN_STREAM_THROTTLE(1.0, "Getting pose difference failed. Skipping control loop. [" << name_ <<"]");
00325 return;
00326 }
00327
00328 getControlOutput();
00329
00330 setControlOutput();
00331
00332 ROS_DEBUG_STREAM_THROTTLE(1.0, "Current state: [" << name_ <<"]");
00333 ROS_DEBUG_STREAM_THROTTLE(1.0, "r = " << r_ << ", theta = " << theta_ << ", delta = " << delta_
00334 << " [" << name_ <<"]");
00335 ROS_DEBUG_STREAM_THROTTLE(1.0, "cur = " << cur_ << ", v = " << v_ << ", w = " << w_ << " [" << name_ <<"]");
00336 }
00337 else
00338 {
00339 ROS_DEBUG_STREAM_THROTTLE(3.0, "Controller is disabled. Idling ... [" << name_ <<"]");
00340 }
00341 };
00342
00343 bool DiffDrivePoseController::getPoseDiff()
00344 {
00345
00346 try
00347 {
00348 tf_listener_.lookupTransform(base_frame_name_, goal_frame_name_, ros::Time(0), tf_goal_pose_rel_);
00349 }
00350 catch (tf::TransformException const &ex)
00351 {
00352 ROS_WARN_STREAM_THROTTLE(1.0, "Couldn't get transform from base to goal pose! [" << name_ <<"]");
00353 ROS_DEBUG_STREAM_THROTTLE(1.0, "tf error: " << ex.what());
00354 return false;
00355 }
00356
00357
00358 r_ = std::sqrt(std::pow(tf_goal_pose_rel_.getOrigin().getX(), 2)
00359 + std::pow(tf_goal_pose_rel_.getOrigin().getY(), 2));
00360
00361 delta_ = std::atan2(-tf_goal_pose_rel_.getOrigin().getY(), tf_goal_pose_rel_.getOrigin().getX());
00362
00363
00364
00365 double heading = mtk::wrapAngle(tf::getYaw(tf_goal_pose_rel_.getRotation()));
00366 theta_ = heading + delta_;
00367
00368 return true;
00369 };
00370
00371 void DiffDrivePoseController::getControlOutput()
00372 {
00373 double atan2_k1_tehta = std::atan2(-theta_, k_1_);
00374
00375 cur_ = (-1 / r_) * (k_2_ * (delta_ - atan2_k1_tehta)
00376 + (1 + (k_1_ / (1 + std::pow((k_1_ * theta_), 2)))) * sin(delta_));
00377 v_ = v_max_ / (1 + beta_ * std::pow(std::abs(cur_), lambda_));
00378
00379 v_ = boundRange(v_, v_min_, v_max_);
00380
00381 w_ = cur_ * v_;
00382 w_ = boundRange(w_, w_min_, w_max_);
00383
00384
00385 if (r_ <= dist_thres_)
00386 {
00387 v_ = 0;
00388 if (std::abs(delta_ - theta_) <= orient_thres_)
00389 {
00390 w_ = 0;
00391 }
00392 }
00393
00394
00395 if ((r_ <= dist_thres_) && (std::abs(delta_ - theta_) <= orient_thres_))
00396 {
00397 if (!pose_reached_)
00398 {
00399 pose_reached_ = true;
00400 ROS_INFO_STREAM("Pose reached. [" << name_ <<"]");
00401 std_msgs::Bool bool_msg;
00402 bool_msg.data = true;
00403 pose_reached_publisher_.publish(bool_msg);
00404 }
00405 }
00406 else if ((r_ > (dist_thres_ + dist_eps_)) || (std::abs(delta_ - theta_) > (orient_thres_ + orient_eps_)))
00407 {
00408 if (pose_reached_)
00409 {
00410 pose_reached_ = false;
00411 ROS_INFO_STREAM("Tracking new goal pose. [" << name_ <<"]");
00412 }
00413 }
00414 };
00415
00416 double DiffDrivePoseController::boundRange(double v, double min, double max)
00417 {
00418
00419 if (v < 0.0)
00420 {
00421 if (v > -min)
00422 {
00423 v = -min;
00424 }
00425 else if (v < -max)
00426 {
00427 v = -max;
00428 }
00429 }
00430 else
00431 {
00432 if (v < min)
00433 {
00434 v = min;
00435 }
00436 else if (v > max)
00437 {
00438 v = max;
00439 }
00440 }
00441
00442 return v;
00443 }
00444
00445 void DiffDrivePoseController::setControlOutput()
00446 {
00447 geometry_msgs::TwistPtr cmd_vel(new geometry_msgs::Twist());
00448 if (!pose_reached_)
00449 {
00450 cmd_vel->linear.x = v_;
00451 cmd_vel->angular.z = w_;
00452 }
00453 command_velocity_publisher_.publish(cmd_vel);
00454 };
00455
00456 void DiffDrivePoseController::controlMaxVelCB(const std_msgs::Float32ConstPtr msg)
00457 {
00458 v_max_ = msg->data;
00459 ROS_INFO_STREAM("Maximum linear control velocity has been set to " << v_max_ << ". [" << name_ << "]");
00460 };
00461
00462 void DiffDrivePoseController::enableCB(const std_msgs::StringConstPtr msg)
00463 {
00464 if (this->enable())
00465 {
00466 goal_frame_name_ = msg->data;
00467 ROS_INFO_STREAM("Controller has been enabled. [" << name_ << "] with goal frame [" << goal_frame_name_ << "]");
00468 }
00469 else
00470 {
00471 ROS_INFO_STREAM("Controller was already enabled. [" << name_ <<"] with Goal frame [" << goal_frame_name_ << "]");
00472 }
00473 };
00474
00475 void DiffDrivePoseController::disableCB(const std_msgs::EmptyConstPtr msg)
00476 {
00477 if (this->disable())
00478 {
00479 ROS_INFO_STREAM("Controller has been disabled. [" << name_ <<"]");
00480 }
00481 else
00482 {
00483 ROS_INFO_STREAM("Controller was already disabled. [" << name_ <<"]");
00484 }
00485 };
00486
00487 }
00488
00489 #endif