12 #include <Eigen/Geometry> 33 const std::string& base_frame,
const std::vector<std::string>& tip_frames,
34 double search_discretization)
40 storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
48 std::cout << std::endl
49 <<
"Joint Model Variable Names: " 50 "------------------------------------------- " 53 std::copy(jm_names.begin(), jm_names.end(), std::ostream_iterator<std::string>(std::cout,
"\n"));
54 std::cout << std::endl;
77 for (std::size_t i = 0; i <
tip_frames_.size(); ++i)
96 "sure they are loaded on the parameter server and are of the correct type(s).");
101 if (!
selfTest({ 0, 0, 0, 0, 0, 0 }))
104 "server appear to be incorrect (self-test failed for '0 0 0 0 0 0').");
107 const std::vector<double> joint_angles = { 0.1, -0.1, 0.2, -0.3, 0.5, -0.8 };
111 "server appear to be incorrect (self-test failed for odd posture: '0.1, -0.1, 0.2, " 112 "-0.3, 0.5, -0.8').");
149 for (
unsigned int i = 0; i <
ik_group_info_.joint_names.size(); i++)
169 fk_pose_moveit = base.inverse() * fk_pose_moveit;
185 auto Ra = Ta.rotation();
186 auto Rb = Tb.rotation();
188 for (
int i = 0; i < Ra.rows(); ++i)
190 for (
int j = 0; j < Ra.cols(); ++j)
192 if (std::abs(Ra(i, j) - Rb(i, j)) >
TOLERANCE)
194 ROS_ERROR_NAMED(LOGNAME,
"Pose orientation error on element (%d, %d).", i, j);
201 auto pa = Ta.translation();
202 auto pb = Tb.translation();
203 for (
int i = 0; i < 3; ++i)
205 if (std::abs(pa(i) - pb(i)) > TOLERANCE)
216 const std::vector<double>& ik_seed_state, std::vector<double>& solution,
217 moveit_msgs::MoveItErrorCodes& error_code,
221 std::vector<double> consistency_limits;
224 consistency_limits, options);
228 const std::vector<double>& ik_seed_state,
double timeout,
229 std::vector<double>& solution,
230 moveit_msgs::MoveItErrorCodes& error_code,
234 std::vector<double> consistency_limits;
236 return searchPositionIK(ik_pose, ik_seed_state, timeout, solution, solution_callback, error_code, consistency_limits,
241 const std::vector<double>& ik_seed_state,
double timeout,
242 const std::vector<double>& consistency_limits,
243 std::vector<double>& solution,
244 moveit_msgs::MoveItErrorCodes& error_code,
248 return searchPositionIK(ik_pose, ik_seed_state, timeout, solution, solution_callback, error_code, consistency_limits,
253 const std::vector<double>& ik_seed_state,
double timeout,
254 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
255 moveit_msgs::MoveItErrorCodes& error_code,
258 std::vector<double> consistency_limits;
259 return searchPositionIK(ik_pose, ik_seed_state, timeout, solution, solution_callback, error_code, consistency_limits,
264 const std::vector<double>& ik_seed_state,
double timeout,
265 const std::vector<double>& consistency_limits,
266 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
267 moveit_msgs::MoveItErrorCodes& error_code,
270 return searchPositionIK(ik_pose, ik_seed_state, timeout, solution, solution_callback, error_code, consistency_limits,
275 const std::vector<double>& ik_seed_state,
double timeout,
276 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
277 moveit_msgs::MoveItErrorCodes& error_code,
278 const std::vector<double>& consistency_limits,
282 std::vector<geometry_msgs::Pose> ik_poses;
283 ik_poses.push_back(ik_pose);
285 return searchPositionIK(ik_poses, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
291 const std::vector<const robot_model::JointModel*>& ajms =
joint_model_group_->getActiveJointModels();
292 for (
size_t i = 0; i < ajms.size(); ++i)
294 const robot_model::JointModel* jm = ajms[i];
295 if (jm->getVariableBounds().size() > 0)
297 for (
auto& bounds : jm->getVariableBounds())
300 if (!bounds.position_bounded_)
303 std::vector<std::vector<double>> additional_solutions;
304 for (
auto& sol : solutions)
306 std::vector<double> down_sol(sol);
307 while (down_sol[i] - 2.0 *
M_PI > bounds.min_position_)
309 down_sol[i] -= 2.0 *
M_PI;
310 additional_solutions.push_back(down_sol);
312 std::vector<double> up_sol(sol);
313 while (up_sol[i] + 2.0 *
M_PI < bounds.max_position_)
315 up_sol[i] += 2.0 *
M_PI;
316 additional_solutions.push_back(up_sol);
320 "Found " << additional_solutions.size() <<
" additional solutions for j=" << i + 1);
321 solutions.insert(solutions.end(), additional_solutions.begin(), additional_solutions.end());
328 const std::vector<double>& ik_seed_state,
double ,
329 const std::vector<double>& ,
330 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
331 moveit_msgs::MoveItErrorCodes& error_code,
338 error_code.val = error_code.NO_IK_SOLUTION;
346 "Seed state must have size " <<
dimension_ <<
" instead of size " << ik_seed_state.size());
347 error_code.val = error_code.NO_IK_SOLUTION;
354 ROS_ERROR_STREAM_NAMED(LOGNAME,
"Mismatched number of pose requests (" << ik_poses.size() <<
") to tip frames (" 356 <<
") in searchPositionIK");
357 error_code.val = error_code.NO_IK_SOLUTION;
361 Eigen::Isometry3d pose;
363 std::vector<std::vector<double>> solutions;
367 error_code.val = error_code.NO_IK_SOLUTION;
378 std::vector<LimitObeyingSol> limit_obeying_solutions;
380 for (
auto& sol : solutions)
389 limit_obeying_solutions.push_back({ sol,
distance(sol, ik_seed_state) });
392 if (limit_obeying_solutions.empty())
394 ROS_DEBUG_NAMED(LOGNAME,
"None of the solutions is within joint limits");
401 std::sort(limit_obeying_solutions.begin(), limit_obeying_solutions.end());
403 if (!solution_callback)
405 solution = limit_obeying_solutions.front().value;
409 for (
auto& sol : limit_obeying_solutions)
411 solution_callback(ik_poses[0], sol.value, error_code);
412 if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS)
414 solution = sol.value;
425 const std::vector<double>& ,
429 if (ik_poses.size() > 1 || ik_poses.size() == 0)
434 Eigen::Isometry3d pose;
440 const std::vector<double>& joint_angles,
441 std::vector<geometry_msgs::Pose>& poses)
const 448 poses.resize(link_names.size());
458 ROS_ERROR_STREAM_NAMED(LOGNAME,
"Mismatched number of pose requests (" << poses.size() <<
") to tip frames (" 460 <<
") in searchPositionFK");
488 ROS_INFO_STREAM(
"Getting kinematic parameters from parameter server.");
492 std::map<std::string, double> geometric_parameters;
493 if (!
lookupParam(
"opw_kinematics_geometric_parameters", geometric_parameters, {}))
499 std::vector<double> joint_offsets;
500 if (!
lookupParam(
"opw_kinematics_joint_offsets", joint_offsets, {}))
506 std::vector<int> joint_sign_corrections;
507 if (!
lookupParam(
"opw_kinematics_joint_sign_corrections", joint_sign_corrections, {}))
521 if (joint_offsets.size() != 6)
523 ROS_ERROR_STREAM(
"Expected joint_offsets to contain 6 elements, but it has " << joint_offsets.size() <<
".");
527 if (joint_sign_corrections.size() != 6)
529 ROS_ERROR_STREAM(
"Expected joint_sign_corrections to contain 6 elements, but it has " 530 << joint_sign_corrections.size() <<
".");
534 for (std::size_t i = 0; i < joint_offsets.size(); ++i)
548 for (
size_t i = 0; i < a.size(); ++i)
549 cost += std::abs(b[i] - a[i]);
555 const std::vector<std::vector<double>>& candidates)
558 double lowest_cost = std::numeric_limits<double>::max();
559 for (
size_t i = 0; i < candidates.size(); ++i)
561 assert(target.size() == candidates[i].size());
562 double c =
distance(target, candidates[i]);
573 std::vector<std::vector<double>>& joint_poses)
const 583 std::array<double, 6 * 8> sols;
587 std::vector<double> tmp(6);
588 for (
int i = 0; i < 8; i++)
590 double* sol = sols.data() + 6 * i;
596 std::copy(sol, sol + 6, tmp.data());
599 joint_poses.push_back(tmp);
604 return joint_poses.size() > 0;
608 std::vector<double>& joint_pose)
const 611 std::vector<std::vector<double>> joint_poses;
std::vector< unsigned int > redundant_joint_indices_
static std::size_t closestJointPose(const std::vector< double > &target, const std::vector< std::vector< double >> &candidates)
const std::vector< std::string > & getJointNames() const override
Return all the joint names in the order they are used internally.
const std::vector< std::string > & getVariableNames() const
Return all the variable names in the order they are represented internally.
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
virtual bool getPositionFK(const std::vector< std::string > &link_names, const std::vector< double > &joint_angles, std::vector< geometry_msgs::Pose > &poses) const override
const std::vector< std::string > & getLinkNames() const override
Return all the link names in the order they are represented internally.
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
bool getIK(const Eigen::Isometry3d &pose, const std::vector< double > &seed_state, std::vector< double > &joint_pose) const
std::vector< std::string > tip_frames_
moveit::core::RobotModelConstPtr robot_model_
int num_possible_redundant_joints_
#define ROS_INFO_STREAM_NAMED(name, args)
bool comparePoses(Eigen::Isometry3d &Ta, Eigen::Isometry3d &Tb)
check if two poses are the same within an absolute tolerance of 1e-6
robot_state::RobotStatePtr robot_state_
moveit_msgs::KinematicSolverInfo ik_group_info_
virtual bool searchPositionIK(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_seed_state, double timeout, std::vector< double > &solution, moveit_msgs::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const override
bool isValid(const T *qs)
void harmonizeTowardZero(T *qs)
virtual bool getPositionIK(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_seed_state, std::vector< double > &solution, moveit_msgs::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const override
#define ROS_DEBUG_NAMED(name,...)
Specific implementation of kinematics using ROS service calls to communicate with external IK solvers...
void storeValues(const moveit::core::RobotModel &robot_model, const std::string &group_name, const std::string &base_frame, const std::vector< std::string > &tip_frames, double search_discretization)
bool isRedundantJoint(unsigned int index) const
const robot_model::JointModelGroup * joint_model_group_
bool lookupParam(const std::string ¶m, T &val, const T &default_val) const
signed char sign_corrections[6]
static double distance(const std::vector< double > &a, const std::vector< double > &b)
bool timedOut(const ros::WallTime &start_time, double duration) const
boost::function< void(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_solution, moveit_msgs::MoveItErrorCodes &error_code)> IKCallbackFn
bool getAllIK(const Eigen::Isometry3d &pose, std::vector< std::vector< double >> &joint_poses) const
int getJointIndex(const std::string &name) const
#define ROS_INFO_STREAM(args)
#define CLASS_LOADER_REGISTER_CLASS(Derived, Base)
bool selfTest(const std::vector< double > &joint_angles)
check forward and inverse kinematics consistency
void expandIKSolutions(std::vector< std::vector< double >> &solutions) const
append IK solutions by adding +-2pi
virtual bool setRedundantJoints(const std::vector< unsigned int > &redundant_joint_indices) override
#define ROS_ERROR_NAMED(name,...)
virtual bool initialize(const moveit::core::RobotModel &robot_model, const std::string &group_name, const std::string &base_frame, const std::vector< std::string > &tip_frames, double search_discretization) override
#define ROS_ERROR_STREAM(args)
opw_kinematics::Parameters< double > opw_parameters_
void inverse(const Parameters< T > ¶ms, const Transform< T > &pose, T *out) noexcept
Computes up to 8 kinematically unique joint solutions that put the tool flange of the robot described...
MoveItOPWKinematicsPlugin()
Default constructor.
Transform< T > forward(const Parameters< T > &p, const T *qs) noexcept
Computes the tool pose of the robot described by when said robot has the joint positions given by qs...