param_parser.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 
00018 #include <cob_omni_drive_controller/UndercarriageCtrlGeomROS.h>
00019 #include <urdf/model.h>
00020 #include <angles/angles.h>
00021 #include <XmlRpcException.h>
00022 
00023 #include <tf2/LinearMath/Quaternion.h>
00024 #include <tf2/LinearMath/Transform.h>
00025 #include <tf2/LinearMath/Vector3.h>
00026 
00027 class MergedXmlRpcStruct : public XmlRpc::XmlRpcValue{
00028     MergedXmlRpcStruct(const XmlRpc::XmlRpcValue& a) :XmlRpc::XmlRpcValue(a){ assertStruct(); }
00029 public:
00030     MergedXmlRpcStruct(){ assertStruct(); }
00031     MergedXmlRpcStruct(const XmlRpc::XmlRpcValue& a, const MergedXmlRpcStruct &b, bool recursive= true) :XmlRpc::XmlRpcValue(a){
00032         assertStruct();
00033 
00034         for(ValueStruct::const_iterator it = b._value.asStruct->begin(); it != b._value.asStruct->end(); ++it){
00035             std::pair<XmlRpc::XmlRpcValue::iterator,bool> res =  _value.asStruct->insert(*it);
00036 
00037             if(recursive && !res.second && res.first->second.getType() == XmlRpc::XmlRpcValue::TypeStruct && it->second.getType() == XmlRpc::XmlRpcValue::TypeStruct){
00038                 res.first->second = MergedXmlRpcStruct(res.first->second, it->second); // recursive struct merge with implicit cast
00039             }
00040         }
00041 
00042 
00043     }
00044 };
00045 
00046 template<typename T> T read_typed(XmlRpc::XmlRpcValue &val){
00047     return val;
00048 }
00049 template<> double read_typed(XmlRpc::XmlRpcValue &val){
00050     if(val.getType() ==  XmlRpc::XmlRpcValue::TypeInt) return read_typed<int>(val);
00051     return val;
00052 }
00053 
00054 template<typename T> bool read_optional(T& val, const std::string &name, XmlRpc::XmlRpcValue &wheel){
00055     try{
00056         if(wheel.hasMember(name)){
00057            val = read_typed<T>(wheel[name]);
00058            return true;
00059         }
00060     }catch(XmlRpc::XmlRpcException &e){
00061         ROS_ERROR_STREAM("Could not access '" << name << "', reason: " << e.getMessage());
00062     }
00063     return false;
00064 }
00065 
00066 template<typename T> bool read_with_default(T& val, const std::string &name, XmlRpc::XmlRpcValue &wheel, const T& def){
00067     if(!read_optional(val, name, wheel)){
00068         val = def;
00069         return false;
00070     }
00071     return true;
00072 }
00073 
00074 template<typename T> bool read(T& val, const std::string &name, XmlRpc::XmlRpcValue &wheel){
00075     if(!read_optional(val, name, wheel)){
00076         ROS_ERROR_STREAM("Parameter not found: " << name);
00077         return false;
00078     }
00079     return true;
00080 }
00081 
00082 bool parseWheelTransform(const std::string& joint_name, const std::string& parent_link_name,
00083                          tf2::Transform &transform, urdf::Model* model)
00084 {
00085     urdf::Pose transform_pose;
00086     if(model)
00087     {
00088         urdf::JointConstSharedPtr joint(model->getJoint(joint_name));
00089         if (!joint)
00090         {
00091             ROS_ERROR_STREAM(joint_name
00092                              << " couldn't be retrieved from model description");
00093             return false;
00094         }
00095 
00096         transform_pose.position = joint->parent_to_joint_origin_transform.position;
00097         transform_pose.rotation = joint->parent_to_joint_origin_transform.rotation;
00098         while(joint->parent_link_name != parent_link_name)
00099         {
00100             urdf::LinkConstSharedPtr link_parent(model->getLink(joint->parent_link_name));
00101             if (!link_parent || !link_parent->parent_joint)
00102             {
00103                 ROS_ERROR_STREAM(joint->parent_link_name
00104                                  << " couldn't be retrieved from model description or his parent joint");
00105                 return false;
00106             }
00107             joint = link_parent->parent_joint;
00108             transform_pose.position = transform_pose.position + joint->parent_to_joint_origin_transform.position;
00109             transform_pose.rotation = transform_pose.rotation * joint->parent_to_joint_origin_transform.rotation;
00110         }
00111 
00112         tf2::Transform rot(tf2::Quaternion(transform_pose.rotation.x,transform_pose.rotation.y,transform_pose.rotation.z,transform_pose.rotation.w),
00113                            tf2::Vector3(0,0,0));
00114 
00115         tf2::Transform trans; trans.setIdentity();
00116         trans.setOrigin(tf2::Vector3(transform_pose.position.x,transform_pose.position.y,transform_pose.position.z));
00117 
00118         transform.setIdentity();
00119         transform = rot * trans;
00120         return true;
00121     }
00122     else
00123         return false;
00124 }
00125 
00126 bool parseCtrlParams(CtrlParams & params, XmlRpc::XmlRpcValue &wheel, urdf::Model* model){
00127     double deg;
00128     read_with_default(deg, "steer_neutral_position", wheel, 0.0);
00129     params.dWheelNeutralPos = angles::from_degrees(deg);
00130 
00131     std::string steer_name, drive_name;
00132     double max_steer_rate, max_drive_rate;
00133     read_with_default(steer_name, "steer", wheel, std::string());
00134     read_with_default(drive_name, "drive", wheel, std::string());
00135 
00136     boost::shared_ptr<const urdf::Joint> steer_joint;
00137     if(model && !steer_name.empty()){
00138         steer_joint = model->getJoint(steer_name);
00139         if(steer_joint){
00140             params.dMaxSteerRateRadpS = steer_joint->limits->velocity;
00141         }
00142     }
00143     if(!read_optional(params.dMaxSteerRateRadpS, "max_steer_rate", wheel) && !steer_joint){
00144         ROS_WARN_STREAM("max_steer_rate not set - defaulting to 0.0");
00145         params.dMaxSteerRateRadpS = 0.0;
00146     }
00147     boost::shared_ptr<const urdf::Joint> drive_joint;
00148     if(model && !drive_name.empty()){
00149         drive_joint = model->getJoint(drive_name);
00150         if(drive_joint){
00151             params.dMaxDriveRateRadpS = drive_joint->limits->velocity;
00152         }
00153     }
00154     if(!read_optional(params.dMaxDriveRateRadpS, "max_drive_rate", wheel) && !drive_joint){
00155         ROS_WARN_STREAM("max_drive_rate not set - defaulting to 0.0");
00156         params.dMaxDriveRateRadpS = 0.0;
00157     }
00158 
00159     ROS_WARN_STREAM("max_steer_rate: " <<  params.dMaxSteerRateRadpS);
00160     ROS_WARN_STREAM("max_drive_rate: " <<  params.dMaxDriveRateRadpS);
00161     
00162     return true;
00163 }
00164 
00165 bool parsePosCtrlParams(PosCtrlParams & params, XmlRpc::XmlRpcValue &wheel){
00166     if(!wheel.hasMember("steer_ctrl")){
00167         ROS_ERROR_STREAM("steer_ctrl not found");
00168         return false;
00169     }
00170     XmlRpc::XmlRpcValue &steer = wheel["steer_ctrl"];
00171 
00172     return read(params.dSpring, "spring", steer)
00173         && read(params.dDamp, "damp", steer)
00174         && read(params.dVirtM, "virt_mass", steer)
00175         && read(params.dDPhiMax, "d_phi_max", steer)
00176         && read(params.dDDPhiMax, "dd_phi_max", steer);
00177 }
00178 
00179 bool parseWheelGeom(WheelGeom & geom, XmlRpc::XmlRpcValue &wheel, MergedXmlRpcStruct &merged, urdf::Model* model){
00180 
00181     read_with_default(geom.steer_name, "steer", wheel, std::string());
00182     read_with_default(geom.drive_name, "drive", wheel, std::string());
00183     read_with_default(geom.dSteerDriveCoupling, "steer_drive_coupling", wheel, 0.0);
00184 
00185     boost::shared_ptr<const urdf::Joint> steer_joint;
00186     urdf::Vector3 steer_pos;
00187 
00188     if(model && !geom.steer_name.empty()){
00189         steer_joint = model->getJoint(geom.steer_name);
00190         if(steer_joint){
00191             tf2::Transform transform;
00192             if(parseWheelTransform(geom.steer_name, model->getRoot()->name, transform, model)){
00193                 steer_pos.x = transform.getOrigin().getX();
00194                 steer_pos.y = transform.getOrigin().getY();
00195                 steer_pos.z = transform.getOrigin().getZ();
00196             }
00197         }
00198     }
00199 
00200     if(!read_optional(steer_pos.x, "x_pos", wheel) && !steer_joint){
00201         ROS_ERROR_STREAM("Could not parse x_pos");
00202         return false;
00203     }
00204 
00205     if(!read_optional(steer_pos.y, "y_pos", wheel) && !steer_joint){
00206         ROS_ERROR_STREAM("Could not parse y_pos");
00207         return false;
00208     }
00209 
00210     if(!read_optional(steer_pos.z, "wheel_radius", merged) && !steer_joint){
00211         ROS_ERROR_STREAM("Could not parse wheel_radius");
00212         return false;
00213     }
00214 
00215     if(steer_pos.z == 0){
00216         ROS_ERROR_STREAM("wheel_radius must be non-zero");
00217         return false;
00218     }
00219 
00220     ROS_DEBUG_STREAM(geom.steer_name<<" steer_pos \tx:"<<steer_pos.x<<" \ty:"<<steer_pos.y<<" \tz:"<<steer_pos.z);
00221 
00222     geom.dWheelXPosMM = steer_pos.x * 1000;
00223     geom.dWheelYPosMM = steer_pos.y * 1000;
00224     geom.dRadiusWheelMM = fabs(steer_pos.z * 1000);
00225 
00226     double offset = 0;
00227 
00228     if(!read_optional(offset, "wheel_offset", merged)){
00229         boost::shared_ptr<const urdf::Joint> drive_joint;
00230         if(model && !geom.drive_name.empty()){
00231             drive_joint = model->getJoint(geom.drive_name);
00232         }
00233         if(drive_joint){
00234             const urdf::Vector3& pos = drive_joint->parent_to_joint_origin_transform.position;
00235             offset = sqrt(pos.x*pos.x + pos.y * pos.y);
00236         }else{
00237             ROS_ERROR_STREAM("Could not parse wheel_offset");
00238             return false;
00239         }
00240     }
00241     geom.dDistSteerAxisToDriveWheelMM = offset * 1000;
00242     return true;
00243 }
00244 
00245 template<typename W> bool parseWheel(W & params, XmlRpc::XmlRpcValue &wheel, MergedXmlRpcStruct &merged, urdf::Model* model);
00246 
00247 template<> bool parseWheel(UndercarriageGeom::WheelParams & params, XmlRpc::XmlRpcValue &wheel, MergedXmlRpcStruct &merged, urdf::Model* model){
00248     return parseWheelGeom(params.geom, wheel, merged, model);
00249 }
00250 
00251 template<> bool parseWheel(UndercarriageDirectCtrl::WheelParams & params, XmlRpc::XmlRpcValue &wheel, MergedXmlRpcStruct &merged, urdf::Model* model){
00252     return parseWheelGeom(params.geom, wheel, merged, model) && parseCtrlParams(params.ctrl, merged, model);
00253 }
00254 
00255 template<> bool parseWheel(UndercarriageCtrl::WheelParams & params, XmlRpc::XmlRpcValue &wheel, MergedXmlRpcStruct &merged, urdf::Model* model){
00256     return parseWheelGeom(params.geom, wheel, merged, model) && parseCtrlParams(params.ctrl, merged, model) && parsePosCtrlParams(params.pos_ctrl, merged);
00257 }
00258 
00259 bool make_wheel_struct(XmlRpc::XmlRpcValue &wheel_list){
00260     if(wheel_list.getType() ==  XmlRpc::XmlRpcValue::TypeArray){
00261         XmlRpc::XmlRpcValue new_stuct;
00262         for(size_t i = 0; i < wheel_list.size(); ++i){
00263             new_stuct[boost::lexical_cast<std::string>(i)] = wheel_list[i];
00264         }
00265         wheel_list = new_stuct;
00266     }else if(wheel_list.getType() !=  XmlRpc::XmlRpcValue::TypeStruct){
00267         return false;
00268     }
00269 
00270     return wheel_list.size() > 0;
00271 }
00272 
00273 template<typename W> bool parseWheels(std::vector<W> &wheel_params, const ros::NodeHandle &nh, bool read_urdf){
00274 
00275     urdf::Model model;
00276 
00277     std::string description_name;
00278     bool has_model = read_urdf && nh.searchParam("robot_description", description_name) &&  model.initParam(description_name);
00279 
00280     MergedXmlRpcStruct defaults;
00281     nh.getParam("defaults", defaults);
00282 
00283     // clear vector in case of reinititialization
00284     wheel_params.clear();
00285 
00286     XmlRpc::XmlRpcValue wheel_list;
00287     if (!nh.getParam("wheels", wheel_list)){
00288         ROS_ERROR("List of wheels not found");
00289         return false;
00290     }
00291 
00292     if (!make_wheel_struct(wheel_list)){
00293         ROS_ERROR("List of wheels is invalid");
00294         return false;
00295     }
00296 
00297     for(XmlRpc::XmlRpcValue::iterator it = wheel_list.begin(); it != wheel_list.end(); ++it){
00298 
00299         W params;
00300         MergedXmlRpcStruct merged(it->second, defaults);
00301 
00302         if(!parseWheel(params, it->second, merged, has_model?&model:0)){
00303             return false;
00304         }
00305 
00306         wheel_params.push_back(params);
00307     }
00308     return !wheel_params.empty();
00309 }
00310 
00311 namespace cob_omni_drive_controller{
00312 
00313 bool parseWheelParams(std::vector<UndercarriageGeom::WheelParams> &params, const ros::NodeHandle &nh, bool read_urdf /* = true*/){
00314     return parseWheels(params, nh, read_urdf);
00315 }
00316 bool parseWheelParams(std::vector<UndercarriageDirectCtrl::WheelParams> &params, const ros::NodeHandle &nh, bool read_urdf /* = true*/){
00317     return parseWheels(params, nh, read_urdf);
00318 }
00319 bool parseWheelParams(std::vector<UndercarriageCtrl::WheelParams> &params, const ros::NodeHandle &nh, bool read_urdf /* = true*/){
00320     return parseWheels(params, nh, read_urdf);
00321 }
00322 
00323 
00324 }


cob_omni_drive_controller
Author(s): Christian Connette, Mathias Lüdtke
autogenerated on Thu Jun 6 2019 21:19:19