Robowflex  v0.1
Making MoveIt Easy
robowflex_library/src/robot.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <deque>
4 #include <numeric>
5 
6 #include <moveit/robot_state/conversions.h>
7 #include <moveit/robot_state/robot_state.h>
8 
10 #include <robowflex_library/io.h>
12 #include <robowflex_library/log.h>
16 #include <robowflex_library/tf.h>
17 #include <robowflex_library/util.h>
18 
19 using namespace robowflex;
20 
21 const std::string Robot::ROBOT_DESCRIPTION = "robot_description";
22 const std::string Robot::ROBOT_SEMANTIC = "_semantic";
23 const std::string Robot::ROBOT_PLANNING = "_planning";
24 const std::string Robot::ROBOT_KINEMATICS = "_kinematics";
25 
26 Robot::Robot(const std::string &name) : name_(name), handler_(name_)
27 {
28 }
29 
30 bool Robot::loadURDFFile(const std::string &urdf_file)
31 {
32  std::string urdf = loadXMLFile(urdf_file);
33  if (urdf.empty())
34  return false;
35 
36  urdf_ = urdf;
37  return true;
38 }
39 
40 bool Robot::loadSRDFFile(const std::string &srdf_file)
41 {
42  std::string srdf = loadXMLFile(srdf_file);
43  if (srdf.empty())
44  return false;
45 
46  srdf_ = srdf;
47  return true;
48 }
49 
50 bool Robot::initialize(const std::string &urdf_file, const std::string &srdf_file,
51  const std::string &limits_file, const std::string &kinematics_file)
52 {
53  if (loader_)
54  {
55  RBX_ERROR("Already initialized!");
56  return false;
57  }
58 
59  if (not loadURDFFile(urdf_file))
60  {
61  RBX_ERROR("Failed to load URDF!");
62  return false;
63  }
64 
65  if (not loadSRDFFile(srdf_file))
66  {
67  RBX_ERROR("Failed to load SRDF!");
68  return false;
69  }
70 
71  if (not limits_file.empty())
73  {
74  RBX_ERROR("Failed to load joint limits!");
75  return false;
76  }
77 
78  if (not kinematics_file.empty())
79  if (not initializeKinematics(kinematics_file))
80  {
81  RBX_ERROR("Failed to load kinematics!");
82  return false;
83  }
84 
86  return true;
87 }
88 
89 bool Robot::initializeFromYAML(const std::string &config_file)
90 {
91  if (loader_)
92  {
93  RBX_ERROR("Already initialized!");
94  return false;
95  }
96 
97  const auto &yaml = IO::loadFileToYAML(config_file);
98  if (not yaml.first)
99  {
100  RBX_ERROR("Failed to load YAML file `%s`.", config_file);
101  return false;
102  }
103 
104  const auto &node = yaml.second;
105 
106  // URDF
107  std::string urdf_file;
108  if (IO::isNode(node["urdf"]))
109  urdf_file = node["urdf"].as<std::string>();
110  else
111  {
112  RBX_ERROR("No URDF entry in YAML file `%s`!", config_file);
113  return false;
114  }
115 
116  // SRDF
117  std::string srdf_file;
118  if (IO::isNode(node["srdf"]))
119  srdf_file = node["srdf"].as<std::string>();
120  else
121  RBX_WARN("No SRDF entry in YAML!");
122 
123  // Joint limits
124  std::string limits_file;
125  if (IO::isNode(node["limits"]))
126  {
127  if (srdf_file.empty())
128  {
129  RBX_ERROR("Cannot provide joint limits without SRDF in YAML file `%s`!", config_file);
130  return false;
131  }
132 
133  limits_file = node["limits"].as<std::string>();
134  }
135  else
136  RBX_WARN("No joint limits provided!");
137 
138  // Kinematics plugins
139  std::string kinematics_file;
140  if (IO::isNode(node["kinematics"]))
141  {
142  if (srdf_file.empty())
143  {
144  RBX_ERROR("Cannot provide kinematics without SRDF in YAML file `%s`!", config_file);
145  return false;
146  }
147 
148  kinematics_file = node["kinematics"].as<std::string>();
149  }
150  else
151  RBX_WARN("No kinematics plugins provided!");
152 
153  // Initialize robot
154  bool r;
155  if (srdf_file.empty())
156  r = initialize(urdf_file);
157  else
158  r = initialize(urdf_file, srdf_file, limits_file, kinematics_file);
159 
160  // Set default state if provided in file.
161  if (r)
162  {
163  if (IO::isNode(node["robot_state"]))
164  {
165  const auto &robot_state = IO::robotStateFromNode(node["robot_state"]);
166  setState(robot_state);
167  }
168  else
169  RBX_WARN("No default state provided!");
170  }
171 
172  return r;
173 }
174 
175 bool Robot::initialize(const std::string &urdf_file)
176 {
177  if (loader_)
178  {
179  RBX_ERROR("Already initialized!");
180  return false;
181  }
182 
183  if (not loadURDFFile(urdf_file))
184  return false;
185 
186  // Generate basic SRDF on the fly.
187  tinyxml2::XMLDocument doc;
188  doc.Parse(urdf_.c_str());
189  const auto &name = doc.FirstChildElement("robot")->Attribute("name");
190  const std::string &srdf = "<?xml version=\"1.0\" ?><robot name=\"" + std::string(name) + "\"></robot>";
191 
192  srdf_ = srdf;
193 
195 
196  return true;
197 }
198 
199 bool Robot::initializeKinematics(const std::string &kinematics_file)
200 {
201  if (kinematics_)
202  {
203  RBX_ERROR("Already loaded kinematics!");
204  return false;
205  }
206 
208 }
209 
211 {
212  urdf_function_ = function;
213 }
214 
215 bool Robot::isLinkURDF(tinyxml2::XMLDocument &doc, const std::string &name)
216 {
217  auto *node = doc.FirstChildElement("robot")->FirstChildElement("link");
218  while (node != nullptr)
219  {
220  if (node->Attribute("name", name.c_str()))
221  return true;
222 
223  node = node->NextSiblingElement("link");
224  }
225  return false;
226 }
227 
229 {
230  srdf_function_ = function;
231 }
232 
234 {
235  limits_function_ = function;
236 }
237 
239 {
240  kinematics_function_ = function;
241 }
242 
243 bool Robot::loadYAMLFile(const std::string &name, const std::string &file)
244 {
245  PostProcessYAMLFunction function;
246  return loadYAMLFile(name, file, function);
247 }
248 
249 bool Robot::loadYAMLFile(const std::string &name, const std::string &file,
250  const PostProcessYAMLFunction &function)
251 {
252  const auto &yaml = IO::loadFileToYAML(file);
253  if (!yaml.first)
254  {
255  RBX_ERROR("Failed to load YAML file `%s`.", file);
256  return false;
257  }
258 
259  if (function)
260  {
261  YAML::Node copy = yaml.second;
262  if (!function(copy))
263  {
264  RBX_ERROR("Failed to process YAML file `%s`.", file);
265  return false;
266  }
267 
268  handler_.loadYAMLtoROS(copy, name);
269  }
270  else
271  handler_.loadYAMLtoROS(yaml.second, name);
272 
273  return true;
274 }
275 
277 {
278  std::string string = IO::loadXMLToString(file);
279  if (string.empty())
280  {
281  RBX_ERROR("Failed to load XML file `%s`.", file);
282  return "";
283  }
284 
285  return string;
286 }
287 
289 {
290  if (function)
291  {
292  tinyxml2::XMLDocument doc;
293  doc.Parse(string.c_str());
294 
295  if (not function(doc))
296  {
297  RBX_ERROR("Failed to process XML string `%s`.", string);
298  return;
299  }
300 
301  tinyxml2::XMLPrinter printer;
302  doc.Print(&printer);
303 
304  string = std::string(printer.CStr());
305  }
306 }
307 
308 void Robot::initializeInternal(bool namespaced)
309 {
310  const std::string &description = ((namespaced) ? handler_.getNamespace() : "") + "/" + ROBOT_DESCRIPTION;
311 
312  loadRobotModel(description);
313  if (urdf_function_)
315 
316  if (srdf_function_)
318 
319  // If either function was called, reload robot.
321  {
322  RBX_INFO("Reloading model after URDF/SRDF post-process function...");
323  loadRobotModel(description);
324  }
325 
326  // set strings on parameter server
329 
330  scratch_.reset(new robot_state::RobotState(model_));
331  scratch_->setToDefaultValues();
332 }
333 
334 void Robot::loadRobotModel(const std::string &description)
335 {
336  robot_model_loader::RobotModelLoader::Options options(description);
337  options.load_kinematics_solvers_ = false;
338  options.urdf_string_ = urdf_;
339  options.srdf_string_ = srdf_;
340 
341  loader_.reset(new robot_model_loader::RobotModelLoader(options));
342  kinematics_.reset(new kinematics_plugin_loader::KinematicsPluginLoader(description));
343 
344  model_ = loader_->getModel();
345 }
346 
347 bool Robot::loadKinematics(const std::string &group_name, bool load_subgroups)
348 {
349  // Needs to be called first to read the groups defined in the SRDF from the ROS params.
350  robot_model::SolverAllocatorFn allocator = kinematics_->getLoaderFunction(loader_->getSRDF());
351 
352  const auto &groups = kinematics_->getKnownGroups();
353  if (groups.empty())
354  {
355  RBX_ERROR("No kinematics plugins defined. Fill and load kinematics.yaml!");
356  return false;
357  }
358 
359  if (!model_->hasJointModelGroup(group_name))
360  {
361  RBX_ERROR("No JMG defined for `%s`!", group_name);
362  return false;
363  }
364 
365  std::vector<std::string> load_names;
366 
367  // If requested, also attempt to load the kinematics solvers for subgroups.
368  if (load_subgroups)
369  {
370  const auto &subgroups = model_->getJointModelGroup(group_name)->getSubgroupNames();
371  load_names.insert(load_names.end(), subgroups.begin(), subgroups.end());
372  }
373 
374  // Check if this group also has an associated kinematics solver to load.
375  if (std::find(groups.begin(), groups.end(), group_name) != groups.end())
376  load_names.emplace_back(group_name);
377 
378  auto timeout = kinematics_->getIKTimeout();
379 
380  for (const auto &name : load_names)
381  {
382  // Check if kinematics have already been loaded for this group.
383  if (imap_.find(name) != imap_.end())
384  continue;
385 
386  if (!model_->hasJointModelGroup(name) ||
387  std::find(groups.begin(), groups.end(), name) == groups.end())
388  {
389  RBX_ERROR("No JMG or Kinematics defined for `%s`!", name);
390  return false;
391  }
392 
393  robot_model::JointModelGroup *jmg = model_->getJointModelGroup(name);
394  kinematics::KinematicsBasePtr solver = allocator(jmg);
395 
396  if (solver)
397  {
398  std::string error_msg;
399  if (solver->supportsGroup(jmg, &error_msg))
400  imap_[name] = allocator;
401  else
402  {
403  RBX_ERROR("Kinematics solver %s does not support joint group %s. Error: %s",
404  typeid(*solver).name(), name, error_msg);
405  return false;
406  }
407  }
408  else
409  {
410  RBX_ERROR("Kinematics solver could not be instantiated for joint group `%s`.", name);
411  return false;
412  }
413 
414  RBX_INFO("Loaded Kinematics Solver for `%s`", name);
415  jmg->setDefaultIKTimeout(timeout[name]);
416  }
417 
418  model_->setKinematicsAllocators(imap_);
419  return true;
420 }
421 
423 {
424  setSRDFPostProcessFunction([&, name](tinyxml2::XMLDocument &doc) -> bool {
425  tinyxml2::XMLElement *virtual_joint = doc.NewElement("virtual_joint");
426  virtual_joint->SetAttribute("name", name.c_str());
427  virtual_joint->SetAttribute("type", "planar");
428  virtual_joint->SetAttribute("parent_frame", "world");
429  virtual_joint->SetAttribute("child_link", model_->getRootLink()->getName().c_str());
430 
431  doc.FirstChildElement("robot")->InsertFirstChild(virtual_joint);
432 
433  return true;
434  });
435 }
436 
438 {
439  setSRDFPostProcessFunction([&, name](tinyxml2::XMLDocument &doc) -> bool {
440  tinyxml2::XMLElement *virtual_joint = doc.NewElement("virtual_joint");
441  virtual_joint->SetAttribute("name", name.c_str());
442  virtual_joint->SetAttribute("type", "floating");
443  virtual_joint->SetAttribute("parent_frame", "world");
444  virtual_joint->SetAttribute("child_link", model_->getRootLink()->getName().c_str());
445 
446  doc.FirstChildElement("robot")->InsertFirstChild(virtual_joint);
447 
448  return true;
449  });
450 }
451 
453 {
454  return model_->getName();
455 }
456 
458 {
459  return name_;
460 }
461 
462 const robot_model::RobotModelPtr &Robot::getModelConst() const
463 {
464  return model_;
465 }
466 
467 robot_model::RobotModelPtr &Robot::getModel()
468 {
469  return model_;
470 }
471 
472 urdf::ModelInterfaceConstSharedPtr Robot::getURDF() const
473 {
474  return model_->getURDF();
475 }
476 
478 {
479  return urdf_;
480 }
481 
482 srdf::ModelConstSharedPtr Robot::getSRDF() const
483 {
484  return model_->getSRDF();
485 }
486 
488 {
489  return srdf_;
490 }
491 
492 const robot_model::RobotStatePtr &Robot::getScratchStateConst() const
493 {
494  return scratch_;
495 }
496 
497 robot_model::RobotStatePtr &Robot::getScratchState()
498 {
499  return scratch_;
500 }
501 
502 robot_model::RobotStatePtr Robot::cloneScratchState() const
503 {
504  auto state = allocState();
505  *state = *scratch_;
506 
507  return state;
508 }
509 
511 {
512  return handler_;
513 }
514 
516 {
517  return handler_;
518 }
519 
520 void Robot::setState(const std::vector<double> &positions)
521 {
522  scratch_->setVariablePositions(positions);
523  scratch_->update();
524 }
525 
527 {
528  scratch_->setVariablePositions(variable_map);
529  scratch_->update();
530 }
531 
532 void Robot::setState(const std::vector<std::string> &variable_names,
533  const std::vector<double> &variable_position)
534 {
535  scratch_->setVariablePositions(variable_names, variable_position);
536  scratch_->update();
537 }
538 
539 void Robot::setState(const sensor_msgs::JointState &state)
540 {
541  scratch_->setVariableValues(state);
542  scratch_->update();
543 }
544 
545 void Robot::setState(const moveit_msgs::RobotState &state)
546 {
548  scratch_->update();
549 }
550 
552 {
553  moveit_msgs::RobotState state;
554  IO::fromYAMLFile(state, file);
555 
556  setState(state);
557 }
558 
559 void Robot::setGroupState(const std::string &name, const std::vector<double> &positions)
560 {
561  scratch_->setJointGroupPositions(name, positions);
562  scratch_->update();
563 }
564 
566 {
567  const double *positions = scratch_->getVariablePositions();
568  std::vector<double> state(positions, positions + scratch_->getVariableCount());
569  return state;
570 }
571 
572 moveit_msgs::RobotState Robot::getStateMsg() const
573 {
574  moveit_msgs::RobotState message;
576 
577  return message;
578 }
579 
580 void Robot::setStateMsgGroupState(moveit_msgs::RobotState &state, const std::string &group,
581  const std::vector<double> &positions) const
582 {
583  robot_state::RobotState temp(getModelConst());
585 
586  auto *jmg = getModelConst()->getJointModelGroup(group);
587  temp.setJointGroupPositions(jmg, positions);
588 
590 }
591 
593 {
594  return scratch_->getVariableNames();
595 }
596 
597 bool Robot::hasJoint(const std::string &joint) const
598 {
599  const auto &joint_names = getJointNames();
600  return (std::find(joint_names.begin(), joint_names.end(), joint) != joint_names.end());
601 }
602 
603 //
604 // IKQuery
605 //
606 
607 Robot::IKQuery::IKQuery(const std::string &group) : group(group)
608 {
609 }
610 
612  const robot_state::RobotState &start, const Eigen::Vector3d &direction,
613  double distance)
614  : IKQuery(group, tip, start, distance * direction.normalized())
615 {
616 }
617 
619  const robot_state::RobotState &start, const Eigen::Vector3d &position_offset,
620  const Eigen::Quaterniond &rotation_offset)
621  : IKQuery(group, tip, start, TF::createPoseQ(position_offset, rotation_offset))
622 {
623 }
624 
626  const robot_state::RobotState &start, const RobotPose &offset)
627  : IKQuery(group, start.getGlobalLinkTransform(tip) * offset)
628 {
629 }
630 
632  const RobotPose &offset, //
633  const ScenePtr &scene, //
634  const std::string &object, //
635  const Eigen::Vector3d &tolerances,
636  bool verbose)
637  : group(group), scene(scene), verbose(verbose)
638 {
639  const auto &pose = scene->getObjectGraspPose(object, offset);
640  addRequest("", //
642  TF::createPoseXYZ(pose.translation()), //
643  Eigen::Quaterniond(pose.rotation()));
644 }
645 
646 Robot::IKQuery::IKQuery(const std::string &group, const RobotPose &pose, double radius,
647  const Eigen::Vector3d &tolerance)
648  : IKQuery(group, //
649  pose.translation(), //
650  Eigen::Quaterniond{pose.rotation()}, //
651  radius, //
652  tolerance)
653 {
654 }
655 
657  const Eigen::Vector3d &position, const Eigen::Quaterniond &orientation, //
658  double radius, const Eigen::Vector3d &tolerance)
659  : IKQuery(group, //
660  Geometry::makeSphere(radius), //
661  TF::createPoseXYZ(position), //
662  orientation, //
663  tolerance)
664 {
665 }
666 
667 Robot::IKQuery::IKQuery(const std::string &group, const GeometryConstPtr &region, const RobotPose &pose,
668  const Eigen::Quaterniond &orientation, const Eigen::Vector3d &tolerance,
669  const ScenePtr &scene, bool verbose)
670  : group(group), scene(scene), verbose(verbose)
671 {
672  addRequest("", region, pose, orientation, tolerance);
673 }
674 
675 Robot::IKQuery::IKQuery(const std::string &group, const moveit_msgs::PositionConstraint &pc,
676  const moveit_msgs::OrientationConstraint &oc)
677  : group(group)
678 {
679  if (pc.link_name != oc.link_name)
680  throw Exception(
681  1, log::format("Link name mismatch in constraints, `%1%` != `%2%`", pc.link_name, oc.link_name));
682 
683  if (not TF::isVecZero(TF::vectorMsgToEigen(pc.target_point_offset)))
684  throw Exception(1, "target_point_offset in position constraint not supported.");
685 
686  const auto &cr = pc.constraint_region;
687 
688  if (not cr.meshes.empty())
689  throw Exception(1, "Cannot specify mesh regions!");
690 
691  if (cr.primitives.size() > 1)
692  throw Exception(1, "Cannot specify more than one primitive!");
693 
694  const auto &region = Geometry::makeSolidPrimitive(cr.primitives[0]);
695  const auto &pose = TF::poseMsgToEigen(cr.primitive_poses[0]);
696 
697  const auto &rotation = TF::quaternionMsgToEigen(oc.orientation);
698  Eigen::Vector3d tolerance{oc.absolute_x_axis_tolerance, //
699  oc.absolute_y_axis_tolerance, //
700  oc.absolute_z_axis_tolerance};
701 
702  addRequest(pc.link_name, region, pose, rotation, tolerance);
703 }
704 
706  const std::vector<std::string> &input_tips, double radius,
707  const Eigen::Vector3d &tolerance, const ScenePtr &scene, bool verbose)
708  : group(group), scene(scene), verbose(verbose)
709 {
710  if (poses.size() != input_tips.size())
711  throw Exception(1, "Invalid multi-target IK query. poses != tips.");
712 
713  for (std::size_t i = 0; i < poses.size(); ++i)
714  addRequest(input_tips[i], //
715  Geometry::makeSphere(radius), //
716  TF::createPoseXYZ(poses[i].translation()), //
717  Eigen::Quaterniond{poses[i].rotation()}, //
718  tolerance);
719 }
720 
722  const std::vector<GeometryConstPtr> &regions, const RobotPoseVector &poses,
723  const std::vector<Eigen::Quaterniond> &orientations,
724  const EigenSTL::vector_Vector3d &tolerances, const ScenePtr &scene, bool verbose)
725  : group(group), scene(scene), verbose(verbose)
726 {
727  if (poses.size() != input_tips.size() //
728  or poses.size() != regions.size() //
729  or poses.size() != orientations.size() //
730  or poses.size() != tolerances.size())
731  throw Exception(1, "Invalid multi-target IK query. Vectors are of different length.");
732 
733  for (std::size_t i = 0; i < poses.size(); ++i)
734  addRequest(input_tips[i], regions[i], poses[i], orientations[i], tolerances[i]);
735 }
736 
737 void Robot::IKQuery::addRequest(const std::string &tip, const GeometryConstPtr &region, const RobotPose &pose,
738  const Eigen::Quaterniond &orientation, const Eigen::Vector3d &tolerance)
739 {
740  tips.emplace_back(tip);
741  regions.emplace_back(region);
742  region_poses.emplace_back(pose);
743  orientations.emplace_back(orientation);
744  tolerances.emplace_back(tolerance);
745 }
746 
747 void Robot::IKQuery::setScene(const ScenePtr &scene_in, bool verbose_in)
748 {
749  scene = scene_in;
750  verbose = verbose_in;
751 }
752 
753 void Robot::IKQuery::addMetric(const Metric &metric_function)
754 {
755  metrics.emplace_back(metric_function);
756 }
757 
759 {
760  addMetric([weight](const robot_state::RobotState &state, const SceneConstPtr &scene,
762  return weight * result.distance;
763  });
764 }
765 
767 {
768  addMetric([&, weight](const robot_state::RobotState &state, const SceneConstPtr &scene,
770  const auto &jmg = state.getJointModelGroup(group);
771  const auto &min = state.getMinDistanceToPositionBounds(jmg);
772  double extent = min.second->getMaximumExtent() / 2.;
773  return weight * (extent - min.first) / extent;
774  });
775 }
776 
778 {
779  addMetric([&, weight](const robot_state::RobotState &state, const SceneConstPtr &scene,
781  if (scene)
782  {
783  double v = scene->distanceToCollision(state);
784  return weight * v;
785  }
786 
787  return 0.;
788  });
789 }
790 
792 {
793  const auto &point = regions[index]->sample();
794  if (point.first)
795  {
796  pose = region_poses[index];
797  pose.translate(point.second);
798  pose.rotate(TF::sampleOrientation(orientations[index], tolerances[index]));
799  }
800 
801  return point.first;
802 }
803 
805 {
806  const std::size_t n = regions.size();
807  poses.resize(n);
808 
809  bool sampled = true;
810  for (std::size_t j = 0; j < n and sampled; ++j)
811  sampled &= sampleRegion(poses[j], j);
812 
813  return sampled;
814 }
815 
816 void Robot::IKQuery::getMessage(const std::string &base_frame, moveit_msgs::Constraints &msg) const
817 {
818  const std::size_t n = regions.size();
819 
820  msg.name = "IKQuery";
821 
822  for (std::size_t i = 0; i < n; ++i)
823  {
824  auto pos = TF::getPositionConstraint(tips[i], base_frame, region_poses[i], regions[i]);
825  auto orn = TF::getOrientationConstraint(tips[i], base_frame, orientations[i], tolerances[i]);
826  pos.weight = 1. / n;
827  orn.weight = 1. / n / 2.;
828 
829  msg.position_constraints.emplace_back(pos);
830  msg.orientation_constraints.emplace_back(orn);
831  }
832 }
833 
834 kinematic_constraints::KinematicConstraintSetPtr Robot::IKQuery::getAsConstraints(const Robot &robot) const
835 {
836  moveit_msgs::Constraints msg;
837  const auto &root = robot.getModelConst()->getRootLink()->getName();
838  getMessage(root, msg);
839 
840  auto constraints = std::make_shared<kinematic_constraints::KinematicConstraintSet>(robot.getModelConst());
841  moveit::core::Transforms none(root);
842 
843  constraints->add(msg, none);
844 
845  return constraints;
846 }
847 
848 double Robot::IKQuery::getMetricValue(const robot_state::RobotState &state,
850 {
851  double v = 0.;
852  for (const auto &metric : metrics)
853  v += metric(state, scene, result);
854 
855  return v;
856 }
857 
858 bool Robot::setFromIK(const IKQuery &query)
859 {
860  return setFromIK(query, *scratch_);
861 }
862 
863 bool Robot::setFromIK(const IKQuery &query, robot_state::RobotState &state) const
864 {
865  // copy query for unconstness
866  IKQuery query_copy(query);
867 
868  // If there are no tips in the query,
869  // we use the tip frame from the original query group
870  if (query_copy.tips[0].empty())
871  query_copy.tips = getSolverTipFrames(query.group);
872 
873  const robot_model::JointModelGroup *jmg = model_->getJointModelGroup(query_copy.group);
874  const auto &gsvcf = (query_copy.scene) ? query_copy.scene->getGSVCF(query_copy.verbose) :
876 
877  bool evaluate = not query_copy.metrics.empty() or query_copy.validate;
879 
880  const auto &constraints = (evaluate) ? query_copy.getAsConstraints(*this) : nullptr;
881 
882  // Best state if evaluating metrics.
883  auto best = (query_copy.metrics.empty()) ? nullptr : std::make_shared<robot_state::RobotState>(state);
884  double best_value = constants::inf;
885 
886  bool success = false;
887  RobotPoseVector targets;
888  for (std::size_t i = 0; i < query_copy.attempts and not success; ++i)
889  {
890  // Sample new target poses from regions.
891  query_copy.sampleRegions(targets);
892 
893 #if ROBOWFLEX_AT_LEAST_MELODIC
894  // Multi-tip IK: Will delegate automatically to RobotState::setFromIKSubgroups() if the kinematics
895  // solver doesn't support multi-tip queries.
896  success =
897  state.setFromIK(jmg, targets, query_copy.tips, query_copy.timeout, gsvcf, query_copy.options);
898 #else
899  // attempts was a prior field that was deprecated in melodic
900  success =
901  state.setFromIK(jmg, targets, query_copy.tips, 1, query_copy.timeout, gsvcf, query_copy.options);
902 #endif
903 
904  if (evaluate)
905  {
906  state.update();
907  result = constraints->decide(state, query_copy.verbose);
908  }
909 
910  // Externally validate result
911  if (query_copy.validate)
912  {
913  if (query_copy.verbose)
914  RBX_INFO("Constraint Distance: %1%", result.distance);
915 
916  bool no_collision =
917  (query_copy.scene) ? not query_copy.scene->checkCollision(state).collision : true;
918 
919  success = //
920  no_collision and //
921  ((query_copy.valid_distance > 0.) ? result.distance <= query_copy.valid_distance :
922  result.satisfied);
923  }
924 
925  // If success, evaluate state for metrics.
926  if (success and not query_copy.metrics.empty())
927  {
928  double v = query_copy.getMetricValue(state, result);
929 
930  if (query_copy.verbose)
931  RBX_INFO("State Metric Value: %1%", v);
932 
933  if (v < best_value)
934  {
935  if (query_copy.verbose)
936  RBX_INFO("State is current best!");
937 
938  best_value = v;
939  *best = state;
940  }
941 
942  success = false;
943  }
944 
945  if (query_copy.random_restart and not success)
946  state.setToRandomPositions(jmg);
947  }
948 
949  // If evaluating metric, copy best state.
950  if (std::isfinite(best_value))
951  {
952  state = *best;
953  success = true;
954  }
955 
956  state.update();
957  return success;
958 }
959 
960 bool Robot::validateIKQuery(const IKQuery &query, const robot_state::RobotState &state) const
961 {
962  const auto &constraints = query.getAsConstraints(*this);
963  const auto &result = constraints->decide(state, query.verbose);
964  return (query.valid_distance > 0.) ? result.distance <= query.valid_distance : result.satisfied;
965 }
966 
967 double Robot::distanceToIKQuery(const IKQuery &query, const robot_state::RobotState &state) const
968 {
969  const auto &constraints = query.getAsConstraints(*this);
970  const auto &result = constraints->decide(state, query.verbose);
971  return result.distance;
972 }
973 
974 const RobotPose &Robot::getLinkTF(const std::string &name) const
975 {
976  return scratch_->getGlobalLinkTransform(name);
977 }
978 
979 const RobotPose Robot::getRelativeLinkTF(const std::string &base, const std::string &target) const
980 {
981  auto base_tf = scratch_->getGlobalLinkTransform(base);
982  auto target_tf = scratch_->getGlobalLinkTransform(target);
983 
984  return base_tf.inverse() * target_tf;
985 }
986 
987 bool Robot::toYAMLFile(const std::string &file) const
988 {
989  moveit_msgs::RobotState msg;
991 
992  const auto &yaml = IO::toNode(msg);
993  return IO::YAMLToFile(yaml, file);
994 }
995 
996 robot_model::RobotStatePtr Robot::allocState() const
997 {
998  // No make_shared() for indigo compatibility
999  robot_state::RobotStatePtr state;
1000  state.reset(new robot_state::RobotState(getModelConst()));
1001  state->setToDefaultValues();
1002 
1003  return state;
1004 }
1005 
1007 {
1008  const auto &jmg = model_->getJointModelGroup(group);
1009  const auto &solver = jmg->getSolverInstance();
1010  if (solver)
1011  return solver->getTipFrames();
1012 
1013  return {};
1014 }
1015 
1017 {
1018  const auto &jmg = model_->getJointModelGroup(group);
1019  const auto &solver = jmg->getSolverInstance();
1020  if (solver)
1021  return solver->getBaseFrame();
1022 
1023  return "";
1024 }
1025 
1026 namespace
1027 {
1028  YAML::Node addLinkGeometry(const urdf::GeometrySharedPtr &geometry, bool resolve = true)
1029  {
1030  YAML::Node node;
1031  switch (geometry->type)
1032  {
1033  case urdf::Geometry::MESH:
1034  {
1035  const auto &mesh = static_cast<urdf::Mesh *>(geometry.get());
1036  node["type"] = "mesh";
1037 
1038  if (resolve)
1039  node["resource"] = IO::resolvePath(mesh->filename);
1040  else
1041  node["resource"] = mesh->filename;
1042 
1043  if (mesh->scale.x != 1 || mesh->scale.y != 1 || mesh->scale.z != 1)
1044  {
1045  node["dimensions"] = std::vector<double>({mesh->scale.x, mesh->scale.y, mesh->scale.z});
1046  ROBOWFLEX_YAML_FLOW(node["dimensions"]);
1047  }
1048  break;
1049  }
1050  case urdf::Geometry::BOX:
1051  {
1052  const auto &box = static_cast<urdf::Box *>(geometry.get());
1053  node["type"] = "box";
1054  node["dimensions"] = std::vector<double>({box->dim.x, box->dim.y, box->dim.z});
1055  ROBOWFLEX_YAML_FLOW(node["dimensions"]);
1056  break;
1057  }
1058  case urdf::Geometry::SPHERE:
1059  {
1060  const auto &sphere = static_cast<urdf::Sphere *>(geometry.get());
1061  node["type"] = "sphere";
1062  node["dimensions"] = std::vector<double>({sphere->radius});
1063  ROBOWFLEX_YAML_FLOW(node["dimensions"]);
1064  break;
1065  }
1066  case urdf::Geometry::CYLINDER:
1067  {
1068  const auto &cylinder = static_cast<urdf::Cylinder *>(geometry.get());
1069  node["type"] = "cylinder";
1070  node["dimensions"] = std::vector<double>({cylinder->length, cylinder->radius});
1071  ROBOWFLEX_YAML_FLOW(node["dimensions"]);
1072  break;
1073  }
1074  default:
1075  break;
1076  }
1077 
1078  return node;
1079  }
1080 
1081  void addLinkMaterial(YAML::Node &node, const urdf::MaterialSharedPtr &material)
1082  {
1083  node["color"] =
1084  std::vector<double>({material->color.r, material->color.g, material->color.b, material->color.a});
1085 
1086  ROBOWFLEX_YAML_FLOW(node["color"]);
1087  // node["texture"] = visual->texture_filename;
1088  }
1089 
1090  void addLinkOrigin(YAML::Node &node, const urdf::Pose &pose)
1091  {
1092  YAML::Node origin;
1093  origin["position"] = std::vector<double>({pose.position.x, pose.position.y, pose.position.z});
1094  origin["orientation"] =
1095  std::vector<double>({pose.rotation.x, pose.rotation.y, pose.rotation.z, pose.rotation.w});
1096  node["origin"] = origin;
1097  ROBOWFLEX_YAML_FLOW(node["origin"]);
1098  }
1099 
1100  YAML::Node addLinkVisual(const urdf::VisualSharedPtr &visual, bool resolve = true)
1101  {
1102  YAML::Node node;
1103  if (visual)
1104  {
1105  if (visual->geometry)
1106  {
1107  const auto &geometry = visual->geometry;
1108  node = addLinkGeometry(geometry, resolve);
1109 
1110  if (visual->material)
1111  {
1112  const auto &material = visual->material;
1113  addLinkMaterial(node, material);
1114  }
1115 
1116  const auto &pose = visual->origin;
1117 
1118  Eigen::Vector3d position(pose.position.x, pose.position.y, pose.position.z);
1119  Eigen::Quaterniond rotation(pose.rotation.w, //
1120  pose.rotation.x, pose.rotation.y, pose.rotation.z);
1121  Eigen::Quaterniond identity = Eigen::Quaterniond::Identity();
1122 
1123  // TODO: Also check if rotation is not zero.
1124  if (position.norm() > 0 || rotation.angularDistance(identity) > 0)
1125  addLinkOrigin(node, pose);
1126  }
1127  }
1128 
1129  return node;
1130  }
1131 
1132  YAML::Node addLinkCollision(const urdf::CollisionSharedPtr &collision)
1133  {
1134  YAML::Node node;
1135  if (collision)
1136  {
1137  if (collision->geometry)
1138  {
1139  const auto &geometry = collision->geometry;
1140  node = addLinkGeometry(geometry);
1141  }
1142  }
1143 
1144  return node;
1145  }
1146 
1147  RobotPose urdfPoseToEigen(const urdf::Pose &pose)
1148  {
1149  geometry_msgs::Pose msg;
1150  msg.position.x = pose.position.x;
1151  msg.position.y = pose.position.y;
1152  msg.position.z = pose.position.z;
1153 
1154  msg.orientation.x = pose.rotation.x;
1155  msg.orientation.y = pose.rotation.y;
1156  msg.orientation.z = pose.rotation.z;
1157  msg.orientation.w = pose.rotation.w;
1158 
1159  return TF::poseMsgToEigen(msg);
1160  }
1161 } // namespace
1162 
1163 bool Robot::dumpGeometry(const std::string &filename) const
1164 {
1165  YAML::Node link_geometry;
1166  const auto &urdf = model_->getURDF();
1167 
1169  urdf->getLinks(links);
1170 
1171  for (const auto &link : links)
1172  {
1173  YAML::Node node;
1174 
1175  YAML::Node visual;
1176 #if ROBOWFLEX_AT_LEAST_KINETIC
1177  for (const auto &element : link->visual_array)
1178  if (element)
1179  visual["elements"].push_back(addLinkVisual(element));
1180 #else
1181  if (link->visual)
1182  visual["elements"].push_back(addLinkVisual(link->visual));
1183 #endif
1184 
1185  YAML::Node collision;
1186 #if ROBOWFLEX_AT_LEAST_KINETIC
1187  for (const auto &element : link->collision_array)
1188  if (element)
1189  collision["elements"].push_back(addLinkCollision(element));
1190 #else
1191  if (link->collision)
1192  collision["elements"].push_back(addLinkCollision(link->collision));
1193 #endif
1194 
1195  if (!visual.IsNull() || !collision.IsNull())
1196  {
1197  YAML::Node add;
1198  add["name"] = link->name;
1199 
1200  if (!visual.IsNull())
1201  add["visual"] = visual;
1202 
1203  if (!collision.IsNull())
1204  add["collision"] = collision;
1205 
1206  link_geometry.push_back(add);
1207  }
1208  }
1209 
1210  return IO::YAMLToFile(link_geometry, filename);
1211 }
1212 
1213 bool Robot::dumpTransforms(const std::string &filename) const
1214 {
1217 
1218  return dumpPathTransforms(trajectory, filename, 0., 0.);
1219 }
1220 
1222  double fps, double threshold) const
1223 {
1224  YAML::Node node, values;
1225  const double rate = 1.0 / fps;
1226 
1227  // Find the total duration of the path.
1228  const std::deque<double> &durations = path.getWayPointDurations();
1229  double total_duration = std::accumulate(durations.begin(), durations.end(), 0.0);
1230 
1231  const auto &urdf = model_->getURDF();
1232 
1233  robot_state::RobotStatePtr previous, state(new robot_state::RobotState(model_));
1234 
1235  for (double duration = 0.0, delay = 0.0; duration <= total_duration; duration += rate, delay += rate)
1236  {
1237  YAML::Node point;
1238 
1239  path.getStateAtDurationFromStart(duration, state);
1240  if (previous && state->distance(*previous) < threshold)
1241  continue;
1242 
1243  state->update();
1244  for (const auto &link_name : model_->getLinkModelNames())
1245  {
1246  const auto &urdf_link = urdf->getLink(link_name);
1247  if (urdf_link->visual)
1248  {
1249  const auto &link = model_->getLinkModel(link_name);
1250  RobotPose tf =
1251  state->getGlobalLinkTransform(link); // * urdfPoseToEigen(urdf_link->visual->origin);
1252  point[link->getName()] = IO::toNode(TF::poseEigenToMsg(tf));
1253  }
1254  }
1255 
1256  YAML::Node value;
1257  value["point"] = point;
1258  value["duration"] = delay;
1259  values.push_back(value);
1260 
1261  delay = 0;
1262 
1263  if (!previous)
1264  previous.reset(new robot_state::RobotState(model_));
1265 
1266  *previous = *state;
1267  }
1268 
1269  node["transforms"] = values;
1270  node["fps"] = fps;
1271 
1272  return IO::YAMLToFile(node, filename);
1273 }
1274 
1275 bool Robot::dumpToScene(const std::string &filename) const
1276 {
1277  YAML::Node node;
1278 
1279  const auto &urdf = model_->getURDF();
1280  for (const auto &link_name : model_->getLinkModelNames())
1281  {
1282  const auto &urdf_link = urdf->getLink(link_name);
1283  if (urdf_link->visual)
1284  {
1285  const auto &link = model_->getLinkModel(link_name);
1286 
1287  std::vector<YAML::Node> visuals;
1288 #if ROBOWFLEX_AT_LEAST_KINETIC
1289  for (const auto &element : urdf_link->visual_array)
1290  if (element)
1291  visuals.emplace_back(addLinkVisual(element, false));
1292 #else
1293  if (urdf_link->visual)
1294  visuals.push_back(addLinkVisual(urdf_link->visual, false));
1295 #endif
1296 
1297  YAML::Node object;
1298  object["id"] = link->getName();
1299 
1300  YAML::Node meshes;
1301  YAML::Node mesh_poses;
1302  YAML::Node primitives;
1303  YAML::Node primitive_poses;
1304 
1305  RobotPose tf = scratch_->getGlobalLinkTransform(link);
1306  for (const auto &visual : visuals)
1307  {
1308  RobotPose pose = tf;
1309  if (IO::isNode(visual["origin"]))
1310  {
1311  RobotPose offset = TF::poseMsgToEigen(IO::poseFromNode(visual["origin"]));
1312  pose = pose * offset;
1313  }
1314 
1315  const auto &posey = IO::toNode(TF::poseEigenToMsg(pose));
1316 
1317  const auto &type = visual["type"].as<std::string>();
1318  if (type == "mesh")
1319  {
1320  YAML::Node mesh;
1321  mesh["resource"] = visual["resource"];
1322  if (IO::isNode(visual["dimensions"]))
1323  mesh["dimensions"] = visual["dimensions"];
1324  else
1325  {
1326  mesh["dimensions"].push_back(1.);
1327  mesh["dimensions"].push_back(1.);
1328  mesh["dimensions"].push_back(1.);
1329  }
1330 
1331  ROBOWFLEX_YAML_FLOW(mesh["dimensions"]);
1332 
1333  meshes.push_back(mesh);
1334  mesh_poses.push_back(posey);
1335  }
1336  else
1337  {
1338  YAML::Node primitive;
1339  primitive["type"] = type;
1340  primitive["dimensions"] = visual["dimensions"];
1341  primitive_poses.push_back(posey);
1342  }
1343  }
1344 
1345  if (meshes.size())
1346  {
1347  object["meshes"] = meshes;
1348  object["mesh_poses"] = mesh_poses;
1349  }
1350 
1351  if (primitives.size())
1352  {
1353  object["primitives"] = primitives;
1354  object["primitive_poses"] = primitive_poses;
1355  }
1356 
1357  node["collision_objects"].push_back(object);
1358  }
1359  }
1360 
1361  YAML::Node scene;
1362  scene["world"] = node;
1363 
1364  return IO::YAMLToFile(scene, filename);
1365 }
1366 
1367 ///
1368 /// robowflex::ParamRobot
1369 ///
1370 
1372 {
1373  // Retrieve values from parameter server.
1376 
1377  initializeInternal(false);
1378 }
T accumulate(T... args)
T begin(T... args)
T c_str(T... args)
const std::deque< double > & getWayPointDurations() const
bool getStateAtDurationFromStart(const double request_duration, robot_state::RobotStatePtr &output_state) const
void addSuffixWayPoint(const robot_state::RobotState &state, double dt)
Exception that contains a message and an error code.
Definition: util.h:15
A const shared pointer wrapper for robowflex::Geometry.
A class that manages both solid and mesh geometry for various parts of the motion planning system.
Definition: geometry.h:36
static GeometryPtr makeSphere(double radius)
Create a sphere.
Definition: geometry.cpp:43
static GeometryPtr makeBox(double x, double y, double z)
Create a box.
Definition: geometry.cpp:48
static GeometryPtr makeSolidPrimitive(const shape_msgs::SolidPrimitive &msg)
Create a solid primitive.
Definition: geometry.cpp:68
ROS parameter server handler to handle namespacing and automatic parameter deletion.
Definition: handler.h:19
void setParam(const std::string &key, const T &value)
Sets a parameter on the parameter server.
Definition: handler.h:53
bool getParam(const std::string &key, T &value) const
Gets a parameter from the parameter server.
Definition: handler.h:71
void loadYAMLtoROS(const YAML::Node &node, const std::string &prefix="")
Loads the contents of a YAML node to the parameter server under a prefix.
const std::string & getNamespace() const
Gets the namespace of the handler.
ParamRobot(const std::string &name="DEFAULT")
Loads information about a robot and maintains information about a robot's state.
bool dumpGeometry(const std::string &file) const
Dumps the names of links and absolute paths to their visual mesh files to a YAML file.
std::vector< std::string > getJointNames() const
Gets the names of joints of the robot.
const RobotPose & getLinkTF(const std::string &name) const
Get the current pose of a link on the scratch state.
void setSRDFPostProcessAddFloatingJoint(const std::string &name)
Adds a planar virtual joint through the SRDF to the loaded robot with name name. This joint will have...
void setLimitsPostProcessFunction(const PostProcessYAMLFunction &function)
Sets a post processing function for loading the joint limits file.
static const std::string ROBOT_KINEMATICS
Default robot kinematics description suffix.
bool initializeFromYAML(const std::string &config_file)
Initializes a robot from a YAML config which includes URDF (urdf) and optional the SRDF (srdf),...
std::vector< double > getState() const
Gets the current joint positions of the scratch state.
kinematics_plugin_loader::KinematicsPluginLoaderPtr kinematics_
Kinematic plugin loader.
void loadRobotModel(const std::string &description)
Loads a robot model from the loaded information on the parameter server.
const RobotPose getRelativeLinkTF(const std::string &base, const std::string &target) const
Get the current pose of a link target in the frame of base.
PostProcessXMLFunction urdf_function_
URDF post-processing function.
bool validateIKQuery(const IKQuery &query, const robot_state::RobotState &state) const
Validates that a state satisfies an IK query's request poses.
Robot(const std::string &name)
Constructor.
bool dumpTransforms(const std::string &filename) const
Dumps the tranforms of all links of a robot at its current state to a file.
IO::Handler & getHandler()
Get the underlying IO handler used for this robot.
robot_model::RobotStatePtr cloneScratchState() const
Allocate a new robot state that is a clone of the current scratch state.
void initializeInternal(bool namespaced=true)
Initializes and loads the robot. Calls post-processing functions and creates scratch state.
srdf::ModelConstSharedPtr getSRDF() const
Get the raw SRDF Model.
PostProcessXMLFunction srdf_function_
SRDF post-processing function.
void setSRDFPostProcessFunction(const PostProcessXMLFunction &function)
Sets a post processing function for loading the SRDF.
const IO::Handler & getHandlerConst() const
Get the underlying IO handler used for this robot.
std::string loadXMLFile(const std::string &file)
Loads an XML or .xacro file into a string.
PostProcessYAMLFunction limits_function_
Limits YAML post-processing function.
void setKinematicsPostProcessFunction(const PostProcessYAMLFunction &function)
Sets a post processing function for loading the kinematics plugin file.
void setURDFPostProcessFunction(const PostProcessXMLFunction &function)
Sets a post processing function for loading the URDF.
std::vector< std::string > getSolverTipFrames(const std::string &group) const
Get the tip frames for the IK solver for a given joint model group group.
void updateXMLString(std::string &string, const PostProcessXMLFunction &function)
Updates a loaded XML string based on an XML post-process function. Called after initial,...
double distanceToIKQuery(const IKQuery &query, const robot_state::RobotState &state) const
Returns the distance of the state to satisfying the IK query.
bool isLinkURDF(tinyxml2::XMLDocument &doc, const std::string &name)
Checks if a node link exist with named name_link.
PostProcessYAMLFunction kinematics_function_
Kinematics plugin YAML post-processing function.
bool loadURDFFile(const std::string &urdf_file)
Loads the URDF file.
bool toYAMLFile(const std::string &file) const
Dumps the current configuration of the robot as a YAML file.
robot_model::RobotStatePtr & getScratchState()
Get a reference to the scratch robot state.
urdf::ModelInterfaceConstSharedPtr getURDF() const
Get the raw URDF Model.
std::string getSolverBaseFrame(const std::string &group) const
Get the base frame for the IK solver given a joint model group group.
IO::Handler handler_
IO handler (namespaced with name_)
void setGroupState(const std::string &name, const std::vector< double > &positions)
Sets the group of the scratch state to a vector of joint positions.
bool initialize(const std::string &urdf_file)
Initializes a robot from a kinematic description. A default semantic description is used.
void setStateMsgGroupState(moveit_msgs::RobotState &state, const std::string &group, const std::vector< double > &positions) const
Set the group state of a MoveIt RobotState message.
bool dumpToScene(const std::string &filename) const
Dumps the current scratch configuration of the robot to a YAML file compatible with a scene.
bool setFromIK(const IKQuery &query)
Sets a group of the scratch state from an IK query. If the IK query fails the scratch state retains i...
bool loadYAMLFile(const std::string &name, const std::string &file)
Loads a YAML file into the robot's namespace under name.
void setSRDFPostProcessAddPlanarJoint(const std::string &name)
Adds a planar virtual joint through the SRDF to the loaded robot with name name. This joint will have...
bool loadKinematics(const std::string &group, bool load_subgroups=true)
Loads the kinematics plugin for a joint group and its subgroups. No kinematics are loaded by default.
const std::string & getName() const
Get the robot's name.
static const std::string ROBOT_DESCRIPTION
Default robot description name.
const robot_model::RobotStatePtr & getScratchStateConst() const
Get a const reference to the scratch robot state.
static const std::string ROBOT_SEMANTIC
Default robot semantic description suffix.
const std::string & getSRDFString() const
Get the raw SRDF Model as a string.
moveit_msgs::RobotState getStateMsg() const
Get the current scratch state as a message.
robot_model::RobotModelPtr & getModel()
Get a reference to the loaded robot model.
std::map< std::string, robot_model::SolverAllocatorFn > imap_
Kinematic solver allocator map.
const std::string & getModelName() const
Get the robot's model name.
robot_state::RobotStatePtr scratch_
Scratch robot state.
void setState(const std::vector< double > &positions)
Sets the scratch state from a vector of joint positions (all must be specified)
std::shared_ptr< robot_model_loader::RobotModelLoader > loader_
Robot model loader.
robot_model::RobotModelPtr model_
Loaded robot model.
bool hasJoint(const std::string &joint) const
Checks if a joint exists in the robot.
const robot_model::RobotModelPtr & getModelConst() const
Get a const reference to the loaded robot model.
robot_model::RobotStatePtr allocState() const
Allocate a new robot state.
static const std::string ROBOT_PLANNING
Default robot planning description suffix.
const std::string & getURDFString() const
Get the raw URDF Model as a string.
void setStateFromYAMLFile(const std::string &file)
Sets the scratch state from a robot state message saved to a YAML file.
bool initializeKinematics(const std::string &kinematics_file)
Initialize a robot with a kinematics description.
bool dumpPathTransforms(const robot_trajectory::RobotTrajectory &path, const std::string &filename, double fps=30, double threshold=0.0) const
Dumps the tranforms of all links of a robot through a robot trajectory to a file.
bool loadSRDFFile(const std::string &srdf_file)
Loads the SRDF file.
A const shared pointer wrapper for robowflex::Scene.
A shared pointer wrapper for robowflex::Scene.
T emplace_back(T... args)
T empty(T... args)
T end(T... args)
T find(T... args)
T insert(T... args)
T isfinite(T... args)
#define RBX_WARN(fmt,...)
Output a warning logging message.
Definition: log.h:110
#define RBX_ERROR(fmt,...)
Output a error logging message.
Definition: log.h:102
#define RBX_INFO(fmt,...)
Output a info logging message.
Definition: log.h:118
#define ROBOWFLEX_YAML_FLOW(n)
Definition: macros.h:54
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::RobotState &robot_state, bool copy_attached_bodies=true)
boost::function< bool(RobotState *robot_state, const JointModelGroup *joint_group, const double *joint_group_variable_values)> GroupStateValidityCallbackFn
Functions for constructing shapes in Blender.
Functions for loading and animating robots in Blender.
bool YAMLToFile(const YAML::Node &node, const std::string &file)
Write the contents of a YAML node out to a potentially new file.
bool isNode(const YAML::Node &node)
Checks if a key exists within a YAML node.
Definition: yaml.cpp:1847
bool fromYAMLFile(moveit_msgs::PlanningScene &msg, const std::string &file)
Loads a planning scene from a YAML file.
Definition: yaml.cpp:1914
std::pair< bool, YAML::Node > loadFileToYAML(const std::string &path)
Loads a file to a YAML node.
moveit_msgs::RobotState robotStateFromNode(const YAML::Node &node)
Converts a robot state YAML to a robot_state message.
Definition: yaml.cpp:1869
std::string resolvePath(const std::string &path)
Resolves package:// URLs and relative file paths to their canonical form.
geometry_msgs::Pose poseFromNode(const YAML::Node &node)
Converts a pose YAML to a goemetry message.
Definition: yaml.cpp:1881
std::string loadXMLToString(const std::string &path)
Loads an XML or .xacro file to a string.
YAML::Node toNode(const geometry_msgs::Pose &msg)
Converts a pose message to YAML.
Definition: yaml.cpp:1874
moveit_msgs::OrientationConstraint getOrientationConstraint(const std::string &ee_name, const std::string &base_name, const Eigen::Quaterniond &orientation, const Eigen::Vector3d &tolerances)
Get an orientation constraint message.
Definition: tf.cpp:189
Eigen::Vector3d vectorMsgToEigen(const geometry_msgs::Vector3 &msg)
Converts a vector message to an Eigen::Vector3d.
Definition: tf.cpp:94
RobotPose poseMsgToEigen(const geometry_msgs::Pose &msg)
Converts a pose message to RobotPose.
Definition: tf.cpp:114
RobotPose createPoseQ(double x, double y, double z, double W, double X, double Y, double Z)
Creates a robot pose from a linear component and a Quaternion.
Definition: tf.cpp:47
RobotPose createPoseXYZ(double x, double y, double z)
Creates a robot pose from a linear component and zero orientation.
Definition: tf.cpp:14
Eigen::Quaterniond sampleOrientation(const Eigen::Quaterniond &orientation, const Eigen::Vector3d &tolerances)
Sample an orientation from a given orientation with XYZ Euler angle tolerances.
Definition: tf.cpp:207
geometry_msgs::Pose poseEigenToMsg(const RobotPose &pose)
Converts an RobotPose to a pose message.
Definition: tf.cpp:120
Eigen::Quaterniond quaternionMsgToEigen(const geometry_msgs::Quaternion &msg)
Converts a quaternion message to Eigen::Quaterniond.
Definition: tf.cpp:135
RobotPose identity()
Creates the Identity pose.
Definition: tf.cpp:9
moveit_msgs::PositionConstraint getPositionConstraint(const std::string &ee_name, const std::string &base_name, const RobotPose &pose, const GeometryConstPtr &geometry)
Get a position constraint message.
Definition: tf.cpp:169
bool isVecZero(const Eigen::Ref< const Eigen::VectorXd > &v, double tolerance=constants::eps)
Checks if a vector is close to zero.
Definition: tf.cpp:321
static const double inf
Definition: constants.h:17
std::shared_ptr< dart::dynamics::SphereShape > makeSphere(double radius)
Create a sphere.
Definition: structure.cpp:385
std::string format(const std::string &fmt, Args &&... args)
Recursion base case, return string form of formatted arguments.
Definition: log.h:60
Main namespace. Contains all library classes and functions.
Definition: scene.cpp:25
std::decay< decltype(std::declval< moveit::core::Transforms >().getTransform("")) >::type RobotPose
A pose (point in SE(3)) used in various functions. Defined from what MoveIt! uses.
Definition: adapter.h:24
Functions for loading and animating scenes in Blender.
T push_back(T... args)
T reset(T... args)
T resize(T... args)
const std::vector< std::string > tips
T size(T... args)
Robot IK Query options. IK queries in Robowflex consist of: a) A position specified by some geometric...
void addRequest(const std::string &tip, const GeometryConstPtr &region, const RobotPose &pose, const Eigen::Quaterniond &orientation, const Eigen::Vector3d &tolerance=constants::ik_vec_tolerance)
Add a request for a tip.
kinematics::KinematicsQueryOptions options
Other query options.
void addCenteringMetric(double weight=1.)
Add a metric to the query to evaluate how "centered" the joints of the robot are (from their 0 positi...
std::string group
Target joint group to do IK for.
bool verbose
Verbose output of collision checking.
void addClearanceMetric(double weight=1.)
Add a metric to the query to evaluate clearance from provided scene.
EigenSTL::vector_Vector3d tolerances
XYZ Euler orientation tolerances.
bool sampleRegion(RobotPose &pose, std::size_t index) const
Sample desired end-effector pose for region at index.
kinematic_constraints::KinematicConstraintSetPtr getAsConstraints(const Robot &robot) const
Get this IK query as a kinematic constraint set.
bool sampleRegions(RobotPoseVector &poses) const
Sample desired end-effector pose for each region.
double getMetricValue(const robot_state::RobotState &state, const kinematic_constraints::ConstraintEvaluationResult &result) const
Get the value of the metrics assigned to this query for a given state and result.
void setScene(const ScenePtr &scene, bool verbose=false)
Set a scene to use for collision checking for this IK request.
std::vector< Eigen::Quaterniond > orientations
Target orientations.
SceneConstPtr scene
If provided, use this scene for collision checking.
void addMetric(const Metric &metric_function)
Add a metric to this IK query.
std::size_t attempts
IK attempts (samples within regions).
void addDistanceMetric(double weight=1.)
Add a metric to the query to evaluate distance to constraint.
std::vector< std::string > tips
List of end-effectors.
IKQuery(const std::string &group)
Constructor. Empty for fine control.
std::vector< GeometryConstPtr > regions
Regions to sample target positions from.
void getMessage(const std::string &base_frame, moveit_msgs::Constraints &msg) const
Get this IK query as a constraint message.
robot_trajectory::RobotTrajectory trajectory(rmodel,"right_arm")