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) \
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
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 =
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
00211 pose = wobj_base_.frame * wobj_pt_.frame;
00212 return true;
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
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 }