|
5 | 5 | from compas.utilities import await_callback |
6 | 6 |
|
7 | 7 | from compas_fab.backends.interfaces import InverseKinematics |
8 | | -from compas_fab.backends.ros.backend_features.helpers import validate_response |
9 | 8 | from compas_fab.backends.ros.backend_features.helpers import convert_constraints_to_rosmsg |
| 9 | +from compas_fab.backends.ros.backend_features.helpers import validate_response |
| 10 | +from compas_fab.backends.ros.messages import RosDistro |
10 | 11 | from compas_fab.backends.ros.messages import AttachedCollisionObject |
11 | 12 | from compas_fab.backends.ros.messages import GetPositionIKRequest |
12 | 13 | from compas_fab.backends.ros.messages import GetPositionIKResponse |
|
18 | 19 | from compas_fab.backends.ros.messages import PositionIKRequest |
19 | 20 | from compas_fab.backends.ros.messages import RobotState |
20 | 21 | from compas_fab.backends.ros.service_description import ServiceDescription |
| 22 | +from compas_fab.robots import Duration |
21 | 23 |
|
22 | 24 | __all__ = [ |
23 | 25 | 'MoveItInverseKinematics', |
@@ -61,10 +63,12 @@ def inverse_kinematics(self, robot, frame_WCF, start_configuration=None, group=N |
61 | 63 | - ``"constraints"``: (:obj:`list` of :class:`compas_fab.robots.Constraint`, optional) |
62 | 64 | A set of constraints that the request must obey. |
63 | 65 | Defaults to ``None``. |
64 | | - - ``"attempts"``: (:obj:`int`, optional) The maximum number of inverse kinematic attempts. |
65 | | - Defaults to ``8``. |
| 66 | + - ``"timeout"``: (:obj:`int`, optional) Maximum allowed time for inverse kinematic calculation in seconds. |
| 67 | + Defaults to ``2``. This value supersedes the ``"attempts"`` argument used before ROS Noetic. |
66 | 68 | - ``"attached_collision_meshes"``: (:obj:`list` of :class:`compas_fab.robots.AttachedCollisionMesh`, optional) |
67 | 69 | Defaults to ``None``. |
| 70 | + - ``"attempts"``: (:obj:`int`, optional) The maximum number of inverse kinematic attempts. |
| 71 | + Defaults to ``8``. This value is ignored on ROS Noetic and newer, use ``"timeout"`` instead. |
68 | 72 |
|
69 | 73 | Raises |
70 | 74 | ------ |
@@ -108,12 +112,22 @@ def inverse_kinematics_async(self, callback, errback, |
108 | 112 |
|
109 | 113 | constraints = convert_constraints_to_rosmsg(options.get('constraints'), header) |
110 | 114 |
|
| 115 | + timeout_in_secs = options.get('timeout', 2) |
| 116 | + timeout_duration = Duration(timeout_in_secs, 0).to_data() |
| 117 | + |
111 | 118 | ik_request = PositionIKRequest(group_name=group, |
112 | 119 | robot_state=start_state, |
113 | 120 | constraints=constraints, |
114 | 121 | pose_stamped=pose_stamped, |
115 | 122 | avoid_collisions=options.get('avoid_collisions', True), |
116 | | - attempts=options.get('attempts', 8)) |
| 123 | + attempts=options.get('attempts', 8), |
| 124 | + timeout=timeout_duration) |
| 125 | + |
| 126 | + # The field `attempts` was removed in Noetic (and higher) |
| 127 | + # so it needs to be removed from the message otherwise it causes a serialization error |
| 128 | + # https://github.com/ros-planning/moveit/pull/1288 |
| 129 | + if self.ros_client.ros_distro not in (RosDistro.KINETIC, RosDistro.MELODIC): |
| 130 | + del ik_request.attempts |
117 | 131 |
|
118 | 132 | def convert_to_positions(response): |
119 | 133 | callback((response.solution.joint_state.position, response.solution.joint_state.name)) |
|
0 commit comments