srh_mixed_position_velocity_controller.cpp
Go to the documentation of this file.
00001 
00029 #include "sr_mechanism_controllers/srh_mixed_position_velocity_controller.hpp"
00030 #include "angles/angles.h"
00031 #include "pluginlib/class_list_macros.h"
00032 #include <sstream>
00033 #include <math.h>
00034 #include "sr_utilities/sr_math_utils.hpp"
00035 
00036 #include <std_msgs/Float64.h>
00037 
00038 PLUGINLIB_EXPORT_CLASS(controller::SrhMixedPositionVelocityJointController, controller_interface::ControllerBase)
00039 
00040 using namespace std;
00041 
00042 namespace controller
00043 {
00044 
00045 SrhMixedPositionVelocityJointController::SrhMixedPositionVelocityJointController()
00046   : max_velocity_(1.0), min_velocity_(-1.0),
00047   position_deadband(0.05), motor_min_force_threshold(0)
00048 {
00049 }
00050 
00051 bool SrhMixedPositionVelocityJointController::init(ros_ethercat_model::RobotState *robot, ros::NodeHandle &n)
00052 {
00053   ROS_ASSERT(robot);
00054   robot_ = robot;
00055   node_ = n;
00056 
00057   if (!node_.getParam("joint", joint_name_))
00058   {
00059     ROS_ERROR("No joint given (namespace: %s)", node_.getNamespace().c_str());
00060     return false;
00061   }
00062 
00063   pid_controller_position_.reset(new control_toolbox::Pid());
00064   if (!pid_controller_position_->init(ros::NodeHandle(node_, "position_pid")))
00065     return false;
00066 
00067   pid_controller_velocity_.reset(new control_toolbox::Pid());
00068   if (!pid_controller_velocity_->init(ros::NodeHandle(node_, "velocity_pid")))
00069     return false;
00070 
00071   controller_state_publisher_.reset(new realtime_tools::RealtimePublisher<sr_robot_msgs::JointControllerState>
00072                                     (node_, "state", 1));
00073 
00074   ROS_DEBUG(" --------- ");
00075   ROS_DEBUG_STREAM("Init: " << joint_name_);
00076 
00077   // joint 0s e.g. FFJ0
00078   has_j2 = is_joint_0();
00079   if (has_j2)
00080   {
00081     get_joints_states_1_2();
00082     if (!joint_state_)
00083     {
00084       ROS_ERROR("SrhMixedPositionVelocityController could not find the first joint relevant to \"%s\"\n", joint_name_.c_str());
00085       return false;
00086     }
00087     if (!joint_state_2)
00088     {
00089       ROS_ERROR("SrhMixedPositionVelocityController could not find the second joint relevant to \"%s\"\n", joint_name_.c_str());
00090       return false;
00091     }
00092     if (!joint_state_2->calibrated_)
00093     {
00094       ROS_ERROR("Joint %s not calibrated for SrhMixedPositionVelocityController", joint_name_.c_str());
00095       return false;
00096     }
00097     else
00098       joint_state_->calibrated_ = true;
00099   }
00100   else //"normal" joints
00101   {
00102     joint_state_ = robot_->getJointState(joint_name_);
00103     if (!joint_state_)
00104     {
00105       ROS_ERROR("SrhMixedPositionVelocityController could not find joint named \"%s\"\n",
00106                 joint_name_.c_str());
00107       return false;
00108     }
00109     if (!joint_state_->calibrated_)
00110     {
00111       ROS_ERROR("Joint %s not calibrated for SrhMixedPositionVelocityJointController", joint_name_.c_str());
00112       return false;
00113     }
00114   }
00115   friction_compensator.reset(new sr_friction_compensation::SrFrictionCompensator(joint_name_));
00116 
00117   //get the min and max value for the current joint:
00118   get_min_max(robot_->robot_model_, joint_name_);
00119 
00120   serve_set_gains_ = node_.advertiseService("set_gains", &SrhMixedPositionVelocityJointController::setGains, this);
00121   serve_reset_gains_ = node_.advertiseService("reset_gains", &SrhMixedPositionVelocityJointController::resetGains, this);
00122 
00123   ROS_DEBUG_STREAM(" joint_state name: " << joint_state_->joint_->name);
00124   ROS_DEBUG_STREAM(" In Init: " << getJointName() << " This: " << this
00125                    << " joint_state: " << joint_state_);
00126 
00127 #ifdef DEBUG_PUBLISHER
00128   if (string("FFJ3").compare(getJointName()) == 0)
00129   {
00130     ROS_INFO("Publishing debug info for FFJ3 mixed position/velocity controller");
00131     stringstream ss2;
00132     ss2 << getJointName() << "debug_velocity";
00133     debug_pub = n_tilde_.advertise<std_msgs::Float64>(ss2.str(), 2);
00134   }
00135 #endif
00136 
00137   after_init();
00138   return true;
00139 }
00140 
00141 void SrhMixedPositionVelocityJointController::starting(const ros::Time& time)
00142 {
00143   resetJointState();
00144   pid_controller_position_->reset();
00145   pid_controller_velocity_->reset();
00146   read_parameters();
00147 
00148   if (has_j2)
00149     ROS_WARN_STREAM("Reseting PID for joints " << joint_state_->joint_->name << " and " << joint_state_2->joint_->name);
00150   else
00151     ROS_WARN_STREAM("Reseting PID for joint  " << joint_state_->joint_->name);
00152 }
00153 
00154 bool SrhMixedPositionVelocityJointController::setGains(sr_robot_msgs::SetMixedPositionVelocityPidGains::Request &req,
00155                                                        sr_robot_msgs::SetMixedPositionVelocityPidGains::Response &resp)
00156 {
00157   ROS_INFO_STREAM("New parameters: " << "PID pos: [" << req.position_p << ", " << req.position_i << ", " << req.position_d << ", " << req.position_i_clamp << "] PID vel: [" << req.velocity_p << ", " << req.velocity_i << ", " << req.velocity_d << ", " << req.velocity_i_clamp << "], max force: " << req.max_force << ", friction deadband: " << req.friction_deadband << " pos deadband: " << req.position_deadband << " min and max vel: [" << req.min_velocity << ", " << req.max_velocity << "]");
00158 
00159   pid_controller_position_->setGains(req.position_p, req.position_i, req.position_d, req.position_i_clamp, -req.position_i_clamp);
00160 
00161   pid_controller_velocity_->setGains(req.velocity_p, req.velocity_i, req.velocity_d, req.velocity_i_clamp, -req.velocity_i_clamp);
00162   max_force_demand = req.max_force;
00163   friction_deadband = req.friction_deadband;
00164   position_deadband = req.position_deadband;
00165 
00166   //setting the position controller parameters
00167   min_velocity_ = req.min_velocity;
00168   max_velocity_ = req.max_velocity;
00169 
00170   //Setting the new parameters in the parameter server
00171   node_.setParam("position_pid/p", req.position_p);
00172   node_.setParam("position_pid/i", req.position_i);
00173   node_.setParam("position_pid/d", req.position_d);
00174   node_.setParam("position_pid/i_clamp", req.position_i_clamp);
00175 
00176   node_.setParam("velocity_pid/p", req.velocity_p);
00177   node_.setParam("velocity_pid/i", req.velocity_i);
00178   node_.setParam("velocity_pid/d", req.velocity_d);
00179   node_.setParam("velocity_pid/i_clamp", req.velocity_i_clamp);
00180 
00181   node_.setParam("position_pid/min_velocity", min_velocity_);
00182   node_.setParam("position_pid/max_velocity", max_velocity_);
00183   node_.setParam("position_pid/position_deadband", position_deadband);
00184 
00185   node_.setParam("velocity_pid/friction_deadband", friction_deadband);
00186   node_.setParam("velocity_pid/max_force", max_force_demand);
00187   node_.setParam("motor_min_force_threshold", motor_min_force_threshold);
00188 
00189   return true;
00190 }
00191 
00192 bool SrhMixedPositionVelocityJointController::resetGains(std_srvs::Empty::Request& req, std_srvs::Empty::Response& resp)
00193 {
00194   resetJointState();
00195 
00196   if (!pid_controller_position_->init(ros::NodeHandle(node_, "position_pid")))
00197     return false;
00198 
00199   if (!pid_controller_velocity_->init(ros::NodeHandle(node_, "velocity_pid")))
00200     return false;
00201 
00202   read_parameters();
00203 
00204   if (has_j2)
00205     ROS_WARN_STREAM("Reseting controller gains: " << joint_state_->joint_->name << " and " << joint_state_2->joint_->name);
00206   else
00207     ROS_WARN_STREAM("Reseting controller gains: " << joint_state_->joint_->name);
00208 
00209   return true;
00210 }
00211 
00212 void SrhMixedPositionVelocityJointController::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
00213 {
00214   pid_controller_position_->getGains(p, i, d, i_max, i_min);
00215 }
00216 
00217 void SrhMixedPositionVelocityJointController::getGains_velocity(double &p, double &i, double &d, double &i_max, double &i_min)
00218 {
00219   pid_controller_velocity_->getGains(p, i, d, i_max, i_min);
00220 }
00221 
00222 void SrhMixedPositionVelocityJointController::update(const ros::Time& time, const ros::Duration& period)
00223 {
00224   if (!has_j2 &&!joint_state_->calibrated_)
00225     return;
00226 
00227   ROS_ASSERT(robot_);
00228   ROS_ASSERT(joint_state_->joint_);
00229 
00230   if (!initialized_)
00231   {
00232     resetJointState();
00233     initialized_ = true;
00234   }
00235   if (has_j2)
00236     command_ = joint_state_->commanded_position_ + joint_state_2->commanded_position_;
00237   else
00238     command_ = joint_state_->commanded_position_;
00239   command_ = clamp_command(command_);
00240 
00242   // POSITION
00244   //Compute velocity demand from position error:
00245   double error_position = 0.0;
00246   if (has_j2)
00247   {
00248     error_position = command_ - (joint_state_->position_ + joint_state_2->position_);
00249     ROS_DEBUG_STREAM("j0: " << joint_state_->position_ + joint_state_2->position_);
00250   }
00251   else
00252     error_position = command_ - joint_state_->position_;
00253 
00254   //are we in the deadband?
00255   bool in_deadband = hysteresis_deadband.is_in_deadband(command_, error_position, position_deadband);
00256 
00257   if (in_deadband) //consider the error as 0 if we're in the deadband
00258   {
00259     error_position = 0.0;
00260     pid_controller_position_->reset();
00261   }
00262 
00263   double commanded_velocity = 0.0;
00264   double error_velocity = 0.0;
00265   double commanded_effort = 0.0;
00266 
00267   //compute the velocity demand using the position pid loop
00268   commanded_velocity = pid_controller_position_->computeCommand(-error_position, period);
00269   //saturate the velocity demand
00270   commanded_velocity = max(commanded_velocity, min_velocity_);
00271   commanded_velocity = min(commanded_velocity, max_velocity_);
00272 
00274   // VELOCITY
00276 
00277   //velocity loop:
00278   if (!in_deadband) //don't compute the error if we're in the deadband
00279   {
00280     //we're not in the deadband, compute the error
00281     if (has_j2)
00282       error_velocity = commanded_velocity - (joint_state_->velocity_ + joint_state_2->velocity_);
00283     else
00284       error_velocity = commanded_velocity - joint_state_->velocity_;
00285   }
00286   commanded_effort = pid_controller_velocity_->computeCommand(-error_velocity, period);
00287 
00288   //clamp the result to max force
00289   commanded_effort = min(commanded_effort, (max_force_demand * max_force_factor_));
00290   commanded_effort = max(commanded_effort, -(max_force_demand * max_force_factor_));
00291 
00292   //Friction compensation, only if we're not in the deadband.
00293   int friction_offset = 0;
00294   if (!in_deadband)
00295   {
00296     if (has_j2)
00297       friction_offset = friction_compensator->friction_compensation(joint_state_->position_ + joint_state_2->position_, joint_state_->velocity_ + joint_state_2->velocity_, int(commanded_effort), friction_deadband);
00298     else
00299       friction_offset = friction_compensator->friction_compensation(joint_state_->position_, joint_state_->velocity_, int(commanded_effort), friction_deadband);
00300 
00301     commanded_effort += friction_offset;
00302   }
00303 
00304   //if the demand is too small to be executed by the motor, then we ask for a force
00305   // of 0
00306   if (fabs(commanded_effort) <= motor_min_force_threshold)
00307     commanded_effort = 0.0;
00308 
00309   joint_state_->commanded_effort_ = commanded_effort;
00310 
00311   if (loop_count_ % 10 == 0)
00312   {
00313     if (controller_state_publisher_ && controller_state_publisher_->trylock())
00314     {
00315       controller_state_publisher_->msg_.header.stamp = time;
00316       controller_state_publisher_->msg_.set_point = command_;
00317       if (has_j2)
00318       {
00319         controller_state_publisher_->msg_.process_value = joint_state_->position_ + joint_state_2->position_;
00320         controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_ + joint_state_2->velocity_;
00321       }
00322       else
00323       {
00324         controller_state_publisher_->msg_.process_value = joint_state_->position_;
00325         controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_;
00326       }
00327       controller_state_publisher_->msg_.commanded_velocity = commanded_velocity;
00328 
00329       controller_state_publisher_->msg_.error = error_position;
00330       controller_state_publisher_->msg_.time_step = period.toSec();
00331 
00332       controller_state_publisher_->msg_.command = commanded_effort;
00333       controller_state_publisher_->msg_.measured_effort = joint_state_->effort_;
00334 
00335       controller_state_publisher_->msg_.friction_compensation = friction_offset;
00336 
00337       double dummy;
00338       getGains(controller_state_publisher_->msg_.position_p,
00339                controller_state_publisher_->msg_.position_i,
00340                controller_state_publisher_->msg_.position_d,
00341                controller_state_publisher_->msg_.position_i_clamp,
00342                dummy);
00343 
00344       getGains_velocity(controller_state_publisher_->msg_.velocity_p,
00345                         controller_state_publisher_->msg_.velocity_i,
00346                         controller_state_publisher_->msg_.velocity_d,
00347                         controller_state_publisher_->msg_.velocity_i_clamp,
00348                         dummy);
00349 
00350       controller_state_publisher_->unlockAndPublish();
00351     }
00352   }
00353   loop_count_++;
00354 }
00355 
00356 void SrhMixedPositionVelocityJointController::read_parameters()
00357 {
00358   node_.param<double>("position_pid/min_velocity", min_velocity_, -1.0);
00359   node_.param<double>("position_pid/max_velocity", max_velocity_, 1.0);
00360   node_.param<double>("position_pid/position_deadband", position_deadband, 0.015);
00361 
00362   node_.param<int>("velocity_pid/friction_deadband", friction_deadband, 5);
00363   node_.param<double>("velocity_pid/max_force", max_force_demand, 1023.0);
00364   node_.param<int>("motor_min_force_threshold", motor_min_force_threshold, 0);
00365 }
00366 
00367 void SrhMixedPositionVelocityJointController::setCommandCB(const std_msgs::Float64ConstPtr& msg)
00368 {
00369   joint_state_->commanded_position_ = msg->data;
00370   if (has_j2)
00371     joint_state_2->commanded_position_ = 0.0;
00372 }
00373 
00374 void SrhMixedPositionVelocityJointController::resetJointState()
00375 {
00376     if (has_j2)
00377     {
00378       joint_state_->commanded_position_ = joint_state_->position_;
00379       joint_state_2->commanded_position_ = joint_state_2->position_;
00380       command_ = joint_state_->position_ + joint_state_2->position_;
00381     }
00382     else
00383     {
00384       joint_state_->commanded_position_ = joint_state_->position_;
00385       command_ = joint_state_->position_;
00386     }
00387 }
00388 }
00389 
00390 /* For the emacs weenies in the crowd.
00391 Local Variables:
00392    c-basic-offset: 2
00393 End:
00394  */
00395 
00396 


sr_mechanism_controllers
Author(s): Ugo Cupcic
autogenerated on Fri Aug 21 2015 12:26:14