srh_muscle_joint_position_controller.cpp
Go to the documentation of this file.
00001 
00027 #include "sr_mechanism_controllers/srh_muscle_joint_position_controller.hpp"
00028 #include "angles/angles.h"
00029 #include "pluginlib/class_list_macros.h"
00030 #include <sstream>
00031 #include <math.h>
00032 #include "sr_utilities/sr_math_utils.hpp"
00033 
00034 #include <std_msgs/Float64.h>
00035 
00036 PLUGINLIB_EXPORT_CLASS(controller::SrhMuscleJointPositionController, controller_interface::ControllerBase)
00037 
00038 using namespace std;
00039 
00040 namespace controller
00041 {
00042 
00043 SrhMuscleJointPositionController::SrhMuscleJointPositionController()
00044   : position_deadband(0.015), command_acc_(0)
00045 {
00046 }
00047 
00048 bool SrhMuscleJointPositionController::init(ros_ethercat_model::RobotState *robot, ros::NodeHandle &n)
00049 {
00050   ROS_ASSERT(robot);
00051   robot_ = robot;
00052   node_ = n;
00053 
00054   if (!node_.getParam("joint", joint_name_))
00055   {
00056     ROS_ERROR("No joint given (namespace: %s)", node_.getNamespace().c_str());
00057     return false;
00058   }
00059 
00060   pid_controller_position_.reset(new control_toolbox::Pid());
00061   if (!pid_controller_position_->init(ros::NodeHandle(node_, "pid")))
00062     return false;
00063 
00064   controller_state_publisher_.reset(
00065                                     new realtime_tools::RealtimePublisher<sr_robot_msgs::JointMusclePositionControllerState>
00066                                     (node_, "state", 1));
00067 
00068   ROS_DEBUG(" --------- ");
00069   ROS_DEBUG_STREAM("Init: " << joint_name_);
00070 
00071   // joint 0s e.g. FFJ0
00072   has_j2 = is_joint_0();
00073   if (has_j2)
00074   {
00075     get_joints_states_1_2();
00076     if (!joint_state_)
00077     {
00078       ROS_ERROR("SrhMuscleJointPositionController could not find the first joint relevant to \"%s\"\n", joint_name_.c_str());
00079       return false;
00080     }
00081     if (!joint_state_2)
00082     {
00083       ROS_ERROR("SrhMuscleJointPositionController could not find the second joint relevant to \"%s\"\n", joint_name_.c_str());
00084       return false;
00085     }
00086   }
00087   else
00088   {
00089     joint_state_ = robot_->getJointState(joint_name_);
00090     if (!joint_state_)
00091     {
00092       ROS_ERROR("SrhMuscleJointPositionController could not find joint named \"%s\"\n", joint_name_.c_str());
00093       return false;
00094     }
00095   }
00096 
00097   //get the min and max value for the current joint:
00098   get_min_max(robot_->robot_model_, joint_name_);
00099 
00100   friction_compensator.reset(new sr_friction_compensation::SrFrictionCompensator(joint_name_));
00101 
00102   serve_set_gains_ = node_.advertiseService("set_gains", &SrhMuscleJointPositionController::setGains, this);
00103   serve_reset_gains_ = node_.advertiseService("reset_gains", &SrhMuscleJointPositionController::resetGains, this);
00104 
00105   after_init();
00106   return true;
00107 }
00108 
00109 void SrhMuscleJointPositionController::starting(const ros::Time& time)
00110 {
00111   resetJointState();
00112   pid_controller_position_->reset();
00113   read_parameters();
00114 
00115   if (has_j2)
00116     ROS_WARN_STREAM("Reseting PID for joints " << joint_state_->joint_->name << " and " << joint_state_2->joint_->name);
00117   else
00118     ROS_WARN_STREAM("Reseting PID for joint  " << joint_state_->joint_->name);
00119 }
00120 
00121 bool SrhMuscleJointPositionController::setGains(sr_robot_msgs::SetPidGains::Request &req,
00122                                                 sr_robot_msgs::SetPidGains::Response &resp)
00123 {
00124   ROS_INFO_STREAM("Setting new PID parameters. P:" << req.p << " / I:" << req.i <<
00125                   " / D:" << req.d << " / IClamp:" << req.i_clamp << ", max force: " << req.max_force << ", friction deadband: " << req.friction_deadband << " pos deadband: " << req.deadband);
00126   pid_controller_position_->setGains(req.p, req.i, req.d, req.i_clamp, -req.i_clamp);
00127   max_force_demand = req.max_force;
00128   friction_deadband = req.friction_deadband;
00129   position_deadband = req.deadband;
00130 
00131   //Setting the new parameters in the parameter server
00132   node_.setParam("pid/p", req.p);
00133   node_.setParam("pid/i", req.i);
00134   node_.setParam("pid/d", req.d);
00135   node_.setParam("pid/i_clamp", req.i_clamp);
00136   node_.setParam("pid/max_force", max_force_demand);
00137   node_.setParam("pid/position_deadband", position_deadband);
00138   node_.setParam("pid/friction_deadband", friction_deadband);
00139 
00140   return true;
00141 }
00142 
00143 bool SrhMuscleJointPositionController::resetGains(std_srvs::Empty::Request& req, std_srvs::Empty::Response& resp)
00144 {
00145   resetJointState();
00146 
00147   if (!pid_controller_position_->init(ros::NodeHandle(node_, "pid")))
00148     return false;
00149 
00150   read_parameters();
00151 
00152   if (has_j2)
00153     ROS_WARN_STREAM("Reseting controller gains: " << joint_state_->joint_->name << " and " << joint_state_2->joint_->name);
00154   else
00155     ROS_WARN_STREAM("Reseting controller gains: " << joint_state_->joint_->name);
00156 
00157   return true;
00158 }
00159 
00160 void SrhMuscleJointPositionController::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
00161 {
00162   pid_controller_position_->getGains(p, i, d, i_max, i_min);
00163 }
00164 
00165 void SrhMuscleJointPositionController::update(const ros::Time& time, const ros::Duration& period)
00166 {
00167   //The valve commands can have values between -4 and 4
00168   int8_t valve[2];
00169 
00170   ROS_ASSERT(robot_ != NULL);
00171   ROS_ASSERT(joint_state_->joint_);
00172 
00173   if (!initialized_)
00174   {
00175     resetJointState();
00176     initialized_ = true;
00177   }
00178   if (has_j2)
00179     command_ = joint_state_->commanded_position_ + joint_state_2->commanded_position_;
00180   else
00181     command_ = joint_state_->commanded_position_;
00182   command_ = clamp_command(command_);
00183 
00184   //IGNORE the following  lines if we don't want to use the pressure sensors data
00185   //We don't want to define a modified version of JointState, as that would imply using a modified version of robot_state.hpp, controller manager,
00186   //ethercat_hardware and ros_etherCAT main loop
00187   // So we have encoded the two uint16 that contain the data from the muscle pressure sensors into the double effort_. (We don't
00188   // have any measured effort in the muscle hand anyway).
00189   // Here we extract the pressure values from joint_state_->effort_ and decode that back into uint16.
00190   double pressure_0_tmp = fmod(joint_state_->effort_, 0x10000);
00191   double pressure_1_tmp = (fmod(joint_state_->effort_, 0x100000000) - pressure_0_tmp) / 0x10000;
00192   uint16_t pressure_0 = static_cast<uint16_t> (pressure_0_tmp + 0.5);
00193   uint16_t pressure_1 = static_cast<uint16_t> (pressure_1_tmp + 0.5);
00194 
00195   //****************************************
00196 
00197   command_ = clamp_command(command_);
00198 
00199   //Compute position demand from position error:
00200   double error_position = 0.0;
00201 
00202   if (has_j2)
00203     error_position = (joint_state_->position_ + joint_state_2->position_) - command_;
00204   else
00205     error_position = joint_state_->position_ - command_;
00206 
00207   bool in_deadband = hysteresis_deadband.is_in_deadband(command_, error_position, position_deadband);
00208 
00209   //don't compute the error if we're in the deadband.
00210   if (in_deadband)
00211     error_position = 0.0;
00212 
00213   //Run the PID loop to get a new command, we don't do this at the full rate
00214   //as that will drive the valves too hard with switch changes. Instead we
00215   //store a longer time in the command accumulator to keep using at the full
00216   //loop rate.
00217   if (loop_count_ % 50 == 0)
00218   {
00219     double commanded_effort = pid_controller_position_->computeCommand(-error_position, period);
00220 
00221     //clamp the result to max force
00222     commanded_effort = min(commanded_effort, max_force_demand);
00223     commanded_effort = max(commanded_effort, -max_force_demand);
00224 
00225     if (!in_deadband)
00226     {
00227       if (has_j2)
00228         commanded_effort += friction_compensator->friction_compensation(joint_state_->position_ + joint_state_2->position_, joint_state_->velocity_ + joint_state_2->velocity_, int(commanded_effort), friction_deadband);
00229       else
00230         commanded_effort += friction_compensator->friction_compensation(joint_state_->position_, joint_state_->velocity_, int(commanded_effort), friction_deadband);
00231     }
00232 
00233     command_acc_ = commanded_effort;
00234   }
00235 
00236   // Drive the joint from the accumulator. This runs at full update speed so
00237   // we can keep valves open continuously (with high enough P). A value of 4 fills
00238   // the valve for the whole of the next 1ms. 2 for half that time etc. Negative
00239   // values empty the valve.
00240   // The 2 involved muscles will act complementary for the moment, when one inflates,
00241   // the other deflates at the same rate
00242   double amt = abs(command_acc_) < 4 ? fabs(command_acc_) : 4;
00243   if (abs(command_acc_) == 0)
00244   {
00245     valve[0] = 0;
00246     valve[1] = 0;
00247   }
00248   else if (command_acc_ > 0)
00249   {
00250     command_acc_ -= amt;
00251     valve[0] = amt;
00252     valve[1] = -amt;
00253   }
00254   else
00255   {
00256     command_acc_ += amt;
00257     valve[0] = -amt;
00258     valve[1] = amt;
00259   }
00260 
00261 
00262   //************************************************
00263   // After doing any computation we consider, we encode the obtained valve commands into joint_state_->commanded_effort_
00264   //We don't want to define a modified version of JointState, as that would imply using a modified version of robot_state.hpp, controller manager,
00265   //ethercat_hardware and ros_etherCAT main loop
00266   // So the controller encodes the two int8 (that are in fact int4) that contain the valve commands into the double commanded_effort_. (We don't
00267   // have any real commanded_effort_ in the muscle hand anyway).
00268 
00269   uint16_t valve_tmp[2];
00270   for (int i = 0; i < 2; ++i)
00271   {
00272     //Check that the limits of the valve command are not exceded
00273     if (valve[i] > 4)
00274       valve[i] = 4;
00275     if (valve[i] < -4)
00276       valve[i] = -4;
00277     //encode
00278     if (valve[i] < 0)
00279       valve_tmp[i] = -valve[i] + 8;
00280     else
00281       valve_tmp[i] = valve[i];
00282   }
00283 
00284   //We encode the valve 0 command in the lowest "half byte" i.e. the lowest 16 integer values in the double var (see decoding in simple_transmission_for_muscle.cpp)
00285   //the valve 1 command is encoded in the next 4 bits
00286   joint_state_->commanded_effort_ = static_cast<double> (valve_tmp[0]) + static_cast<double> (valve_tmp[1] << 4);
00287 
00288   //*******************************************************************************
00289 
00290   // Send status msg
00291   if (loop_count_ % 10 == 0)
00292   {
00293     if (controller_state_publisher_ && controller_state_publisher_->trylock())
00294     {
00295       controller_state_publisher_->msg_.header.stamp = time;
00296       controller_state_publisher_->msg_.set_point = command_;
00297       if (has_j2)
00298       {
00299         controller_state_publisher_->msg_.process_value = joint_state_->position_ + joint_state_2->position_;
00300         controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_ + joint_state_2->velocity_;
00301       }
00302       else
00303       {
00304         controller_state_publisher_->msg_.process_value = joint_state_->position_;
00305         controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_;
00306       }
00307 
00308       controller_state_publisher_->msg_.error = error_position;
00309       controller_state_publisher_->msg_.time_step = period.toSec();
00310       controller_state_publisher_->msg_.pseudo_command = command_acc_;
00311       controller_state_publisher_->msg_.valve_muscle_0 = valve[0];
00312       controller_state_publisher_->msg_.valve_muscle_1 = valve[1];
00313       controller_state_publisher_->msg_.packed_valve = joint_state_->commanded_effort_;
00314       controller_state_publisher_->msg_.muscle_pressure_0 = pressure_0;
00315       controller_state_publisher_->msg_.muscle_pressure_1 = pressure_1;
00316 
00317 
00318       double dummy;
00319       getGains(controller_state_publisher_->msg_.p,
00320                controller_state_publisher_->msg_.i,
00321                controller_state_publisher_->msg_.d,
00322                controller_state_publisher_->msg_.i_clamp,
00323                dummy);
00324       controller_state_publisher_->unlockAndPublish();
00325     }
00326   }
00327   loop_count_++;
00328 }
00329 
00330 void SrhMuscleJointPositionController::read_parameters()
00331 {
00332   node_.param<double>("pid/max_force", max_force_demand, 1023.0);
00333   node_.param<double>("pid/position_deadband", position_deadband, 0.015);
00334   node_.param<int>("pid/friction_deadband", friction_deadband, 5);
00335 }
00336 
00337 void SrhMuscleJointPositionController::setCommandCB(const std_msgs::Float64ConstPtr& msg)
00338 {
00339   joint_state_->commanded_position_ = msg->data;
00340   if (has_j2)
00341     joint_state_2->commanded_position_ = 0.0;
00342 }
00343 
00344 void SrhMuscleJointPositionController::resetJointState()
00345 {
00346   if (has_j2)
00347   {
00348     joint_state_->commanded_position_ = joint_state_->position_;
00349     joint_state_2->commanded_position_ = joint_state_2->position_;
00350     command_ = joint_state_->position_ + joint_state_2->position_;
00351   }
00352   else
00353   {
00354     joint_state_->commanded_position_ = joint_state_->position_;
00355     command_ = joint_state_->position_;
00356   }
00357 }
00358 }
00359 
00360 /* For the emacs weenies in the crowd.
00361 Local Variables:
00362    c-basic-offset: 2
00363 End:
00364  */
00365 
00366 


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