yumi_hw.cpp
Go to the documentation of this file.
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     // SET NAME AND MODEL
00008     robot_namespace_ = name;
00009     urdf_string_ = urdf_string;
00010 
00011     // ALLOCATE MEMORY
00012 
00013     // JOINT NAMES ARE TAKEN FROM URDF NAME CONVENTION
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     // VARIABLES
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     // RESET VARIABLES
00042     reset();
00043 
00044     ROS_INFO("Parsing transmissions from the URDF...");
00045 
00046     // GET TRANSMISSIONS THAT BELONG TO THIS LWR 4+ ARM
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     //std::cout << "Initializing KDL variables..." << std::endl;
00059     // INIT KDL STUFF
00060     //initKDLdescription(urdf_model_ptr);
00061 
00062     ROS_INFO("Succesfully created an abstract Yumi with interfaces to ROS control");
00063 }
00064 
00065 // reset values
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     // Check that this transmission has one joint
00090     if( transmissions.empty() )
00091     {
00092         ROS_ERROR("No drivable joints in urdf");
00093         return;
00094     }
00095 
00096     // Initialize values
00097     for(int j=0; j < n_joints_; j++)
00098     {
00099         // Check that this transmission has one joint
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         // Debug //FIXME
00127         std::cout << "\x1B[37m" << "lwr_hw: " << "Loading joint '" << joint_names_[j]
00128             << "' of type '" << hardware_interface << "'" << "\x1B[0m" << std::endl;
00129 
00130         // Create joint state interface for all joints
00131         state_interface_.registerHandle(hardware_interface::JointStateHandle(
00132                     joint_names_[j], &joint_position_[j], &joint_velocity_[j], &joint_effort_[j]));
00133 
00134         //No control in effort space at the moment TODO
00135         // Decide what kind of command interface this actuator/joint has
00136         /*      hardware_interface::JointHandle joint_handle_effort;
00137         joint_handle_effort = hardware_interface::JointHandle(state_interface_.getHandle(joint_names_[j]),
00138                 &joint_effort_command_[j]);
00139         effort_interface_.registerHandle(joint_handle_effort); */
00140 
00141         // position handle
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         // velocity command handle
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                 //joint_handle_effort,
00155                 joint_handle_position,
00156                 joint_handle_velocity,
00157                 urdf_model,
00158                 &joint_lower_limits_[j], &joint_upper_limits_[j]);
00159     }
00160 
00161     // Register interfaces
00162     registerInterface(&state_interface_);
00163     //registerInterface(&effort_interface_);
00164     registerInterface(&position_interface_);
00165     registerInterface(&velocity_interface_);
00166 }
00167 
00168 // Register the limits of the joint specified by joint_name and\ joint_handle. The limits are
00169 // retrieved from the urdf_model.
00170 // Return the joint's type, lower position limit, upper position limit, and effort limit.
00171 void YumiHW::registerJointLimits(const std::string& joint_name,
00172         //const hardware_interface::JointHandle& joint_handle_effort,
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             // Get limits from the URDF file.
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 // Get Transmissions from the URDF
00231 bool YumiHW::parseTransmissionsFromURDF(const std::string& urdf_string)
00232 {
00233     std::vector<transmission_interface::TransmissionInfo> transmissions;
00234 
00235     // Only *standard* transmission_interface are parsed
00236     transmission_interface::TransmissionParser::parse(urdf_string, transmissions);
00237 
00238     // Now iterate and save only transmission from this robot
00239     for (int j = 0; j < n_joints_; ++j)
00240     {
00241         // std::cout << "Check joint " << joint_names_[j] << std::endl;
00242         std::vector<transmission_interface::TransmissionInfo>::iterator it = transmissions.begin();
00243         for(; it != transmissions.end(); ++it)
00244         {
00245             // std::cout << "With transmission " << it->name_ << std::endl;
00246             if (joint_names_[j].compare(it->joints_[0].name_) == 0)
00247             {
00248                 transmissions_.push_back( *it );
00249                 // std::cout << "Found a match for transmission " << it->name_ << std::endl;
00250             }
00251         }
00252     }
00253 
00254     if( transmissions_.empty() )
00255         return false;
00256 
00257     return true;
00258 }
00259 
00260 #if 0
00261 // Init KDL stuff
00262 bool YumiHW::initKDLdescription(const urdf::Model *const urdf_model)
00263 {
00264     // KDL code to compute f_dyn(q)
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     // Get the info from parameters
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; // default
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"); ; // default
00288 
00289     std::cout << "Using root: " << root_name << " and tip: " << tip_name << std::endl;
00290 
00291     // this depends on how the world frame is set, in all our setups, world has always positive z pointing up.
00292     gravity_ = KDL::Vector::Zero();
00293     gravity_(2) = -9.81;
00294 
00295     // Extract the chain from the tree
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             // Debug
00339             // std::cout << "This controller does not use any command interface, so it is only sensing, no problem" << std::endl;
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; // default
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             //jade and karmic
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             //indigo and below
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         //joint_effort_command_[j] = 0.0;
00415 
00417         try{  position_interface_.getHandle(joint_names_[j]).setCommand(joint_position_command_[j]);  }
00418         catch(const hardware_interface::HardwareInterfaceException&){}
00419         //try{  effort_interface_.getHandle(joint_names_[j]).setCommand(joint_effort_command_[j]);  }
00420         //catch(const hardware_interface::HardwareInterfaceException&){}
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 


yumi_hw
Author(s):
autogenerated on Sat Jun 8 2019 20:47:40