treeiksolverpos_online.cpp
Go to the documentation of this file.
00001 // Copyright  (C)  2011  PAL Robotics S.L.  All rights reserved.
00002 // Copyright  (C)  2007-2008  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
00003 // Copyright  (C)  2008  Mikael Mayer
00004 // Copyright  (C)  2008  Julia Jesse
00005 
00006 // Version: 1.0
00007 // Author: Marcus Liebhardt
00008 // This class has been derived from the KDL::TreeIkSolverPos_NR_JL class
00009 // by Julia Jesse, Mikael Mayer and Ruben Smits
00010 
00011 // This library is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU Lesser General Public
00013 // License as published by the Free Software Foundation; either
00014 // version 2.1 of the License, or (at your option) any later version.
00015 
00016 // This library is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00024 
00025 #include "tree_kinematics/treeiksolverpos_online.hpp"
00026 #include <algorithm>
00027 
00028 namespace KDL {
00029 
00030 TreeIkSolverPos_Online::TreeIkSolverPos_Online(const double& nr_of_jnts,
00031                                                const std::vector<std::string>& endpoints,
00032                                                TreeFkSolverPos& fksolver,
00033                                                TreeIkSolverVel& iksolver,
00034                                                const JntArray& q_min,
00035                                                const JntArray& q_max,
00036                                                const JntArray& q_dot_min,
00037                                                const JntArray& q_dot_max,
00038                                                const double x_dot_trans_max,
00039                                                const double x_dot_rot_max,
00040                                                const double x_dot_trans_min,
00041                                                const double x_dot_rot_min,
00042                                                const double low_pass_factor,
00043                                                const unsigned int maxiter,
00044                                                const double eps) :
00045                                                fksolver_(fksolver),
00046                                                iksolver_(iksolver),
00047                                                q_min_(nr_of_jnts),
00048                                                q_max_(nr_of_jnts),
00049                                                q_dot_min_(nr_of_jnts),
00050                                                q_dot_max_(nr_of_jnts),
00051                                                maxiter_(maxiter),
00052                                                eps_(eps),
00053                                                q_dot_(nr_of_jnts),
00054                                                q_dot_old_(nr_of_jnts),
00055                                                q_dot_new_(nr_of_jnts),
00056                                                q_out_old_(nr_of_jnts)
00057 {
00058     assert(q_min.rows() == nr_of_jnts);
00059     assert(q_max.rows() == nr_of_jnts);
00060     assert(q_dot_max.rows() == nr_of_jnts);
00061     assert(q_out_old_.rows() == nr_of_jnts);
00062 
00063     SetToZero(q_out_old_);
00064     q_min_ = q_min;
00065     q_max_ = q_max;
00066     q_dot_min_ = q_dot_min;
00067     q_dot_max_ = q_dot_max;
00068     x_dot_trans_max_ = x_dot_trans_max;
00069     x_dot_rot_max_ = x_dot_rot_max;
00070     x_dot_trans_min_ = x_dot_trans_min;
00071     x_dot_rot_min_ = x_dot_rot_min;
00072     low_pass_factor_ = low_pass_factor;
00073     low_pass_adj_factor_ = 0.0;
00074     nr_of_still_endeffectors_ = 0;
00075     small_task_space_movement_ = false;
00076 
00077     for (size_t i = 0; i < endpoints.size(); i++)
00078     {
00079 
00080       frames_.insert(Frames::value_type(endpoints[i], Frame::Identity()));
00081       delta_twists_.insert(Twists::value_type(endpoints[i], Twist::Zero()));
00082       old_twists_.insert(Twists::value_type(endpoints[i], Twist::Zero()));
00083 
00084       frames_pos_lim_.insert(Frames::value_type(endpoints[i], Frame::Identity()));
00085       frames_vel_lim_.insert(Frames::value_type(endpoints[i], Frame::Identity()));
00086       p_in_old_.insert(Frames::value_type(endpoints[i], Frame::Identity()));
00087 
00088     }
00089 
00090 }
00091 
00092 
00093 TreeIkSolverPos_Online::~TreeIkSolverPos_Online()
00094 {}
00095 
00096 
00097 double TreeIkSolverPos_Online::CartToJnt(const JntArray& q_in, const Frames& p_in, JntArray& q_out)
00098 {
00099   assert(q_out.rows() == q_in.rows());
00100   assert(q_dot_.rows() == q_out.rows());
00101 
00102   q_out = q_in;
00103 
00104   // First check, if all elements in p_in are available
00105   for(Frames::const_iterator f_des_it=p_in.begin();f_des_it!=p_in.end();++f_des_it)
00106     if(frames_.find(f_des_it->first)==frames_.end())
00107       return -2;
00108 
00109   for (Frames::const_iterator f_des_it=p_in.begin();f_des_it!=p_in.end();++f_des_it)
00110   {
00111     // Get all iterators for this endpoint
00112     Frames::iterator f_it = frames_.find(f_des_it->first);
00113     Twists::iterator delta_twists_it = delta_twists_.find(f_des_it->first);
00114 
00115     fksolver_.JntToCart(q_out, f_it->second, f_it->first);
00116     twist_ = diff(f_it->second, f_des_it->second);
00117 
00118     // Checks, if the twist (twist_) exceeds the maximum translational and/or rotational velocity
00119     // And scales them, if necessary
00120     enforceCartVelLimits();
00121 
00122     delta_twists_it->second = twist_;
00123   }
00124 
00125   double res = iksolver_.CartToJnt(q_out, delta_twists_, q_dot_);
00126 
00127   // Checks, if joint velocities (q_dot_) exceed their maximum velocities and scales them, if necessary
00128   enforceJointVelLimits();
00129 
00130   // Integrate
00131   Add(q_out, q_dot_, q_out);
00132 
00133   // Limit joint positions
00134   for (unsigned int j = 0; j < q_min_.rows(); j++)
00135   {
00136     if (q_out(j) < q_min_(j))
00137       q_out(j) = q_min_(j);
00138     else if (q_out(j) > q_max_(j))
00139       q_out(j) = q_max_(j);
00140   }
00141 
00142   return res;
00143 }
00144 
00145 
00146 double TreeIkSolverPos_Online::CartToJnt_it(const JntArray& q_in, const Frames& p_in, JntArray& q_out)
00147 {
00148   assert(q_out.rows() == q_in.rows());
00149   assert(q_out_old_.rows() == q_in.rows());
00150   assert(q_dot_.rows() == q_in.rows());
00151   assert(q_dot_old_.rows() == q_in.rows());
00152   assert(q_dot_new_.rows() == q_in.rows());
00153 
00154 
00155 
00156   q_out = q_in;
00157   SetToZero(q_dot_);
00158   SetToZero(q_dot_old_);
00159   SetToZero(q_dot_new_);
00160   twist_ = Twist::Zero();
00161 
00162   // First check, if all elements in p_in are available
00163   unsigned int nr_of_endeffectors = 0;
00164   nr_of_still_endeffectors_ = 0;
00165   low_pass_adj_factor_ = 0.0;
00166 
00167   for(Frames::const_iterator f_des_it=p_in.begin();f_des_it!=p_in.end();++f_des_it)
00168   {
00169     if(frames_.find(f_des_it->first)==frames_.end())
00170       return -2;
00171     else
00172     {
00173       /*
00174       Twists::iterator old_twists_it = old_twists_.find(f_des_it->first);
00175       old_twists_it->second = Twist::Zero();
00176       Frames::iterator f_0_it = frames_0_.find(f_des_it->first);
00177       */
00178       /*
00179       Twists::iterator old_twists_it = old_twists_.find(f_des_it->first);
00180       old_twists_it->second = diff(f_old_it->second, f_des_it->second);
00181       if (){};
00182       */
00183       Frames::iterator f_old_it = p_in_old_.find(f_des_it->first);
00184       Frames::iterator f_des_pos_l_it = frames_pos_lim_.find(f_des_it->first);
00185       twist_ = diff(f_old_it->second, f_des_it->second);
00186       /*
00187       if(sqrt(pow(twist_.vel.x(), 2) + pow(twist_.vel.y(), 2) + pow(twist_.vel.z(), 2)) < x_dot_trans_min_)
00188       {
00189         f_des_pos_l_it->second.p = addDelta(f_old_it->second.p, (0.1 * x_dot_trans_max_ * twist_.vel));
00190         std::cout << "old position is used." << std::endl;
00191       }
00192       else
00193         f_des_pos_l_it->second.p = f_des_it->second.p;
00194 
00195       if(sqrt(pow(twist_.rot.x(), 2) + pow(twist_.rot.y(), 2) + pow(twist_.rot.z(), 2)) < x_dot_rot_min_)
00196       {
00197         f_des_pos_l_it->second.M = addDelta(f_old_it->second.M, (0.1 * x_dot_rot_max_ * twist_.rot));
00198         std::cout << "old orientation is used." << std::endl;
00199       }
00200       else
00201         f_des_pos_l_it->second.M = f_des_it->second.M;
00202       */
00203       f_des_pos_l_it->second.p = f_des_it->second.p;
00204       f_des_pos_l_it->second.M = f_des_it->second.M;
00205 
00206       Frames::iterator f_des_vel_l_it = frames_vel_lim_.find(f_des_it->first);
00207       fksolver_.JntToCart(q_in, f_des_vel_l_it->second, f_des_it->first);
00208       twist_ = diff(f_des_vel_l_it->second, f_des_pos_l_it->second);
00209 
00210 
00211 
00212       f_des_vel_l_it->second = addDelta(f_des_vel_l_it->second, twist_);
00213       nr_of_endeffectors++;
00214     }
00215   }
00216   if(nr_of_still_endeffectors_ == nr_of_endeffectors)
00217   {
00218     small_task_space_movement_ = true;
00219 
00220   }
00221   else
00222     small_task_space_movement_ = false;
00223 
00224   unsigned int k=0;
00225   double res = 0.0;
00226   while(++k <= maxiter_)
00227   {
00228     //for (Frames::const_iterator f_des_it=p_in.begin(); f_des_it!=p_in.end(); ++f_des_it)
00229     for (Frames::const_iterator f_des_it=frames_vel_lim_.begin(); f_des_it!=frames_vel_lim_.end(); ++f_des_it)
00230     {
00231       // Get all iterators for this endpoint
00232       Frames::iterator f_it = frames_.find(f_des_it->first);
00233       Twists::iterator delta_twists_it = delta_twists_.find(f_des_it->first);
00234       Twists::iterator old_twists_it = old_twists_.find(f_des_it->first);
00235       Frames::iterator f_0_it = frames_vel_lim_.find(f_des_it->first);
00236 
00237       fksolver_.JntToCart(q_out, f_it->second, f_it->first);
00238 
00239       // Checks, if the current overall twist exceeds the maximum translational and/or rotational velocity.
00240       // If so, the velocities of the overall twist get scaled and a new current twist is calculated.
00241       delta_twists_it->second = diff(f_it->second, f_des_it->second);
00242 
00243 
00244       old_twists_it->second = diff(f_0_it->second, f_it->second);
00245 
00246       enforceCartVelLimits_it(old_twists_it->second, delta_twists_it->second);
00247 
00248 
00249     }
00250 
00251     res = iksolver_.CartToJnt(q_out, delta_twists_, q_dot_);
00252 
00253     if (res < eps_)
00254     {
00255       break;
00256       //return res;
00257     }
00258 
00259     // Checks, if joint velocities (q_dot_) exceed their maximum velocities and scales them, if necessary
00260     //Subtract(q_out, q_in, q_dot_old_);
00261     //enforceJointVelLimits_it(q_dot_old_, q_dot_);
00262 
00263     Subtract(q_out, q_in, q_dot_old_);
00264 
00265     Add(q_dot_old_, q_dot_, q_dot_);
00266 
00267     enforceJointVelLimits();
00268 
00269     Subtract(q_dot_, q_dot_old_, q_dot_);
00270 
00271     // Integrate
00272     Add(q_out, q_dot_, q_out);
00273 
00274     // Limit joint positions
00275     for (unsigned int j = 0; j < q_min_.rows(); ++j)
00276     {
00277       if (q_out(j) < q_min_(j))
00278         q_out(j) = q_min_(j);
00279       else if (q_out(j) > q_max_(j))
00280         q_out(j) = q_max_(j);
00281     }
00282   }
00283 
00284   Subtract(q_out, q_in, q_dot_);
00285 
00286 
00287   Add(q_in, q_dot_, q_out);
00288   filter(q_dot_, q_out, q_out_old_);
00289 
00290 
00291 
00292   q_out_old_ = q_out;
00293   p_in_old_ = p_in;
00294 
00295 
00296   if (k <= maxiter_)
00297     return res;
00298   else
00299     return -3;
00300 }
00301 
00302 
00303 bool TreeIkSolverPos_Online::enforceCartVelLimits()
00304 {
00305   // relative overshoot
00306   double rel_os_trans = 0.0;
00307   double rel_os_rot = 0.0;
00308   // biggest relative overshoot
00309   double rel_os_max = 0.0;
00310   bool max_exceeded = false;
00311   double x_dot_trans, x_dot_rot;
00312   x_dot_trans = sqrt( pow(twist_.vel.x(), 2) + pow(twist_.vel.y(), 2) + pow(twist_.vel.z(), 2));
00313   x_dot_rot = sqrt( pow(twist_.rot.x(), 2) + pow(twist_.rot.y(), 2) + pow(twist_.rot.z(), 2));
00314 
00315   if (x_dot_trans <= x_dot_trans_min_ && x_dot_rot <= x_dot_rot_min_ && x_dot_trans_min_ != 0.0 && x_dot_rot_min_ != 0.0)
00316   {
00317     double trans_low_pass_factor = 0.1 + 0.9 * (x_dot_trans / x_dot_trans_min_);
00318     double rot_low_pass_factor = 0.1 + 0.9 * (x_dot_rot / x_dot_rot_min_);
00319 
00320     if(low_pass_adj_factor_ < max(trans_low_pass_factor, rot_low_pass_factor))
00321       low_pass_adj_factor_ = max(trans_low_pass_factor, rot_low_pass_factor);
00322 
00323 
00324     nr_of_still_endeffectors_++;
00325   }
00326 
00327   if ( x_dot_trans > x_dot_trans_max_ || x_dot_rot > x_dot_rot_max_ )
00328   {
00329     rel_os_trans = (x_dot_trans - x_dot_trans_max_) / x_dot_trans_max_;
00330     rel_os_rot = (x_dot_rot - x_dot_rot_max_) / x_dot_rot_max_;
00331 
00332     if ( rel_os_trans >= rel_os_rot )
00333     {
00334       max_exceeded = true;
00335       rel_os_max = rel_os_trans;
00336     }
00337     else if ( rel_os_trans < rel_os_rot )
00338     {
00339       max_exceeded = true;
00340       rel_os_max = rel_os_rot;
00341     }
00342   }
00343 
00344   if ( max_exceeded == true )
00345   {
00346     twist_.vel = twist_.vel * ( 1.0 / ( 1.0 + rel_os_max ) );
00347     twist_.rot = twist_.rot * ( 1.0 / ( 1.0 + rel_os_max ) );
00348     return true;
00349   }
00350   else
00351     return false;
00352 }
00353 
00354 
00355 bool TreeIkSolverPos_Online::enforceJointVelLimits()
00356 {
00357   // check, if one (or more) joint velocities exceed the maximum value
00358   // and if so, safe the biggest overshoot for scaling q_dot_ properly
00359   // to keep the direction of the velocity vector the same
00360 
00361   // relative overshoot
00362   double rel_os = 0.0;
00363   // biggest relative overshoot
00364   double rel_os_max = 0.0;
00365   bool max_exceeded = false;
00366 
00367   for (unsigned int i = 0; i < q_dot_.rows(); ++i)
00368   {
00369     if ( q_dot_(i) > q_dot_max_(i) && q_dot_max_(i) != 0.0)
00370     {
00371       max_exceeded = true;
00372       rel_os = (q_dot_(i) - q_dot_max_(i)) / q_dot_max_(i);
00373       if ( rel_os > rel_os_max )
00374       {
00375         rel_os_max = rel_os;
00376       }
00377     }
00378     else if ( q_dot_(i) < -q_dot_max_(i) && q_dot_max_(i) != 0.0)
00379     {
00380       max_exceeded = true;
00381       rel_os = (-q_dot_(i) - q_dot_max_(i)) / q_dot_max_(i);
00382       if ( rel_os > rel_os_max)
00383       {
00384         rel_os_max = rel_os;
00385       }
00386     }
00387     else if (q_dot_max_(i) == 0.0)
00388       q_dot_(i) = 0.0;
00389   }
00390 
00391   // scales q_dot_, if one joint exceeds the maximum value
00392   if ( max_exceeded == true )
00393   {
00394     Multiply(q_dot_, ( 1.0 / ( 1.0 + rel_os_max ) ), q_dot_);
00395     return true;
00396   }
00397   else
00398     return false;
00399 }
00400 
00401 
00402 void TreeIkSolverPos_Online::enforceCartVelLimits_it(Twist& old_twist, Twist& current_twist)
00403 {
00404   bool max_exceeded = false;
00405   double x_dot_trans, x_dot_rot;
00406 
00407   twist_ = old_twist + current_twist;
00408 
00409   x_dot_trans = sqrt( pow(twist_.vel.x(), 2) + pow(twist_.vel.y(), 2) + pow(twist_.vel.z(), 2));
00410   x_dot_rot = sqrt( pow(twist_.rot.x(), 2) + pow(twist_.rot.y(), 2) + pow(twist_.rot.z(), 2));
00411 
00412   if ( x_dot_trans > x_dot_trans_max_ || x_dot_rot > x_dot_rot_max_ )
00413   {
00414     if ( x_dot_trans > x_dot_rot )
00415     {
00416       twist_.vel = twist_.vel * ( x_dot_trans_max_ / x_dot_trans );
00417       twist_.rot = twist_.rot * ( x_dot_trans_max_ / x_dot_trans );
00418       max_exceeded = true;
00419     }
00420     else if ( x_dot_rot > x_dot_trans )
00421     {
00422       twist_.vel = twist_.vel * ( x_dot_rot_max_ / x_dot_rot );
00423       twist_.rot = twist_.rot * ( x_dot_rot_max_ / x_dot_rot );
00424       max_exceeded = true;
00425     }
00426   }
00427 
00428   if ( max_exceeded == true )
00429     current_twist = twist_ - old_twist;
00430 
00431   //old_twist = old_twist + current_twist;
00432 }
00433 
00434 
00435 void TreeIkSolverPos_Online::enforceJointVelLimits_it(JntArray& q_dot_old, JntArray& q_dot_current)
00436 {
00437   // check, if one (or more) joint velocities exceed the maximum value
00438   // and if so, safe the biggest overshoot for scaling q_dot_ properly
00439   // to keep the direction of the velocity vector the same
00440   double rel_os = 0.0; // relative overshoot
00441   double rel_os_max = 0.0; // biggest relative overshoot
00442   bool max_exceeded = false;
00443 
00444   // current overall joint velocities
00445   Add(q_dot_old, q_dot_current, q_dot_new_);
00446 
00447   for (unsigned int i = 0; i < q_dot_new_.rows(); ++i)
00448   {
00449     if ( q_dot_new_(i) > q_dot_max_(i) )
00450     {
00451       max_exceeded = true;
00452       rel_os = (q_dot_new_(i) - q_dot_max_(i)) / q_dot_max_(i);
00453       if ( rel_os > rel_os_max )
00454       {
00455         rel_os_max = rel_os;
00456       }
00457     }
00458     else if ( q_dot_new_(i) < -q_dot_max_(i) )
00459     {
00460       max_exceeded = true;
00461       rel_os = (-q_dot_new_(i) - q_dot_max_(i)) / q_dot_max_(i);
00462       if ( rel_os > rel_os_max)
00463       {
00464         rel_os_max = rel_os;
00465       }
00466     }
00467   }
00468 
00469   // scales q_dot_, if one joint exceeds the maximum value
00470   if ( max_exceeded == true )
00471   {
00472     Multiply(q_dot_new_, ( 1.0 / ( 1.0 + rel_os_max ) ), q_dot_new_);
00473     // the scaled current velocities (because q_dot_new_ is scaled)
00474     Subtract(q_dot_new_, q_dot_old, q_dot_current);
00475   }
00476 }
00477 
00478 
00479 void TreeIkSolverPos_Online::filter(JntArray& q_dot, JntArray& q_out, JntArray& q_out_old)
00480 {
00481   // deadband filter
00482   //bool min_exceeded = false;
00483   //bool low_min_exceeded = false;
00484   double low_pass_factor = 1.0;
00485   /*
00486   for (unsigned int i = 0; i < q_dot.rows(); ++i)
00487   {
00488     if (q_dot(i) > q_dot_min_(i) || -q_dot(i) > q_dot_min_(i))
00489     {
00490       min_exceeded = true;
00491     }
00492     else if (q_dot(i) > (q_dot_min_(i) * 0.3) || -q_dot(i) > (q_dot_min_(i) * 0.3))
00493     {q
00494 
00495       low_min_exceeded = true;
00496     }
00497   }
00498 
00499   if(!low_min_exceeded)
00500     low_pass_factor = 0.3 * low_pass_factor_;
00501   else if(!min_exceeded)
00502     low_pass_factor = 0.7 * low_pass_factor_;
00503   else
00504     low_pass_factor = 1.0 * low_pass_factor_;
00505   */
00506 
00507   if(small_task_space_movement_)
00508   {
00509     low_pass_factor = low_pass_adj_factor_ * low_pass_factor_;
00510     small_task_space_movement_ = false;
00511   }
00512   else
00513     low_pass_factor = low_pass_factor_;
00514 
00515   for (unsigned int i = 0; i < q_dot.rows(); ++i)
00516   {
00517     q_out(i) = low_pass_factor * q_out(i) + (1.0 - low_pass_factor) * q_out_old(i);
00518   }
00519 }
00520 
00521 } // namespace
00522 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends


tree_kinematics
Author(s): Marcus Liebhardt
autogenerated on Thu Jun 27 2013 16:12:20