cart_trajectory_pt.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2014, Dan Solomon
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  * http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 /*
00019  * cart_trajectory_pt.cpp
00020  *
00021  *  Created on: Oct 3, 2014
00022  *      Author: Dan Solomon
00023  */
00024 
00025 #include <tuple>
00026 #include <map>
00027 #include <algorithm>
00028 #include <console_bridge/console.h>
00029 #include <ros/console.h>
00030 #include <boost/uuid/uuid_io.hpp>
00031 #include "descartes_trajectory/cart_trajectory_pt.h"
00032 #include <descartes_core/utils.h>
00033 
00034 #define NOT_IMPLEMENTED_ERR(ret) logError("%s not implemented", __PRETTY_FUNCTION__); return ret;
00035 
00036 const double EQUALITY_TOLERANCE = 0.0001f;
00037 
00038 using namespace descartes_core;
00039 
00040 namespace descartes_trajectory
00041 {
00042  EigenSTL::vector_Affine3d uniform(const TolerancedFrame & frame, const double orient_increment,
00043                                   const double pos_increment)
00044 {
00045 
00046    EigenSTL::vector_Affine3d rtn;
00047 
00048    if(pos_increment < 0.0 || orient_increment < 0.0)
00049    {
00050      ROS_WARN_STREAM("Negative position/orientation intcrement: " << pos_increment
00051                      << "/" << orient_increment);
00052      rtn.clear();
00053      return rtn;
00054    }
00055 
00056   Eigen::Affine3d sampled_frame;
00057 
00058   // Calculating the number of samples for each tolerance (position and orientation)
00059   size_t ntx, nty, ntz, nrx, nry, nrz;
00060 
00061   if(orient_increment > 0)
00062   {
00063     nrx = ((frame.orientation_tolerance.x_upper - frame.orientation_tolerance.x_lower)/orient_increment) + 1;
00064     nry = ((frame.orientation_tolerance.y_upper - frame.orientation_tolerance.y_lower)/orient_increment) + 1;
00065     nrz = ((frame.orientation_tolerance.z_upper - frame.orientation_tolerance.z_lower)/orient_increment) + 1;
00066   }
00067   else
00068   {
00069     nrx = nry = nrz = 1;
00070   }
00071 
00072   if(pos_increment > 0)
00073   {
00074     ntx = ((frame.position_tolerance.x_upper - frame.position_tolerance.x_lower)/pos_increment) + 1;
00075     nty = ((frame.position_tolerance.y_upper - frame.position_tolerance.y_lower)/pos_increment) + 1;
00076     ntz = ((frame.position_tolerance.z_upper - frame.position_tolerance.z_lower)/pos_increment) + 1;
00077   }
00078   else
00079   {
00080     ntx = nty = ntz = 1;
00081   }
00082 
00083   // Estimating the number of samples base on tolerance zones and sampling increment.
00084   size_t est_num_samples = ntx * nty * ntz * nrx * nry * nrz;
00085 
00086   ROS_DEBUG_STREAM("Estimated number of samples: " << est_num_samples << ", reserving space");
00087   rtn.reserve(est_num_samples);
00088 
00089   //TODO: The following for loops do not ensure that the rull range is sample (lower to upper)
00090   //since there could be round off error in the incrementing of samples.  As a result, the
00091   //exact upper bound may not be sampled.  Since this isn't a final implementation, this will
00092   //be ignored.
00093   double rx, ry, rz, tx, ty, tz;
00094 
00095   for(size_t ii = 0; ii < nrx; ++ii)
00096   {
00097     rx = frame.orientation_tolerance.x_lower + orient_increment * ii;
00098     for(size_t jj = 0; jj < nry; ++jj)
00099     {
00100       ry = frame.orientation_tolerance.y_lower + orient_increment * jj;
00101       for(size_t kk = 0; kk < nrz; ++kk)
00102       {
00103         rz = frame.orientation_tolerance.z_lower + orient_increment * kk;
00104         for(size_t ll = 0; ll < ntx; ++ll)
00105         {
00106           tx = frame.position_tolerance.x_lower + pos_increment * ll;
00107           for(size_t mm = 0; mm < nty; ++mm)
00108           {
00109             ty = frame.position_tolerance.y_lower + pos_increment * mm;
00110             for(size_t nn = 0; nn < ntz; ++nn)
00111             {
00112               tz = frame.position_tolerance.z_lower + pos_increment * nn;
00113 
00114 /*              sampled_frame = Eigen::Translation3d(tx,ty,tz) *
00115                   Eigen::AngleAxisd(rx, Eigen::Vector3d::UnitX()) *
00116                   Eigen::AngleAxisd(ry, Eigen::Vector3d::UnitY()) *
00117                   Eigen::AngleAxisd(rz, Eigen::Vector3d::UnitZ());*/
00118               sampled_frame = descartes_core::utils::toFrame(tx,ty, tz,
00119                                              rx, ry, rz,descartes_core::utils::EulerConventions::XYZ);
00120               rtn.push_back(sampled_frame);
00121             }
00122           }
00123         }
00124       }
00125     }
00126   }
00127   ROS_DEBUG_STREAM("Uniform sampling of frame, utilizing orientation increment: " << orient_increment
00128                    << ", and position increment: " << pos_increment
00129                    << " resulted in " << rtn.size() << " samples");
00130   return rtn;
00131 }
00132 
00133 
00134 double distance(const std::vector<double>& j1, const std::vector<double>& j2)
00135 {
00136  double rt = 0;
00137  double d;
00138  if(j1.size() == j2.size())
00139  {
00140    for(int i = 0 ; i < j1.size(); i++)
00141    {
00142      d = j1[i] - j2[i];
00143      rt += d*d;
00144    }
00145  }
00146  else
00147  {
00148    ROS_WARN_STREAM("Unequal size vectors, returning negative distance");
00149    return -1;
00150  }
00151 
00152  return std::sqrt(rt);
00153 }
00154 
00155 CartTrajectoryPt::CartTrajectoryPt(const descartes_core::TimingConstraint& timing)
00156   : descartes_core::TrajectoryPt(timing),
00157   tool_base_(Eigen::Affine3d::Identity()),
00158   tool_pt_(Eigen::Affine3d::Identity()),
00159   wobj_base_(Eigen::Affine3d::Identity()),
00160   wobj_pt_(Eigen::Affine3d::Identity()),
00161   pos_increment_(0.0),
00162   orient_increment_(0.0)
00163 {}
00164 
00165 CartTrajectoryPt::CartTrajectoryPt(const Frame &wobj_base, const TolerancedFrame &wobj_pt, const Frame &tool,
00166                  const TolerancedFrame &tool_pt, double pos_increment, double orient_increment,
00167                  const descartes_core::TimingConstraint& timing)
00168   : descartes_core::TrajectoryPt(timing),
00169   tool_base_(tool),
00170   tool_pt_(tool_pt),
00171   wobj_base_(wobj_base),
00172   wobj_pt_(wobj_pt),
00173   pos_increment_(pos_increment),
00174   orient_increment_(orient_increment)
00175 {}
00176 
00177 
00178 CartTrajectoryPt::CartTrajectoryPt(const TolerancedFrame &wobj_pt, double pos_increment,
00179                                    double orient_increment, const descartes_core::TimingConstraint& timing)
00180   : descartes_core::TrajectoryPt(timing),
00181   tool_base_(Eigen::Affine3d::Identity()),
00182   tool_pt_(Eigen::Affine3d::Identity()),
00183   wobj_base_(Eigen::Affine3d::Identity()),
00184   wobj_pt_(wobj_pt),
00185   pos_increment_(pos_increment),
00186   orient_increment_(orient_increment)
00187 {}
00188 
00189 
00190 CartTrajectoryPt::CartTrajectoryPt(const Frame &wobj_pt, const descartes_core::TimingConstraint& timing)
00191 : descartes_core::TrajectoryPt(timing),
00192 tool_base_(Eigen::Affine3d::Identity()),
00193 tool_pt_(Eigen::Affine3d::Identity()),
00194 wobj_base_(Eigen::Affine3d::Identity()),
00195 wobj_pt_(wobj_pt),
00196 pos_increment_(0),
00197 orient_increment_(0)
00198 {}
00199 
00200 bool CartTrajectoryPt::getClosestCartPose(const std::vector<double> &seed_state,
00201                                           const RobotModel &model, Eigen::Affine3d &pose) const
00202 {
00203   NOT_IMPLEMENTED_ERR(false);
00204 }
00205 
00206 bool CartTrajectoryPt::getNominalCartPose(const std::vector<double> &seed_state,
00207                                           const RobotModel &model, Eigen::Affine3d &pose) const
00208 {
00209   /* Simply return wobj_pt expressed in world */
00210   pose = wobj_base_.frame * wobj_pt_.frame;
00211   return true;  //TODO can this ever return false?
00212 }
00213 
00214 bool CartTrajectoryPt::computeCartesianPoses(EigenSTL::vector_Affine3d &poses) const
00215 {
00216   EigenSTL::vector_Affine3d sampled_wobj_pts = uniform(wobj_pt_, orient_increment_,
00217                                                      pos_increment_);
00218   EigenSTL::vector_Affine3d sampled_tool_pts = uniform(tool_pt_, orient_increment_,
00219                                                        pos_increment_);
00220 
00221   poses.clear();
00222   poses.reserve(sampled_wobj_pts.size()*sampled_tool_pts.size());
00223   for(size_t wobj_pt = 0; wobj_pt < sampled_wobj_pts.size(); ++wobj_pt)
00224   {
00225     for(size_t tool_pt = 0; tool_pt < sampled_tool_pts.size(); ++tool_pt)
00226     {
00227       Eigen::Affine3d pose = wobj_base_.frame * sampled_wobj_pts[wobj_pt] *
00228           sampled_tool_pts[tool_pt].inverse() * tool_base_.frame_inv;
00229 
00230       poses.push_back(pose);
00231     }
00232   }
00233 
00234   return !poses.empty();
00235 }
00236 
00237 void CartTrajectoryPt::getCartesianPoses(const RobotModel &model, EigenSTL::vector_Affine3d &poses) const
00238 {
00239   EigenSTL::vector_Affine3d all_poses;
00240   poses.clear();
00241 
00242   if(computeCartesianPoses(all_poses))
00243   {
00244     poses.reserve(all_poses.size());
00245     for(const auto& pose: all_poses)
00246     {
00247       if(model.isValid(pose))
00248       {
00249         poses.push_back(pose);
00250       }
00251     }
00252   }
00253   else
00254   {
00255     ROS_ERROR("Failed for find ANY cartesian poses");
00256   }
00257 
00258   if( poses.empty())
00259   {
00260     ROS_WARN("Failed for find VALID cartesian poses, returning");
00261   }
00262   else
00263   {
00264     ROS_DEBUG_STREAM("Get cartesian poses, sampled: " << all_poses.size()
00265                      << ", with " << poses.size() << " valid(returned) poses");
00266   }
00267 
00268 }
00269 
00270 bool CartTrajectoryPt::getClosestJointPose(const std::vector<double> &seed_state,
00271                                            const RobotModel &model,
00272                                            std::vector<double> &joint_pose) const
00273 {
00274   Eigen::Affine3d nominal_pose,candidate_pose;
00275 
00276   if(!model.getFK(seed_state,candidate_pose))
00277   {
00278     ROS_ERROR_STREAM("FK failed for seed pose for closest joint pose");
00279     return false;
00280   }
00281 
00282   // getting pose values
00283   Eigen::Vector3d t = candidate_pose.translation();
00284   Eigen::Vector3d rpy = candidate_pose.rotation().eulerAngles(0,1,2);
00285 
00286   std::vector< std::tuple<double,double,double> > vals =
00287   {
00288    std::make_tuple(t(0),wobj_pt_.position_tolerance.x_lower,wobj_pt_.position_tolerance.x_upper),
00289    std::make_tuple(t(1),wobj_pt_.position_tolerance.y_lower,wobj_pt_.position_tolerance.y_upper),
00290    std::make_tuple(t(2),wobj_pt_.position_tolerance.z_lower,wobj_pt_.position_tolerance.z_upper),
00291    std::make_tuple(rpy(0),wobj_pt_.orientation_tolerance.x_lower,wobj_pt_.orientation_tolerance.x_upper),
00292    std::make_tuple(rpy(1),wobj_pt_.orientation_tolerance.y_lower,wobj_pt_.orientation_tolerance.y_upper),
00293    std::make_tuple(rpy(2),wobj_pt_.orientation_tolerance.z_lower,wobj_pt_.orientation_tolerance.z_upper)
00294   };
00295 
00296   std::vector<double> closest_pose_vals = {t(0),t(1),t(2),rpy(0),rpy(1),rpy(2)};
00297   bool solve_ik = false;
00298   for(int i = 0; i < vals.size();i++)
00299   {
00300     auto &lower = std::get<1>(vals[i]);
00301     auto &upper = std::get<2>(vals[i]);
00302     auto &v = std::get<0>(vals[i]);
00303 
00304     if( std::abs(upper -lower) > EQUALITY_TOLERANCE)
00305     {
00306       auto bounds = std::make_pair(lower,upper);
00307       if(std::minmax({lower,v,upper}) != bounds)
00308       {
00309         solve_ik =  true;
00310         closest_pose_vals[i] = v < lower ? lower : upper;
00311         ROS_DEBUG("Cartesian nominal [%i] exceeded bounds: [val: %f, lower: %f, upper: %f]",i,v,lower,upper);
00312       }
00313     }
00314     else
00315     {
00316       if(std::abs(v-lower) > EQUALITY_TOLERANCE)
00317       {
00318         solve_ik =  true;
00319         ROS_DEBUG("Cartesian nominals [%i] differ: [val: %f, lower: %f, upper: %f]",i,v,lower,upper);
00320         closest_pose_vals[i] = lower;
00321       }
00322     }
00323 
00324   }
00325 
00326   if(solve_ik)
00327   {
00328 
00329     Eigen::Affine3d closest_pose = descartes_core::utils::toFrame(closest_pose_vals[0],
00330                                                                  closest_pose_vals[1],
00331                                                                  closest_pose_vals[2],
00332                                                                  closest_pose_vals[3],
00333                                                                  closest_pose_vals[4],
00334                                                                  closest_pose_vals[5],
00335                                                                  descartes_core::utils::EulerConventions::XYZ);
00336     if(!model.getIK(closest_pose,seed_state,joint_pose))
00337     {
00338       ROS_WARN_STREAM("Ik failed on closest pose");
00339 
00340       std::vector<std::vector<double> > joint_poses;
00341       getJointPoses(model,joint_poses);
00342       if(joint_poses.size() > 0)
00343       {
00344 
00345         ROS_WARN_STREAM("Closest cartesian pose not found, returning closest to seed joint pose");
00346 
00347         double sd = std::numeric_limits<double>::max();
00348         double d;
00349         for(auto j: joint_poses)
00350         {
00351           d = distance(seed_state,j);
00352           if(sd > d)
00353           {
00354             sd = d;
00355             joint_pose = j;
00356           }
00357         }
00358 
00359       }
00360       else
00361       {
00362         ROS_ERROR_STREAM("getClosestJointPose failed, no valid joint poses for this point");
00363         return false;
00364       }
00365 
00366       return true;
00367     }
00368   }
00369   else
00370   {
00371 
00372     joint_pose.assign(seed_state.begin(),seed_state.end());
00373   }
00374 
00375   return true;
00376 }
00377 
00378 bool CartTrajectoryPt::getNominalJointPose(const std::vector<double> &seed_state,
00379                                            const RobotModel &model,
00380                                            std::vector<double> &joint_pose) const
00381 {
00382   Eigen::Affine3d robot_pose = wobj_base_.frame * wobj_pt_.frame *
00383       tool_pt_.frame_inv * tool_base_.frame_inv;
00384   return model.getIK(robot_pose, seed_state, joint_pose);
00385 }
00386 
00387 void CartTrajectoryPt::getJointPoses(const RobotModel &model,
00388                                      std::vector<std::vector<double> > &joint_poses) const
00389 {
00390   joint_poses.clear();
00391 
00392   EigenSTL::vector_Affine3d poses;
00393   if(computeCartesianPoses(poses))
00394   {
00395     poses.reserve(poses.size());
00396     for(const auto& pose: poses)
00397     {
00398       std::vector<std::vector<double> > local_joint_poses;
00399       if(model.getAllIK(pose, local_joint_poses))
00400       {
00401         joint_poses.insert(joint_poses.end(), local_joint_poses.begin(), local_joint_poses.end());
00402       }
00403     }
00404   }
00405   else
00406   {
00407     ROS_ERROR("Failed for find ANY cartesian poses");
00408   }
00409 
00410   if( joint_poses.empty())
00411   {
00412     ROS_WARN("Failed for find ANY joint poses, returning");
00413   }
00414   else
00415   {
00416     ROS_DEBUG_STREAM("Get joint poses, sampled: " << poses.size()
00417                      << ", with " << joint_poses.size() << " valid(returned) poses");
00418   }
00419 }
00420 
00421 bool CartTrajectoryPt::isValid(const RobotModel &model) const
00422 {
00423   Eigen::Affine3d robot_pose = wobj_base_.frame * wobj_pt_.frame *
00424       tool_pt_.frame_inv * tool_base_.frame_inv;
00425   return model.isValid(robot_pose);
00426 }
00427 
00428 
00429 bool CartTrajectoryPt::setDiscretization(const std::vector<double> &discretization)
00430 {
00431   NOT_IMPLEMENTED_ERR(false);
00432 }
00433 
00434 } /* namespace descartes_trajectory */


descartes_trajectory
Author(s): Jorge Nicho
autogenerated on Wed Aug 26 2015 11:21:27