00001 #include<yumi_hw/yumi_hw.h>
00002
00003 void YumiHW::create(std::string name, std::string urdf_string)
00004 {
00005 ROS_INFO_STREAM("Creating a Yumi HW interface for: " << name <<" with "<<n_joints_<<" joints");
00006
00007
00008 robot_namespace_ = name;
00009 urdf_string_ = urdf_string;
00010
00011
00012
00013
00014 joint_names_.push_back( robot_namespace_ + std::string("_joint_1_l") );
00015 joint_names_.push_back( robot_namespace_ + std::string("_joint_2_l") );
00016 joint_names_.push_back( robot_namespace_ + std::string("_joint_3_l") );
00017 joint_names_.push_back( robot_namespace_ + std::string("_joint_4_l") );
00018 joint_names_.push_back( robot_namespace_ + std::string("_joint_5_l") );
00019 joint_names_.push_back( robot_namespace_ + std::string("_joint_6_l") );
00020 joint_names_.push_back( robot_namespace_ + std::string("_joint_7_l") );
00021
00022 joint_names_.push_back( robot_namespace_ + std::string("_joint_1_r") );
00023 joint_names_.push_back( robot_namespace_ + std::string("_joint_2_r") );
00024 joint_names_.push_back( robot_namespace_ + std::string("_joint_3_r") );
00025 joint_names_.push_back( robot_namespace_ + std::string("_joint_4_r") );
00026 joint_names_.push_back( robot_namespace_ + std::string("_joint_5_r") );
00027 joint_names_.push_back( robot_namespace_ + std::string("_joint_6_r") );
00028 joint_names_.push_back( robot_namespace_ + std::string("_joint_7_r") );
00029
00030
00031 joint_position_.resize(n_joints_);
00032 joint_position_prev_.resize(n_joints_);
00033 joint_velocity_.resize(n_joints_);
00034 joint_effort_.resize(n_joints_);
00035 joint_position_command_.resize(n_joints_);
00036 joint_velocity_command_.resize(n_joints_);
00037
00038 joint_lower_limits_.resize(n_joints_);
00039 joint_upper_limits_.resize(n_joints_);
00040
00041
00042 reset();
00043
00044 ROS_INFO("Parsing transmissions from the URDF...");
00045
00046
00047 if (!parseTransmissionsFromURDF(urdf_string_))
00048 {
00049 ROS_ERROR("Error parsing URDF in yumi_hw.");
00050 return;
00051 }
00052
00053 ROS_INFO("Registering interfaces...");
00054
00055 const urdf::Model *const urdf_model_ptr = urdf_model_.initString(urdf_string_) ? &urdf_model_ : NULL;
00056 registerInterfaces(urdf_model_ptr, transmissions_);
00057
00058
00059
00060
00061
00062 ROS_INFO("Succesfully created an abstract Yumi with interfaces to ROS control");
00063 }
00064
00065
00066 void YumiHW::reset()
00067 {
00068 for (int j = 0; j < n_joints_; ++j)
00069 {
00070 joint_position_[j] = 0.0;
00071 joint_position_prev_[j] = 0.0;
00072 joint_velocity_[j] = 0.0;
00073 joint_effort_[j] = 0.0;
00074
00075 joint_position_command_[j] = 0.0;
00076 joint_velocity_command_[j] = 0.0;
00077 }
00078
00079 current_strategy_ = JOINT_POSITION;
00080
00081 return;
00082 }
00083
00084
00085 void YumiHW::registerInterfaces(const urdf::Model *const urdf_model,
00086 std::vector<transmission_interface::TransmissionInfo> transmissions)
00087 {
00088
00089
00090 if( transmissions.empty() )
00091 {
00092 ROS_ERROR("No drivable joints in urdf");
00093 return;
00094 }
00095
00096
00097 for(int j=0; j < n_joints_; j++)
00098 {
00099
00100 if(transmissions[j].joints_.size() == 0)
00101 {
00102 ROS_WARN_STREAM("Transmission " << transmissions[j].name_
00103 << " has no associated joints." << std::endl);
00104 continue;
00105 }
00106 else if(transmissions[j].joints_.size() > 1)
00107 {
00108 ROS_WARN_STREAM("Transmission " << transmissions[j].name_
00109 << " has more than one joint, and they can't be controlled simultaneously"
00110 << std::endl);
00111 continue;
00112 }
00113
00114 std::vector<std::string> joint_interfaces = transmissions[j].joints_[0].hardware_interfaces_;
00115
00116 if( joint_interfaces.empty() )
00117 {
00118 ROS_WARN_STREAM("Joint " << transmissions[j].joints_[0].name_ <<
00119 " of transmission " << transmissions[j].name_ << " does not specify any hardware interface. " <<
00120 "You need to, otherwise the joint can't be controlled." << std::endl);
00121 continue;
00122 }
00123
00124 const std::string& hardware_interface = joint_interfaces.front();
00125
00126
00127 std::cout << "\x1B[37m" << "lwr_hw: " << "Loading joint '" << joint_names_[j]
00128 << "' of type '" << hardware_interface << "'" << "\x1B[0m" << std::endl;
00129
00130
00131 state_interface_.registerHandle(hardware_interface::JointStateHandle(
00132 joint_names_[j], &joint_position_[j], &joint_velocity_[j], &joint_effort_[j]));
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 hardware_interface::JointHandle joint_handle_position;
00143 joint_handle_position = hardware_interface::JointHandle(state_interface_.getHandle(joint_names_[j]),
00144 &joint_position_command_[j]);
00145 position_interface_.registerHandle(joint_handle_position);
00146
00147
00148 hardware_interface::JointHandle joint_handle_velocity;
00149 joint_handle_velocity = hardware_interface::JointHandle(state_interface_.getHandle(joint_names_[j]),
00150 &joint_velocity_command_[j]);
00151 velocity_interface_.registerHandle(joint_handle_velocity);
00152
00153 registerJointLimits(joint_names_[j],
00154
00155 joint_handle_position,
00156 joint_handle_velocity,
00157 urdf_model,
00158 &joint_lower_limits_[j], &joint_upper_limits_[j]);
00159 }
00160
00161
00162 registerInterface(&state_interface_);
00163
00164 registerInterface(&position_interface_);
00165 registerInterface(&velocity_interface_);
00166 }
00167
00168
00169
00170
00171 void YumiHW::registerJointLimits(const std::string& joint_name,
00172
00173 const hardware_interface::JointHandle& joint_handle_position,
00174 const hardware_interface::JointHandle& joint_handle_velocity,
00175 const urdf::Model *const urdf_model,
00176 double *const lower_limit, double *const upper_limit)
00177 {
00178 *lower_limit = -std::numeric_limits<double>::max();
00179 *upper_limit = std::numeric_limits<double>::max();
00180
00181 joint_limits_interface::JointLimits limits;
00182 bool has_limits = false;
00183 joint_limits_interface::SoftJointLimits soft_limits;
00184 bool has_soft_limits = false;
00185
00186 if (urdf_model != NULL)
00187 {
00188 const boost::shared_ptr<const urdf::Joint> urdf_joint = urdf_model->getJoint(joint_name);
00189 const boost::shared_ptr<const urdf::Joint> urdf_joint_sitffness = urdf_model->getJoint(joint_name + std::string("_stiffness"));
00190 if (urdf_joint != NULL)
00191 {
00192
00193 if (joint_limits_interface::getJointLimits(urdf_joint, limits))
00194 has_limits = true;
00195 if (joint_limits_interface::getSoftJointLimits(urdf_joint, soft_limits))
00196 has_soft_limits = true;
00197 }
00198 }
00199
00200 if (!has_limits)
00201 {
00202 return;
00203 }
00204
00205 if (limits.has_position_limits)
00206 {
00207 *lower_limit = limits.min_position;
00208 *upper_limit = limits.max_position;
00209 }
00210
00211
00212 if (has_soft_limits)
00213 {
00214 const joint_limits_interface::PositionJointSoftLimitsHandle limits_handle_position(joint_handle_position, limits, soft_limits);
00215 pj_limits_interface_.registerHandle(limits_handle_position);
00216 const joint_limits_interface::VelocityJointSoftLimitsHandle limits_handle_velocity(joint_handle_velocity, limits, soft_limits);
00217 vj_limits_interface_.registerHandle(limits_handle_velocity);
00218
00219 }
00220 else
00221 {
00222 const joint_limits_interface::PositionJointSaturationHandle sat_handle_position(joint_handle_position, limits);
00223 pj_sat_interface_.registerHandle(sat_handle_position);
00224 const joint_limits_interface::VelocityJointSaturationHandle sat_handle_velocity(joint_handle_velocity, limits);
00225 vj_sat_interface_.registerHandle(sat_handle_velocity);
00226 }
00227
00228 }
00229
00230
00231 bool YumiHW::parseTransmissionsFromURDF(const std::string& urdf_string)
00232 {
00233 std::vector<transmission_interface::TransmissionInfo> transmissions;
00234
00235
00236 transmission_interface::TransmissionParser::parse(urdf_string, transmissions);
00237
00238
00239 for (int j = 0; j < n_joints_; ++j)
00240 {
00241
00242 std::vector<transmission_interface::TransmissionInfo>::iterator it = transmissions.begin();
00243 for(; it != transmissions.end(); ++it)
00244 {
00245
00246 if (joint_names_[j].compare(it->joints_[0].name_) == 0)
00247 {
00248 transmissions_.push_back( *it );
00249
00250 }
00251 }
00252 }
00253
00254 if( transmissions_.empty() )
00255 return false;
00256
00257 return true;
00258 }
00259
00260 #if 0
00261
00262 bool YumiHW::initKDLdescription(const urdf::Model *const urdf_model)
00263 {
00264
00265 KDL::Tree kdl_tree;
00266 if (!kdl_parser::treeFromUrdfModel(*urdf_model, kdl_tree))
00267 {
00268 ROS_ERROR("Failed to construct kdl tree");
00269 return false;
00270 }
00271
00272 std::cout << "LWR kinematic successfully parsed with "
00273 << kdl_tree.getNrOfJoints()
00274 << " joints, and "
00275 << kdl_tree.getNrOfJoints()
00276 << " segments." << std::endl;
00277
00278
00279 std::string root_name;
00280 ros::param::get(std::string("/") + robot_namespace_ + std::string("/root"), root_name);
00281 if( root_name.empty() )
00282 root_name = kdl_tree.getRootSegment()->first;
00283
00284 std::string tip_name;
00285 ros::param::get(std::string("/") + robot_namespace_ + std::string("/tip"), tip_name);
00286 if( tip_name.empty() )
00287 tip_name = robot_namespace_ + std::string("_7_link"); ;
00288
00289 std::cout << "Using root: " << root_name << " and tip: " << tip_name << std::endl;
00290
00291
00292 gravity_ = KDL::Vector::Zero();
00293 gravity_(2) = -9.81;
00294
00295
00296 if(!kdl_tree.getChain(root_name, tip_name, lwr_chain_))
00297 {
00298 ROS_ERROR("Failed to get KDL chain from tree: ");
00299 return false;
00300 }
00301
00302 ROS_INFO("Number of segments: %d", lwr_chain_.getNrOfSegments());
00303 ROS_INFO("Number of joints in chain: %d", lwr_chain_.getNrOfJoints());
00304
00305 f_dyn_solver_.reset(new KDL::ChainDynParam(lwr_chain_,gravity_));
00306
00307 joint_position_kdl_ = KDL::JntArray(lwr_chain_.getNrOfJoints());
00308 gravity_effort_ = KDL::JntArray(lwr_chain_.getNrOfJoints());
00309
00310 return true;
00311 }
00312 #endif
00313
00314
00315 bool YumiHW::canSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list) const
00316 {
00317 std::vector<ControlStrategy> desired_strategies;
00318
00319 for ( std::list<hardware_interface::ControllerInfo>::const_iterator it = start_list.begin(); it != start_list.end(); ++it )
00320 {
00321 if( it->type.compare( std::string("hardware_interface::VelocityJointInterface") ) == 0 )
00322 {
00323 desired_strategies.push_back( JOINT_VELOCITY );
00324 ROS_WARN("Uncharted teritories here: switching to VelocityInterface\n");
00325 }
00326 else if( it->type.compare( std::string("hardware_interface::PositionJointInterface") ) == 0 )
00327 {
00328 desired_strategies.push_back( JOINT_POSITION );
00329 ROS_INFO("Switching to Positon Control mode");
00330 }
00331 else if( it->type.compare( std::string("hardware_interface::EffortJointInterface") ) == 0 )
00332 {
00333 ROS_WARN("Effort not implemented!");
00334 }
00335 else
00336 {
00337 ROS_INFO("Controller of type %s?", it->type.c_str());
00338
00339
00340 }
00341 }
00342
00343 if( desired_strategies.size() > 1 )
00344 {
00345 ROS_ERROR("Only a single controller can be active at a time. Choose one control strategy only");
00346 return false;
00347 }
00348
00349 return true;
00350 }
00351
00352 void YumiHW::doSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list)
00353 {
00354 ControlStrategy desired_strategy = JOINT_POSITION;
00355
00356 bool wantsPosition = false;
00357 bool wantsVelocity = false;
00358
00359 for ( std::list<hardware_interface::ControllerInfo>::const_iterator it = start_list.begin(); it != start_list.end(); ++it )
00360 {
00361 #if ROS_VERSION_MINIMUM(1,12,0)
00362
00363 for(int i=0; i<it->claimed_resources.size(); i++) {
00364
00365 if( it->claimed_resources[i].hardware_interface.compare( std::string("hardware_interface::PositionJointInterface") ) == 0 )
00366 {
00367 ROS_INFO("Request to switch to hardware_interface::PositionJointInterface (JOINT_POSITION)");
00368 wantsPosition = true;
00369 }
00370 else if( it->claimed_resources[i].hardware_interface.compare( std::string("hardware_interface::VelocityJointInterface") ) == 0 )
00371 {
00372 ROS_INFO("Request to switch to hardware_interface::VelocityJointInterface (JOINT_VELOCITY)");
00373 wantsVelocity = true;
00374 }
00375 else
00376 {
00377 ROS_INFO("Controller of type %s, requested interface of type %s. Impossible, sorry.\n",
00378 it->type.c_str(), it->claimed_resources[i].hardware_interface.c_str());
00379 }
00380 }
00381 #else
00382
00383
00384 if( it->hardware_interface.compare( std::string("hardware_interface::PositionJointInterface") ) == 0 )
00385 {
00386 ROS_INFO("Request to switch to hardware_interface::PositionJointInterface (JOINT_POSITION)");
00387 desired_strategy = JOINT_POSITION;
00388 break;
00389 }
00390 else if( it->hardware_interface.compare( std::string("hardware_interface::VelocityJointInterface") ) == 0 )
00391 {
00392 ROS_INFO("Request to switch to hardware_interface::VelocityJointInterface (JOINT_VELOCITY)");
00393 desired_strategy = JOINT_VELOCITY;
00394 break;
00395 }
00396 #endif
00397 }
00398 if(wantsPosition) {
00399 desired_strategy = JOINT_POSITION;
00400 }
00401 if(wantsVelocity) {
00402 desired_strategy = JOINT_VELOCITY;
00403 }
00404
00405 if(wantsPosition && wantsVelocity) {
00406 ROS_ERROR("Cannot have both position and velocity interface. Will assume Velocity. Beware!");
00407 }
00408
00409 for (int j = 0; j < n_joints_; ++j)
00410 {
00412 joint_position_command_[j] = joint_position_[j];
00413 joint_velocity_command_[j] = 0.0;
00414
00415
00417 try{ position_interface_.getHandle(joint_names_[j]).setCommand(joint_position_command_[j]); }
00418 catch(const hardware_interface::HardwareInterfaceException&){}
00419
00420
00421 try{ velocity_interface_.getHandle(joint_names_[j]).setCommand(joint_velocity_command_[j]); }
00422 catch(const hardware_interface::HardwareInterfaceException&){}
00423
00425 pj_sat_interface_.reset();
00426 pj_limits_interface_.reset();
00427 }
00428
00429 if(desired_strategy == getControlStrategy())
00430 {
00431 std::cout << "The ControlStrategy didn't change, it is already: " << getControlStrategy() << std::endl;
00432 }
00433 else
00434 {
00435 setControlStrategy(desired_strategy);
00436 std::cout << "The ControlStrategy changed to: " << getControlStrategy() << std::endl;
00437 }
00438 }
00439
00440 void YumiHW::enforceLimits(ros::Duration period)
00441 {
00442 vj_sat_interface_.enforceLimits(period);
00443 vj_limits_interface_.enforceLimits(period);
00444 pj_sat_interface_.enforceLimits(period);
00445 pj_limits_interface_.enforceLimits(period);
00446 }
00447