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
00035 #include "joint_qualification_controllers/hysteresis_controller.h"
00036 #include "pluginlib/class_list_macros.h"
00037 #include "urdf_model/joint.h"
00038
00039 PLUGINLIB_DECLARE_CLASS(joint_qualification_controllers, HysteresisController,
00040 joint_qualification_controllers::HysteresisController,
00041 pr2_controller_interface::Controller)
00042
00043 #define MAX_DATA_POINTS 120000
00044
00045 using namespace std;
00046 using namespace joint_qualification_controllers;
00047
00048 HysteresisController::HysteresisController() :
00049 joint_(NULL),
00050 robot_(NULL),
00051 data_sent_(false),
00052 hyst_pub_(NULL)
00053 {
00054 test_data_.joint_name = "default joint";
00055 test_data_.time_up.resize(MAX_DATA_POINTS);
00056 test_data_.effort_up.resize(MAX_DATA_POINTS);
00057 test_data_.position_up.resize(MAX_DATA_POINTS);
00058 test_data_.velocity_up.resize(MAX_DATA_POINTS);
00059
00060 test_data_.time_down.resize(MAX_DATA_POINTS);
00061 test_data_.effort_down.resize(MAX_DATA_POINTS);
00062 test_data_.position_down.resize(MAX_DATA_POINTS);
00063 test_data_.velocity_down.resize(MAX_DATA_POINTS);
00064
00065 test_data_.arg_name.resize(14);
00066 test_data_.arg_value.resize(14);
00067 test_data_.arg_name[0] = "Min. Expected Effort";
00068 test_data_.arg_name[1] = "Max. Expected Effort";
00069 test_data_.arg_name[2] = "Minimum Position";
00070 test_data_.arg_name[3] = "Maximum Position";
00071 test_data_.arg_name[4] = "Velocity";
00072 test_data_.arg_name[5] = "Timeout";
00073 test_data_.arg_name[6] = "Max. Allowed Effort";
00074 test_data_.arg_name[7] = "Tolerance";
00075 test_data_.arg_name[8] = "SD Max";
00076 test_data_.arg_name[9] = "Slope";
00077 test_data_.arg_name[10] = "P Gain";
00078 test_data_.arg_name[11] = "I Gain";
00079 test_data_.arg_name[12] = "D Gain";
00080 test_data_.arg_name[13] = "I-Clamp";
00081
00082 state_ = STOPPED;
00083 starting_count_ = 0;
00084 velocity_ = 0;
00085 initial_time_ = ros::Time(0);
00086 max_effort_ = 0;
00087 complete = false;
00088 up_count_ = 0;
00089 down_count_ = 0;
00090 }
00091
00092 HysteresisController::~HysteresisController()
00093 {
00094 if (velocity_controller_) delete velocity_controller_;
00095 }
00096
00097 bool HysteresisController::init( pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n)
00098 {
00099 assert(robot);
00100 robot_ = robot;
00101
00102 std::string name;
00103 if (!n.getParam("velocity_controller/joint", name)){
00104 ROS_ERROR("Hysteresis Controller: No joint name found on parameter namespace: %s)",
00105 n.getNamespace().c_str());
00106 return false;
00107 }
00108 if (!(joint_ = robot->getJointState(name)))
00109 {
00110 ROS_ERROR("HysteresisController could not find joint named \"%s\"\n", name.c_str());
00111 return false;
00112 }
00113
00114 if (!n.getParam("velocity", velocity_)){
00115 ROS_ERROR("Hysteresis Controller: No velocity found on parameter namespace: %s)",
00116 n.getNamespace().c_str());
00117 return false;
00118 }
00119 velocity_ = velocity_ > 0 ? velocity_ : -1.0 * velocity_;
00120
00121 if (!n.getParam("max_effort", max_effort_)){
00122 ROS_ERROR("Hysteresis Controller: No max effort found on parameter namespace: %s)",
00123 n.getNamespace().c_str());
00124 return false;
00125 }
00126
00127 double min_expected, max_expected, max_pos, min_pos;
00128
00129 if (!n.getParam("min_expected", min_expected)){
00130 ROS_ERROR("Hysteresis Controller: No min expected effort found on parameter namespace: %s)",
00131 n.getNamespace().c_str());
00132 return false;
00133 }
00134
00135 if (!n.getParam("max_expected", max_expected)){
00136 ROS_ERROR("Hysteresis Controller: No max expected effort found on parameter namespace: %s)",
00137 n.getNamespace().c_str());
00138 return false;
00139 }
00140
00141 if (!n.getParam("max_position", max_pos)){
00142 ROS_ERROR("Hysteresis Controller: No max position found on parameter namespace: %s)",
00143 n.getNamespace().c_str());
00144 return false;
00145 }
00146
00147 if (!n.getParam("min_position", min_pos)){
00148 ROS_ERROR("Hysteresis Controller: No min position found on parameter namespace: %s)",
00149 n.getNamespace().c_str());
00150 return false;
00151 }
00152
00153 if (!n.getParam("timeout", timeout_)){
00154 ROS_ERROR("Hysteresis Controller: No timeout found on parameter namespace: %s)",
00155 n.getNamespace().c_str());
00156 return false;
00157 }
00158
00159 double tolerance, sd_max;
00160 if (!n.getParam("tolerance", tolerance)){
00161 ROS_WARN("Parameter 'tolerance' is not set on namespace: %s. Default is 0.20.",
00162 n.getNamespace().c_str());
00163
00164 tolerance = 0.20;
00165 }
00166
00167 if (!n.getParam("sd_max", sd_max)) {
00168 ROS_WARN("Parameter 'sd_max' is not set on namespace: %s. Default is 0.20.",
00169 n.getNamespace().c_str());
00170
00171 sd_max = 0.20;
00172 }
00173
00174 double slope;
00175 if (!n.getParam("slope", slope))
00176 slope = 0;
00177
00178 initial_time_ = robot_->getTime();
00179 initial_position_ = joint_->position_;
00180
00181
00182 test_data_.joint_name = name;
00183 test_data_.arg_value[0] = min_expected;
00184 test_data_.arg_value[1] = max_expected;
00185 test_data_.arg_value[2] = min_pos;
00186 test_data_.arg_value[3] = max_pos;
00187 test_data_.arg_value[4] = velocity_;
00188 test_data_.arg_value[5] = timeout_;
00189 test_data_.arg_value[6] = max_effort_;
00190 test_data_.arg_value[7] = tolerance;
00191 test_data_.arg_value[8] = sd_max;
00192 test_data_.arg_value[9] = slope;
00193
00194 velocity_controller_ = new controller::JointVelocityController();
00195 ros::NodeHandle n_vel(n, "velocity_controller");
00196 if (!velocity_controller_->init(robot, n_vel)) return false;
00197
00198
00199 double p, i, d, iClamp, imin;
00200 velocity_controller_->getGains(p, i, d, iClamp, imin);
00201
00202 test_data_.arg_value[10] = p;
00203 test_data_.arg_value[11] = i;
00204 test_data_.arg_value[12] = d;
00205 test_data_.arg_value[13] = iClamp;
00206
00207 hyst_pub_.reset(new realtime_tools::RealtimePublisher<joint_qualification_controllers::HysteresisData>(n, "/test_data", 1, true));
00208
00209 return true;
00210 }
00211
00212 void HysteresisController::starting()
00213 {
00214 velocity_controller_->starting();
00215
00216 initial_time_ = robot_->getTime();
00217 initial_position_ = joint_->position_;
00218 }
00219
00220 void HysteresisController::update()
00221 {
00222 if (!joint_->calibrated_)
00223 return;
00224
00225 ros::Time time = robot_->getTime();
00226 velocity_controller_->update();
00227
00228
00229 if ((time - initial_time_).toSec() > timeout_ && state_ != ANALYZING && state_ != DONE)
00230 {
00231 state_ = ANALYZING;
00232 test_data_.arg_value[5] = -1;
00233 velocity_controller_->setCommand(0.0);
00234 }
00235
00236 switch (state_)
00237 {
00238 case STOPPED:
00239 velocity_controller_->setCommand(-1.0 * velocity_);
00240 starting_count_ = 0;
00241 state_ = MOVING_HOME;
00242 break;
00243 case MOVING_HOME:
00244 starting_count_++;
00245 if (turn() and starting_count_ > 100)
00246 {
00247 velocity_controller_->setCommand(velocity_);
00248 state_ = MOVING_UP;
00249 starting_count_ = 0;
00250 }
00251 break;
00252 case MOVING_UP:
00253 starting_count_++;
00254 if (up_count_ < MAX_DATA_POINTS)
00255 {
00256 test_data_.time_up[up_count_] = time.toSec();
00257 test_data_.effort_up[up_count_] = joint_->measured_effort_;
00258 test_data_.position_up[up_count_] = joint_->position_;
00259 test_data_.velocity_up[up_count_] = joint_->velocity_;
00260 up_count_++;
00261 }
00262
00263 if ((turn() and starting_count_ > 100) or up_count_ >= MAX_DATA_POINTS)
00264 {
00265 velocity_controller_->setCommand(-1.0 * velocity_);
00266 state_ = MOVING_DOWN;
00267 starting_count_ = 0;
00268 }
00269 break;
00270 case MOVING_DOWN:
00271 starting_count_++;
00272 if (down_count_ < MAX_DATA_POINTS)
00273 {
00274 test_data_.time_down[down_count_] = time.toSec();
00275 test_data_.effort_down[down_count_] = joint_->measured_effort_;
00276 test_data_.position_down[down_count_] = joint_->position_;
00277 test_data_.velocity_down[down_count_] = joint_->velocity_;
00278 down_count_++;
00279 }
00280 if ((turn() and starting_count_ > 100) or down_count_ >= MAX_DATA_POINTS)
00281 {
00282 velocity_controller_->setCommand(0.0);
00283 state_ = ANALYZING;
00284 starting_count_ = 0;
00285 }
00286 break;
00287 case ANALYZING:
00288 velocity_controller_->setCommand(0.0);
00289 analysis();
00290 state_ = DONE;
00291 break;
00292 case DONE:
00293 velocity_controller_->setCommand(0.0);
00294 if (!data_sent_)
00295 data_sent_ = sendData();
00296 break;
00297 }
00298
00299 }
00300
00301 bool HysteresisController::turn()
00302 {
00303 if (joint_->joint_->type!=urdf::Joint::CONTINUOUS)
00304 {
00305 return (fabs(joint_->velocity_) < 0.001 && fabs(joint_->commanded_effort_) > max_effort_);
00306 }
00307 else
00308 {
00309 if (fabs(joint_->position_-initial_position_) > 6.28)
00310 {
00311 initial_position_ = joint_->position_;
00312 return true;
00313 }
00314 return false;
00315 }
00316 }
00317
00318 void HysteresisController::analysis()
00319 {
00320
00321 if (up_count_ == 0)
00322 up_count_ = 1;
00323 if (down_count_ == 0)
00324 down_count_ = 1;
00325
00326 test_data_.time_up.resize(up_count_);
00327 test_data_.effort_up.resize(up_count_);
00328 test_data_.position_up.resize(up_count_);
00329 test_data_.velocity_up.resize(up_count_);
00330
00331 test_data_.time_down.resize(down_count_);
00332 test_data_.effort_down.resize(down_count_);
00333 test_data_.position_down.resize(down_count_);
00334 test_data_.velocity_down.resize(down_count_);
00335
00336 return;
00337 }
00338
00339 bool HysteresisController::sendData()
00340 {
00341 if (hyst_pub_->trylock())
00342 {
00343 joint_qualification_controllers::HysteresisData *out = &hyst_pub_->msg_;
00344 out->joint_name = test_data_.joint_name;
00345
00346 out->time_up = test_data_.time_up;
00347 out->effort_up = test_data_.effort_up;
00348 out->position_up = test_data_.position_up;
00349 out->velocity_up = test_data_.velocity_up;
00350
00351 out->time_down = test_data_.time_down;
00352 out->effort_down = test_data_.effort_down;
00353 out->position_down = test_data_.position_down;
00354 out->velocity_down = test_data_.velocity_down;
00355
00356
00357 out->arg_name = test_data_.arg_name;
00358 out->arg_value = test_data_.arg_value;
00359
00360 hyst_pub_->unlockAndPublish();
00361 return true;
00362 }
00363 return false;
00364 }
00365
00366
00367