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
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
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
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
00167 min_velocity_ = req.min_velocity;
00168 max_velocity_ = req.max_velocity;
00169
00170
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
00244
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
00255 bool in_deadband = hysteresis_deadband.is_in_deadband(command_, error_position, position_deadband);
00256
00257 if (in_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
00268 commanded_velocity = pid_controller_position_->computeCommand(-error_position, period);
00269
00270 commanded_velocity = max(commanded_velocity, min_velocity_);
00271 commanded_velocity = min(commanded_velocity, max_velocity_);
00272
00274
00276
00277
00278 if (!in_deadband)
00279 {
00280
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
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
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
00305
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
00391
00392
00393
00394
00395
00396