dynamics_solver.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2012, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of Willow Garage Inc. nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 /* Author: Sachin Chitta */
00036 
00037 #include <moveit/dynamics_solver/dynamics_solver.h>
00038 
00039 // KDL
00040 #include <kdl/jntarray.hpp>
00041 #include <kdl_parser/kdl_parser.hpp>
00042 #include <kdl/chainiksolverpos_nr_jl.hpp>
00043 #include <kdl/chainiksolvervel_pinv.hpp>
00044 #include <kdl/chainfksolverpos_recursive.hpp>
00045 #include <kdl/chainjnttojacsolver.hpp>
00046 #include <kdl/tree.hpp>
00047 
00048 namespace dynamics_solver
00049 {
00050 
00051 namespace
00052 {
00053 inline geometry_msgs::Vector3 transformVector(const Eigen::Affine3d &transform,
00054                                               const geometry_msgs::Vector3 &vector)
00055 {
00056   Eigen::Vector3d p;
00057   p = Eigen::Vector3d(vector.x, vector.y, vector.z);
00058   p = transform.rotation()*p;
00059 
00060   geometry_msgs::Vector3 result;
00061   result.x = p.x();
00062   result.y = p.y();
00063   result.z = p.z();
00064 
00065   return result;
00066 }
00067 }
00068 
00069 DynamicsSolver::DynamicsSolver(const robot_model::RobotModelConstPtr &kinematic_model,
00070                                const std::string &group_name,
00071                                const geometry_msgs::Vector3 &gravity_vector)
00072 {
00073   group_name_ = group_name;
00074   kinematic_model_ = kinematic_model;
00075   joint_model_group_ = kinematic_model_->getJointModelGroup(group_name);
00076   if (!joint_model_group_)
00077     return;
00078 
00079   if(!joint_model_group_->isChain())
00080   {
00081     logError("Group %s is not a chain. Will not initialize dynamics solver", group_name_.c_str());
00082     joint_model_group_ = NULL;
00083     return;
00084   }
00085 
00086   if(joint_model_group_->getMimicJointModels().size() > 0)
00087   {
00088     logError("Group %s has a mimic joint. Will not initialize dynamics solver", group_name_.c_str());
00089     joint_model_group_ = NULL;
00090     return;
00091   }
00092 
00093   const robot_model::JointModel* joint = joint_model_group_->getJointRoots()[0];
00094   if(!joint->getParentLinkModel())
00095   {
00096     logError("Group %s does not have a parent link",group_name_.c_str());
00097     joint_model_group_ = NULL;
00098     return;
00099   }
00100 
00101   base_name_ = joint->getParentLinkModel()->getName();
00102 
00103   tip_name_ = joint_model_group_->getLinkModelNames().back();
00104   logDebug("Base name: %s, Tip name: %s", base_name_.c_str(), tip_name_.c_str());
00105 
00106   const boost::shared_ptr<const urdf::ModelInterface> urdf_model = kinematic_model_->getURDF();
00107   const boost::shared_ptr<const srdf::Model> srdf_model = kinematic_model_->getSRDF();
00108   KDL::Tree tree;
00109 
00110   if (!kdl_parser::treeFromUrdfModel(*urdf_model, tree))
00111   {
00112     logError("Could not initialize tree object");
00113     joint_model_group_ = NULL;
00114     return;
00115   }
00116   if (!tree.getChain(base_name_, tip_name_, kdl_chain_))
00117   {
00118     logError("Could not initialize chain object");
00119     joint_model_group_ = NULL;
00120     return;
00121   }
00122   num_joints_ = kdl_chain_.getNrOfJoints();
00123   num_segments_ = kdl_chain_.getNrOfSegments();
00124 
00125   kinematic_state_.reset(new robot_state::RobotState(kinematic_model_));
00126   joint_state_group_ = kinematic_state_->getJointStateGroup(joint_model_group_->getName());
00127 
00128   const std::vector<std::string> joint_model_names = joint_model_group_->getJointModelNames();
00129   for(unsigned int i=0; i < joint_model_names.size(); ++i)
00130   {
00131     const urdf::Joint* ujoint = urdf_model->getJoint(joint_model_names[i]).get();
00132     if (ujoint->limits)
00133       max_torques_.push_back(ujoint->limits->effort);
00134     else
00135       max_torques_.push_back(0.0);
00136   }
00137 
00138   KDL::Vector gravity(gravity_vector.x,gravity_vector.y,gravity_vector.z); // \todo Not sure if KDL expects the negative of this (Sachin)
00139   gravity_ = gravity.Norm();
00140   logDebug("Gravity norm set to %f", gravity_);
00141 
00142   chain_id_solver_.reset(new KDL::ChainIdSolver_RNE(kdl_chain_, gravity));
00143 }
00144 
00145 bool DynamicsSolver::getTorques(const std::vector<double> &joint_angles,
00146                                 const std::vector<double> &joint_velocities,
00147                                 const std::vector<double> &joint_accelerations,
00148                                 const std::vector<geometry_msgs::Wrench> &wrenches,
00149                                 std::vector<double> &torques) const
00150 {
00151   if(!joint_model_group_)
00152   {
00153     logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00154     return false;
00155   }
00156   if(joint_angles.size() != num_joints_)
00157   {
00158     logError("Joint angles vector should be size %d", num_joints_);
00159     return false;
00160   }
00161   if(joint_velocities.size() != num_joints_)
00162   {
00163     logError("Joint velocities vector should be size %d", num_joints_);
00164     return false;
00165   }
00166   if(joint_accelerations.size() != num_joints_)
00167   {
00168     logError("Joint accelerations vector should be size %d", num_joints_);
00169     return false;
00170   }
00171   if(wrenches.size() != num_segments_)
00172   {
00173     logError("Wrenches vector should be size %d", num_segments_);
00174     return false;
00175   }
00176   if(torques.size() != num_joints_)
00177   {
00178     logError("Torques vector should be size %d", num_joints_);
00179     return false;
00180   }
00181 
00182   KDL::JntArray kdl_angles(num_joints_), kdl_velocities(num_joints_), kdl_accelerations(num_joints_), kdl_torques(num_joints_);
00183   KDL::Wrenches kdl_wrenches(num_segments_);
00184 
00185   for(unsigned int i=0; i < num_joints_; ++i)
00186   {
00187     kdl_angles(i) = joint_angles[i];
00188     kdl_velocities(i) = joint_velocities[i];
00189     kdl_accelerations(i) = joint_accelerations[i];
00190   }
00191 
00192   for(unsigned int i=0; i < num_segments_; ++i)
00193   {
00194     kdl_wrenches[i](0) = wrenches[i].force.x;
00195     kdl_wrenches[i](1) = wrenches[i].force.y;
00196     kdl_wrenches[i](2) = wrenches[i].force.z;
00197 
00198     kdl_wrenches[i](3) = wrenches[i].torque.x;
00199     kdl_wrenches[i](4) = wrenches[i].torque.y;
00200     kdl_wrenches[i](5) = wrenches[i].torque.z;
00201   }
00202 
00203   if(chain_id_solver_->CartToJnt(kdl_angles, kdl_velocities, kdl_accelerations, kdl_wrenches, kdl_torques) < 0)
00204   {
00205     logError("Something went wrong computing torques");
00206     return false;
00207   }
00208 
00209   for(unsigned int i=0; i < num_joints_; ++i)
00210     torques[i] = kdl_torques(i);
00211 
00212   return true;
00213 }
00214 
00215 bool DynamicsSolver::getMaxPayload(const std::vector<double> &joint_angles,
00216                                    double &payload,
00217                                    unsigned int &joint_saturated) const
00218 {
00219   if(!joint_model_group_)
00220   {
00221     logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00222     return false;
00223   }
00224   if(joint_angles.size() != num_joints_)
00225   {
00226     logError("Joint angles vector should be size %d", num_joints_);
00227     return false;
00228   }
00229   std::vector<double> joint_velocities(num_joints_, 0.0), joint_accelerations(num_joints_, 0.0);
00230   std::vector<double> torques(num_joints_, 0.0), zero_torques(num_joints_, 0.0);
00231 
00232   std::vector<geometry_msgs::Wrench> wrenches(num_segments_);
00233   if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, zero_torques))
00234     return false;
00235 
00236   for(unsigned int i=0; i < num_joints_; ++i)
00237   {
00238     if(fabs(zero_torques[i]) >= max_torques_[i])
00239     {
00240       payload = 0.0;
00241       joint_saturated = i;
00242       return true;
00243     }
00244   }
00245 
00246   joint_state_group_->setVariableValues(joint_angles);
00247   const Eigen::Affine3d &base_frame = kinematic_state_->getFrameTransform(base_name_);
00248   const Eigen::Affine3d &tip_frame = kinematic_state_->getFrameTransform(tip_name_);
00249   Eigen::Affine3d transform = tip_frame.inverse() * base_frame;
00250   wrenches.back().force.z = 1.0;
00251   wrenches.back().force = transformVector(transform, wrenches.back().force);
00252   wrenches.back().torque = transformVector(transform, wrenches.back().torque);
00253 
00254   logDebug("New wrench (local frame): %f %f %f", wrenches.back().force.x, wrenches.back().force.y, wrenches.back().force.z);
00255 
00256   if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, torques))
00257     return false;
00258 
00259   double min_payload = std::numeric_limits<double>::max();
00260   for(unsigned int i=0; i < num_joints_; ++i)
00261   {
00262     double payload_joint = std::max<double>((max_torques_[i]-zero_torques[i])/(torques[i]-zero_torques[i]),(-max_torques_[i]-zero_torques[i])/(torques[i]-zero_torques[i]));//because we set the payload to 1.0
00263     logDebug("Joint: %d, Actual Torque: %f, Max Allowed: %f, Gravity: %f", i, torques[i], max_torques_[i], zero_torques[i]);
00264     logDebug("Joint: %d, Payload Allowed (N): %f", i, payload_joint);
00265     if(payload_joint < min_payload)
00266     {
00267       min_payload = payload_joint;
00268       joint_saturated = i;
00269     }
00270   }
00271   payload = min_payload/gravity_;
00272   logDebug("Max payload (kg): %f", payload);
00273   return true;
00274 }
00275 
00276 bool DynamicsSolver::getPayloadTorques(const std::vector<double> &joint_angles,
00277                                        double payload,
00278                                        std::vector<double> &joint_torques) const
00279 {
00280   if(!joint_model_group_)
00281   {
00282     logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00283     return false;
00284   }
00285   if(joint_angles.size() != num_joints_)
00286   {
00287     logError("Joint angles vector should be size %d", num_joints_);
00288     return false;
00289   }
00290   if(joint_torques.size() != num_joints_)
00291   {
00292     logError("Joint torques vector should be size %d", num_joints_);
00293     return false;
00294   }
00295   std::vector<double> joint_velocities(num_joints_, 0.0), joint_accelerations(num_joints_, 0.0);
00296   std::vector<geometry_msgs::Wrench> wrenches(num_segments_);
00297 
00298   joint_state_group_->setVariableValues(joint_angles);
00299   const Eigen::Affine3d &base_frame = kinematic_state_->getFrameTransform(base_name_);
00300   const Eigen::Affine3d &tip_frame = kinematic_state_->getFrameTransform(tip_name_);
00301   Eigen::Affine3d transform = tip_frame.inverse()* base_frame;
00302   wrenches.back().force.z = payload * gravity_;
00303   wrenches.back().force = transformVector(transform, wrenches.back().force);
00304   wrenches.back().torque = transformVector(transform, wrenches.back().torque);
00305 
00306   logDebug("New wrench (local frame): %f %f %f", wrenches.back().force.x, wrenches.back().force.y, wrenches.back().force.z);
00307 
00308   if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, joint_torques))
00309     return false;
00310   return true;
00311 }
00312 
00313 const std::vector<double>& DynamicsSolver::getMaxTorques() const
00314 {
00315   return max_torques_;
00316 }
00317 
00318 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Mon Oct 6 2014 02:24:46