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)                                                                                       \
00035   logError("%s not implemented", __PRETTY_FUNCTION__);                                                                 \
00036   return ret;
00037 
00038 const double EQUALITY_TOLERANCE = 0.0001f;
00039 
00040 using namespace descartes_core;
00041 
00042 namespace descartes_trajectory
00043 {
00044 EigenSTL::vector_Affine3d uniform(const TolerancedFrame &frame, const double orient_increment,
00045                                   const double pos_increment)
00046 {
00047   EigenSTL::vector_Affine3d rtn;
00048 
00049   if (pos_increment < 0.0 || orient_increment < 0.0)
00050   {
00051     ROS_WARN_STREAM("Negative position/orientation intcrement: " << pos_increment << "/" << 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 =
00119                   descartes_core::utils::toFrame(tx, ty, tz, 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: "
00128                    << orient_increment << ", and position increment: " << pos_increment << " resulted in " << rtn.size()
00129                    << " samples");
00130   return rtn;
00131 }
00132 
00133 double distance(const std::vector<double> &j1, const std::vector<double> &j2)
00134 {
00135   double rt = 0;
00136   double d;
00137   if (j1.size() == j2.size())
00138   {
00139     for (int i = 0; i < j1.size(); i++)
00140     {
00141       d = j1[i] - j2[i];
00142       rt += d * d;
00143     }
00144   }
00145   else
00146   {
00147     ROS_WARN_STREAM("Unequal size vectors, returning negative distance");
00148     return -1;
00149   }
00150 
00151   return std::sqrt(rt);
00152 }
00153 
00154 CartTrajectoryPt::CartTrajectoryPt(const descartes_core::TimingConstraint &timing)
00155   : descartes_core::TrajectoryPt(timing)
00156   , tool_base_(Eigen::Affine3d::Identity())
00157   , tool_pt_(Eigen::Affine3d::Identity())
00158   , wobj_base_(Eigen::Affine3d::Identity())
00159   , wobj_pt_(Eigen::Affine3d::Identity())
00160   , pos_increment_(0.0)
00161   , orient_increment_(0.0)
00162 {
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, double orient_increment,
00179                                    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 
00201 bool CartTrajectoryPt::getClosestCartPose(const std::vector<double> &seed_state, const RobotModel &model,
00202                                           Eigen::Affine3d &pose) const
00203 {
00204   NOT_IMPLEMENTED_ERR(false);
00205 }
00206 
00207 bool CartTrajectoryPt::getNominalCartPose(const std::vector<double> &seed_state, const RobotModel &model,
00208                                           Eigen::Affine3d &pose) const
00209 {
00210   /* Simply return wobj_pt expressed in world */
00211   pose = wobj_base_.frame * wobj_pt_.frame;
00212   return true;  // TODO can this ever return false?
00213 }
00214 
00215 bool CartTrajectoryPt::computeCartesianPoses(EigenSTL::vector_Affine3d &poses) const
00216 {
00217   EigenSTL::vector_Affine3d sampled_wobj_pts = uniform(wobj_pt_, orient_increment_, pos_increment_);
00218   EigenSTL::vector_Affine3d sampled_tool_pts = uniform(tool_pt_, orient_increment_, pos_increment_);
00219 
00220   poses.clear();
00221   poses.reserve(sampled_wobj_pts.size() * sampled_tool_pts.size());
00222   for (size_t wobj_pt = 0; wobj_pt < sampled_wobj_pts.size(); ++wobj_pt)
00223   {
00224     for (size_t tool_pt = 0; tool_pt < sampled_tool_pts.size(); ++tool_pt)
00225     {
00226       Eigen::Affine3d pose =
00227           wobj_base_.frame * sampled_wobj_pts[wobj_pt] * sampled_tool_pts[tool_pt].inverse() * tool_base_.frame_inv;
00228 
00229       poses.push_back(pose);
00230     }
00231   }
00232 
00233   return !poses.empty();
00234 }
00235 
00236 void CartTrajectoryPt::getCartesianPoses(const RobotModel &model, EigenSTL::vector_Affine3d &poses) const
00237 {
00238   EigenSTL::vector_Affine3d all_poses;
00239   poses.clear();
00240 
00241   if (computeCartesianPoses(all_poses))
00242   {
00243     poses.reserve(all_poses.size());
00244     for (const auto &pose : all_poses)
00245     {
00246       if (model.isValid(pose))
00247       {
00248         poses.push_back(pose);
00249       }
00250     }
00251   }
00252   else
00253   {
00254     ROS_ERROR("Failed for find ANY cartesian poses");
00255   }
00256 
00257   if (poses.empty())
00258   {
00259     ROS_WARN("Failed for find VALID cartesian poses, returning");
00260   }
00261   else
00262   {
00263     ROS_DEBUG_STREAM("Get cartesian poses, sampled: " << all_poses.size() << ", with " << poses.size()
00264                                                       << " valid(returned) poses");
00265   }
00266 }
00267 
00268 bool CartTrajectoryPt::getClosestJointPose(const std::vector<double> &seed_state, const RobotModel &model,
00269                                            std::vector<double> &joint_pose) const
00270 {
00271   Eigen::Affine3d nominal_pose, candidate_pose;
00272 
00273   if (!model.getFK(seed_state, candidate_pose))
00274   {
00275     ROS_ERROR_STREAM("FK failed for seed pose for closest joint pose");
00276     return false;
00277   }
00278 
00279   // getting pose values
00280   Eigen::Vector3d t = candidate_pose.translation();
00281   Eigen::Vector3d rpy = candidate_pose.rotation().eulerAngles(0, 1, 2);
00282 
00283   std::vector<std::tuple<double, double, double> > vals = {
00284     std::make_tuple(t(0), wobj_pt_.position_tolerance.x_lower, wobj_pt_.position_tolerance.x_upper),
00285     std::make_tuple(t(1), wobj_pt_.position_tolerance.y_lower, wobj_pt_.position_tolerance.y_upper),
00286     std::make_tuple(t(2), wobj_pt_.position_tolerance.z_lower, wobj_pt_.position_tolerance.z_upper),
00287     std::make_tuple(rpy(0), wobj_pt_.orientation_tolerance.x_lower, wobj_pt_.orientation_tolerance.x_upper),
00288     std::make_tuple(rpy(1), wobj_pt_.orientation_tolerance.y_lower, wobj_pt_.orientation_tolerance.y_upper),
00289     std::make_tuple(rpy(2), wobj_pt_.orientation_tolerance.z_lower, wobj_pt_.orientation_tolerance.z_upper)
00290   };
00291 
00292   std::vector<double> closest_pose_vals = { t(0), t(1), t(2), rpy(0), rpy(1), rpy(2) };
00293   bool solve_ik = false;
00294   for (int i = 0; i < vals.size(); i++)
00295   {
00296     auto &lower = std::get<1>(vals[i]);
00297     auto &upper = std::get<2>(vals[i]);
00298     auto &v = std::get<0>(vals[i]);
00299 
00300     if (std::abs(upper - lower) > EQUALITY_TOLERANCE)
00301     {
00302       auto bounds = std::make_pair(lower, upper);
00303       if (std::minmax({ lower, v, upper }) != bounds)
00304       {
00305         solve_ik = true;
00306         closest_pose_vals[i] = v < lower ? lower : upper;
00307         ROS_DEBUG("Cartesian nominal [%i] exceeded bounds: [val: %f, lower: %f, upper: %f]", i, v, lower, upper);
00308       }
00309     }
00310     else
00311     {
00312       if (std::abs(v - lower) > EQUALITY_TOLERANCE)
00313       {
00314         solve_ik = true;
00315         ROS_DEBUG("Cartesian nominals [%i] differ: [val: %f, lower: %f, upper: %f]", i, v, lower, upper);
00316         closest_pose_vals[i] = lower;
00317       }
00318     }
00319   }
00320 
00321   if (solve_ik)
00322   {
00323     Eigen::Affine3d closest_pose = descartes_core::utils::toFrame(
00324         closest_pose_vals[0], closest_pose_vals[1], closest_pose_vals[2], closest_pose_vals[3], closest_pose_vals[4],
00325         closest_pose_vals[5], descartes_core::utils::EulerConventions::XYZ);
00326     if (!model.getIK(closest_pose, seed_state, joint_pose))
00327     {
00328       ROS_WARN_STREAM("Ik failed on closest pose");
00329 
00330       std::vector<std::vector<double> > joint_poses;
00331       getJointPoses(model, joint_poses);
00332       if (joint_poses.size() > 0)
00333       {
00334         ROS_WARN_STREAM("Closest cartesian pose not found, returning closest to seed joint pose");
00335 
00336         double sd = std::numeric_limits<double>::max();
00337         double d;
00338         for (auto j : joint_poses)
00339         {
00340           d = distance(seed_state, j);
00341           if (sd > d)
00342           {
00343             sd = d;
00344             joint_pose = j;
00345           }
00346         }
00347       }
00348       else
00349       {
00350         ROS_ERROR_STREAM("getClosestJointPose failed, no valid joint poses for this point");
00351         return false;
00352       }
00353 
00354       return true;
00355     }
00356   }
00357   else
00358   {
00359     joint_pose.assign(seed_state.begin(), seed_state.end());
00360   }
00361 
00362   return true;
00363 }
00364 
00365 bool CartTrajectoryPt::getNominalJointPose(const std::vector<double> &seed_state, const RobotModel &model,
00366                                            std::vector<double> &joint_pose) const
00367 {
00368   Eigen::Affine3d robot_pose = wobj_base_.frame * wobj_pt_.frame * tool_pt_.frame_inv * tool_base_.frame_inv;
00369   return model.getIK(robot_pose, seed_state, joint_pose);
00370 }
00371 
00372 void CartTrajectoryPt::getJointPoses(const RobotModel &model, std::vector<std::vector<double> > &joint_poses) const
00373 {
00374   joint_poses.clear();
00375 
00376   EigenSTL::vector_Affine3d poses;
00377   if (computeCartesianPoses(poses))
00378   {
00379     poses.reserve(poses.size());
00380     for (const auto &pose : poses)
00381     {
00382       std::vector<std::vector<double> > local_joint_poses;
00383       if (model.getAllIK(pose, local_joint_poses))
00384       {
00385         joint_poses.insert(joint_poses.end(), local_joint_poses.begin(), local_joint_poses.end());
00386       }
00387     }
00388   }
00389   else
00390   {
00391     ROS_ERROR("Failed for find ANY cartesian poses");
00392   }
00393 
00394   if (joint_poses.empty())
00395   {
00396     ROS_WARN("Failed for find ANY joint poses, returning");
00397   }
00398   else
00399   {
00400     ROS_DEBUG_STREAM("Get joint poses, sampled: " << poses.size() << ", with " << joint_poses.size()
00401                                                   << " valid(returned) poses");
00402   }
00403 }
00404 
00405 bool CartTrajectoryPt::isValid(const RobotModel &model) const
00406 {
00407   Eigen::Affine3d robot_pose = wobj_base_.frame * wobj_pt_.frame * tool_pt_.frame_inv * tool_base_.frame_inv;
00408   return model.isValid(robot_pose);
00409 }
00410 
00411 bool CartTrajectoryPt::setDiscretization(const std::vector<double> &discretization)
00412 {
00413   NOT_IMPLEMENTED_ERR(false);
00414 }
00415 
00416 } /* namespace descartes_trajectory */


descartes_trajectory
Author(s): Jorge Nicho
autogenerated on Thu Jun 6 2019 21:36:04