Go to the documentation of this file.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 "pr2_calibration_controllers/joint_calibration_controller.h"
00036 #include "ros/time.h"
00037 #include "pluginlib/class_list_macros.h"
00038
00039 PLUGINLIB_EXPORT_CLASS(controller::JointCalibrationController, pr2_controller_interface::Controller)
00040
00041 using namespace std;
00042
00043 namespace controller {
00044
00045 JointCalibrationController::JointCalibrationController()
00046 : robot_(NULL), last_publish_time_(0),
00047 actuator_(NULL), joint_(NULL)
00048 {
00049 }
00050
00051 JointCalibrationController::~JointCalibrationController()
00052 {
00053 }
00054
00055 bool JointCalibrationController::init(pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n)
00056 {
00057 robot_ = robot;
00058 node_ = n;
00059
00060
00061 std::string joint_name;
00062 if (!node_.getParam("joint", joint_name))
00063 {
00064 ROS_ERROR("No joint given (namespace: %s)", node_.getNamespace().c_str());
00065 return false;
00066 }
00067 if (!(joint_ = robot->getJointState(joint_name)))
00068 {
00069 ROS_ERROR("Could not find joint %s (namespace: %s)",
00070 joint_name.c_str(), node_.getNamespace().c_str());
00071 return false;
00072 }
00073 if (!joint_->joint_->calibration)
00074 {
00075 ROS_ERROR("Joint %s has no calibration reference position specified (namespace: %s)",
00076 joint_name.c_str(), node_.getNamespace().c_str());
00077 return false;
00078 }
00079
00080
00081 std::string actuator_name;
00082 if (!node_.getParam("actuator", actuator_name))
00083 {
00084 ROS_ERROR("No actuator given (namespace: %s)", node_.getNamespace().c_str());
00085 return false;
00086 }
00087 if (!(actuator_ = robot->model_->getActuator(actuator_name)))
00088 {
00089 ROS_ERROR("Could not find actuator %s (namespace: %s)",
00090 actuator_name.c_str(), node_.getNamespace().c_str());
00091 return false;
00092 }
00093
00094 bool force_calibration = false;
00095 node_.getParam("force_calibration", force_calibration);
00096
00097 state_ = INITIALIZED;
00098 joint_->calibrated_ = false;
00099 if (actuator_->state_.zero_offset_ != 0)
00100 {
00101 if (force_calibration)
00102 {
00103 ROS_INFO("Joint %s will be recalibrated, but was already calibrated at offset %f",
00104 joint_name.c_str(), actuator_->state_.zero_offset_);
00105 }
00106 else
00107 {
00108 ROS_INFO("Joint %s is already calibrated at offset %f",
00109 joint_name.c_str(), actuator_->state_.zero_offset_);
00110 state_ = CALIBRATED;
00111 joint_->calibrated_ = true;
00112 }
00113 }
00114 else{
00115 ROS_INFO("Joint %s is not yet calibrated", joint_name.c_str());
00116 }
00117
00118
00119 std::string transmission_name;
00120 if (!node_.getParam("transmission", transmission_name))
00121 {
00122 ROS_ERROR("No transmission given (namespace: %s)", node_.getNamespace().c_str());
00123 return false;
00124 }
00125 if (!(transmission_ = robot->model_->getTransmission(transmission_name)))
00126 {
00127 ROS_ERROR("Could not find transmission %s (namespace: %s)",
00128 transmission_name.c_str(), node_.getNamespace().c_str());
00129 return false;
00130 }
00131
00132 if (!node_.getParam("velocity", search_velocity_))
00133 {
00134 ROS_ERROR("Velocity value was not specified (namespace: %s)", node_.getNamespace().c_str());
00135 return false;
00136 }
00137
00138
00139 if (!joint_->joint_->calibration->falling && !joint_->joint_->calibration->rising){
00140 ROS_ERROR("No rising or falling edge is specified for calibration of joint %s. Note that the reference_position is not used any more", joint_name.c_str());
00141 return false;
00142 }
00143 if (joint_->joint_->calibration->falling && joint_->joint_->calibration->rising && joint_->joint_->type != urdf::Joint::CONTINUOUS){
00144 ROS_ERROR("Both rising and falling edge are specified for non-continuous joint %s. This is not supported.", joint_name.c_str());
00145 return false;
00146 }
00147 if (search_velocity_ < 0){
00148 search_velocity_ *= -1;
00149 ROS_ERROR("Negative search velocity is not supported for joint %s. Making the search velocity positive.", joint_name.c_str());
00150 }
00151
00152
00153 if (joint_->joint_->calibration->falling && joint_->joint_->calibration->rising){
00154 joint_->reference_position_ = *(joint_->joint_->calibration->rising);
00155 ROS_DEBUG("Using positive search velocity for joint %s", joint_name.c_str());
00156 }
00157 else if (joint_->joint_->calibration->falling){
00158 joint_->reference_position_ = *(joint_->joint_->calibration->falling);
00159 search_velocity_ *= -1.0;
00160 ROS_DEBUG("Using negative search velocity for joint %s", joint_name.c_str());
00161 }
00162 else if (joint_->joint_->calibration->rising){
00163 joint_->reference_position_ = *(joint_->joint_->calibration->rising);
00164 ROS_DEBUG("Using positive search velocity for joint %s", joint_name.c_str());
00165 }
00166
00167
00168
00169 if (!vc_.init(robot, node_))
00170 return false;
00171
00172
00173 is_calibrated_srv_ = node_.advertiseService("is_calibrated", &JointCalibrationController::isCalibrated, this);
00174
00175
00176 pub_calibrated_.reset(new realtime_tools::RealtimePublisher<std_msgs::Empty>(node_, "calibrated", 1));
00177
00178
00179 return true;
00180 }
00181
00182
00183 void JointCalibrationController::starting()
00184 {
00185 state_ = INITIALIZED;
00186 joint_->calibrated_ = false;
00187 actuator_->state_.zero_offset_ = 0.0;
00188 }
00189
00190
00191 bool JointCalibrationController::isCalibrated(pr2_controllers_msgs::QueryCalibrationState::Request& req,
00192 pr2_controllers_msgs::QueryCalibrationState::Response& resp)
00193 {
00194 ROS_DEBUG("Is calibrated service %d", state_ == CALIBRATED);
00195 resp.is_calibrated = (state_ == CALIBRATED);
00196 return true;
00197 }
00198
00199
00200 void JointCalibrationController::update()
00201 {
00202 assert(joint_);
00203 assert(actuator_);
00204
00205 switch(state_)
00206 {
00207 case INITIALIZED:
00208 vc_.setCommand(0.0);
00209 state_ = BEGINNING;
00210 break;
00211 case BEGINNING:
00212 if (actuator_->state_.calibration_reading_ & 1)
00213 state_ = MOVING_TO_LOW;
00214 else{
00215 state_ = MOVING_TO_HIGH;
00216 original_position_ = joint_->position_;
00217 }
00218 break;
00219 case MOVING_TO_LOW:
00220 vc_.setCommand(-search_velocity_);
00221 if (!(actuator_->state_.calibration_reading_ & 1))
00222 {
00223 if (--countdown_ <= 0){
00224 state_ = MOVING_TO_HIGH;
00225 original_position_ = joint_->position_;
00226 }
00227 }
00228 else
00229 countdown_ = 200;
00230 break;
00231 case MOVING_TO_HIGH: {
00232 vc_.setCommand(search_velocity_);
00233
00234 if (actuator_->state_.calibration_reading_ & 1)
00235 {
00236
00237 if ((search_velocity_ > 0.0 && (joint_->position_ - original_position_) < 0) ||
00238 (search_velocity_ < 0.0 && (joint_->position_ - original_position_) > 0))
00239 {
00240 state_ = BEGINNING;
00241 ROS_ERROR("Joint hit the falling edge instead of the rising edge. Calibrating again...");
00242 ros::Duration(1.0).sleep();
00243 break;
00244 }
00245
00246 pr2_hardware_interface::Actuator a;
00247 pr2_mechanism_model::JointState j;
00248
00249
00250 actuator_->state_.zero_offset_ = actuator_->state_.last_calibration_rising_edge_;
00251
00252
00253 joint_->calibrated_ = true;
00254
00255 state_ = CALIBRATED;
00256 vc_.setCommand(0.0);
00257 }
00258 break;
00259 }
00260 case CALIBRATED:
00261 if (pub_calibrated_) {
00262 if (last_publish_time_ + ros::Duration(0.5) < robot_->getTime()){
00263 assert(pub_calibrated_);
00264 if (pub_calibrated_->trylock()) {
00265 last_publish_time_ = robot_->getTime();
00266 pub_calibrated_->unlockAndPublish();
00267 }
00268 }
00269 }
00270 break;
00271 }
00272
00273 if (state_ != CALIBRATED)
00274 vc_.update();
00275 }
00276 }