moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Ioan Sucan */
36
37#include <algorithm>
38
39#include <geometric_shapes/solid_primitive_dims.h>
42#include <rclcpp/logger.hpp>
43#include <rclcpp/logging.hpp>
44#include <rclcpp/node.hpp>
45#include <rclcpp/parameter_value.hpp>
47
48#include <rclcpp/node.hpp>
49#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
50#include <tf2_eigen/tf2_eigen.hpp>
51
52using namespace moveit::core;
53
55{
56namespace
57{
58rclcpp::Logger getLogger()
59{
60 return moveit::getLogger("moveit.core.kinematic_constraints");
61}
62} // namespace
63
64moveit_msgs::msg::Constraints mergeConstraints(const moveit_msgs::msg::Constraints& first,
65 const moveit_msgs::msg::Constraints& second)
66{
67 moveit_msgs::msg::Constraints r;
68
69 // add all joint constraints that are in first but not in second
70 // and merge joint constraints that are for the same joint
71 for (const moveit_msgs::msg::JointConstraint& jc_first : first.joint_constraints)
72 {
73 bool add = true;
74 for (const moveit_msgs::msg::JointConstraint& jc_second : second.joint_constraints)
75 {
76 if (jc_second.joint_name == jc_first.joint_name)
77 {
78 add = false;
79 // now we merge
80 moveit_msgs::msg::JointConstraint m;
81 const moveit_msgs::msg::JointConstraint& a = jc_first;
82 const moveit_msgs::msg::JointConstraint& b = jc_second;
83 double low = std::max(a.position - a.tolerance_below, b.position - b.tolerance_below);
84 double high = std::min(a.position + a.tolerance_above, b.position + b.tolerance_above);
85 if (low > high)
86 {
87 RCLCPP_ERROR(getLogger(),
88 "Attempted to merge incompatible constraints for joint '%s'. Discarding constraint.",
89 a.joint_name.c_str());
90 }
91 else
92 {
93 m.joint_name = a.joint_name;
94 m.position =
95 std::max(low, std::min((a.position * a.weight + b.position * b.weight) / (a.weight + b.weight), high));
96 m.weight = (a.weight + b.weight) / 2.0;
97 m.tolerance_above = std::max(0.0, high - m.position);
98 m.tolerance_below = std::max(0.0, m.position - low);
99 r.joint_constraints.push_back(m);
100 }
101 break;
102 }
103 }
104 if (add)
105 r.joint_constraints.push_back(jc_first);
106 }
107
108 // add all joint constraints that are in second but not in first
109 for (const moveit_msgs::msg::JointConstraint& jc_second : second.joint_constraints)
110 {
111 bool add = true;
112 for (const moveit_msgs::msg::JointConstraint& jc_first : first.joint_constraints)
113 {
114 if (jc_second.joint_name == jc_first.joint_name)
115 {
116 add = false;
117 break;
118 }
119 }
120 if (add)
121 r.joint_constraints.push_back(jc_second);
122 }
123
124 // merge rest of constraints
125 r.position_constraints = first.position_constraints;
126 for (const moveit_msgs::msg::PositionConstraint& position_constraint : second.position_constraints)
127 r.position_constraints.push_back(position_constraint);
128
129 r.orientation_constraints = first.orientation_constraints;
130 for (const moveit_msgs::msg::OrientationConstraint& orientation_constraint : second.orientation_constraints)
131 r.orientation_constraints.push_back(orientation_constraint);
132
133 r.visibility_constraints = first.visibility_constraints;
134 for (const moveit_msgs::msg::VisibilityConstraint& visibility_constraint : second.visibility_constraints)
135 r.visibility_constraints.push_back(visibility_constraint);
136
137 return r;
138}
139
140std::size_t countIndividualConstraints(const moveit_msgs::msg::Constraints& constr)
141{
142 return constr.position_constraints.size() + constr.orientation_constraints.size() +
143 constr.visibility_constraints.size() + constr.joint_constraints.size();
144}
145
146moveit_msgs::msg::Constraints constructGoalConstraints(const moveit::core::RobotState& state,
147 const moveit::core::JointModelGroup* jmg, double tolerance)
148{
149 return constructGoalConstraints(state, jmg, tolerance, tolerance);
150}
151
152moveit_msgs::msg::Constraints constructGoalConstraints(const moveit::core::RobotState& state,
153 const moveit::core::JointModelGroup* jmg, double tolerance_below,
154 double tolerance_above)
155{
156 moveit_msgs::msg::Constraints goal;
157 std::vector<double> vals;
158 state.copyJointGroupPositions(jmg, vals);
159 goal.joint_constraints.resize(vals.size());
160 for (std::size_t i = 0; i < vals.size(); ++i)
161 {
162 goal.joint_constraints[i].joint_name = jmg->getVariableNames()[i];
163 goal.joint_constraints[i].position = vals[i];
164 goal.joint_constraints[i].tolerance_above = tolerance_above;
165 goal.joint_constraints[i].tolerance_below = tolerance_below;
166 goal.joint_constraints[i].weight = 1.0;
167 }
168
169 return goal;
170}
171
172bool updateJointConstraints(moveit_msgs::msg::Constraints& constraints, const moveit::core::RobotState& state,
174{
175 const std::vector<std::string>& jmg_active_joints = jmg->getActiveJointModelNames();
176
177 // For each constraint, update it if the joint is found within jmg
178 for (auto& constraint : constraints.joint_constraints)
179 {
180 const auto itr = find(jmg_active_joints.begin(), jmg_active_joints.end(), constraint.joint_name);
181 if (itr != jmg_active_joints.end())
182 {
183 constraint.position = state.getVariablePosition(constraint.joint_name);
184 }
185 // The joint was not found within jmg
186 else
187 {
188 return false;
189 }
190 }
191 return true;
192}
193
194moveit_msgs::msg::Constraints constructGoalConstraints(const std::string& link_name,
195 const geometry_msgs::msg::PoseStamped& pose,
196 double tolerance_pos, double tolerance_angle)
197{
198 moveit_msgs::msg::Constraints goal;
199
200 goal.position_constraints.resize(1);
201 moveit_msgs::msg::PositionConstraint& pcm = goal.position_constraints[0];
202 pcm.link_name = link_name;
203 pcm.target_point_offset.x = 0;
204 pcm.target_point_offset.y = 0;
205 pcm.target_point_offset.z = 0;
206 pcm.constraint_region.primitives.resize(1);
207 shape_msgs::msg::SolidPrimitive& bv = pcm.constraint_region.primitives[0];
208 bv.type = shape_msgs::msg::SolidPrimitive::SPHERE;
209 bv.dimensions.resize(geometric_shapes::solidPrimitiveDimCount<shape_msgs::msg::SolidPrimitive::SPHERE>());
210 bv.dimensions[shape_msgs::msg::SolidPrimitive::SPHERE_RADIUS] = tolerance_pos;
211
212 pcm.header = pose.header;
213 pcm.constraint_region.primitive_poses.resize(1);
214 // orientation of constraint region does not affect anything, since it is a sphere
215 pcm.constraint_region.primitive_poses[0].position = pose.pose.position;
216 pcm.weight = 1.0;
217
218 goal.orientation_constraints.resize(1);
219 moveit_msgs::msg::OrientationConstraint& ocm = goal.orientation_constraints[0];
220 ocm.parameterization = moveit_msgs::msg::OrientationConstraint::ROTATION_VECTOR;
221 ocm.link_name = link_name;
222 ocm.header = pose.header;
223 ocm.orientation = pose.pose.orientation;
224 ocm.absolute_x_axis_tolerance = tolerance_angle;
225 ocm.absolute_y_axis_tolerance = tolerance_angle;
226 ocm.absolute_z_axis_tolerance = tolerance_angle;
227 ocm.weight = 1.0;
228
229 return goal;
230}
231
232moveit_msgs::msg::Constraints constructGoalConstraints(const std::string& link_name,
233 const geometry_msgs::msg::PoseStamped& pose,
234 const std::vector<double>& tolerance_pos,
235 const std::vector<double>& tolerance_angle)
236{
237 moveit_msgs::msg::Constraints goal = constructGoalConstraints(link_name, pose);
238 if (tolerance_pos.size() == 3)
239 {
240 shape_msgs::msg::SolidPrimitive& bv = goal.position_constraints[0].constraint_region.primitives[0];
241 bv.type = shape_msgs::msg::SolidPrimitive::BOX;
242 bv.dimensions.resize(geometric_shapes::solidPrimitiveDimCount<shape_msgs::msg::SolidPrimitive::BOX>());
243 bv.dimensions[shape_msgs::msg::SolidPrimitive::BOX_X] = tolerance_pos[0];
244 bv.dimensions[shape_msgs::msg::SolidPrimitive::BOX_Y] = tolerance_pos[1];
245 bv.dimensions[shape_msgs::msg::SolidPrimitive::BOX_Z] = tolerance_pos[2];
246 }
247 if (tolerance_angle.size() == 3)
248 {
249 moveit_msgs::msg::OrientationConstraint& ocm = goal.orientation_constraints[0];
250 ocm.absolute_x_axis_tolerance = tolerance_angle[0];
251 ocm.absolute_y_axis_tolerance = tolerance_angle[1];
252 ocm.absolute_z_axis_tolerance = tolerance_angle[2];
253 }
254 return goal;
255}
256
257bool updatePoseConstraint(moveit_msgs::msg::Constraints& constraints, const std::string& link_name,
258 const geometry_msgs::msg::PoseStamped& pose)
259{
260 // Convert message types so the existing functions can be used
261 geometry_msgs::msg::PointStamped point;
262 point.header = pose.header;
263 point.point.x = pose.pose.position.x;
264 point.point.y = pose.pose.position.y;
265 point.point.z = pose.pose.position.z;
266
267 geometry_msgs::msg::QuaternionStamped quat_stamped;
268 quat_stamped.header = pose.header;
269 quat_stamped.quaternion = pose.pose.orientation;
270
271 return updatePositionConstraint(constraints, link_name, point) &&
272 updateOrientationConstraint(constraints, link_name, quat_stamped);
273}
274
275moveit_msgs::msg::Constraints constructGoalConstraints(const std::string& link_name,
276 const geometry_msgs::msg::QuaternionStamped& quat,
277 double tolerance)
278{
279 moveit_msgs::msg::Constraints goal;
280 goal.orientation_constraints.resize(1);
281 moveit_msgs::msg::OrientationConstraint& ocm = goal.orientation_constraints[0];
282 ocm.link_name = link_name;
283 ocm.header = quat.header;
284 ocm.orientation = quat.quaternion;
285 ocm.absolute_x_axis_tolerance = tolerance;
286 ocm.absolute_y_axis_tolerance = tolerance;
287 ocm.absolute_z_axis_tolerance = tolerance;
288 ocm.weight = 1.0;
289 return goal;
290}
291
292bool updateOrientationConstraint(moveit_msgs::msg::Constraints& constraints, const std::string& link_name,
293 const geometry_msgs::msg::QuaternionStamped& quat)
294{
295 for (auto& constraint : constraints.orientation_constraints)
296 {
297 if (constraint.link_name == link_name)
298 {
299 if (quat.header.frame_id.empty())
300 {
301 RCLCPP_ERROR(getLogger(), "Cannot update orientation constraint, frame_id in the header is empty");
302 return false;
303 }
304 constraint.header = quat.header;
305 constraint.orientation = quat.quaternion;
306 return true;
307 }
308 }
309 return false;
310}
311
312moveit_msgs::msg::Constraints constructGoalConstraints(const std::string& link_name,
313 const geometry_msgs::msg::PointStamped& goal_point,
314 double tolerance)
315{
316 geometry_msgs::msg::Point p;
317 p.x = 0;
318 p.y = 0;
319 p.z = 0;
320 return constructGoalConstraints(link_name, p, goal_point, tolerance);
321}
322
323bool updatePositionConstraint(moveit_msgs::msg::Constraints& constraints, const std::string& link_name,
324 const geometry_msgs::msg::PointStamped& goal_point)
325{
326 for (auto& constraint : constraints.position_constraints)
327 {
328 if (constraint.link_name == link_name)
329 {
330 if (goal_point.header.frame_id.empty())
331 {
332 RCLCPP_ERROR(getLogger(), "Cannot update position constraint, frame_id in the header is empty");
333 return false;
334 }
335 constraint.header = goal_point.header;
336 constraint.constraint_region.primitive_poses.at(0).position.x = goal_point.point.x;
337 constraint.constraint_region.primitive_poses.at(0).position.y = goal_point.point.y;
338 constraint.constraint_region.primitive_poses.at(0).position.z = goal_point.point.z;
339 return true;
340 }
341 }
342 return false;
343}
344
345moveit_msgs::msg::Constraints constructGoalConstraints(const std::string& link_name,
346 const geometry_msgs::msg::Point& reference_point,
347 const geometry_msgs::msg::PointStamped& goal_point,
348 double tolerance)
349{
350 moveit_msgs::msg::Constraints goal;
351 goal.position_constraints.resize(1);
352 moveit_msgs::msg::PositionConstraint& pcm = goal.position_constraints[0];
353 pcm.link_name = link_name;
354 pcm.target_point_offset.x = reference_point.x;
355 pcm.target_point_offset.y = reference_point.y;
356 pcm.target_point_offset.z = reference_point.z;
357 pcm.constraint_region.primitives.resize(1);
358 pcm.constraint_region.primitives[0].type = shape_msgs::msg::SolidPrimitive::SPHERE;
359 pcm.constraint_region.primitives[0].dimensions.resize(
360 geometric_shapes::solidPrimitiveDimCount<shape_msgs::msg::SolidPrimitive::SPHERE>());
361 pcm.constraint_region.primitives[0].dimensions[shape_msgs::msg::SolidPrimitive::SPHERE_RADIUS] = tolerance;
362
363 pcm.header = goal_point.header;
364 pcm.constraint_region.primitive_poses.resize(1);
365 pcm.constraint_region.primitive_poses[0].position = goal_point.point;
366
367 // orientation of constraint region does not affect anything, since it is a sphere
368 pcm.constraint_region.primitive_poses[0].orientation.x = 0.0;
369 pcm.constraint_region.primitive_poses[0].orientation.y = 0.0;
370 pcm.constraint_region.primitive_poses[0].orientation.z = 0.0;
371 pcm.constraint_region.primitive_poses[0].orientation.w = 1.0;
372 pcm.weight = 1.0;
373
374 return goal;
375}
376
377// Initialize a PoseStamped message from node parameters specified at pose_param.
378static bool constructPoseStamped(const rclcpp::Node::SharedPtr& node, const std::string& pose_param,
379 geometry_msgs::msg::PoseStamped& pose)
380{
381 if (!node->get_parameter(pose_param + ".frame_id", pose.header.frame_id))
382 return false;
383
384 std::vector<double> orientation;
385 if (!node->get_parameter(pose_param + ".orientation", orientation) || orientation.size() != 3)
386 return false;
387
388 tf2::Quaternion q;
389 q.setRPY(orientation[0], orientation[1], orientation[2]);
390 pose.pose.orientation = toMsg(q);
391
392 std::vector<double> position;
393 if (!node->get_parameter(pose_param + ".position", position) || position.size() != 3)
394 return false;
395
396 pose.pose.position.x = position[0];
397 pose.pose.position.y = position[1];
398 pose.pose.position.z = position[2];
399
400 return true;
401}
402
403// Initialize a JointConstraint message from node parameters specified at constraint_param.
404static bool constructConstraint(const rclcpp::Node::SharedPtr& node, const std::string& constraint_param,
405 moveit_msgs::msg::JointConstraint& constraint)
406{
407 node->get_parameter(constraint_param + ".weight", constraint.weight);
408 node->get_parameter(constraint_param + ".joint_name", constraint.joint_name);
409 node->get_parameter(constraint_param + ".position", constraint.position);
410
411 double tolerance;
412 if (node->get_parameter(constraint_param + ".tolerance", tolerance))
413 {
414 constraint.tolerance_below = tolerance;
415 constraint.tolerance_above = tolerance;
416 }
417 else if (node->has_parameter(constraint_param + ".tolerances"))
418 {
419 std::vector<double> tolerances;
420 node->get_parameter(constraint_param + ".tolerances", tolerances);
421 if (tolerances.size() != 2)
422 return false;
423
424 constraint.tolerance_below = tolerances[0];
425 constraint.tolerance_above = tolerances[1];
426 }
427 else if (node->has_parameter(constraint_param + ".bounds"))
428 {
429 std::vector<double> bounds;
430 node->get_parameter(constraint_param + ".bounds", bounds);
431 if (bounds.size() != 2)
432 return false;
433
434 const double lower_bound = bounds[0];
435 const double upper_bound = bounds[1];
436
437 constraint.position = (lower_bound + upper_bound) / 2;
438 constraint.tolerance_below = constraint.position - lower_bound;
439 constraint.tolerance_above = upper_bound - constraint.position;
440 }
441
442 return true;
443}
444
445// Initialize a PositionConstraint message from node parameters specified at constraint_param.
446static bool constructConstraint(const rclcpp::Node::SharedPtr& node, const std::string& constraint_param,
447 moveit_msgs::msg::PositionConstraint& constraint)
448{
449 node->get_parameter(constraint_param + ".frame_id", constraint.header.frame_id);
450 node->get_parameter(constraint_param + ".weight", constraint.weight);
451 node->get_parameter(constraint_param + ".link_name", constraint.link_name);
452
453 std::vector<double> target_offset;
454 if (node->get_parameter(constraint_param + ".target_offset", target_offset))
455 {
456 if (target_offset.size() != 3)
457 return false;
458
459 constraint.target_point_offset.x = target_offset[0];
460 constraint.target_point_offset.y = target_offset[1];
461 constraint.target_point_offset.z = target_offset[2];
462 }
463 if (!node->list_parameters({ constraint_param + ".region" }, 1).names.empty()) // TODO(henningkayser): specify depth
464 {
465 geometry_msgs::msg::Pose region_pose;
466 region_pose.orientation.w = 1.0;
467
468 shape_msgs::msg::SolidPrimitive region_primitive;
469 region_primitive.type = shape_msgs::msg::SolidPrimitive::BOX;
470 region_primitive.dimensions.resize(3);
471
472 const auto parse_dimension = [&](const std::string& dimension_param, double& center, double& dimension) -> bool {
473 std::vector<double> dimension_limits;
474 if (!node->get_parameter(constraint_param + ".region." + dimension_param, dimension_limits) ||
475 dimension_limits.size() != 2)
476 return false;
477
478 center = (dimension_limits[0] + dimension_limits[1]) / 2;
479 dimension = dimension_limits[1] - dimension_limits[2];
480 return true;
481 };
482
483 if (!parse_dimension("x", region_pose.position.x,
484 region_primitive.dimensions[shape_msgs::msg::SolidPrimitive::BOX_X]) ||
485 !parse_dimension("y", region_pose.position.y,
486 region_primitive.dimensions[shape_msgs::msg::SolidPrimitive::BOX_Y]) ||
487 !parse_dimension("z", region_pose.position.z,
488 region_primitive.dimensions[shape_msgs::msg::SolidPrimitive::BOX_Z]))
489 return false;
490
491 constraint.constraint_region.primitive_poses.push_back(region_pose);
492 constraint.constraint_region.primitives.emplace_back(region_primitive);
493 }
494
495 return true;
496}
497
498// Initialize an OrientationConstraint message from node parameters specified at constraint_param.
499static bool constructConstraint(const rclcpp::Node::SharedPtr& node, const std::string& constraint_param,
500 moveit_msgs::msg::OrientationConstraint& constraint)
501{
502 node->get_parameter(constraint_param + ".frame_id", constraint.header.frame_id);
503 node->get_parameter(constraint_param + ".weight", constraint.weight);
504 node->get_parameter(constraint_param + ".link_name", constraint.link_name);
505
506 std::vector<double> orientation;
507 if (node->get_parameter(constraint_param + ".orientation", orientation))
508 {
509 if (orientation.size() != 3)
510 return false;
511
512 tf2::Quaternion q;
513 q.setRPY(orientation[0], orientation[1], orientation[2]);
514 constraint.orientation = toMsg(q);
515 }
516
517 std::vector<double> tolerances;
518 if (node->get_parameter(constraint_param + ".tolerances", tolerances))
519 {
520 if (tolerances.size() != 3)
521 return false;
522
523 constraint.absolute_x_axis_tolerance = tolerances[0];
524 constraint.absolute_y_axis_tolerance = tolerances[1];
525 constraint.absolute_z_axis_tolerance = tolerances[2];
526 }
527
528 return true;
529}
530
531// Initialize a VisibilityConstraint message from node parameters specified at constraint_param.
532static bool constructConstraint(const rclcpp::Node::SharedPtr& node, const std::string& constraint_param,
533 moveit_msgs::msg::VisibilityConstraint& constraint)
534{
535 node->get_parameter(constraint_param + ".weight", constraint.weight);
536 node->get_parameter(constraint_param + ".target_radius", constraint.target_radius);
537 node->get_parameter(constraint_param + ".cone_sides", constraint.cone_sides);
538 node->get_parameter(constraint_param + ".max_view_angle", constraint.max_view_angle);
539 node->get_parameter(constraint_param + ".max_range_angle", constraint.max_range_angle);
540
541 // TODO(henningkayser): specify depth
542 if (!node->list_parameters({ constraint_param + ".target_pose" }, 1).names.empty())
543 {
544 if (!constructPoseStamped(node, constraint_param + ".target_pose", constraint.target_pose))
545 return false;
546 }
547 // TODO(henningkayser): specify depth
548 if (!node->list_parameters({ constraint_param + ".sensor_pose" }, 1).names.empty())
549 {
550 if (!constructPoseStamped(node, constraint_param + ".sensor_pose", constraint.sensor_pose))
551 return false;
552 }
553
554 constraint.sensor_view_direction = moveit_msgs::msg::VisibilityConstraint::SENSOR_X;
555
556 return true;
557}
558
559// Initialize a Constraints message containing constraints specified by node parameters under constraint_ids.
560static bool collectConstraints(const rclcpp::Node::SharedPtr& node, const std::vector<std::string>& constraint_ids,
561 moveit_msgs::msg::Constraints& constraints)
562{
563 for (const auto& constraint_id : constraint_ids)
564 {
565 const auto constraint_param = "constraints." + constraint_id;
566 if (!node->has_parameter(constraint_param + ".type"))
567 {
568 RCLCPP_ERROR(getLogger(), "constraint parameter \"%s\" does not specify its type", constraint_param.c_str());
569 return false;
570 }
571 std::string constraint_type;
572 node->get_parameter(constraint_param + ".type", constraint_type);
573 if (constraint_type == "joint")
574 {
575 constraints.joint_constraints.emplace_back();
576 if (!constructConstraint(node, constraint_param, constraints.joint_constraints.back()))
577 return false;
578 }
579 else if (constraint_type == "position")
580 {
581 constraints.position_constraints.emplace_back();
582 if (!constructConstraint(node, constraint_param, constraints.position_constraints.back()))
583 return false;
584 }
585 else if (constraint_type == "orientation")
586 {
587 constraints.orientation_constraints.emplace_back();
588 if (!constructConstraint(node, constraint_param, constraints.orientation_constraints.back()))
589 return false;
590 }
591 else if (constraint_type == "visibility")
592 {
593 constraints.visibility_constraints.emplace_back();
594 if (!constructConstraint(node, constraint_param, constraints.visibility_constraints.back()))
595 return false;
596 }
597 else
598 {
599 RCLCPP_ERROR_STREAM(getLogger(), "Unable to process unknown constraint type: " << constraint_type);
600 return false;
601 }
602 }
603
604 return true;
605}
606
607bool constructConstraints(const rclcpp::Node::SharedPtr& node, const std::string& constraints_param,
608 moveit_msgs::msg::Constraints& constraints)
609{
610 if (!node->get_parameter(constraints_param + ".name", constraints.name))
611 return false;
612
613 std::vector<std::string> constraint_ids;
614 if (!node->get_parameter(constraints_param + ".constraint_ids", constraint_ids))
615 return false;
616
617 for (auto& constraint_id : constraint_ids)
618 constraint_id.insert(0, constraints_param + std::string("."));
619
620 return collectConstraints(node, constraint_ids, constraints);
621}
622
623bool resolveConstraintFrames(const moveit::core::RobotState& state, moveit_msgs::msg::Constraints& constraints)
624{
625 for (auto& c : constraints.position_constraints)
626 {
627 bool frame_found;
628 const moveit::core::LinkModel* robot_link;
629 const Eigen::Isometry3d& transform = state.getFrameInfo(c.link_name, robot_link, frame_found);
630 if (!frame_found)
631 return false;
632
633 // If the frame of the constraint is not part of the robot link model (but an attached body or subframe),
634 // the constraint needs to be expressed in the frame of a robot link.
635 if (c.link_name != robot_link->getName())
636 {
637 Eigen::Isometry3d robot_link_to_link_name = state.getGlobalLinkTransform(robot_link).inverse() * transform;
638 Eigen::Vector3d offset_link_name(c.target_point_offset.x, c.target_point_offset.y, c.target_point_offset.z);
639 Eigen::Vector3d offset_robot_link = robot_link_to_link_name * offset_link_name;
640
641 c.link_name = robot_link->getName();
642 tf2::toMsg(offset_robot_link, c.target_point_offset);
643 }
644 }
645
646 for (auto& c : constraints.orientation_constraints)
647 {
648 bool frame_found;
649 const moveit::core::LinkModel* robot_link;
650 // getFrameInfo() returns a valid isometry by contract
651 const Eigen::Isometry3d& transform = state.getFrameInfo(c.link_name, robot_link, frame_found);
652 if (!frame_found)
653 return false;
654
655 // If the frame of the constraint is not part of the robot link model (but an attached body or subframe),
656 // the constraint needs to be expressed in the frame of a robot link.
657 if (c.link_name != robot_link->getName())
658 {
659 if (c.parameterization == moveit_msgs::msg::OrientationConstraint::XYZ_EULER_ANGLES)
660 {
661 RCLCPP_ERROR(getLogger(),
662 "Euler angles parameterization is not supported for non-link frames in orientation constraints. \n"
663 "Switch to rotation vector parameterization.");
664 return false;
665 }
666 c.link_name = robot_link->getName();
667 Eigen::Quaterniond link_name_to_robot_link(transform.linear().transpose() *
668 state.getGlobalLinkTransform(robot_link).linear());
669 // adapt goal orientation
670 Eigen::Quaterniond quat_target;
671 tf2::fromMsg(c.orientation, quat_target);
672 c.orientation = tf2::toMsg(quat_target * link_name_to_robot_link);
673 }
674 }
675 return true;
676}
677} // namespace kinematic_constraints
const std::vector< std::string > & getActiveJointModelNames() const
Get the names of the active joints in this group. These are the names of the joints returned by getJo...
const std::vector< std::string > & getVariableNames() const
Get the names of the variables that make up the joints included in this group. The number of returned...
A link from the robot. Contains the constant transform applied to the link and its geometry.
Definition link_model.h:72
const std::string & getName() const
The name of this link.
Definition link_model.h:86
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition robot_state.h:90
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
double getVariablePosition(const std::string &variable) const
Get the position of a particular variable. An exception is thrown if the variable is not known.
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
const Eigen::Isometry3d & getFrameInfo(const std::string &frame_id, const LinkModel *&robot_link, bool &frame_found) const
Get the transformation matrix from the model frame (root of model) to the frame identified by frame_i...
Representation and evaluation of kinematic constraints.
bool updateOrientationConstraint(moveit_msgs::msg::Constraints &constraints, const std::string &link_name, const geometry_msgs::msg::QuaternionStamped &quat)
Update an orientation constraint for one link with a new quaternion.
Definition utils.cpp:292
std::size_t countIndividualConstraints(const moveit_msgs::msg::Constraints &constr)
Definition utils.cpp:140
bool updatePositionConstraint(moveit_msgs::msg::Constraints &constraints, const std::string &link_name, const geometry_msgs::msg::PointStamped &goal_point)
Update a position constraint for one link with a new position.
Definition utils.cpp:323
moveit_msgs::msg::Constraints constructGoalConstraints(const moveit::core::RobotState &state, const moveit::core::JointModelGroup *jmg, double tolerance_below, double tolerance_above)
Generates a constraint message intended to be used as a goal constraint for a joint group....
Definition utils.cpp:152
bool updateJointConstraints(moveit_msgs::msg::Constraints &constraints, const moveit::core::RobotState &state, const moveit::core::JointModelGroup *jmg)
Update joint constraints with a new JointModelGroup state.
Definition utils.cpp:172
bool resolveConstraintFrames(const moveit::core::RobotState &state, moveit_msgs::msg::Constraints &constraints)
Resolves frames used in constraints to links in the robot model.
Definition utils.cpp:623
bool constructConstraints(const rclcpp::Node::SharedPtr &node, const std::string &constraints_param, moveit_msgs::msg::Constraints &constraints)
extract constraint message from node parameters.
Definition utils.cpp:607
bool updatePoseConstraint(moveit_msgs::msg::Constraints &constraints, const std::string &link_name, const geometry_msgs::msg::PoseStamped &pose)
Update a pose constraint for one link with a new pose.
Definition utils.cpp:257
moveit_msgs::msg::Constraints mergeConstraints(const moveit_msgs::msg::Constraints &first, const moveit_msgs::msg::Constraints &second)
Merge two sets of constraints into one.
Definition utils.cpp:64
Core components of MoveIt.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition logger.cpp:79