kinematic_group.cpp
Go to the documentation of this file.
1 
28 #include <console_bridge/console.h>
30 
34 #include <tesseract_common/utils.h>
35 
39 
51 std::vector<std::string> getLinksInFixedJointKinematicTree(const std::string& input_link,
52  const tesseract_scene_graph::SceneGraph& scene_graph)
53 {
54  // Create a set to contain the names of the links of the fixed-joint kinematic tree
55  std::set<std::string> fixed_joint_tree_links;
56 
57  // Create a list of links to traverse, populated initially with only the name of the link in question
58  std::vector<std::string> links = { input_link };
59 
60  while (!links.empty())
61  {
62  // Pop the back entry
63  const std::string link = links.back();
64  links.pop_back();
65 
66  // Traverse through the inbound joints until we find a non-fixed joint
67  for (const std::shared_ptr<const tesseract_scene_graph::Joint>& joint : scene_graph.getInboundJoints(link))
68  {
69  switch (joint->type)
70  {
72  // Add this joint's parent link to the list of links to traverse
73  links.push_back(joint->parent_link_name);
74  break;
75  default:
76  {
77  // Since this link is connected to its parent by a non-fixed joint:
78  // 1. Add this link to the list of relatives
79  fixed_joint_tree_links.insert(link);
80 
81  // 2. Add the fixed-joint children of this link to the list of relatives
82  const std::vector<std::string> children = scene_graph.getLinkChildrenNames(link);
83  fixed_joint_tree_links.insert(children.begin(), children.end());
84  }
85  break;
86  }
87  }
88  }
89 
90  // Convert to vector
91  std::vector<std::string> output;
92  output.reserve(fixed_joint_tree_links.size());
93  std::copy(fixed_joint_tree_links.begin(), fixed_joint_tree_links.end(), std::back_inserter(output));
94 
95  return output;
96 }
97 
98 namespace tesseract_kinematics
99 {
100 // NOLINTNEXTLINE(modernize-pass-by-value)
101 KinGroupIKInput::KinGroupIKInput(const Eigen::Isometry3d& p, std::string wf, std::string tl)
102  : pose(p), working_frame(std::move(wf)), tip_link_name(std::move(tl))
103 {
104 }
105 
107  std::vector<std::string> joint_names,
108  std::unique_ptr<InverseKinematics> inv_kin,
109  const tesseract_scene_graph::SceneGraph& scene_graph,
110  const tesseract_scene_graph::SceneState& scene_state)
111  : JointGroup(std::move(name), joint_names, scene_graph, scene_state)
112  , joint_names_(std::move(joint_names))
113  , inv_kin_(std::move(inv_kin))
114 {
115  std::vector<std::string> inv_kin_joint_names = inv_kin_->getJointNames();
116 
117  if (static_cast<Eigen::Index>(joint_names_.size()) != inv_kin_->numJoints())
118  throw std::runtime_error("KinematicGroup: joint_names is not the correct size");
119 
120  if (!tesseract_common::isIdentical(joint_names_, inv_kin_joint_names, false))
121  throw std::runtime_error("KinematicGroup: joint_names does not match same names in inverse kinematics object!");
122 
123  reorder_required_ = !tesseract_common::isIdentical(joint_names_, inv_kin_joint_names, true);
124 
125  if (reorder_required_)
126  {
127  inv_kin_joint_map_.reserve(joint_names_.size());
128  for (const auto& joint_name : joint_names_)
129  inv_kin_joint_map_.push_back(std::distance(
130  inv_kin_joint_names.begin(), std::find(inv_kin_joint_names.begin(), inv_kin_joint_names.end(), joint_name)));
131  }
132 
133  std::vector<std::string> active_link_names = state_solver_->getActiveLinkNames();
134 
135  // Get the IK solver working frame name, and check that it exists in the scene state
136  const std::string working_frame = inv_kin_->getWorkingFrame();
137  if (state_.link_transforms.find(working_frame) == state_.link_transforms.end())
138  throw std::runtime_error("Working frame '" + working_frame + "' is not a link in the scene state");
139 
140  // Get the IK solver tip link names, and make sure they exist in the scene state
141  const std::vector<std::string> tip_links = inv_kin_->getTipLinkNames();
142  for (const std::string& link : tip_links)
143  if (state_.link_transforms.find(link) == state_.link_transforms.end())
144  throw std::runtime_error("Tip link '" + link + "' is not a link in the scene state");
145 
146  // Configure working frames
147  auto it = std::find(active_link_names.begin(), active_link_names.end(), working_frame);
148  if (it == active_link_names.end())
149  {
150  working_frames_.reserve(static_link_names_.size());
151  std::copy(static_link_names_.begin(), static_link_names_.end(), std::back_inserter(working_frames_));
152  }
153  else
154  {
155  working_frames_.push_back(working_frame);
156 
157  // The working frame can be any link in the fixed-joint kinematic tree that contains the input working frame.
158  const std::vector<std::string> working_frame_fixed_joint_kin_tree_links =
159  getLinksInFixedJointKinematicTree(working_frame, scene_graph);
160  for (const std::string& link : working_frame_fixed_joint_kin_tree_links)
161  {
162  // Check that the link exists in the scene state
163  if (state_.link_transforms.find(link) == state_.link_transforms.end())
164  throw std::runtime_error("Working frame '" + link + "' is not a link in the scene state");
165 
166  working_frames_.push_back(link);
167  }
168  }
169 
170  // Configure the tip link frames
171  // The tip links can be any link in the fixed-joint kinematic tree that contains the input tip link
172  for (const auto& tip_link : tip_links)
173  {
174  const std::vector<std::string> tip_link_fixed_joint_kin_tree_links =
175  getLinksInFixedJointKinematicTree(tip_link, scene_graph);
176  for (const std::string& link : tip_link_fixed_joint_kin_tree_links)
177  {
178  // Check that the link exists in the scene state
179  if (state_.link_transforms.find(link) == state_.link_transforms.end())
180  throw std::runtime_error("Tip link '" + link + "' is not a link in the scene state");
181 
182  inv_tip_links_map_[link] = tip_link;
183  }
184  }
185 
186  inv_to_fwd_base_ = state_.link_transforms.at(inv_kin_->getBaseLinkName()).inverse() *
187  state_.link_transforms.at(state_solver_->getBaseLinkName());
188 
189  if (static_link_names_.size() + active_link_names.size() != scene_graph.getLinks().size())
190  throw std::runtime_error("KinematicGroup: Static link names are not correct!");
191 }
192 
193 KinematicGroup::KinematicGroup(const KinematicGroup& other) : JointGroup(other) { *this = other; }
194 
196 
198 {
199  JointGroup::operator=(other);
200  joint_names_ = other.joint_names_;
203  inv_kin_ = other.inv_kin_->clone();
207  return *this;
208 }
209 
211  const Eigen::Ref<const Eigen::VectorXd>& seed) const
212 {
213  // Convert to IK Inputs
215  for (const auto& tip_link_pose : tip_link_poses)
216  {
217  // Check that the specified pose working frame exists in the list of identified working frames
218  if (std::find(working_frames_.begin(), working_frames_.end(), tip_link_pose.working_frame) == working_frames_.end())
219  {
220  std::stringstream ss;
221  ss << "Specified working frame (" << tip_link_pose.working_frame
222  << ") is not in the list of identified working frames. Available working frames are: [";
223  for (const std::string& f : working_frames_)
224  ss << f << ", ";
225  ss << "].";
226  throw std::runtime_error(ss.str());
227  }
228 
229  // Check that specified pose tip link exists in the map of known tip links
230  if (inv_tip_links_map_.find(tip_link_pose.tip_link_name) == inv_tip_links_map_.end())
231  {
232  std::stringstream ss;
233  ss << "Failed to find specified tip link (" << tip_link_pose.tip_link_name << "). Available tip links are: [";
234  for (const auto& pair : inv_tip_links_map_)
235  ss << pair.first << ", ";
236  ss << "].";
237  throw std::runtime_error(ss.str());
238  }
239 
240  // Check that the orientation component of the specified pose is orthogonal
241  assert(std::abs(1.0 - tip_link_pose.pose.matrix().determinant()) < 1e-6); // NOLINT
242 
243  // The IK Solvers tip link and working frame
244  std::string ik_solver_tip_link = inv_tip_links_map_.at(tip_link_pose.tip_link_name);
245  std::string working_frame = inv_kin_->getWorkingFrame();
246 
247  // Get transform from working frame to user working frame (reference frame for the target IK pose)
248  const Eigen::Isometry3d& world_to_user_wf = state_.link_transforms.at(tip_link_pose.working_frame);
249  const Eigen::Isometry3d& world_to_wf = state_.link_transforms.at(working_frame);
250  const Eigen::Isometry3d wf_to_user_wf = world_to_wf.inverse() * world_to_user_wf;
251 
252  // Get the transform from IK solver tip link to the user tip link
253  const Eigen::Isometry3d& world_to_user_tl = state_.link_transforms.at(tip_link_pose.tip_link_name);
254  const Eigen::Isometry3d& world_to_tl = state_.link_transforms.at(ik_solver_tip_link);
255  const Eigen::Isometry3d tl_to_user_tl = world_to_tl.inverse() * world_to_user_tl;
256 
257  // Get the transformation from the IK solver working frame to the IK solver tip frame
258  const Eigen::Isometry3d& user_wf_to_user_tl = tip_link_pose.pose; // an unnecessary but helpful alias
259  const Eigen::Isometry3d wf_to_tl = wf_to_user_wf * user_wf_to_user_tl * tl_to_user_tl.inverse();
260 
261  ik_inputs[ik_solver_tip_link] = wf_to_tl;
262  }
263 
264  // format seed for inverse kinematic solver
265  if (reorder_required_)
266  {
267  Eigen::VectorXd ordered_seed = seed;
268  for (Eigen::Index i = 0; i < inv_kin_->numJoints(); ++i)
269  ordered_seed(inv_kin_joint_map_[static_cast<std::size_t>(i)]) = seed(i);
270 
271  IKSolutions solutions = inv_kin_->calcInvKin(ik_inputs, ordered_seed);
272  IKSolutions solutions_filtered;
273  solutions_filtered.reserve(solutions.size());
274  for (const auto& solution : solutions)
275  {
276  Eigen::VectorXd ordered_sol = solution;
277  for (Eigen::Index i = 0; i < inv_kin_->numJoints(); ++i)
278  ordered_sol(i) = solution(inv_kin_joint_map_[static_cast<std::size_t>(i)]);
279 
280  tesseract_kinematics::harmonizeTowardMedian<double>(ordered_sol, redundancy_indices_, limits_.joint_limits);
282  solutions_filtered.push_back(ordered_sol);
283  }
284 
285  return solutions_filtered;
286  }
287 
288  IKSolutions solutions = inv_kin_->calcInvKin(ik_inputs, seed);
289  IKSolutions solutions_filtered;
290  solutions_filtered.reserve(solutions.size());
291  for (auto& solution : solutions)
292  {
293  tesseract_kinematics::harmonizeTowardMedian<double>(solution, redundancy_indices_, limits_.joint_limits);
295  solutions_filtered.push_back(solution);
296  }
297 
298  return solutions_filtered;
299 }
300 
302  const Eigen::Ref<const Eigen::VectorXd>& seed) const
303 {
304  return calcInvKin(KinGroupIKInputs{ tip_link_pose }, seed); // NOLINT
305 }
306 
307 std::vector<std::string> KinematicGroup::getAllValidWorkingFrames() const { return working_frames_; }
308 
309 std::vector<std::string> KinematicGroup::getAllPossibleTipLinkNames() const
310 {
311  std::vector<std::string> ik_tip_links;
312  ik_tip_links.reserve(inv_tip_links_map_.size());
313  for (const auto& pair : inv_tip_links_map_)
314  ik_tip_links.push_back(pair.first);
315 
316  return ik_tip_links;
317 }
318 
320 
321 } // namespace tesseract_kinematics
tesseract_kinematics::KinGroupIKInput::KinGroupIKInput
KinGroupIKInput()=default
graph.h
tesseract_kinematics::KinGroupIKInput
Structure containing the data required to solve inverse kinematics.
Definition: kinematic_group.h:48
tesseract_common::isIdentical
bool isIdentical(const std::vector< T > &vec1, const std::vector< T > &vec2, bool ordered=true, const std::function< bool(const T &, const T &)> &equal_pred=[](const T &v1, const T &v2) { return v1==v2;}, const std::function< bool(const T &, const T &)> &comp=[](const T &v1, const T &v2) { return v1< v2;})
tesseract_scene_graph::SceneGraph::getLinks
std::vector< std::shared_ptr< const Link > > getLinks() const
tesseract_kinematics::KinematicGroup::~KinematicGroup
~KinematicGroup() override
utils.h
tesseract_common::TransformMap
AlignedMap< std::string, Eigen::Isometry3d > TransformMap
tesseract_kinematics::JointGroup
A Joint Group is defined by a list of joint_names.
Definition: joint_group.h:44
joint.h
inverse_kinematics.h
Inverse kinematics functions.
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
tesseract_kinematics::JointGroup::state_
tesseract_scene_graph::SceneState state_
Definition: joint_group.h:206
tesseract_scene_graph::SceneGraph
tesseract_kinematics::JointGroup::static_link_names_
std::vector< std::string > static_link_names_
Definition: joint_group.h:210
tesseract_kinematics::JointGroup::limits_
tesseract_common::KinematicLimits limits_
Definition: joint_group.h:212
tesseract_kinematics::KinGroupIKInputs
tesseract_common::AlignedVector< KinGroupIKInput > KinGroupIKInputs
Definition: kinematic_group.h:73
tesseract_scene_graph::SceneState
utils.h
Kinematics utility functions.
tesseract_kinematics::JointGroup::operator=
JointGroup & operator=(const JointGroup &other)
Definition: joint_group.cpp:111
tesseract_kinematics::KinematicGroup::joint_names_
std::vector< std::string > joint_names_
Definition: kinematic_group.h:153
tesseract_kinematics::KinematicGroup::getAllPossibleTipLinkNames
std::vector< std::string > getAllPossibleTipLinkNames() const
Get the tip link name.
Definition: kinematic_group.cpp:309
tesseract_kinematics::KinematicGroup::working_frames_
std::vector< std::string > working_frames_
Definition: kinematic_group.h:158
tesseract_kinematics::JointGroup::state_solver_
std::unique_ptr< tesseract_scene_graph::StateSolver > state_solver_
Definition: joint_group.h:207
tesseract_scene_graph::SceneGraph::getInboundJoints
std::vector< std::shared_ptr< const Joint > > getInboundJoints(const std::string &link_name) const
tesseract_kinematics::KinematicGroup::calcInvKin
IKSolutions calcInvKin(const KinGroupIKInputs &tip_link_poses, const Eigen::Ref< const Eigen::VectorXd > &seed) const
Calculates joint solutions given a pose.
Definition: kinematic_group.cpp:210
tesseract_kinematics::KinematicGroup::KinematicGroup
KinematicGroup(const KinematicGroup &other)
Definition: kinematic_group.cpp:193
tesseract_kinematics::KinematicGroup::inv_to_fwd_base_
Eigen::Isometry3d inv_to_fwd_base_
Definition: kinematic_group.h:157
tesseract_kinematics::KinematicGroup::inv_kin_joint_map_
std::vector< Eigen::Index > inv_kin_joint_map_
Definition: kinematic_group.h:155
state_solver.h
tesseract_kinematics::KinematicGroup::getAllValidWorkingFrames
std::vector< std::string > getAllValidWorkingFrames() const
Returns all possible working frames in which goal poses can be defined.
Definition: kinematic_group.cpp:307
tesseract_kinematics::KinematicGroup::inv_kin_
std::unique_ptr< InverseKinematics > inv_kin_
Definition: kinematic_group.h:156
tesseract_kinematics::KinematicGroup::getInverseKinematics
const InverseKinematics & getInverseKinematics() const
Get the inverse kinematics sovler.
Definition: kinematic_group.cpp:319
kinematic_group.h
A kinematic group with forward and inverse kinematics methods.
tesseract_kinematics::InverseKinematics
Inverse kinematics functions.
Definition: inverse_kinematics.h:43
TESSERACT_COMMON_IGNORE_WARNINGS_POP
#define TESSERACT_COMMON_IGNORE_WARNINGS_POP
getLinksInFixedJointKinematicTree
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH TESSERACT_COMMON_IGNORE_WARNINGS_POP std::vector< std::string > getLinksInFixedJointKinematicTree(const std::string &input_link, const tesseract_scene_graph::SceneGraph &scene_graph)
Returns the names of the links that comprise a fixed-joint kinematic tree with the input link.
Definition: kinematic_group.cpp:51
tesseract_kinematics
Definition: forward_kinematics.h:40
tesseract_kinematics::KinematicGroup::inv_tip_links_map_
std::unordered_map< std::string, std::string > inv_tip_links_map_
Definition: kinematic_group.h:159
tesseract_common::satisfiesLimits< double >
template bool satisfiesLimits< double >(const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 1 >> &values, const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 2 >> &limits, const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 1 >> &max_diff, const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 1 >> &max_rel_diff)
tesseract_kinematics::KinematicGroup::operator=
KinematicGroup & operator=(const KinematicGroup &other)
Definition: kinematic_group.cpp:197
tesseract_kinematics::KinematicGroup::reorder_required_
bool reorder_required_
Definition: kinematic_group.h:154
tesseract_scene_graph::SceneState::link_transforms
tesseract_common::TransformMap link_transforms
tesseract_kinematics::IKSolutions
std::vector< Eigen::VectorXd > IKSolutions
The inverse kinematics solutions container.
Definition: types.h:38
macros.h
tesseract_kinematics::KinematicGroup
Definition: kinematic_group.h:75
tesseract_common::KinematicLimits::joint_limits
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::MatrixX2d joint_limits
tesseract_scene_graph::JointType::FIXED
@ FIXED
tesseract_scene_graph::SceneGraph::getLinkChildrenNames
std::vector< std::string > getLinkChildrenNames(const std::string &name) const
tesseract_kinematics::JointGroup::redundancy_indices_
std::vector< Eigen::Index > redundancy_indices_
Definition: joint_group.h:213


tesseract_kinematics
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:02:14