00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
00090
00091
00092
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
00115
00116
00117
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
00210 pose = wobj_base_.frame * wobj_pt_.frame;
00211 return true;
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
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 }