35 #include <bio_ik/goal.h> 37 #include "forward_kinematics.h" 39 #include "ik_parallel.h" 44 #include <Eigen/Dense> 45 #include <Eigen/Geometry> 46 #include <kdl_parser/kdl_parser.hpp> 47 #include <moveit/kinematics_base/kinematics_base.h> 48 #include <moveit/rdf_loader/rdf_loader.h> 49 #include <pluginlib/class_list_macros.h> 50 #include <srdfdom/model.h> 51 #include <urdf/model.h> 52 #include <urdf_model/model.h> 54 #include <eigen_conversions/eigen_msg.h> 55 #include <tf2_eigen/tf2_eigen.h> 57 #include <moveit/kinematics_base/kinematics_base.h> 58 #include <moveit/robot_model/robot_model.h> 59 #include <moveit/robot_state/robot_state.h> 65 #include <type_traits> 67 #include <bio_ik/goal_types.h> 75 std::mutex bioIKKinematicsQueryOptionsMutex;
76 std::unordered_set<const void *> bioIKKinematicsQueryOptionsList;
78 BioIKKinematicsQueryOptions::BioIKKinematicsQueryOptions()
79 : replace(false), solution_fitness(0) {
80 std::lock_guard<std::mutex> lock(bioIKKinematicsQueryOptionsMutex);
81 bioIKKinematicsQueryOptionsList.insert(
this);
84 BioIKKinematicsQueryOptions::~BioIKKinematicsQueryOptions() {
85 std::lock_guard<std::mutex> lock(bioIKKinematicsQueryOptionsMutex);
86 bioIKKinematicsQueryOptionsList.erase(
this);
89 bool isBioIKKinematicsQueryOptions(
const void *ptr) {
90 std::lock_guard<std::mutex> lock(bioIKKinematicsQueryOptionsMutex);
91 return bioIKKinematicsQueryOptionsList.find(ptr) !=
92 bioIKKinematicsQueryOptionsList.end();
95 const BioIKKinematicsQueryOptions *
96 toBioIKKinematicsQueryOptions(
const void *ptr) {
97 if (isBioIKKinematicsQueryOptions(ptr))
98 return (
const BioIKKinematicsQueryOptions *)ptr;
111 static void lookupParam(
const std::string ¶m, T &val,
112 const T &default_val) {
113 ros::NodeHandle nodeHandle(
"~");
114 val = nodeHandle.param(param, default_val);
118 std::vector<std::string> joint_names, link_names;
119 moveit::core::RobotModelConstPtr robot_model;
120 const moveit::core::JointModelGroup *joint_model_group;
121 mutable std::unique_ptr<IKParallel> ik;
122 mutable std::vector<double> state, temp;
123 mutable std::unique_ptr<moveit::core::RobotState> temp_state;
124 mutable std::vector<Frame> tipFrames;
125 RobotInfo robot_info;
126 bool enable_profiler;
130 virtual const std::vector<std::string> &getJointNames()
const {
135 virtual const std::vector<std::string> &getLinkNames()
const {
140 virtual bool getPositionFK(
const std::vector<std::string> &link_names,
141 const std::vector<double> &joint_angles,
142 std::vector<geometry_msgs::Pose> &poses)
const {
147 virtual bool getPositionIK(
const geometry_msgs::Pose &ik_pose,
148 const std::vector<double> &ik_seed_state,
149 std::vector<double> &solution,
150 moveit_msgs::MoveItErrorCodes &error_code,
151 const kinematics::KinematicsQueryOptions &options =
152 kinematics::KinematicsQueryOptions())
const {
157 EigenSTL::vector_Isometry3d tip_reference_frames;
159 mutable std::vector<std::unique_ptr<Goal>> default_goals;
161 mutable std::vector<const bio_ik::Goal *> all_goals;
167 static moveit::core::RobotModelConstPtr
168 loadRobotModel(
const std::string &robot_description) {
169 static std::map<std::string, moveit::core::RobotModelConstPtr>
171 static std::mutex cache_mutex;
172 std::lock_guard<std::mutex> lock(cache_mutex);
173 if (robot_model_cache.find(robot_description) == robot_model_cache.end()) {
174 rdf_loader::RDFLoader rdf_loader(robot_description);
175 auto srdf = rdf_loader.getSRDF();
176 auto urdf_model = rdf_loader.getURDF();
178 if (!urdf_model || !srdf) {
179 LOG(
"URDF and SRDF must be loaded for kinematics solver to work.");
182 robot_model_cache[robot_description] = moveit::core::RobotModelConstPtr(
183 new robot_model::RobotModel(urdf_model, srdf));
185 return robot_model_cache[robot_description];
191 bool load(
const moveit::core::RobotModelConstPtr &model,
192 std::string robot_description, std::string group_name) {
198 LOG(
"bio ik init", ros::this_node::getName());
213 this->robot_model = model;
215 this->robot_model = loadRobotModel(robot_description);
218 joint_model_group = robot_model->getJointModelGroup(group_name);
219 if (!joint_model_group) {
220 LOG(
"failed to get joint model group");
226 for (
auto *joint_model : joint_model_group->getJointModels())
227 if (joint_model->getName() != base_frame_ &&
228 joint_model->getType() != moveit::core::JointModel::UNKNOWN &&
229 joint_model->getType() != moveit::core::JointModel::FIXED)
230 joint_names.push_back(joint_model->getName());
232 auto tips2 = tip_frames_;
233 joint_model_group->getEndEffectorTips(tips2);
237 link_names = tip_frames_;
243 lookupParam(
"profiler", enable_profiler,
false);
246 robot_info = RobotInfo(robot_model);
248 ikparams.robot_model = robot_model;
249 ikparams.joint_model_group = joint_model_group;
252 lookupParam(
"mode", ikparams.solver_class_name,
253 std::string(
"bio2_memetic"));
254 lookupParam(
"counter", ikparams.enable_counter,
false);
255 lookupParam(
"threads", ikparams.thread_count, 0);
258 lookupParam(
"dpos", ikparams.dpos, DBL_MAX);
259 lookupParam(
"drot", ikparams.drot, DBL_MAX);
260 lookupParam(
"dtwist", ikparams.dtwist, 1e-5);
263 lookupParam(
"no_wipeout", ikparams.opt_no_wipeout,
false);
264 lookupParam(
"population_size", ikparams.population_size, 8);
265 lookupParam(
"elite_count", ikparams.elite_count, 4);
266 lookupParam(
"linear_fitness", ikparams.linear_fitness,
false);
268 temp_state.reset(
new moveit::core::RobotState(robot_model));
274 BLOCKPROFILER(
"default ik goals");
276 default_goals.clear();
278 for (
size_t i = 0; i < tip_frames_.size(); i++) {
279 PoseGoal *goal =
new PoseGoal();
281 goal->setLinkName(tip_frames_[i]);
285 double rotation_scale = 0.5;
287 lookupParam(
"rotation_scale", rotation_scale, rotation_scale);
289 bool position_only_ik =
false;
290 lookupParam(
"position_only_ik", position_only_ik, position_only_ik);
291 if (position_only_ik)
294 goal->setRotationScale(rotation_scale);
296 default_goals.emplace_back(goal);
301 lookupParam(
"center_joints_weight", weight, weight);
303 auto *avoid_joint_limits_goal =
new bio_ik::CenterJointsGoal();
304 avoid_joint_limits_goal->setWeight(weight);
305 default_goals.emplace_back(avoid_joint_limits_goal);
311 lookupParam(
"avoid_joint_limits_weight", weight, weight);
313 auto *avoid_joint_limits_goal =
new bio_ik::AvoidJointLimitsGoal();
314 avoid_joint_limits_goal->setWeight(weight);
315 default_goals.emplace_back(avoid_joint_limits_goal);
321 lookupParam(
"minimal_displacement_weight", weight, weight);
323 auto *minimal_displacement_goal =
324 new bio_ik::MinimalDisplacementGoal();
325 minimal_displacement_goal->setWeight(weight);
326 default_goals.emplace_back(minimal_displacement_goal);
336 virtual bool initialize(
const std::string &robot_description,
337 const std::string &group_name,
338 const std::string &base_frame,
339 const std::string &tip_frame,
340 double search_discretization) {
342 std::vector<std::string> tip_frames;
343 tip_frames.push_back(tip_frame);
344 initialize(robot_description, group_name, base_frame, tip_frames,
345 search_discretization);
349 virtual bool initialize(
const std::string &robot_description,
350 const std::string &group_name,
351 const std::string &base_frame,
352 const std::vector<std::string> &tip_frames,
353 double search_discretization) {
355 setValues(robot_description, group_name, base_frame, tip_frames,
356 search_discretization);
357 load(moveit::core::RobotModelConstPtr(), robot_description, group_name);
361 virtual bool initialize(
const moveit::core::RobotModel &robot_model,
362 const std::string &group_name,
363 const std::string &base_frame,
364 const std::vector<std::string> &tip_frames,
365 double search_discretization) {
367 setValues(
"", group_name, base_frame, tip_frames, search_discretization);
368 load(moveit::core::RobotModelConstPtr(
369 (moveit::core::RobotModel *)&robot_model,
370 [](
const moveit::core::RobotModel *robot_model) {}),
376 searchPositionIK(
const geometry_msgs::Pose &ik_pose,
377 const std::vector<double> &ik_seed_state,
double timeout,
378 std::vector<double> &solution,
379 moveit_msgs::MoveItErrorCodes &error_code,
380 const kinematics::KinematicsQueryOptions &options =
381 kinematics::KinematicsQueryOptions())
const {
383 return searchPositionIK(std::vector<geometry_msgs::Pose>{ik_pose},
384 ik_seed_state, timeout, std::vector<double>(),
385 solution, IKCallbackFn(), error_code, options);
389 searchPositionIK(
const geometry_msgs::Pose &ik_pose,
390 const std::vector<double> &ik_seed_state,
double timeout,
391 const std::vector<double> &consistency_limits,
392 std::vector<double> &solution,
393 moveit_msgs::MoveItErrorCodes &error_code,
394 const kinematics::KinematicsQueryOptions &options =
395 kinematics::KinematicsQueryOptions())
const {
397 return searchPositionIK(std::vector<geometry_msgs::Pose>{ik_pose},
398 ik_seed_state, timeout, consistency_limits,
399 solution, IKCallbackFn(), error_code, options);
403 searchPositionIK(
const geometry_msgs::Pose &ik_pose,
404 const std::vector<double> &ik_seed_state,
double timeout,
405 std::vector<double> &solution,
406 const IKCallbackFn &solution_callback,
407 moveit_msgs::MoveItErrorCodes &error_code,
408 const kinematics::KinematicsQueryOptions &options =
409 kinematics::KinematicsQueryOptions())
const {
411 return searchPositionIK(std::vector<geometry_msgs::Pose>{ik_pose},
412 ik_seed_state, timeout, std::vector<double>(),
413 solution, solution_callback, error_code, options);
417 searchPositionIK(
const geometry_msgs::Pose &ik_pose,
418 const std::vector<double> &ik_seed_state,
double timeout,
419 const std::vector<double> &consistency_limits,
420 std::vector<double> &solution,
421 const IKCallbackFn &solution_callback,
422 moveit_msgs::MoveItErrorCodes &error_code,
423 const kinematics::KinematicsQueryOptions &options =
424 kinematics::KinematicsQueryOptions())
const {
426 return searchPositionIK(std::vector<geometry_msgs::Pose>{ik_pose},
427 ik_seed_state, timeout, consistency_limits,
428 solution, solution_callback, error_code, options);
437 searchPositionIK(
const std::vector<geometry_msgs::Pose> &ik_poses,
438 const std::vector<double> &ik_seed_state,
double timeout,
439 const std::vector<double> &consistency_limits,
440 std::vector<double> &solution,
441 const IKCallbackFn &solution_callback,
442 moveit_msgs::MoveItErrorCodes &error_code,
443 const kinematics::KinematicsQueryOptions &options =
444 kinematics::KinematicsQueryOptions(),
445 const moveit::core::RobotState *context_state = NULL)
const {
446 double t0 = ros::WallTime::now().toSec();
455 auto *bio_ik_options = toBioIKKinematicsQueryOptions(&options);
465 state.resize(robot_model->getVariableCount());
467 for (
size_t i = 0; i < robot_model->getVariableCount(); i++)
468 state[i] = context_state->getVariablePositions()[i];
470 robot_model->getVariableDefaultPositions(state);
473 solution = ik_seed_state;
476 for (
auto &joint_name : getJointNames()) {
477 auto *joint_model = robot_model->getJointModel(joint_name);
480 for (
size_t vi = 0; vi < joint_model->getVariableCount(); vi++)
481 state.at(joint_model->getFirstVariableIndex() + vi) =
486 if (!bio_ik_options || !bio_ik_options->replace) {
489 for (
size_t i = 0; i < ik_poses.size(); i++) {
490 Eigen::Isometry3d p, r;
491 tf::poseMsgToEigen(ik_poses[i], p);
493 r = context_state->getGlobalLinkTransform(getBaseFrame());
496 temp_state->setToDefaultValues();
497 r = temp_state->getGlobalLinkTransform(getBaseFrame());
499 tipFrames.emplace_back(r * p);
505 problem.timeout = t0 + timeout;
506 problem.initial_guess = state;
539 if (!bio_ik_options || !bio_ik_options->replace) {
540 for (
size_t i = 0; i < tip_frames_.size(); i++) {
541 auto *goal = (PoseGoal *)default_goals[i].
get();
542 goal->setPosition(tipFrames[i].pos);
543 goal->setOrientation(tipFrames[i].rot);
549 if (!bio_ik_options || !bio_ik_options->replace)
550 for (
auto &goal : default_goals)
551 all_goals.push_back(goal.get());
554 for (
auto &goal : bio_ik_options->goals)
555 all_goals.push_back(goal.get());
558 BLOCKPROFILER(
"problem init");
559 problem.initialize(ikparams.robot_model, ikparams.joint_model_group,
560 ikparams, all_goals, bio_ik_options);
566 BLOCKPROFILER(
"ik init");
567 ik->initialize(problem);
572 BLOCKPROFILER(
"ik_solve");
577 state = ik->getSolution();
580 for (
auto ivar : problem.active_variables) {
581 auto v = state[ivar];
582 if (robot_info.isRevolute(ivar) &&
583 robot_model->getMimicJointModels().empty()) {
584 auto r = problem.initial_guess[ivar];
585 auto lo = robot_info.getMin(ivar);
586 auto hi = robot_info.getMax(ivar);
589 if (r < v - M_PI || r > v + M_PI) {
601 v -= std::ceil(std::max(0.0, v - hi) / (2 * M_PI)) * (2 * M_PI);
603 v += std::ceil(std::max(0.0, lo - v) / (2 * M_PI)) * (2 * M_PI);
615 robot_model->enforcePositionBounds(state.data());
620 for (
auto &joint_name : getJointNames()) {
621 auto *joint_model = robot_model->getJointModel(joint_name);
624 for (
size_t vi = 0; vi < joint_model->getVariableCount(); vi++)
626 state.at(joint_model->getFirstVariableIndex() + vi));
631 if (bio_ik_options) {
632 bio_ik_options->solution_fitness = ik->getSolutionFitness();
637 if (!ik->getSuccess() && !options.return_approximate_solution) {
638 error_code.val = error_code.NO_IK_SOLUTION;
643 if (!solution_callback.empty()) {
645 solution_callback(ik_poses.front(), solution, error_code);
648 return error_code.val == error_code.SUCCESS;
651 error_code.val = error_code.SUCCESS;
656 virtual bool supportsGroup(
const moveit::core::JointModelGroup *jmg,
657 std::string *error_text_out = 0)
const {
670 kinematics::KinematicsBase);