robot_model.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, Ioan A. Sucan
5  * Copyright (c) 2013, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the Willow Garage nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 /* Author: Ioan Sucan */
37 
40 #include <boost/math/constants/constants.hpp>
42 #include <algorithm>
43 #include <limits>
44 #include <cmath>
45 #include <memory>
46 #include "order_robot_model_items.inc"
47 
48 namespace moveit
49 {
50 namespace core
51 {
52 namespace
53 {
54 constexpr char LOGNAME[] = "robot_model";
55 } // namespace
56 
57 RobotModel::RobotModel(const urdf::ModelInterfaceSharedPtr& urdf_model, const srdf::ModelConstSharedPtr& srdf_model)
58 {
59  root_joint_ = nullptr;
60  urdf_ = urdf_model;
61  srdf_ = srdf_model;
62  buildModel(*urdf_model, *srdf_model);
63 }
64 
66 {
67  for (std::pair<const std::string, JointModelGroup*>& it : joint_model_group_map_)
68  delete it.second;
69  for (JointModel* joint_model : joint_model_vector_)
70  delete joint_model;
71  for (LinkModel* link_model : link_model_vector_)
72  delete link_model;
73 }
74 
75 const JointModel* RobotModel::getRootJoint() const
76 {
77  return root_joint_;
78 }
79 
80 const LinkModel* RobotModel::getRootLink() const
81 {
82  return root_link_;
83 }
84 
85 void RobotModel::buildModel(const urdf::ModelInterface& urdf_model, const srdf::Model& srdf_model)
86 {
88  moveit::tools::Profiler::ScopedBlock prof_block("RobotModel::buildModel");
89 
90  root_joint_ = nullptr;
91  root_link_ = nullptr;
93  variable_count_ = 0;
94  model_name_ = urdf_model.getName();
95  ROS_INFO_NAMED(LOGNAME, "Loading robot model '%s'...", model_name_.c_str());
96 
97  if (urdf_model.getRoot())
98  {
99  const urdf::Link* root_link_ptr = urdf_model.getRoot().get();
100  model_frame_ = root_link_ptr->name;
101 
102  ROS_DEBUG_NAMED(LOGNAME, "... building kinematic chain");
103  root_joint_ = buildRecursive(nullptr, root_link_ptr, srdf_model);
104  if (root_joint_)
106  ROS_DEBUG_NAMED(LOGNAME, "... building mimic joints");
107  buildMimic(urdf_model);
108 
109  ROS_DEBUG_NAMED(LOGNAME, "... computing joint indexing");
110  buildJointInfo();
111 
113  ROS_WARN_NAMED(LOGNAME, "No geometry is associated to any robot links");
114 
115  // build groups
116 
117  ROS_DEBUG_NAMED(LOGNAME, "... constructing joint groups");
118  buildGroups(srdf_model);
119 
120  ROS_DEBUG_NAMED(LOGNAME, "... constructing joint group states");
121  buildGroupStates(srdf_model);
122 
123  // For debugging entire model
124  // printModelInfo(std::cout);
125  }
126  else
127  ROS_WARN_NAMED(LOGNAME, "No root link found");
128 }
129 
130 namespace
131 {
132 typedef std::map<const JointModel*, std::pair<std::set<const LinkModel*, OrderLinksByIndex>,
133  std::set<const JointModel*, OrderJointsByIndex>>>
134  DescMap;
135 
136 void computeDescendantsHelper(const JointModel* joint, std::vector<const JointModel*>& parents,
137  std::set<const JointModel*>& seen, DescMap& descendants)
138 {
139  if (!joint)
140  return;
141  if (seen.find(joint) != seen.end())
142  return;
143  seen.insert(joint);
144 
145  for (const JointModel* parent : parents)
146  descendants[parent].second.insert(joint);
147 
148  const LinkModel* lm = joint->getChildLinkModel();
149  if (!lm)
150  return;
151 
152  for (const JointModel* parent : parents)
153  descendants[parent].first.insert(lm);
154  descendants[joint].first.insert(lm);
155 
156  parents.push_back(joint);
157  const std::vector<const JointModel*>& ch = lm->getChildJointModels();
158  for (const JointModel* child_joint_model : ch)
159  computeDescendantsHelper(child_joint_model, parents, seen, descendants);
160  const std::vector<const JointModel*>& mim = joint->getMimicRequests();
161  for (const JointModel* mimic_joint_model : mim)
162  computeDescendantsHelper(mimic_joint_model, parents, seen, descendants);
163  parents.pop_back();
164 }
165 
166 void computeCommonRootsHelper(const JointModel* joint, std::vector<int>& common_roots, int size)
167 {
168  if (!joint)
169  return;
170  const LinkModel* lm = joint->getChildLinkModel();
171  if (!lm)
172  return;
173 
174  const std::vector<const JointModel*>& ch = lm->getChildJointModels();
175  for (std::size_t i = 0; i < ch.size(); ++i)
176  {
177  const std::vector<const JointModel*>& a = ch[i]->getDescendantJointModels();
178  for (std::size_t j = i + 1; j < ch.size(); ++j)
179  {
180  const std::vector<const JointModel*>& b = ch[j]->getDescendantJointModels();
181  for (const JointModel* m : b)
182  common_roots[ch[i]->getJointIndex() * size + m->getJointIndex()] =
183  common_roots[ch[i]->getJointIndex() + m->getJointIndex() * size] = joint->getJointIndex();
184  for (const JointModel* k : a)
185  {
186  common_roots[k->getJointIndex() * size + ch[j]->getJointIndex()] =
187  common_roots[k->getJointIndex() + ch[j]->getJointIndex() * size] = joint->getJointIndex();
188  for (const JointModel* m : b)
189  common_roots[k->getJointIndex() * size + m->getJointIndex()] =
190  common_roots[k->getJointIndex() + m->getJointIndex() * size] = joint->getJointIndex();
191  }
192  }
193  computeCommonRootsHelper(ch[i], common_roots, size);
194  }
195 }
196 } // namespace
197 
199 {
200  // compute common roots for all pairs of joints;
201  // there are 3 cases of pairs (X, Y):
202  // X != Y && X and Y are not descendants of one another
203  // X == Y
204  // X != Y && X and Y are descendants of one another
205 
206  // by default, the common root is always the global root;
208 
209  // look at all descendants recursively; for two sibling nodes A, B, both children of X, all the pairs of respective
210  // descendants of A and B
211  // have X as the common root.
212  computeCommonRootsHelper(root_joint_, common_joint_roots_, joint_model_vector_.size());
213 
214  for (const JointModel* joint_model : joint_model_vector_)
215  {
216  // the common root of a joint and itself is the same joint:
217  common_joint_roots_[joint_model->getJointIndex() * (1 + joint_model_vector_.size())] = joint_model->getJointIndex();
218 
219  // a node N and one of its descendants have as common root the node N itself:
220  const std::vector<const JointModel*>& d = joint_model->getDescendantJointModels();
221  for (const JointModel* descendant_joint_model : d)
222  common_joint_roots_[descendant_joint_model->getJointIndex() * joint_model_vector_.size() +
223  joint_model->getJointIndex()] =
224  common_joint_roots_[descendant_joint_model->getJointIndex() +
225  joint_model->getJointIndex() * joint_model_vector_.size()] = joint_model->getJointIndex();
226  }
227 }
228 
230 {
231  // compute the list of descendants for all joints
232  std::vector<const JointModel*> parents;
233  std::set<const JointModel*> seen;
234 
235  DescMap descendants;
236  computeDescendantsHelper(root_joint_, parents, seen, descendants);
237  for (std::pair<const JointModel* const, std::pair<std::set<const LinkModel*, OrderLinksByIndex>,
238  std::set<const JointModel*, OrderJointsByIndex>>>& descendant :
239  descendants)
240  {
241  JointModel* jm = const_cast<JointModel*>(descendant.first);
242  for (const JointModel* jt : descendant.second.second)
243  jm->addDescendantJointModel(jt);
244  for (const LinkModel* jt : descendant.second.first)
245  jm->addDescendantLinkModel(jt);
246  }
247 }
248 
250 {
252  moveit::tools::Profiler::ScopedBlock prof_block("RobotModel::buildJointInfo");
253 
254  // construct additional maps for easy access by name
255  variable_count_ = 0;
257  variable_names_.reserve(joint_model_vector_.size());
259 
260  for (std::size_t i = 0; i < joint_model_vector_.size(); ++i)
261  {
262  joint_model_vector_[i]->setJointIndex(i);
263  const std::vector<std::string>& name_order = joint_model_vector_[i]->getVariableNames();
264 
265  // compute index map
266  if (!name_order.empty())
267  {
268  for (std::size_t j = 0; j < name_order.size(); ++j)
269  {
270  joint_variables_index_map_[name_order[j]] = variable_count_ + j;
271  variable_names_.push_back(name_order[j]);
273  }
274  if (joint_model_vector_[i]->getMimic() == nullptr)
275  {
281  }
282 
283  if (joint_model_vector_[i]->getType() == JointModel::REVOLUTE &&
284  static_cast<const RevoluteJointModel*>(joint_model_vector_[i])->isContinuous())
286 
287  joint_model_vector_[i]->setFirstVariableIndex(variable_count_);
289 
290  // compute variable count
291  std::size_t vc = joint_model_vector_[i]->getVariableCount();
292  variable_count_ += vc;
293  if (vc == 1)
295  else
297  }
298  }
299 
300  std::vector<bool> link_considered(link_model_vector_.size(), false);
301  for (const LinkModel* link : link_model_vector_)
302  {
303  if (link_considered[link->getLinkIndex()])
304  continue;
305 
306  LinkTransformMap associated_transforms;
307  computeFixedTransforms(link, link->getJointOriginTransform().inverse(), associated_transforms);
308  for (auto& tf_base : associated_transforms)
309  {
310  link_considered[tf_base.first->getLinkIndex()] = true;
311  for (auto& tf_target : associated_transforms)
312  {
313  if (&tf_base != &tf_target)
314  const_cast<LinkModel*>(tf_base.first) // regain write access to base LinkModel*
315  ->addAssociatedFixedTransform(tf_target.first, tf_base.second.inverse() * tf_target.second);
316  }
317  }
318  }
319 
321  computeCommonRoots(); // must be called _after_ list of descendants was computed
322 }
323 
324 void RobotModel::buildGroupStates(const srdf::Model& srdf_model)
325 {
326  // copy the default states to the groups
327  const std::vector<srdf::Model::GroupState>& ds = srdf_model.getGroupStates();
328  for (const srdf::Model::GroupState& group_state : ds)
329  {
330  if (hasJointModelGroup(group_state.group_))
331  {
332  JointModelGroup* jmg = getJointModelGroup(group_state.group_);
333  std::vector<const JointModel*> remaining_joints = jmg->getActiveJointModels();
334  std::map<std::string, double> state;
335  for (std::map<std::string, std::vector<double>>::const_iterator jt = group_state.joint_values_.begin();
336  jt != group_state.joint_values_.end(); ++jt)
337  {
338  if (jmg->hasJointModel(jt->first))
339  {
340  const JointModel* jm = jmg->getJointModel(jt->first);
341  const std::vector<std::string>& vn = jm->getVariableNames();
342  // Remove current joint name from remaining list.
343  auto it_found = std::find(remaining_joints.begin(), remaining_joints.end(), jm);
344  if (it_found != remaining_joints.end())
345  remaining_joints.erase(it_found);
346  if (vn.size() == jt->second.size())
347  for (std::size_t j = 0; j < vn.size(); ++j)
348  state[vn[j]] = jt->second[j];
349  else
351  "The model for joint '%s' requires %d variable values, "
352  "but only %d variable values were supplied in default state '%s' for group '%s'",
353  jt->first.c_str(), (int)vn.size(), (int)jt->second.size(), group_state.name_.c_str(),
354  jmg->getName().c_str());
355  }
356  else
358  "Group state '%s' specifies value for joint '%s', "
359  "but that joint is not part of group '%s'",
360  group_state.name_.c_str(), jt->first.c_str(), jmg->getName().c_str());
361  }
362  if (!remaining_joints.empty())
363  {
364  std::stringstream missing;
365  missing << (*remaining_joints.begin())->getName();
366  for (auto j = ++remaining_joints.begin(); j != remaining_joints.end(); j++)
367  {
368  missing << ", " << (*j)->getName();
369  }
370  ROS_WARN_STREAM_NAMED(LOGNAME, "Group state '" << group_state.name_
371  << "' doesn't specify all group joints in group '"
372  << group_state.group_ << "'. " << missing.str() << " "
373  << (remaining_joints.size() > 1 ? "are" : "is") << " missing.");
374  }
375  if (!state.empty())
376  jmg->addDefaultState(group_state.name_, state);
377  }
378  else
379  ROS_ERROR_NAMED(LOGNAME, "Group state '%s' specified for group '%s', but that group does not exist",
380  group_state.name_.c_str(), group_state.group_.c_str());
381  }
382 }
383 
384 void RobotModel::buildMimic(const urdf::ModelInterface& urdf_model)
385 {
386  // compute mimic joints
387  for (JointModel* joint_model : joint_model_vector_)
388  {
389  const urdf::Joint* jm = urdf_model.getJoint(joint_model->getName()).get();
390  if (jm)
391  if (jm->mimic)
392  {
393  JointModelMap::const_iterator jit = joint_model_map_.find(jm->mimic->joint_name);
394  if (jit != joint_model_map_.end())
395  {
396  if (joint_model->getVariableCount() == jit->second->getVariableCount())
397  joint_model->setMimic(jit->second, jm->mimic->multiplier, jm->mimic->offset);
398  else
399  ROS_ERROR_NAMED(LOGNAME, "Join '%s' cannot mimic joint '%s' because they have different number of DOF",
400  joint_model->getName().c_str(), jm->mimic->joint_name.c_str());
401  }
402  else
403  ROS_ERROR_NAMED(LOGNAME, "Joint '%s' cannot mimic unknown joint '%s'", joint_model->getName().c_str(),
404  jm->mimic->joint_name.c_str());
405  }
406  }
407 
408  // in case we have a joint that mimics a joint that already mimics another joint, we can simplify things:
409  bool change = true;
410  while (change)
411  {
412  change = false;
413  for (JointModel* joint_model : joint_model_vector_)
414  if (joint_model->getMimic())
415  {
416  if (joint_model->getMimic()->getMimic())
417  {
418  joint_model->setMimic(joint_model->getMimic()->getMimic(),
419  joint_model->getMimicFactor() * joint_model->getMimic()->getMimicFactor(),
420  joint_model->getMimicOffset() +
421  joint_model->getMimicFactor() * joint_model->getMimic()->getMimicOffset());
422  change = true;
423  }
424  if (joint_model == joint_model->getMimic())
425  {
426  ROS_ERROR_NAMED(LOGNAME, "Cycle found in joint that mimic each other. Ignoring all mimic joints.");
427  for (JointModel* joint_model_recal : joint_model_vector_)
428  joint_model_recal->setMimic(nullptr, 0.0, 0.0);
429  change = false;
430  break;
431  }
432  }
433  }
434  // build mimic requests
435  for (JointModel* joint_model : joint_model_vector_)
436  if (joint_model->getMimic())
437  {
438  const_cast<JointModel*>(joint_model->getMimic())->addMimicRequest(joint_model);
439  mimic_joints_.push_back(joint_model);
440  }
441 }
442 
443 bool RobotModel::hasEndEffector(const std::string& eef) const
444 {
445  return end_effectors_map_.find(eef) != end_effectors_map_.end();
446 }
447 
448 const JointModelGroup* RobotModel::getEndEffector(const std::string& name) const
449 {
450  JointModelGroupMap::const_iterator it = end_effectors_map_.find(name);
451  if (it == end_effectors_map_.end())
452  {
453  it = joint_model_group_map_.find(name);
454  if (it != joint_model_group_map_.end() && it->second->isEndEffector())
455  return it->second;
456  ROS_ERROR_NAMED(LOGNAME, "End-effector '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
457  return nullptr;
458  }
459  return it->second;
460 }
461 
462 JointModelGroup* RobotModel::getEndEffector(const std::string& name)
463 {
464  JointModelGroupMap::const_iterator it = end_effectors_map_.find(name);
465  if (it == end_effectors_map_.end())
466  {
467  it = joint_model_group_map_.find(name);
468  if (it != joint_model_group_map_.end() && it->second->isEndEffector())
469  return it->second;
470  ROS_ERROR_NAMED(LOGNAME, "End-effector '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
471  return nullptr;
472  }
473  return it->second;
474 }
475 
476 bool RobotModel::hasJointModelGroup(const std::string& name) const
477 {
478  return joint_model_group_map_.find(name) != joint_model_group_map_.end();
479 }
480 
481 const JointModelGroup* RobotModel::getJointModelGroup(const std::string& name) const
482 {
483  JointModelGroupMap::const_iterator it = joint_model_group_map_.find(name);
484  if (it == joint_model_group_map_.end())
485  {
486  ROS_ERROR_NAMED(LOGNAME, "Group '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
487  return nullptr;
488  }
489  return it->second;
490 }
491 
492 JointModelGroup* RobotModel::getJointModelGroup(const std::string& name)
493 {
494  JointModelGroupMap::const_iterator it = joint_model_group_map_.find(name);
495  if (it == joint_model_group_map_.end())
496  {
497  ROS_ERROR_NAMED(LOGNAME, "Group '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
498  return nullptr;
499  }
500  return it->second;
501 }
502 
503 void RobotModel::buildGroups(const srdf::Model& srdf_model)
504 {
505  const std::vector<srdf::Model::Group>& group_configs = srdf_model.getGroups();
506 
507  // the only thing tricky is dealing with subgroups
508  std::vector<bool> processed(group_configs.size(), false);
509 
510  bool added = true;
511  while (added)
512  {
513  added = false;
514 
515  // going to make passes until we can't do anything else
516  for (std::size_t i = 0; i < group_configs.size(); ++i)
517  if (!processed[i])
518  {
519  // if we haven't processed, check and see if the dependencies are met yet
520  bool all_subgroups_added = true;
521  for (const std::string& subgroup : group_configs[i].subgroups_)
522  if (joint_model_group_map_.find(subgroup) == joint_model_group_map_.end())
523  {
524  all_subgroups_added = false;
525  break;
526  }
527  if (all_subgroups_added)
528  {
529  added = true;
530  processed[i] = true;
531  if (!addJointModelGroup(group_configs[i]))
532  ROS_WARN_NAMED(LOGNAME, "Failed to add group '%s'", group_configs[i].name_.c_str());
533  }
534  }
535  }
536 
537  for (std::size_t i = 0; i < processed.size(); ++i)
538  if (!processed[i])
539  ROS_WARN_NAMED(LOGNAME, "Could not process group '%s' due to unmet subgroup dependencies",
540  group_configs[i].name_.c_str());
541 
542  for (JointModelGroupMap::const_iterator it = joint_model_group_map_.begin(); it != joint_model_group_map_.end(); ++it)
543  joint_model_groups_.push_back(it->second);
544  std::sort(joint_model_groups_.begin(), joint_model_groups_.end(), OrderGroupsByName());
545  for (JointModelGroup* joint_model_group : joint_model_groups_)
546  {
547  joint_model_groups_const_.push_back(joint_model_group);
548  joint_model_group_names_.push_back(joint_model_group->getName());
549  }
550 
552  buildGroupsInfoEndEffectors(srdf_model);
553 }
554 
556 {
557  // compute subgroups
558  for (JointModelGroupMap::const_iterator it = joint_model_group_map_.begin(); it != joint_model_group_map_.end(); ++it)
559  {
560  JointModelGroup* jmg = it->second;
561  std::vector<std::string> subgroup_names;
562  std::set<const JointModel*> joints(jmg->getJointModels().begin(), jmg->getJointModels().end());
563  for (JointModelGroupMap::const_iterator jt = joint_model_group_map_.begin(); jt != joint_model_group_map_.end();
564  ++jt)
565  if (jt->first != it->first)
566  {
567  bool ok = true;
568  JointModelGroup* sub_jmg = jt->second;
569  const std::vector<const JointModel*>& sub_joints = sub_jmg->getJointModels();
570  for (const JointModel* sub_joint : sub_joints)
571  if (joints.find(sub_joint) == joints.end())
572  {
573  ok = false;
574  break;
575  }
576  if (ok)
577  subgroup_names.push_back(sub_jmg->getName());
578  }
579  if (!subgroup_names.empty())
580  jmg->setSubgroupNames(subgroup_names);
581  }
582 }
583 
585 {
586  // set the end-effector flags
587  const std::vector<srdf::Model::EndEffector>& eefs = srdf_model.getEndEffectors();
588  for (JointModelGroupMap::const_iterator it = joint_model_group_map_.begin(); it != joint_model_group_map_.end(); ++it)
589  {
590  // check if this group is a known end effector
591  for (const srdf::Model::EndEffector& eef : eefs)
592  if (eef.component_group_ == it->first)
593  {
594  // if it is, mark it as such
595  it->second->setEndEffectorName(eef.name_);
596  end_effectors_map_[eef.name_] = it->second;
597  end_effectors_.push_back(it->second);
598 
599  // check to see if there are groups that contain the parent link of this end effector.
600  // record this information if found;
601  std::vector<JointModelGroup*> possible_parent_groups;
602  for (JointModelGroupMap::const_iterator jt = joint_model_group_map_.begin(); jt != joint_model_group_map_.end();
603  ++jt)
604  if (jt->first != it->first)
605  {
606  if (jt->second->hasLinkModel(eef.parent_link_))
607  {
608  jt->second->attachEndEffector(eef.name_);
609  possible_parent_groups.push_back(jt->second);
610  }
611  }
612 
613  JointModelGroup* eef_parent_group = nullptr;
614  // if a parent group is specified in SRDF, try to use it
615  if (!eef.parent_group_.empty())
616  {
617  JointModelGroupMap::const_iterator jt = joint_model_group_map_.find(eef.parent_group_);
618  if (jt != joint_model_group_map_.end())
619  {
620  if (jt->second->hasLinkModel(eef.parent_link_))
621  {
622  if (jt->second != it->second)
623  eef_parent_group = jt->second;
624  else
625  ROS_ERROR_NAMED(LOGNAME, "Group '%s' for end-effector '%s' cannot be its own parent",
626  eef.parent_group_.c_str(), eef.name_.c_str());
627  }
628  else
630  "Group '%s' was specified as parent group for end-effector '%s' "
631  "but it does not include the parent link '%s'",
632  eef.parent_group_.c_str(), eef.name_.c_str(), eef.parent_link_.c_str());
633  }
634  else
635  ROS_ERROR_NAMED(LOGNAME, "Group name '%s' not found (specified as parent group for end-effector '%s')",
636  eef.parent_group_.c_str(), eef.name_.c_str());
637  }
638 
639  // if no parent group was specified, use a default one
640  if (eef_parent_group == nullptr)
641  if (!possible_parent_groups.empty())
642  {
643  // if there are multiple options for the group that contains this end-effector,
644  // we pick the group with fewest joints.
645  std::size_t best = 0;
646  for (std::size_t g = 1; g < possible_parent_groups.size(); ++g)
647  if (possible_parent_groups[g]->getJointModels().size() <
648  possible_parent_groups[best]->getJointModels().size())
649  best = g;
650  eef_parent_group = possible_parent_groups[best];
651  }
652 
653  if (eef_parent_group)
654  {
655  it->second->setEndEffectorParent(eef_parent_group->getName(), eef.parent_link_);
656  }
657  else
658  {
659  ROS_WARN_NAMED(LOGNAME, "Could not identify parent group for end-effector '%s'", eef.name_.c_str());
660  it->second->setEndEffectorParent("", eef.parent_link_);
661  }
662  }
663  }
664  std::sort(end_effectors_.begin(), end_effectors_.end(), OrderGroupsByName());
665 }
666 
668 {
670  {
671  ROS_WARN_NAMED(LOGNAME, "A group named '%s' already exists. Not adding.", gc.name_.c_str());
672  return false;
673  }
674 
675  std::set<const JointModel*> jset;
676 
677  // add joints from chains
678  for (const std::pair<std::string, std::string>& chain : gc.chains_)
679  {
680  const LinkModel* base_link = getLinkModel(chain.first);
681  const LinkModel* tip_link = getLinkModel(chain.second);
682  if (base_link && tip_link)
683  {
684  // go from tip, up the chain, until we hit the root or we find the base_link
685  const LinkModel* lm = tip_link;
686  std::vector<const JointModel*> cj;
687  while (lm)
688  {
689  if (lm == base_link)
690  break;
691  cj.push_back(lm->getParentJointModel());
693  }
694  // if we did not find the base_link, we could have a chain like e.g.,
695  // from one end-effector to another end-effector, so the root is in between
696  if (lm != base_link)
697  {
698  // we go up the chain from the base this time, and see where we intersect the other chain
699  lm = base_link;
700  std::size_t index = 0;
701  std::vector<const JointModel*> cj2;
702  while (lm)
703  {
704  for (std::size_t j = 0; j < cj.size(); ++j)
705  if (cj[j] == lm->getParentJointModel())
706  {
707  index = j + 1;
708  break;
709  }
710  if (index > 0)
711  break;
712  cj2.push_back(lm->getParentJointModel());
713  lm = lm->getParentJointModel()->getParentLinkModel();
714  }
715  if (index > 0)
716  {
717  jset.insert(cj.begin(), cj.begin() + index);
718  jset.insert(cj2.begin(), cj2.end());
719  }
720  }
721  else
722  // if we have a simple chain, just add the joints
723  jset.insert(cj.begin(), cj.end());
724  }
725  }
726 
727  // add joints
728  for (const std::string& joint : gc.joints_)
729  {
730  const JointModel* j = getJointModel(joint);
731  if (j)
732  jset.insert(j);
733  }
734 
735  // add joints that are parents of included links
736  for (const std::string& link : gc.links_)
737  {
738  const LinkModel* l = getLinkModel(link);
739  if (l)
740  jset.insert(l->getParentJointModel());
741  }
742 
743  // add joints from subgroups
744  for (const std::string& subgroup : gc.subgroups_)
745  {
746  const JointModelGroup* sg = getJointModelGroup(subgroup);
747  if (sg)
748  {
749  // active joints
750  const std::vector<const JointModel*>& js = sg->getJointModels();
751  for (const JointModel* j : js)
752  jset.insert(j);
753 
754  // fixed joints
755  const std::vector<const JointModel*>& fs = sg->getFixedJointModels();
756  for (const JointModel* f : fs)
757  jset.insert(f);
758 
759  // mimic joints
760  const std::vector<const JointModel*>& ms = sg->getMimicJointModels();
761  for (const JointModel* m : ms)
762  jset.insert(m);
763  }
764  }
765 
766  if (jset.empty())
767  {
768  ROS_WARN_NAMED(LOGNAME, "Group '%s' must have at least one valid joint", gc.name_.c_str());
769  return false;
770  }
771 
772  std::vector<const JointModel*> joints;
773  joints.reserve(jset.size());
774  for (const JointModel* it : jset)
775  joints.push_back(it);
776 
777  JointModelGroup* jmg = new JointModelGroup(gc.name_, gc, joints, this);
778  joint_model_group_map_[gc.name_] = jmg;
779 
780  return true;
781 }
782 
783 JointModel* RobotModel::buildRecursive(LinkModel* parent, const urdf::Link* urdf_link, const srdf::Model& srdf_model)
784 {
785  // construct the joint
786  JointModel* joint = urdf_link->parent_joint ?
787  constructJointModel(urdf_link->parent_joint.get(), urdf_link, srdf_model) :
788  constructJointModel(nullptr, urdf_link, srdf_model);
789  if (joint == nullptr)
790  return nullptr;
791 
792  // bookkeeping for the joint
793  joint_model_map_[joint->getName()] = joint;
794  joint->setJointIndex(joint_model_vector_.size());
795  joint_model_vector_.push_back(joint);
796  joint_model_vector_const_.push_back(joint);
797  joint_model_names_vector_.push_back(joint->getName());
798  joint->setParentLinkModel(parent);
799 
800  // construct the link
801  LinkModel* link = constructLinkModel(urdf_link);
802  joint->setChildLinkModel(link);
803  link->setParentLinkModel(parent);
804 
805  // bookkeeping for the link
806  link_model_map_[joint->getChildLinkModel()->getName()] = link;
807  link->setLinkIndex(link_model_vector_.size());
808  link_model_vector_.push_back(link);
809  link_model_vector_const_.push_back(link);
810  link_model_names_vector_.push_back(link->getName());
811  if (!link->getShapes().empty())
812  {
814  link_model_names_with_collision_geometry_vector_.push_back(link->getName());
815  link->setFirstCollisionBodyTransformIndex(link_geometry_count_);
816  link_geometry_count_ += link->getShapes().size();
817  }
818  link->setParentJointModel(joint);
819 
820  // recursively build child links (and joints)
821  for (unsigned int i = 0; i < urdf_link->child_links.size(); ++i)
822  {
823  const urdf::LinkSharedPtr& child_link{ urdf_link->child_links[i] };
824  const urdf::JointSharedPtr& child_joint{ urdf_link->child_joints[i] };
825 
826  if (child_link->parent_joint->name != child_joint->name)
827  {
828  ROS_ERROR_STREAM_NAMED(LOGNAME, "Found link '" << child_link->name << "' with multiple parent joints '"
829  << child_link->parent_joint->name << "' and '" << child_joint->name
830  << "'. Ignoring the latter joint because cycles in the kinematic "
831  "structure are not supported.");
832  continue;
833  }
834 
835  JointModel* jm = buildRecursive(link, child_link.get(), srdf_model);
836  if (jm)
837  link->addChildJointModel(jm);
838  }
839  return joint;
840 }
841 
842 namespace
843 {
844 // construct bounds for 1DOF joint
845 static inline VariableBounds jointBoundsFromURDF(const urdf::Joint* urdf_joint)
846 {
847  VariableBounds b;
848  if (urdf_joint->safety)
849  {
850  b.position_bounded_ = true;
851  b.min_position_ = urdf_joint->safety->soft_lower_limit;
852  b.max_position_ = urdf_joint->safety->soft_upper_limit;
853  if (urdf_joint->limits)
854  {
855  if (urdf_joint->limits->lower > b.min_position_)
856  b.min_position_ = urdf_joint->limits->lower;
857  if (urdf_joint->limits->upper < b.max_position_)
858  b.max_position_ = urdf_joint->limits->upper;
859  }
860  }
861  else
862  {
863  if (urdf_joint->limits)
864  {
865  b.position_bounded_ = true;
866  b.min_position_ = urdf_joint->limits->lower;
867  b.max_position_ = urdf_joint->limits->upper;
868  }
869  }
870  if (urdf_joint->limits)
871  {
872  b.max_velocity_ = fabs(urdf_joint->limits->velocity);
873  b.min_velocity_ = -b.max_velocity_;
874  b.velocity_bounded_ = b.max_velocity_ > std::numeric_limits<double>::epsilon();
875  }
876  return b;
877 }
878 } // namespace
879 
880 JointModel* RobotModel::constructJointModel(const urdf::Joint* urdf_joint, const urdf::Link* child_link,
881  const srdf::Model& srdf_model)
882 {
883  JointModel* new_joint_model = nullptr;
884 
885  // if urdf_joint exists, must be the root link transform
886  if (urdf_joint)
887  {
888  switch (urdf_joint->type)
889  {
890  case urdf::Joint::REVOLUTE:
891  {
892  RevoluteJointModel* j = new RevoluteJointModel(urdf_joint->name);
893  j->setVariableBounds(j->getName(), jointBoundsFromURDF(urdf_joint));
894  j->setContinuous(false);
895  j->setAxis(Eigen::Vector3d(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z));
896  new_joint_model = j;
897  }
898  break;
899  case urdf::Joint::CONTINUOUS:
900  {
901  RevoluteJointModel* j = new RevoluteJointModel(urdf_joint->name);
902  j->setVariableBounds(j->getName(), jointBoundsFromURDF(urdf_joint));
903  j->setContinuous(true);
904  j->setAxis(Eigen::Vector3d(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z));
905  new_joint_model = j;
906  }
907  break;
908  case urdf::Joint::PRISMATIC:
909  {
910  PrismaticJointModel* j = new PrismaticJointModel(urdf_joint->name);
911  j->setVariableBounds(j->getName(), jointBoundsFromURDF(urdf_joint));
912  j->setAxis(Eigen::Vector3d(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z));
913  new_joint_model = j;
914  }
915  break;
916  case urdf::Joint::FLOATING:
917  new_joint_model = new FloatingJointModel(urdf_joint->name);
918  break;
919  case urdf::Joint::PLANAR:
920  new_joint_model = new PlanarJointModel(urdf_joint->name);
921  break;
922  case urdf::Joint::FIXED:
923  new_joint_model = new FixedJointModel(urdf_joint->name);
924  break;
925  default:
926  ROS_ERROR_NAMED(LOGNAME, "Unknown joint type: %d", (int)urdf_joint->type);
927  break;
928  }
929  }
930  else // if urdf_joint passed in as null, then we're at root of URDF model
931  {
932  const std::vector<srdf::Model::VirtualJoint>& virtual_joints = srdf_model.getVirtualJoints();
933  for (const srdf::Model::VirtualJoint& virtual_joint : virtual_joints)
934  {
935  if (virtual_joint.child_link_ != child_link->name)
936  {
937  if (child_link->name == "world" && virtual_joint.type_ == "fixed" && child_link->collision_array.empty() &&
938  !child_link->collision && child_link->visual_array.empty() && !child_link->visual)
939  // Gazebo requires a fixed link from a dummy world link to the first robot's link
940  // Skip warning in this case and create a fixed joint with given name
941  new_joint_model = new FixedJointModel(virtual_joint.name_);
942  else
944  "Skipping virtual joint '%s' because its child frame '%s' "
945  "does not match the URDF frame '%s'",
946  virtual_joint.name_.c_str(), virtual_joint.child_link_.c_str(), child_link->name.c_str());
947  }
948  else if (virtual_joint.parent_frame_.empty())
949  {
950  ROS_WARN_NAMED(LOGNAME, "Skipping virtual joint '%s' because its parent frame is empty",
951  virtual_joint.name_.c_str());
952  }
953  else
954  {
955  if (virtual_joint.type_ == "fixed")
956  new_joint_model = new FixedJointModel(virtual_joint.name_);
957  else if (virtual_joint.type_ == "planar")
958  new_joint_model = new PlanarJointModel(virtual_joint.name_);
959  else if (virtual_joint.type_ == "floating")
960  new_joint_model = new FloatingJointModel(virtual_joint.name_);
961  if (new_joint_model)
962  {
963  // for fixed frames we still use the robot root link
964  if (virtual_joint.type_ != "fixed")
965  {
966  model_frame_ = virtual_joint.parent_frame_;
967  }
968  break;
969  }
970  }
971  }
972  if (!new_joint_model)
973  {
974  ROS_INFO_NAMED(LOGNAME, "No root/virtual joint specified in SRDF. Assuming fixed joint");
975  new_joint_model = new FixedJointModel("ASSUMED_FIXED_ROOT_JOINT");
976  }
977  }
978 
979  if (new_joint_model)
980  {
981  new_joint_model->setDistanceFactor(new_joint_model->getStateSpaceDimension());
982  const std::vector<srdf::Model::PassiveJoint>& pjoints = srdf_model.getPassiveJoints();
983  const std::string& joint_name = new_joint_model->getName();
984  for (const srdf::Model::PassiveJoint& pjoint : pjoints)
985  {
986  if (joint_name == pjoint.name_)
987  {
988  new_joint_model->setPassive(true);
989  break;
990  }
991  }
992 
993  // parse a joint property string as a double with error handling
994  // if the property was successfully parsed,
995  // stores the resulting property value in prop_value and returns true
996  // otherwise logs a ROS_ERROR and returns false
997  auto parse_property_double = [&joint_name](auto& prop_name, auto& prop_value_str, double& prop_value) -> bool {
998  try
999  {
1000  prop_value = moveit::core::toDouble(prop_value_str);
1001  return true;
1002  }
1003  catch (const std::runtime_error& e)
1004  {
1005  ROS_ERROR_STREAM_NAMED(LOGNAME, "Unable to parse property " << prop_name << " for joint " << joint_name
1006  << " as double: '" << prop_value_str << "'");
1007  }
1008  return false;
1009  };
1010 
1011  for (const auto& [property_name, property_value_str] : srdf_model.getJointProperties(joint_name))
1012  {
1013  if (property_name == "angular_distance_weight")
1014  {
1015  double angular_distance_weight;
1016  if (parse_property_double(property_name, property_value_str, angular_distance_weight))
1017  {
1018  if (new_joint_model->getType() == JointModel::JointType::PLANAR)
1019  {
1020  ((PlanarJointModel*)new_joint_model)->setAngularDistanceWeight(angular_distance_weight);
1021  }
1022  else if (new_joint_model->getType() == JointModel::JointType::FLOATING)
1023  {
1024  ((FloatingJointModel*)new_joint_model)->setAngularDistanceWeight(angular_distance_weight);
1025  }
1026  else
1027  {
1028  ROS_ERROR_NAMED(LOGNAME, "Cannot apply property %s to joint type: %s", property_name.c_str(),
1029  new_joint_model->getTypeName().c_str());
1030  }
1031  }
1032  }
1033  else if (property_name == "motion_model")
1034  {
1035  if (new_joint_model->getType() != JointModel::JointType::PLANAR)
1036  {
1037  ROS_ERROR_NAMED(LOGNAME, "Cannot apply property %s to joint type: %s", property_name.c_str(),
1038  new_joint_model->getTypeName().c_str());
1039  continue;
1040  }
1041 
1042  PlanarJointModel::MotionModel motion_model;
1043  if (property_value_str == "holonomic")
1044  {
1045  motion_model = PlanarJointModel::MotionModel::HOLONOMIC;
1046  }
1047  else if (property_value_str == "diff_drive")
1048  {
1049  motion_model = PlanarJointModel::MotionModel::DIFF_DRIVE;
1050  }
1051  else
1052  {
1053  ROS_ERROR_STREAM_NAMED(LOGNAME, "Unknown value for property " << property_name << " (" << joint_name << "): '"
1054  << property_value_str << "'");
1055  ROS_ERROR_NAMED(LOGNAME, "Valid values are 'holonomic' and 'diff_drive'");
1056  continue;
1057  }
1058 
1059  ((PlanarJointModel*)new_joint_model)->setMotionModel(motion_model);
1060  }
1061  else if (property_name == "min_translational_distance")
1062  {
1063  if (new_joint_model->getType() != JointModel::JointType::PLANAR)
1064  {
1065  ROS_ERROR_NAMED(LOGNAME, "Cannot apply property %s to joint type: %s", property_name.c_str(),
1066  new_joint_model->getTypeName().c_str());
1067  continue;
1068  }
1069  double min_translational_distance;
1070  if (parse_property_double(property_name, property_value_str, min_translational_distance))
1071  {
1072  ((PlanarJointModel*)new_joint_model)->setMinTranslationalDistance(min_translational_distance);
1073  }
1074  }
1075  else
1076  {
1077  ROS_ERROR_NAMED(LOGNAME, "Unknown joint property: %s", property_name.c_str());
1078  }
1079  }
1080  }
1081 
1082  return new_joint_model;
1083 }
1084 
1085 namespace
1086 {
1087 static inline Eigen::Isometry3d urdfPose2Isometry3d(const urdf::Pose& pose)
1088 {
1089  Eigen::Quaterniond q(pose.rotation.w, pose.rotation.x, pose.rotation.y, pose.rotation.z);
1090  Eigen::Isometry3d af(Eigen::Translation3d(pose.position.x, pose.position.y, pose.position.z) * q);
1091  return af;
1092 }
1093 } // namespace
1094 
1095 LinkModel* RobotModel::constructLinkModel(const urdf::Link* urdf_link)
1096 {
1097  LinkModel* new_link_model = new LinkModel(urdf_link->name);
1098 
1099  const std::vector<urdf::CollisionSharedPtr>& col_array =
1100  urdf_link->collision_array.empty() ? std::vector<urdf::CollisionSharedPtr>(1, urdf_link->collision) :
1101  urdf_link->collision_array;
1102 
1103  std::vector<shapes::ShapeConstPtr> shapes;
1105 
1106  for (const urdf::CollisionSharedPtr& col : col_array)
1107  {
1108  if (col && col->geometry)
1109  {
1110  shapes::ShapeConstPtr s = constructShape(col->geometry.get());
1111  if (s)
1112  {
1113  shapes.push_back(s);
1114  poses.push_back(urdfPose2Isometry3d(col->origin));
1115  }
1116  }
1117  }
1118 
1119  // Should we warn that old (melodic) behaviour has changed, not copying visual to collision geometries anymore?
1120  bool warn_about_missing_collision = false;
1121  if (shapes.empty())
1122  {
1123  const auto& vis_array = urdf_link->visual_array.empty() ? std::vector<urdf::VisualSharedPtr>{ urdf_link->visual } :
1124  urdf_link->visual_array;
1125  for (const urdf::VisualSharedPtr& vis : vis_array)
1126  {
1127  if (vis && vis->geometry)
1128  warn_about_missing_collision = true;
1129  }
1130  }
1131  if (warn_about_missing_collision)
1132  {
1133  ROS_WARN_STREAM_NAMED(LOGNAME + ".empty_collision_geometry",
1134  "Link " << urdf_link->name
1135  << " has visual geometry but no collision geometry. "
1136  "Collision geometry will be left empty. "
1137  "Fix your URDF file by explicitly specifying collision geometry.");
1138  }
1139 
1140  new_link_model->setGeometry(shapes, poses);
1141 
1142  // figure out visual mesh (try visual urdf tag first, collision tag otherwise
1143  if (urdf_link->visual && urdf_link->visual->geometry)
1144  {
1145  if (urdf_link->visual->geometry->type == urdf::Geometry::MESH)
1146  {
1147  const urdf::Mesh* mesh = static_cast<const urdf::Mesh*>(urdf_link->visual->geometry.get());
1148  if (!mesh->filename.empty())
1149  new_link_model->setVisualMesh(mesh->filename, urdfPose2Isometry3d(urdf_link->visual->origin),
1150  Eigen::Vector3d(mesh->scale.x, mesh->scale.y, mesh->scale.z));
1151  }
1152  }
1153  else if (urdf_link->collision && urdf_link->collision->geometry)
1154  {
1155  if (urdf_link->collision->geometry->type == urdf::Geometry::MESH)
1156  {
1157  const urdf::Mesh* mesh = static_cast<const urdf::Mesh*>(urdf_link->collision->geometry.get());
1158  if (!mesh->filename.empty())
1159  new_link_model->setVisualMesh(mesh->filename, urdfPose2Isometry3d(urdf_link->collision->origin),
1160  Eigen::Vector3d(mesh->scale.x, mesh->scale.y, mesh->scale.z));
1161  }
1162  }
1163 
1164  if (urdf_link->parent_joint)
1165  new_link_model->setJointOriginTransform(
1166  urdfPose2Isometry3d(urdf_link->parent_joint->parent_to_joint_origin_transform));
1167 
1168  return new_link_model;
1169 }
1170 
1171 shapes::ShapePtr RobotModel::constructShape(const urdf::Geometry* geom)
1172 {
1173  moveit::tools::Profiler::ScopedBlock prof_block("RobotModel::constructShape");
1174 
1175  shapes::Shape* new_shape = nullptr;
1176  switch (geom->type)
1177  {
1178  case urdf::Geometry::SPHERE:
1179  new_shape = new shapes::Sphere(static_cast<const urdf::Sphere*>(geom)->radius);
1180  break;
1181  case urdf::Geometry::BOX:
1182  {
1183  urdf::Vector3 dim = static_cast<const urdf::Box*>(geom)->dim;
1184  new_shape = new shapes::Box(dim.x, dim.y, dim.z);
1185  }
1186  break;
1187  case urdf::Geometry::CYLINDER:
1188  new_shape = new shapes::Cylinder(static_cast<const urdf::Cylinder*>(geom)->radius,
1189  static_cast<const urdf::Cylinder*>(geom)->length);
1190  break;
1191  case urdf::Geometry::MESH:
1192  {
1193  const urdf::Mesh* mesh = static_cast<const urdf::Mesh*>(geom);
1194  if (!mesh->filename.empty())
1195  {
1196  Eigen::Vector3d scale(mesh->scale.x, mesh->scale.y, mesh->scale.z);
1197  shapes::Mesh* m = shapes::createMeshFromResource(mesh->filename, scale);
1198  new_shape = m;
1199  }
1200  }
1201  break;
1202  default:
1203  ROS_ERROR_NAMED(LOGNAME, "Unknown geometry type: %d", (int)geom->type);
1204  break;
1205  }
1206 
1207  return shapes::ShapePtr(new_shape);
1208 }
1209 
1210 bool RobotModel::hasJointModel(const std::string& name) const
1211 {
1212  return joint_model_map_.find(name) != joint_model_map_.end();
1213 }
1214 
1215 bool RobotModel::hasLinkModel(const std::string& name) const
1216 {
1217  return link_model_map_.find(name) != link_model_map_.end();
1218 }
1219 
1220 const JointModel* RobotModel::getJointModel(const std::string& name) const
1221 {
1222  JointModelMap::const_iterator it = joint_model_map_.find(name);
1223  if (it != joint_model_map_.end())
1224  return it->second;
1225  ROS_ERROR_NAMED(LOGNAME, "Joint '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
1226  return nullptr;
1227 }
1228 
1229 const JointModel* RobotModel::getJointModel(int index) const
1230 {
1231  if (index < 0 || index >= static_cast<int>(joint_model_vector_.size()))
1232  {
1233  ROS_ERROR_NAMED(LOGNAME, "Joint index '%i' out of bounds of joints in model '%s'", index, model_name_.c_str());
1234  return nullptr;
1235  }
1236  assert(joint_model_vector_[index]->getJointIndex() == index);
1238 }
1239 
1240 JointModel* RobotModel::getJointModel(const std::string& name)
1241 {
1242  JointModelMap::const_iterator it = joint_model_map_.find(name);
1243  if (it != joint_model_map_.end())
1244  return it->second;
1245  ROS_ERROR_NAMED(LOGNAME, "Joint '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
1246  return nullptr;
1247 }
1248 
1249 const LinkModel* RobotModel::getLinkModel(const std::string& name, bool* has_link) const
1250 {
1251  return const_cast<RobotModel*>(this)->getLinkModel(name, has_link);
1252 }
1253 
1254 const LinkModel* RobotModel::getLinkModel(int index) const
1255 {
1256  if (index < 0 || index >= static_cast<int>(link_model_vector_.size()))
1257  {
1258  ROS_ERROR_NAMED(LOGNAME, "Link index '%i' out of bounds of links in model '%s'", index, model_name_.c_str());
1259  return nullptr;
1260  }
1261  assert(link_model_vector_[index]->getLinkIndex() == index);
1262  return link_model_vector_[index];
1263 }
1264 
1265 LinkModel* RobotModel::getLinkModel(const std::string& name, bool* has_link)
1266 {
1267  if (has_link)
1268  *has_link = true; // Start out optimistic
1269  LinkModelMap::const_iterator it = link_model_map_.find(name);
1270  if (it != link_model_map_.end())
1271  return it->second;
1272 
1273  if (has_link)
1274  *has_link = false; // Report failure via argument
1275  else // Otherwise print error
1276  ROS_ERROR_NAMED(LOGNAME, "Link '%s' not found in model '%s'", name.c_str(), model_name_.c_str());
1277  return nullptr;
1278 }
1279 
1280 const LinkModel* RobotModel::getRigidlyConnectedParentLinkModel(const LinkModel* link, Eigen::Isometry3d& transform,
1281  const JointModelGroup* jmg)
1282 {
1283  if (!link)
1284  return link;
1285 
1286  transform.setIdentity();
1287  const moveit::core::LinkModel* parent_link = link->getParentLinkModel();
1288  const moveit::core::JointModel* joint = link->getParentJointModel();
1289  decltype(jmg->getJointModels().cbegin()) begin{}, end{};
1290  if (jmg)
1291  {
1292  begin = jmg->getJointModels().cbegin();
1293  end = jmg->getJointModels().cend();
1294  }
1296  auto is_fixed_or_not_in_jmg = [begin, end](const moveit::core::JointModel* joint) {
1297  if (joint->getType() == moveit::core::JointModel::FIXED)
1298  return true;
1299  if (begin != end && // we do have a non-empty jmg
1300  std::find(begin, end, joint) == end) // joint does not belong to jmg
1301  return true;
1302  return false;
1303  };
1304 
1305  while (parent_link && is_fixed_or_not_in_jmg(joint))
1306  {
1308  link = parent_link;
1309  joint = link->getParentJointModel();
1310  parent_link = joint->getParentLinkModel();
1311  }
1312  return link;
1313 }
1314 
1315 void RobotModel::updateMimicJoints(double* values) const
1316 {
1317  for (const JointModel* mimic_joint : mimic_joints_)
1318  {
1319  int src = mimic_joint->getMimic()->getFirstVariableIndex();
1320  int dest = mimic_joint->getFirstVariableIndex();
1321  values[dest] = values[src] * mimic_joint->getMimicFactor() + mimic_joint->getMimicOffset();
1322  }
1323 }
1324 
1326 {
1327  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1330 }
1333  std::map<std::string, double>& values) const
1334 {
1335  std::vector<double> tmp(variable_count_);
1336  getVariableRandomPositions(rng, &tmp[0]);
1337  values.clear();
1338  for (std::size_t i = 0; i < variable_names_.size(); ++i)
1339  values[variable_names_[i]] = tmp[i];
1340 }
1341 
1342 void RobotModel::getVariableDefaultPositions(double* values) const
1343 {
1344  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1347 }
1348 
1349 void RobotModel::getVariableDefaultPositions(std::map<std::string, double>& values) const
1350 {
1351  std::vector<double> tmp(variable_count_);
1352  getVariableDefaultPositions(&tmp[0]);
1353  values.clear();
1354  for (std::size_t i = 0; i < variable_names_.size(); ++i)
1355  values[variable_names_[i]] = tmp[i];
1356 }
1357 
1358 void RobotModel::getMissingVariableNames(const std::vector<std::string>& variables,
1359  std::vector<std::string>& missing_variables) const
1360 {
1361  missing_variables.clear();
1362  std::set<std::string> keys(variables.begin(), variables.end());
1363  for (const std::string& variable_name : variable_names_)
1364  if (keys.find(variable_name) == keys.end())
1365  if (getJointOfVariable(variable_name)->getMimic() == nullptr)
1366  missing_variables.push_back(variable_name);
1367 }
1368 
1369 int RobotModel::getVariableIndex(const std::string& variable) const
1370 {
1371  VariableIndexMap::const_iterator it = joint_variables_index_map_.find(variable);
1372  if (it == joint_variables_index_map_.end())
1373  throw Exception("Variable '" + variable + "' is not known to model '" + model_name_ + "'");
1374  return it->second;
1375 }
1376 
1377 double RobotModel::getMaximumExtent(const JointBoundsVector& active_joint_bounds) const
1378 {
1379  double max_distance = 0.0;
1380  for (std::size_t j = 0; j < active_joint_model_vector_.size(); ++j)
1381  max_distance += active_joint_model_vector_[j]->getMaximumExtent(*active_joint_bounds[j]) *
1382  active_joint_model_vector_[j]->getDistanceFactor();
1383  return max_distance;
1384 }
1385 
1386 bool RobotModel::satisfiesPositionBounds(const double* state, const JointBoundsVector& active_joint_bounds,
1387  double margin) const
1388 {
1389  assert(active_joint_bounds.size() == active_joint_model_vector_.size());
1390  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1392  *active_joint_bounds[i], margin))
1393  return false;
1394  return true;
1395 }
1396 
1397 bool RobotModel::enforcePositionBounds(double* state, const JointBoundsVector& active_joint_bounds) const
1399  assert(active_joint_bounds.size() == active_joint_model_vector_.size());
1400  bool change = false;
1401  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1403  *active_joint_bounds[i]))
1404  change = true;
1405  if (change)
1406  updateMimicJoints(state);
1407  return change;
1409 
1410 double RobotModel::distance(const double* state1, const double* state2) const
1411 {
1412  double d = 0.0;
1413  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1414  d += active_joint_model_vector_[i]->getDistanceFactor() *
1416  state2 + active_joint_model_start_index_[i]);
1417  return d;
1418 }
1419 
1420 void RobotModel::interpolate(const double* from, const double* to, double t, double* state) const
1421 {
1423  // we interpolate values only for active joint models (non-mimic)
1424  for (std::size_t i = 0; i < active_joint_model_vector_.size(); ++i)
1427  state + active_joint_model_start_index_[i]);
1428  // now we update mimic as needed
1429  updateMimicJoints(state);
1430 }
1431 
1432 void RobotModel::setKinematicsAllocators(const std::map<std::string, SolverAllocatorFn>& allocators)
1433 {
1434  // we first set all the "simple" allocators -- where a group has one IK solver
1436  {
1437  std::map<std::string, SolverAllocatorFn>::const_iterator jt = allocators.find(jmg->getName());
1438  if (jt != allocators.end())
1439  {
1440  std::pair<SolverAllocatorFn, SolverAllocatorMapFn> solver_allocator_pair;
1441  solver_allocator_pair.first = jt->second;
1442  jmg->setSolverAllocators(solver_allocator_pair);
1443  }
1444  }
1445 
1446  // now we set compound IK solvers; we do this later because we need the index maps computed by the previous calls to
1447  // setSolverAllocators()
1448  for (JointModelGroup* jmg : joint_model_groups_)
1449  {
1450  std::pair<SolverAllocatorFn, SolverAllocatorMapFn> solver_allocator_pair;
1451  std::map<std::string, SolverAllocatorFn>::const_iterator jt = allocators.find(jmg->getName());
1452  if (jt == allocators.end())
1453  {
1454  // if an kinematics allocator is NOT available for this group, we try to see if we can use subgroups for IK
1455  std::set<const JointModel*> joints;
1456  joints.insert(jmg->getJointModels().begin(), jmg->getJointModels().end());
1457 
1458  std::vector<const JointModelGroup*> subs;
1459 
1460  // go through the groups that have IK allocators and see if they are part of jmg; collect them in subs
1461  for (const std::pair<const std::string, SolverAllocatorFn>& allocator : allocators)
1462  {
1463  const JointModelGroup* sub = getJointModelGroup(allocator.first);
1464  if (!sub) // this should actually not happen, all groups should be well defined
1465  {
1466  subs.clear();
1467  break;
1468  }
1469  std::set<const JointModel*> sub_joints;
1470  sub_joints.insert(sub->getJointModels().begin(), sub->getJointModels().end());
1471 
1472  if (std::includes(joints.begin(), joints.end(), sub_joints.begin(), sub_joints.end()))
1473  { // sub_joints included in joints: add sub, remove sub_joints from joints set
1474  std::set<const JointModel*> joint_model_set;
1475  std::set_difference(joints.begin(), joints.end(), sub_joints.begin(), sub_joints.end(),
1476  std::inserter(joint_model_set, joint_model_set.end()));
1477  // TODO: instead of maintaining disjoint joint sets here,
1478  // should we leave that work to JMG's setSolverAllocators() / computeIKIndexBijection()?
1479  // There, a disjoint bijection from joints to solvers is computed anyway.
1480  // Underlying question: How do we resolve overlaps? Now the first considered sub group "wins"
1481  // But, if the overlap only involves fixed joints, we could consider all sub groups
1482  subs.push_back(sub);
1483  joints.swap(joint_model_set);
1484  }
1485  }
1487  // if we found subgroups, pass that information to the planning group
1488  if (!subs.empty())
1489  {
1490  std::stringstream ss;
1491  for (const JointModelGroup* sub : subs)
1492  {
1493  ss << sub->getName() << " ";
1494  solver_allocator_pair.second[sub] = allocators.find(sub->getName())->second;
1495  }
1496  ROS_DEBUG_NAMED(LOGNAME, "Added sub-group IK allocators for group '%s': [ %s]", jmg->getName().c_str(),
1497  ss.str().c_str());
1498  }
1499  jmg->setSolverAllocators(solver_allocator_pair);
1500  }
1501  }
1502 }
1503 
1504 void RobotModel::printModelInfo(std::ostream& out) const
1505 {
1506  out << "Model " << model_name_ << " in frame " << model_frame_ << ", using " << getVariableCount() << " variables"
1507  << std::endl;
1508 
1509  std::ios_base::fmtflags old_flags = out.flags();
1510  out.setf(std::ios::fixed, std::ios::floatfield);
1511  std::streamsize old_prec = out.precision();
1512  out.precision(5);
1513  out << "Joints: " << std::endl;
1514  for (JointModel* joint_model : joint_model_vector_)
1515  {
1516  out << " '" << joint_model->getName() << "' (" << joint_model->getTypeName() << ")" << std::endl;
1517  out << " * Joint Index: " << joint_model->getJointIndex() << std::endl;
1518  const std::vector<std::string>& vn = joint_model->getVariableNames();
1519  out << " * " << vn.size() << (vn.size() > 1 ? " variables:" : (vn.empty() ? " variables" : " variable:"))
1520  << std::endl;
1521  int idx = joint_model->getFirstVariableIndex();
1522  for (const std::string& it : vn)
1523  {
1524  out << " * '" << it << "', index " << idx++ << " in full state";
1525  if (joint_model->getMimic())
1526  out << ", mimic '" << joint_model->getMimic()->getName() << "'";
1527  if (joint_model->isPassive())
1528  out << ", passive";
1529  out << std::endl;
1530  out << " " << joint_model->getVariableBounds(it) << std::endl;
1531  }
1532  }
1533  out << std::endl;
1534  out.precision(old_prec);
1535  out.flags(old_flags);
1536  out << "Links: " << std::endl;
1537  for (LinkModel* link_model : link_model_vector_)
1538  {
1539  out << " '" << link_model->getName() << "' with " << link_model->getShapes().size() << " geoms" << std::endl;
1540  if (link_model->parentJointIsFixed())
1541  out << " * "
1542  << "parent joint is fixed" << std::endl;
1543  if (link_model->jointOriginTransformIsIdentity())
1544  out << " * "
1545  << "joint origin transform is identity" << std::endl;
1546  }
1547 
1548  out << "Available groups: " << std::endl;
1549  for (JointModelGroup* joint_model_group : joint_model_groups_)
1550  joint_model_group->printGroupInfo(out);
1551 }
1552 
1553 void RobotModel::computeFixedTransforms(const LinkModel* link, const Eigen::Isometry3d& transform,
1554  LinkTransformMap& associated_transforms)
1555 {
1556  associated_transforms[link] = transform * link->getJointOriginTransform();
1557  for (std::size_t i = 0; i < link->getChildJointModels().size(); ++i)
1558  if (link->getChildJointModels()[i]->getType() == JointModel::FIXED)
1559  computeFixedTransforms(link->getChildJointModels()[i]->getChildLinkModel(),
1560  transform * link->getJointOriginTransform(), associated_transforms);
1561 }
1562 
1563 } // end of namespace core
1564 } // end of namespace moveit
moveit::core::LinkModel::getJointOriginTransform
const Eigen::Isometry3d & getJointOriginTransform() const
When transforms are computed for this link, they are usually applied to the link's origin....
Definition: link_model.h:142
moveit::core::LinkModel
A link from the robot. Contains the constant transform applied to the link and its geometry.
Definition: link_model.h:71
moveit::core::RobotModel::variable_count_
std::size_t variable_count_
Get the number of variables necessary to describe this model.
Definition: robot_model.h:644
moveit::core::RobotModel::getJointModel
const JointModel * getJointModel(const std::string &joint) const
Get a joint by its name. Output error and return NULL when the joint is missing.
Definition: robot_model.cpp:1286
moveit::core::RobotModel::end_effectors_
std::vector< const JointModelGroup * > end_effectors_
The array of end-effectors, in alphabetical order.
Definition: robot_model.h:677
shapes
EigenSTL::vector_Isometry3d
std::vector< Eigen::Isometry3d, Eigen::aligned_allocator< Eigen::Isometry3d > > vector_Isometry3d
moveit::core::RobotModel::active_joint_model_vector_
std::vector< JointModel * > active_joint_model_vector_
The vector of joints in the model, in the order they appear in the state vector.
Definition: robot_model.h:610
moveit::core::RobotModel::active_joint_model_vector_const_
std::vector< const JointModel * > active_joint_model_vector_const_
The vector of joints in the model, in the order they appear in the state vector.
Definition: robot_model.h:616
moveit::core::JointModelGroup
Definition: joint_model_group.h:134
moveit::core::LinkModel::getChildJointModels
const std::vector< const JointModel * > & getChildJointModels() const
A link may have 0 or more child joints. From those joints there will certainly be other descendant li...
Definition: link_model.h:127
moveit::core::RobotModel::setKinematicsAllocators
void setKinematicsAllocators(const std::map< std::string, SolverAllocatorFn > &allocators)
A map of known kinematics solvers (associated to their group name)
Definition: robot_model.cpp:1498
moveit::core::RobotModel::constructLinkModel
LinkModel * constructLinkModel(const urdf::Link *urdf_link)
Given a urdf link, build the corresponding LinkModel object.
Definition: robot_model.cpp:1161
moveit::core::RobotModel::joint_model_vector_const_
std::vector< const JointModel * > joint_model_vector_const_
The vector of joints in the model, in the order they appear in the state vector.
Definition: robot_model.h:604
moveit::core::RobotModel::addJointModelGroup
bool addJointModelGroup(const srdf::Model::Group &group)
Construct a JointModelGroup given a SRDF description group.
Definition: robot_model.cpp:733
s
XmlRpcServer s
moveit::core::RobotModel::joint_model_groups_const_
std::vector< const JointModelGroup * > joint_model_groups_const_
The array of joint model groups, in alphabetical order.
Definition: robot_model.h:671
moveit::core::RobotModel::buildGroupsInfoSubgroups
void buildGroupsInfoSubgroups()
Compute helpful information about groups (that can be queried later)
Definition: robot_model.cpp:621
srdf::Model::Group::chains_
std::vector< std::pair< std::string, std::string > > chains_
moveit::core::RobotModel::getRigidlyConnectedParentLinkModel
static const moveit::core::LinkModel * getRigidlyConnectedParentLinkModel(const LinkModel *link, Eigen::Isometry3d &transform, const JointModelGroup *jmg=nullptr)
Get the latest link upwards the kinematic tree, which is only connected via fixed joints.
Definition: robot_model.cpp:1346
srdf::Model::getPassiveJoints
const std::vector< PassiveJoint > & getPassiveJoints() const
moveit::core::RobotModel::link_geometry_count_
std::size_t link_geometry_count_
Total number of geometric shapes in this model.
Definition: robot_model.h:590
moveit::core::RobotModel::computeDescendants
void computeDescendants()
For every joint, pre-compute the list of descendant joints & links.
Definition: robot_model.cpp:295
moveit::core::RobotModel::joint_model_names_vector_
std::vector< std::string > joint_model_names_vector_
The vector of joint names that corresponds to joint_model_vector_.
Definition: robot_model.h:607
moveit::core::RobotModel::getVariableBounds
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a specific variable. Throw an exception of variable is not found.
Definition: robot_model.h:512
moveit::core::RobotModel::continuous_joint_model_vector_
std::vector< const JointModel * > continuous_joint_model_vector_
The set of continuous joints this model contains.
Definition: robot_model.h:619
moveit::core::RobotModel::getRootJoint
const JointModel * getRootJoint() const
Get the root joint. There will be one root joint unless the model is empty. This is either extracted ...
Definition: robot_model.cpp:141
moveit::core::RobotModel::joint_model_vector_
std::vector< JointModel * > joint_model_vector_
The vector of joints in the model, in the order they appear in the state vector.
Definition: robot_model.h:601
shapes::Cylinder
moveit::core::LinkModel::getParentJointModel
const JointModel * getParentJointModel() const
Get the joint model whose child this link is. There will always be a parent joint.
Definition: link_model.h:107
shape_operations.h
moveit::core::RobotModel::joint_model_group_map_
JointModelGroupMap joint_model_group_map_
A map from group names to joint groups.
Definition: robot_model.h:662
moveit::core::JointBoundsVector
std::vector< const JointModel::Bounds * > JointBoundsVector
Definition: joint_model_group.h:132
moveit::tools::Profiler::ScopedStart
This instance will call Profiler::start() when constructed and Profiler::stop() when it goes out of s...
Definition: profiler.h:98
moveit::core::RobotModel::getVariableCount
std::size_t getVariableCount() const
Get the number of variables that describe this model.
Definition: robot_model.h:497
ROS_ERROR_NAMED
#define ROS_ERROR_NAMED(name,...)
moveit::core::RobotModel::buildRecursive
JointModel * buildRecursive(LinkModel *parent, const urdf::Link *link, const srdf::Model &srdf_model)
(This function is mostly intended for internal use). Given a parent link, build up (recursively),...
Definition: robot_model.cpp:849
shapes::Shape
transform
template Halfspace< double > transform(const Halfspace< double > &a, const Transform3< double > &tf)
shapes::Mesh
moveit::core::RobotModel::computeCommonRoots
void computeCommonRoots()
For every pair of joints, pre-compute the common roots of the joints.
Definition: robot_model.cpp:264
moveit::core::RobotModel::joint_model_group_names_
std::vector< std::string > joint_model_group_names_
A vector of all group names, in alphabetical order.
Definition: robot_model.h:674
moveit::core::RobotModel::joint_model_groups_
std::vector< JointModelGroup * > joint_model_groups_
The array of joint model groups, in alphabetical order.
Definition: robot_model.h:668
moveit::core::RobotModel::getJointModelGroup
const JointModelGroup * getJointModelGroup(const std::string &name) const
Get a joint group from this model (by name)
Definition: robot_model.cpp:547
moveit::core::RobotModel::buildMimic
void buildMimic(const urdf::ModelInterface &urdf_model)
Given the URDF model, build up the mimic joints (mutually constrained joints)
Definition: robot_model.cpp:450
moveit::core::RobotModel::interpolate
void interpolate(const double *from, const double *to, double t, double *state) const
Definition: robot_model.cpp:1486
ok
ROSCPP_DECL bool ok()
robot_model.h
moveit::core::RobotModel::joint_model_map_
JointModelMap joint_model_map_
A map from joint names to their instances.
Definition: robot_model.h:598
moveit::core::JointModel::getType
JointType getType() const
Get the type of joint.
Definition: joint_model.h:202
moveit::core::RobotModel::single_dof_joints_
std::vector< const JointModel * > single_dof_joints_
Definition: robot_model.h:624
moveit::core::JointModel::REVOLUTE
@ REVOLUTE
Definition: joint_model.h:180
moveit::core::RobotModel::link_model_map_
LinkModelMap link_model_map_
A map from link names to their instances.
Definition: robot_model.h:572
moveit::core::JointModel::getChildLinkModel
const LinkModel * getChildLinkModel() const
Get the link that this joint connects to. There will always be such a link.
Definition: joint_model.h:219
moveit::core::RobotModel::link_model_vector_const_
std::vector< const LinkModel * > link_model_vector_const_
The vector of links that are updated when computeTransforms() is called, in the order they are update...
Definition: robot_model.h:578
moveit::core::RobotModel::srdf_
srdf::ModelConstSharedPtr srdf_
Definition: robot_model.h:562
moveit::core::RobotModel::link_model_vector_
std::vector< LinkModel * > link_model_vector_
The vector of links that are updated when computeTransforms() is called, in the order they are update...
Definition: robot_model.h:575
moveit::core::JointModelGroup::getName
const std::string & getName() const
Get the name of the joint group.
Definition: joint_model_group.h:185
moveit::core::RobotModel::getMaximumExtent
double getMaximumExtent() const
Definition: robot_model.h:429
moveit::core::RobotModel::hasEndEffector
bool hasEndEffector(const std::string &eef) const
Check if an end effector exists.
Definition: robot_model.cpp:509
profiler.h
moveit::core::JointModel::getParentLinkModel
const LinkModel * getParentLinkModel() const
Get the link that this joint connects to. The robot is assumed to start with a joint,...
Definition: joint_model.h:213
srdf::Model::getGroupStates
const std::vector< GroupState > & getGroupStates() const
shapes::ShapePtr
std::shared_ptr< Shape > ShapePtr
moveit::core::RobotModel::link_models_with_collision_geometry_vector_
std::vector< const LinkModel * > link_models_with_collision_geometry_vector_
Only links that have collision geometry specified.
Definition: robot_model.h:584
moveit::core::RobotModel::common_joint_roots_
std::vector< int > common_joint_roots_
For every two joints, the index of the common root for thw joints is stored.
Definition: robot_model.h:635
srdf::Model::Group::name_
std::string name_
moveit::core::RobotModel::mimic_joints_
std::vector< const JointModel * > mimic_joints_
The set of mimic joints this model contains.
Definition: robot_model.h:622
shapes::Box
name
std::string name
moveit::core::RobotModel::model_frame_
std::string model_frame_
The reference (base) frame for this model. The frame is either extracted from the SRDF as a virtual j...
Definition: robot_model.h:560
ROS_INFO_NAMED
#define ROS_INFO_NAMED(name,...)
shapes::Sphere
moveit::core::RobotModel::multi_dof_joints_
std::vector< const JointModel * > multi_dof_joints_
Definition: robot_model.h:626
moveit::core::RobotModel::root_link_
const LinkModel * root_link_
The first physical link for the robot.
Definition: robot_model.h:569
ROS_DEBUG_NAMED
#define ROS_DEBUG_NAMED(name,...)
moveit::core::RobotModel::link_model_names_vector_
std::vector< std::string > link_model_names_vector_
The vector of link names that corresponds to link_model_vector_.
Definition: robot_model.h:581
moveit::core::RobotModel::urdf_
urdf::ModelInterfaceSharedPtr urdf_
Definition: robot_model.h:564
ROS_ERROR_STREAM_NAMED
#define ROS_ERROR_STREAM_NAMED(name, args)
moveit::core::RobotModel::RobotModel
RobotModel(const urdf::ModelInterfaceSharedPtr &urdf_model, const srdf::ModelConstSharedPtr &srdf_model)
Construct a kinematic model from a parsed description and a list of planning groups.
Definition: robot_model.cpp:123
moveit::core::JointModel::getMimicRequests
const std::vector< const JointModel * > & getMimicRequests() const
The joint models whose values would be modified if the value of this joint changed.
Definition: joint_model.h:465
moveit::core::RobotModel::getJointOfVariable
const JointModel * getJointOfVariable(int variable_index) const
Definition: robot_model.h:281
srdf::Model::getJointProperties
const JointPropertyMap & getJointProperties() const
moveit::core::RobotModel::buildGroupsInfoEndEffectors
void buildGroupsInfoEndEffectors(const srdf::Model &srdf_model)
Compute helpful information about groups (that can be queried later)
Definition: robot_model.cpp:650
srdf::ModelConstSharedPtr
std::shared_ptr< const Model > ModelConstSharedPtr
srdf::Model::Group::links_
std::vector< std::string > links_
moveit::core::RobotModel::computeFixedTransforms
void computeFixedTransforms(const LinkModel *link, const Eigen::Isometry3d &transform, LinkTransformMap &associated_transforms)
Get the transforms between link and all its rigidly attached descendants.
Definition: robot_model.cpp:1619
moveit::core::RobotModel::hasJointModelGroup
bool hasJointModelGroup(const std::string &group) const
Check if the JointModelGroup group exists.
Definition: robot_model.cpp:542
moveit::core::RobotModel::joints_of_variable_
std::vector< const JointModel * > joints_of_variable_
The joints that correspond to each variable index.
Definition: robot_model.h:657
moveit::core::RobotModel::satisfiesPositionBounds
bool satisfiesPositionBounds(const double *state, double margin=0.0) const
Definition: robot_model.h:423
setup.d
d
Definition: setup.py:8
moveit::core::RobotModel::active_joint_models_bounds_
JointBoundsVector active_joint_models_bounds_
The bounds for all the active joint models.
Definition: robot_model.h:654
shapes::createMeshFromResource
Mesh * createMeshFromResource(const std::string &resource)
moveit::core::PlanarJointModel::MotionModel
MotionModel
different types of planar joints we support
Definition: planar_joint_model.h:146
moveit::core::RobotModel::enforcePositionBounds
bool enforcePositionBounds(double *state) const
Definition: robot_model.h:418
srdf::Model::getGroups
const std::vector< Group > & getGroups() const
moveit::core::RobotModel::constructJointModel
JointModel * constructJointModel(const urdf::Joint *urdf_joint_model, const urdf::Link *child_link, const srdf::Model &srdf_model)
Given a urdf joint model, a child link and a set of virtual joints, build up the corresponding JointM...
Definition: robot_model.cpp:946
moveit::core::JointModel::getJointIndex
int getJointIndex() const
Get the index of this joint within the robot model.
Definition: joint_model.h:279
moveit::core::RobotModel::link_model_names_with_collision_geometry_vector_
std::vector< std::string > link_model_names_with_collision_geometry_vector_
The vector of link names that corresponds to link_models_with_collision_geometry_vector_.
Definition: robot_model.h:587
moveit::core::RobotModel::variable_names_
std::vector< std::string > variable_names_
The names of the DOF that make up this state (this is just a sequence of joint variable names; not ne...
Definition: robot_model.h:641
moveit::core::LOGNAME
const std::string LOGNAME
Definition: joint_model_group.cpp:165
moveit::core::RobotModel::buildGroupStates
void buildGroupStates(const srdf::Model &srdf_model)
Given a SRDF model describing the groups, build the default states defined in the SRDF.
Definition: robot_model.cpp:390
moveit::core::RobotModel::getRootLink
const LinkModel * getRootLink() const
Get the physical root link of the robot.
Definition: robot_model.cpp:146
moveit::core::RobotModel::buildJointInfo
void buildJointInfo()
Compute helpful information about joints.
Definition: robot_model.cpp:315
moveit::core::LinkTransformMap
std::map< const LinkModel *, Eigen::Isometry3d, std::less< const LinkModel * >, Eigen::aligned_allocator< std::pair< const LinkModel *const, Eigen::Isometry3d > > > LinkTransformMap
Map from link model instances to Eigen transforms.
Definition: link_model.h:68
moveit::core::RobotModel::active_joint_model_start_index_
std::vector< int > active_joint_model_start_index_
Definition: robot_model.h:651
moveit::core::JointModelGroup::getJointModels
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
Definition: joint_model_group.h:209
moveit::core::RobotModel::getName
const std::string & getName() const
Get the model name.
Definition: robot_model.h:153
srdf::Model::PassiveJoint
ROS_WARN_STREAM_NAMED
#define ROS_WARN_STREAM_NAMED(name, args)
random_numbers::RandomNumberGenerator
srdf::Model::GroupState
moveit::core::RobotModel::printModelInfo
void printModelInfo(std::ostream &out) const
Print information about the constructed model.
Definition: robot_model.cpp:1570
moveit::core::JointModelGroup::setSolverAllocators
void setSolverAllocators(const SolverAllocatorFn &solver, const SolverAllocatorMapFn &solver_map=SolverAllocatorMapFn())
Definition: joint_model_group.h:594
moveit::core::RobotModel::getLinkModel
const LinkModel * getLinkModel(const std::string &link, bool *has_link=nullptr) const
Get a link by its name. Output error and return NULL when the link is missing.
Definition: robot_model.cpp:1315
srdf::Model::VirtualJoint
moveit::core::JointModelGroup::setSubgroupNames
void setSubgroupNames(const std::vector< std::string > &subgroups)
Set the names of the subgroups for this group.
Definition: joint_model_group.cpp:334
moveit::core::RobotModel::getMissingVariableNames
void getMissingVariableNames(const std::vector< std::string > &variables, std::vector< std::string > &missing_variables) const
Definition: robot_model.cpp:1424
moveit
Main namespace for MoveIt.
Definition: background_processing.h:46
values
std::vector< double > values
moveit::core::RobotModel::model_name_
std::string model_name_
The name of the robot.
Definition: robot_model.h:556
moveit::core::RobotModel::active_joint_model_names_vector_
std::vector< std::string > active_joint_model_names_vector_
The vector of joint names that corresponds to active_joint_model_vector_.
Definition: robot_model.h:613
moveit::core::RobotModel::getVariableIndex
int getVariableIndex(const std::string &variable) const
Get the index of a variable in the robot state.
Definition: robot_model.cpp:1435
moveit::tools::Profiler::ScopedBlock
This instance will call Profiler::begin() when constructed and Profiler::end() when it goes out of sc...
Definition: profiler.h:77
ROS_WARN_NAMED
#define ROS_WARN_NAMED(name,...)
index
unsigned int index
moveit::core::RobotModel::distance
double distance(const double *state1, const double *state2) const
Return the sum of joint distances between two states. Only considers active joints.
Definition: robot_model.cpp:1476
srdf::Model::getEndEffectors
const std::vector< EndEffector > & getEndEffectors() const
shapes::ShapeConstPtr
std::shared_ptr< const Shape > ShapeConstPtr
moveit::core::RobotModel::getJointModels
const std::vector< const JointModel * > & getJointModels() const
Get the array of joints, in the order they appear in the robot state.
Definition: robot_model.h:218
moveit::core::RevoluteJointModel
A revolute joint.
Definition: revolute_joint_model.h:110
moveit::core::RobotModel::hasJointModel
bool hasJointModel(const std::string &name) const
Check if a joint exists. Return true if it does.
Definition: robot_model.cpp:1276
srdf::Model::Group::subgroups_
std::vector< std::string > subgroups_
moveit::core::RobotModel::constructShape
shapes::ShapePtr constructShape(const urdf::Geometry *geom)
Given a geometry spec from the URDF and a filename (for a mesh), construct the corresponding shape ob...
Definition: robot_model.cpp:1237
moveit::core::RobotModel::joint_variables_index_map_
VariableIndexMap joint_variables_index_map_
The state includes all the joint variables that make up the joints the state consists of....
Definition: robot_model.h:649
srdf::Model::Group
moveit::core::RobotModel::root_joint_
const JointModel * root_joint_
The root joint.
Definition: robot_model.h:595
moveit::core::RobotModel::buildGroups
void buildGroups(const srdf::Model &srdf_model)
Given a SRDF model describing the groups, build up the groups in this kinematic model.
Definition: robot_model.cpp:569
moveit::core::RobotModel::getVariableDefaultPositions
void getVariableDefaultPositions(double *values) const
Compute the default values for a RobotState.
Definition: robot_model.cpp:1408
moveit::core::toDouble
double toDouble(const std::string &s)
Converts a std::string to double using the classic C locale.
Definition: lexical_casts.cpp:145
moveit::core::checkInterpolationParamBounds
static void checkInterpolationParamBounds(const char LOGNAME[], double t)
Definition: robot_model.h:132
moveit::core::JointModel::FIXED
@ FIXED
Definition: joint_model.h:184
srdf::Model
moveit::core::RobotModel::getVariableRandomPositions
void getVariableRandomPositions(random_numbers::RandomNumberGenerator &rng, double *values) const
Compute the random values for a RobotState.
Definition: robot_model.cpp:1391
moveit::core::RobotModel::updateMimicJoints
void updateMimicJoints(double *values) const
Update the variable values for the state of a group with respect to the mimic joints.
Definition: robot_model.cpp:1381
moveit::core::RobotModel::~RobotModel
~RobotModel()
Destructor. Clear all memory.
Definition: robot_model.cpp:131
srdf::Model::Group::joints_
std::vector< std::string > joints_
moveit::core::RobotModel::buildModel
void buildModel(const urdf::ModelInterface &urdf_model, const srdf::Model &srdf_model)
Given an URDF model and a SRDF model, build a full kinematic model.
Definition: robot_model.cpp:151
t
geometry_msgs::TransformStamped t
moveit::core::JointModel
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
Definition: joint_model.h:173
srdf::Model::getVirtualJoints
const std::vector< VirtualJoint > & getVirtualJoints() const
srdf::Model::EndEffector
moveit::core::RobotModel::hasLinkModel
bool hasLinkModel(const std::string &name) const
Check if a link exists. Return true if it does.
Definition: robot_model.cpp:1281
moveit::core::RobotModel::getEndEffector
const JointModelGroup * getEndEffector(const std::string &name) const
Get the joint group that corresponds to a given end-effector name.
Definition: robot_model.cpp:514
moveit::core::LinkModel::getParentLinkModel
const LinkModel * getParentLinkModel() const
Get the link model whose child this link is (through some joint). There may not always be a parent li...
Definition: link_model.h:116
fcl::Vector3d
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.h:89
moveit::core::RobotModel::end_effectors_map_
JointModelGroupMap end_effectors_map_
The known end effectors.
Definition: robot_model.h:665


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Thu Apr 18 2024 02:23:40