LCOV - code coverage report
Current view: top level - src - Parser.cpp (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 141 194 72.7 %
Date: 2021-10-05 16:55:17 Functions: 19 26 73.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2019 IIT-HHCM
       3             :  * Author: Luca Muratore
       4             :  * email:  luca.muratore@iit.it
       5             :  *
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at
       9             :  * http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             : */
      17             : 
      18             : #include <ros_end_effector/Parser.h>
      19             : 
      20             : #define CHAIN_PER_GROUP 1
      21             : 
      22         113 : ROSEE::Parser::Parser ( const ros::NodeHandle& nh ) :
      23         113 :     _nh ( nh ) {
      24             : 
      25         113 : }
      26             : 
      27             : 
      28         113 : ROSEE::Parser::~Parser() {
      29             : 
      30         113 : }
      31             : 
      32         294 : bool ROSEE::Parser::getJointsInFinger ( std::string base_link,
      33             :                                         std::string tip_link,
      34             :                                         std::string finger_name
      35             :                                       ) {
      36             : 
      37             :     //we add here the finger to the map because later is added only if the joint is actuated.
      38             :     //Instead we want in the map all the fingers, even if they have no actuated joint in.
      39             :     //this is necessary to not cause later problem due to have the right number of finger
      40         294 :     _finger_joint_map.insert(std::make_pair(finger_name, std::vector<std::string>())); 
      41             :     
      42             :     
      43         588 :     KDL::Chain actual_chain;
      44         294 :     if ( _robot_tree.getChain ( base_link, tip_link, actual_chain ) ) {
      45             : 
      46         294 :         int segments_num = actual_chain.getNrOfSegments();
      47         957 :         for ( int i = 0; i < segments_num; i++ ) {
      48             : 
      49        1326 :             KDL::Segment actual_segment = actual_chain.getSegment ( i );
      50        1326 :             KDL::Joint actual_joint = actual_segment.getJoint();
      51             : 
      52         663 :             bool is_valid_joint = false;
      53             : 
      54             :             // Check if joint is revolute or prismatic
      55         663 :             is_valid_joint = actual_joint.getTypeName() == "RotAxis";   
      56             :             
      57             : //                              || actual_joint.getTypeName() == "TransAxis";
      58             :             
      59        1326 :             auto urdf_joint = _urdf_model->getJoint(actual_joint.getName());
      60         663 :             bool is_mimic_joint = (urdf_joint->mimic == nullptr) ? false : true;
      61             :             
      62             : 
      63             :             // if the joint is revolute or prismatic AND not a mimic (mimic joint is a not actuated joint)
      64         663 :             if ( is_valid_joint && (!is_mimic_joint) ) {
      65             : 
      66         600 :                 _finger_joint_map[finger_name].push_back ( actual_joint.getName() );
      67         600 :                 _joint_finger_map[actual_joint.getName()] = finger_name;
      68         600 :                 _urdf_joint_map[actual_joint.getName()] = _urdf_model->getJoint ( actual_joint.getName() );
      69             : 
      70         600 :                 _joints_num++;
      71             : 
      72             :             }
      73             :         }
      74             : 
      75         294 :         return true;
      76             :     }
      77             : 
      78           0 :     ROS_ERROR_STREAM ( "chain from base_link " << base_link << " to tip_link " << tip_link << " not found in the URDF" );
      79             : 
      80           0 :     return false;
      81             : }
      82             : 
      83             : 
      84             : 
      85         113 : bool ROSEE::Parser::parseSRDF() {
      86             : 
      87             :     // initialize srdfdom
      88         113 :     _srdfdom.initFile ( *_urdf_model, _srdf_path );
      89             : 
      90             :     // get the end-effectors in the SRDF file
      91         226 :     std::vector<srdf::Model::EndEffector> srdf_end_effectors = _srdfdom.getEndEffectors();
      92             : 
      93             :     // NOTE only one end-effectors supported
      94             :     // TBD support multiple end-effectors
      95         113 :     if ( srdf_end_effectors.size() != 1 ) {
      96             : 
      97           0 :         return false;
      98             :     }
      99             : 
     100         113 :     ROS_INFO_STREAM ( "ros_end_effector Parser found end_effector: " << srdf_end_effectors.at ( 0 ).name_ );
     101             : 
     102             :     // get all the groups in the SRDF
     103         226 :     std::vector<srdf::Model::Group> srdf_groups = _srdfdom.getGroups();
     104             : 
     105             :     // TBD will be a vector
     106         226 :     srdf::Model::Group fingers_group;
     107             :     // find end effector fingers chains group
     108             :     // TBD will be a vector
     109         113 :     int group_num = srdf_groups.size();
     110             :     // TBD will be a vector
     111         226 :     std::string end_effector_group_name = srdf_end_effectors.at ( 0 ).component_group_;
     112         520 :     for ( int i = 0; i < group_num; i++ ) {
     113         407 :         if ( srdf_groups[i].name_ == end_effector_group_name ) {
     114         113 :             fingers_group = srdf_groups[i];
     115         113 :             ROS_INFO_STREAM ( "ros_end_effector Parser found group: " << end_effector_group_name << " in the SRDF with the following fingers: " );
     116             :         }
     117             :     }
     118             : 
     119         113 :     _fingers_num = fingers_group.subgroups_.size();
     120         113 :     _fingers_names.resize ( _fingers_num );
     121         113 :     _fingers_group_id.resize ( _fingers_num );
     122             : 
     123             :     // fill the chain names vector
     124         407 :     for ( int i = 0; i < _fingers_num; i++ ) {
     125             : 
     126         294 :         _fingers_names[i] = fingers_group.subgroups_[i];
     127             : 
     128             :         // find the id of the current finger group
     129        1380 :         for ( int j = 0; j < group_num; j++ ) {
     130        1086 :             if ( srdf_groups[j].name_ == _fingers_names[i] ) {
     131         294 :                 _fingers_group_id[i] = j;
     132             :             }
     133             :         }
     134         294 :         ROS_INFO_STREAM ( _fingers_names[i] );
     135             :     }
     136             : 
     137             :     // iterate over the fingers and find revolute joints
     138         407 :     for ( int i = 0; i < _fingers_num; i++ ) {
     139         588 :         srdf::Model::Group current_finger_group = srdf_groups[ _fingers_group_id[i] ];
     140             : 
     141             :         // NOTE only one chain per group
     142         294 :         if ( current_finger_group.chains_.size() != CHAIN_PER_GROUP )  {
     143             : 
     144           0 :             ROS_ERROR_STREAM ( "for the finger chain groups you can specify only one chain per group in your SRDF check " << 
     145             :                                current_finger_group.name_.c_str() << " group" );
     146           0 :             return false;
     147             :         }
     148             : 
     149             :         // fill the enabled/disabled joints in chain map
     150         588 :         if ( !getJointsInFinger ( current_finger_group.chains_[0].first,
     151         294 :                                   current_finger_group.chains_[0].second,
     152             :                                   current_finger_group.name_
     153             :                                 ) ) {
     154           0 :             return false;
     155             :         }
     156             :     }
     157             :     
     158         113 :     addNotInFingerJoints();
     159             :     
     160         113 :     removePassiveJoints();
     161             : 
     162             :     // save srdf as string 
     163         226 :     std::ifstream t_srdf ( _srdf_path );
     164         226 :     std::stringstream buffer_srdf;
     165         113 :     buffer_srdf << t_srdf.rdbuf();
     166         113 :     _srdf_string = buffer_srdf.str();
     167             :     
     168         113 :     return true;
     169             : 
     170             : }
     171             : 
     172         113 : void ROSEE::Parser::addNotInFingerJoints() {
     173             :     
     174        1002 :     for (auto it : _urdf_model->joints_) { //this contains all joints
     175             :         
     176         889 :         if (it.second->mimic == nullptr) { //not a mimic joint...
     177             :         
     178        1652 :             if (it.second->type == urdf::Joint::CONTINUOUS ||
     179         826 :                 it.second->type == urdf::Joint::REVOLUTE ) {
     180             :                 //it.second->type == urdf::Joint::PRISMATIC
     181             :             
     182         600 :                 if (_urdf_joint_map.find(it.second->name) == _urdf_joint_map.end() ) {
     183             :                     
     184           0 :                     _urdf_joint_map.insert(std::make_pair(it.second->name, it.second));
     185           0 :                     _finger_joint_map["virtual_finger"].push_back ( it.second->name );
     186           0 :                     _joint_finger_map[it.second->name] = "virtual_finger";
     187           0 :                     _joints_num++;
     188             :                 }
     189             :             }
     190             :         }
     191             :         
     192             :     }
     193             :     
     194         113 : }
     195             : 
     196         113 : bool ROSEE::Parser::removePassiveJoints() {
     197             :     
     198         226 :     std::vector<srdf::Model::PassiveJoint> passiveJointList = _srdfdom.getPassiveJoints();
     199             :     
     200         113 :     for (auto passiveJoint : passiveJointList) {
     201             :         //the passive can be also already deleted so we chech if we delete it(e.g. it is also mimic)
     202           0 :         if (_urdf_joint_map.erase(passiveJoint.name_) > 0) {
     203             :             
     204             :             //we have also to remove it from the other maps
     205           0 :             std::string fingerOfPassive = _joint_finger_map.at(passiveJoint.name_);
     206           0 :             _joint_finger_map.erase(passiveJoint.name_);
     207             :             
     208           0 :             for (auto it = _finger_joint_map.at(fingerOfPassive).begin(); 
     209           0 :                  it!= _finger_joint_map.at(fingerOfPassive).end(); ++it){
     210             :                 
     211           0 :                 if (it->compare(passiveJoint.name_) == 0 ) {
     212           0 :                     _finger_joint_map.at(fingerOfPassive).erase(it);
     213           0 :                     break;
     214             :                 }
     215             :             }
     216             : 
     217           0 :             _joints_num--;
     218             :         }   
     219             :     }
     220             : 
     221         226 :     return true;
     222             : }
     223             : 
     224             : 
     225         113 : bool ROSEE::Parser::parseURDF() {
     226             : 
     227         226 :     std::string xml_string;
     228         226 :     std::fstream xml_file ( _urdf_path.c_str(), std::fstream::in );
     229         113 :     if ( xml_file.is_open() ) {
     230             : 
     231       56449 :         while ( xml_file.good() ) {
     232             : 
     233       56336 :             std::string line;
     234       28168 :             std::getline ( xml_file, line );
     235       28168 :             xml_string += ( line + "\n" );
     236             :         }
     237             : 
     238         113 :         xml_file.close();
     239         113 :         _urdf_model = urdf::parseURDF ( xml_string );
     240             : 
     241             :         // create the robot KDL tree from the URDF model
     242         113 :         if ( !kdl_parser::treeFromUrdfModel ( *_urdf_model, _robot_tree ) ) {
     243             : 
     244           0 :             ROS_ERROR_STREAM ( "in " << __func__ << " Failed to construct kdl tree" );
     245           0 :             return false;
     246             :         }
     247             : 
     248             :         // save urdf and string (can be useful to have, thanks @alaurenzi!)
     249         226 :         std::ifstream t_urdf ( _urdf_path );
     250         226 :         std::stringstream buffer_urdf;
     251         113 :         buffer_urdf << t_urdf.rdbuf();
     252         113 :         _urdf_string = buffer_urdf.str();
     253             : 
     254         113 :         return true;
     255             : 
     256             :     } else {
     257             : 
     258           0 :         ROS_ERROR_STREAM ( "in " << __func__ << " : Can NOT open " << _urdf_path << " !" );
     259           0 :         return false;
     260             :     }
     261             : }
     262             : 
     263             : 
     264         113 : bool ROSEE::Parser::getROSEndEffectorConfig() {
     265             : 
     266         113 :     bool success = true;
     267             : 
     268             :     // check if the ROSEE config path exists
     269         226 :     std::ifstream fin ( _ros_ee_config_path );
     270         113 :     if ( fin.fail() ) {
     271             : 
     272           0 :         ROS_ERROR_STREAM ( "in " << __func__ << " : Can NOT open " << _ros_ee_config_path << "!" );
     273           0 :         success = false;
     274             :     } else {
     275             : 
     276             :         // load the node for the _ros_ee_config_path
     277         226 :         YAML::Node cfg = YAML::LoadFile ( _ros_ee_config_path );
     278             : 
     279             :         // find the internal node ros_end_effector
     280         226 :         YAML::Node ros_ee_node;
     281         113 :         if ( cfg["ros_end_effector"] ) {
     282             : 
     283         113 :             ros_ee_node = cfg["ros_end_effector"];
     284             :         } else {
     285             : 
     286           0 :             ROS_ERROR_STREAM ( "in " << __func__ << " : YAML file  " << _ros_ee_config_path << " does not contain ros_end_effector mandatory node!!" );
     287           0 :             success = false;
     288             :         }
     289             : 
     290             :         // check the urdf_filename
     291         113 :         if ( ros_ee_node["urdf_path"] ) {
     292             : 
     293             :             // TBD relative path in more elegant way
     294         113 :             _urdf_path = ROSEE::Utils::getPackagePath() + "/configs/" + ros_ee_node["urdf_path"].as<std::string>();
     295         113 :             ROS_INFO_STREAM ( "ros_end_effector Parser found URDF path: " << _urdf_path );
     296             :         } else {
     297             : 
     298           0 :             ROS_ERROR_STREAM ( "in " << __func__ << " : ros_end_effector node of  " << _ros_ee_config_path << " does not contain urdf_path mandatory node!!" );
     299           0 :             success = false;
     300             :         }
     301             : 
     302             :         // check the srdf_filename
     303         113 :         if ( ros_ee_node["srdf_path"] ) {
     304             : 
     305             :             // TBD relative path in more elegant way
     306         113 :             _srdf_path = ROSEE::Utils::getPackagePath() + "/configs/" + ros_ee_node["srdf_path"].as<std::string>();
     307         113 :             ROS_INFO_STREAM ( "ros_end_effector Parser found SRDF path: " << _srdf_path );
     308             :         } else {
     309             : 
     310           0 :             ROS_ERROR_STREAM ( "in " << __func__ << " : ros_end_effector node of  " << _ros_ee_config_path << " does not contain srdf_path mandatory node!!" );
     311           0 :             success = false;
     312             :         }
     313             :         
     314         113 :         if ( ros_ee_node["action_path"] ) {
     315         113 :             _action_path = ROSEE::Utils::getPackagePath() + "/configs/" + ros_ee_node["action_path"].as<std::string>();
     316         113 :             ROS_INFO_STREAM ( "ros_end_effector Parser found config folder for actions: " << _action_path );
     317             : 
     318             :         }
     319             :     }
     320             : 
     321         226 :     return success;
     322             : }
     323             : 
     324         113 : bool ROSEE::Parser::configure() {
     325             : 
     326         113 :     bool ret = true;
     327         113 :     if ( getROSEndEffectorConfig() ) {
     328             : 
     329         113 :         if ( parseURDF() ) {
     330             :             
     331         113 :             if ( parseSRDF() ) {
     332             :                 
     333         113 :                 ROS_INFO_STREAM ( "ROSEndEffector Parser successfully configured using config file:  " << _ros_ee_config_path );
     334             :             
     335             :             } else {
     336             :             
     337           0 :                 ROS_ERROR_STREAM ( "ROSEndEffector Parser error while parsing SRDF");
     338           0 :                 ret = false;
     339             :             }
     340             :             
     341             :         } else {
     342             :             
     343           0 :             ROS_ERROR_STREAM ( "ROSEndEffector Parser error while parsing URDF");
     344           0 :             ret = false;
     345             :         }
     346             : 
     347             :     } else {
     348             : 
     349           0 :         ret = false;
     350             :     }
     351             : 
     352             : 
     353         113 :     return ret;
     354             : }
     355             : 
     356             : 
     357             : 
     358          41 : bool ROSEE::Parser::init() {
     359             : 
     360             :     // try to retrive the path to config from the ROS param server TBD namespace should be take into account
     361          41 :     if ( _nh.getParam ( "/ros_ee_config_path", _ros_ee_config_path ) ) {
     362             : 
     363          41 :         _is_initialized =  configure();
     364          41 :         return _is_initialized;
     365             :     }
     366             : 
     367             :     // error
     368           0 :     ROS_ERROR_STREAM ( "in " << __func__ << " : ros_ee_config_path not found on ROS parameter server" );
     369           0 :     return false;
     370             : 
     371             : }
     372             : 
     373          72 : bool ROSEE::Parser::init ( const std::string& path_to_cfg ) {
     374             : 
     375          72 :     _ros_ee_config_path = path_to_cfg;
     376             : 
     377          72 :     _is_initialized =  configure();
     378          72 :     return _is_initialized;
     379             : }
     380             : 
     381          61 : void ROSEE::Parser::printEndEffectorFingerJointsMap() const {
     382             : 
     383          61 :     if ( _is_initialized ) {
     384             : 
     385          61 :         ROS_INFO_STREAM ( "ROS End Effector: Finger Joints Map" );
     386          61 :         ROS_INFO_STREAM ( "-------------------------" );
     387         225 :         for ( auto& chain_joints: _finger_joint_map ) {
     388         164 :             ROS_INFO_STREAM ( chain_joints.first );
     389             : 
     390         164 :             int nJointInFinger = chain_joints.second.size();
     391             :             
     392         164 :             if ( nJointInFinger == 0 ) {
     393             :                 
     394           8 :                 ROS_INFO_STREAM ( "No actuated joint in this finger" );
     395             :                 
     396             :             } else {
     397             :                 
     398         496 :                 for ( int i = 0; i < nJointInFinger ; i++ ) {
     399         340 :                     ROS_INFO_STREAM ( chain_joints.second.at ( i ) );
     400             :                 }
     401             :             }
     402             : 
     403         164 :             ROS_INFO_STREAM ( "-------------------------" );
     404             :         }
     405             :     } else {
     406             : 
     407           0 :         ROS_ERROR_STREAM ( "in " << __func__ << " :  ROSEE::Parser needs to be initialized. Call init() frist." );
     408             :     }
     409          61 : }
     410             : 
     411         113 : int ROSEE::Parser::getActuatedJointsNumber() const {
     412             :     
     413         113 :     return _joints_num;
     414             : }
     415             : 
     416         113 : std::map< std::string, std::vector< std::string >> ROSEE::Parser::getFingerJointMap() const {
     417             : 
     418         113 :     return _finger_joint_map;
     419             : }
     420             : 
     421           0 : std::map< std::string, std::string > ROSEE::Parser::getJointFingerMap() const {
     422             :     
     423           0 :     return _joint_finger_map;
     424             : }
     425             : 
     426         113 : std::map< std::string, urdf::JointConstSharedPtr > ROSEE::Parser::getUrdfJointMap() const {
     427             : 
     428         113 :     return _urdf_joint_map;
     429             : }
     430             : 
     431           0 : void ROSEE::Parser::getFingerJointMap( std::map< std::string, std::vector< std::string >>& finger_joint_map ) const {
     432             : 
     433           0 :     finger_joint_map = _finger_joint_map;
     434           0 : }
     435             : 
     436           0 : void ROSEE::Parser::getJointFingerMap ( std::map< std::string, std::string >& joint_finger_map ) const {
     437             : 
     438           0 :     joint_finger_map = _joint_finger_map;
     439           0 : }
     440             : 
     441         113 : std::string ROSEE::Parser::getEndEffectorName() const {
     442             : 
     443         113 :     return _urdf_model->getName();
     444             : }
     445             : 
     446           0 : std::string ROSEE::Parser::getUrdfString() const {
     447           0 :     return _urdf_string;
     448             : }
     449             : 
     450           0 : std::string ROSEE::Parser::getSrdfString() const {
     451           0 :     return _srdf_string;
     452             : }
     453             : 
     454           0 : std::string ROSEE::Parser::getRoseeConfigPath() const {
     455           0 :     return _ros_ee_config_path;
     456             : }
     457             : 
     458          93 : std::string ROSEE::Parser::getActionPath() const {
     459          93 :     return _action_path;
     460         147 : };
     461             : 
     462             : 
     463             : 
     464             : 

Generated by: LCOV version 1.13