box_stacking_example.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 # coding: utf-8
3 
4 # Copyright 2019 RT Corporation
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 
18 import rospy
19 import math
20 import sys
21 
22 from visualization_msgs.msg import Marker, MarkerArray
23 from geometry_msgs.msg import Pose
24 
25 # for NeckYawPitch
26 import actionlib
27 from control_msgs.msg import (
28  FollowJointTrajectoryAction,
29  FollowJointTrajectoryGoal,
30  JointTrajectoryControllerState
31 )
32 from trajectory_msgs.msg import JointTrajectoryPoint
33 
34 # for Stacker
35 import moveit_commander
36 import actionlib
37 from tf.transformations import quaternion_from_euler
38 from control_msgs.msg import GripperCommandAction, GripperCommandGoal
39 
40 
41 class NeckYawPitch(object):
42  def __init__(self):
43  self._client = actionlib.SimpleActionClient("/sciurus17/controller3/neck_controller/follow_joint_trajectory",
44  FollowJointTrajectoryAction)
45  self._client.wait_for_server(rospy.Duration(5.0))
46  if not self._client.wait_for_server(rospy.Duration(5.0)):
47  rospy.logerr("Action Server Not Found")
48  rospy.signal_shutdown("Action Server not found")
49  sys.exit(1)
50 
51 
52  def set_angle(self, yaw_angle, pitch_angle, goal_secs=1.0e-9):
53  # 首を指定角度に動かす
54  # Moves the neck to the designated angle.
55  goal = FollowJointTrajectoryGoal()
56  goal.trajectory.joint_names = ["neck_yaw_joint", "neck_pitch_joint"]
57 
58  yawpoint = JointTrajectoryPoint()
59  yawpoint.positions.append(yaw_angle)
60  yawpoint.positions.append(pitch_angle)
61  yawpoint.time_from_start = rospy.Duration(goal_secs)
62  goal.trajectory.points.append(yawpoint)
63 
64  self._client.send_goal(goal)
65  self._client.wait_for_result(rospy.Duration(0.1))
66  return self._client.get_result()
67 
68 
69 class Stacker(object):
70  _RIGHT_ARM = 1
71  _LEFT_ARM = 2
72  # グリッパの開閉角度(radians)
73  # Gripper opening and closing angles (radians)
74  _GRIPPER_OPEN = 0.8
75  _GRIPPER_CLOSE = 0.42
76 
77  def __init__(self):
78  self._markers = MarkerArray()
79 
80  self._marker_sub = rospy.Subscriber("/sciurus17/example/markers",
81  MarkerArray, self._markers_callback, queue_size=1)
82 
83  self._right_arm = moveit_commander.MoveGroupCommander("r_arm_waist_group")
84  self._right_arm.set_max_velocity_scaling_factor(0.1)
85  self._right_gripper = actionlib.SimpleActionClient("/sciurus17/controller1/right_hand_controller/gripper_cmd", GripperCommandAction)
86  self._right_gripper.wait_for_server()
87 
88  self._left_arm = moveit_commander.MoveGroupCommander("l_arm_waist_group")
89  self._left_arm.set_max_velocity_scaling_factor(0.1)
90  self._left_gripper = actionlib.SimpleActionClient("/sciurus17/controller2/left_hand_controller/gripper_cmd", GripperCommandAction)
91  self._left_gripper.wait_for_server()
92 
93  self._gripper_goal = GripperCommandGoal()
94  self._gripper_goal.command.max_effort = 2.0
95 
96  # アームとグリッパー姿勢の初期化
97  # Initializes arm and gripper pose
98  self.initialize_arms()
99 
100  self._current_arm = None
101 
102 
103  def _markers_callback(self, msg):
104  self._markers = msg
105 
107  return len(self._markers.markers)
108 
110  # 一番高さが低いオブジェクトのPoseを返す
111  # Returns the Pose of the object with the lowest height.
112 
113  lowest_z = 1000
114  lowest_pose = Pose()
115 
116  for marker in self._markers.markers:
117  if marker.pose.position.z < lowest_z:
118  # marker.pose.position は箱の中心座標を表す
119  lowest_pose = marker.pose
120  lowest_z = marker.pose.position.z
121  lowest_pose.position.z += marker.scale.z * 0.5 # 箱の大きさ分高さを加算する
122 
123  return lowest_pose
124 
126  # 一番高さが高いオブジェクトのPoseを返す
127  # Returns the Pose of the object with the highest height
128 
129  highest_z = 0
130  highest_pose = Pose()
131 
132  for marker in self._markers.markers:
133  if marker.pose.position.z > highest_z:
134  # marker.pose.position は箱の中心座標を表す
135  # marker.pose.position represents the box centre coordinates
136  highest_pose = marker.pose
137  highest_z = marker.pose.position.z
138  # 箱の大きさ分高さを加算する
139  # Adds the box size to the height.
140  highest_pose.position.z += marker.scale.z * 0.5
141 
142  return highest_pose
143 
144 
145  def _move_arm(self, current_arm, target_pose):
146  if current_arm == self._RIGHT_ARM:
147  # 手先を下に向ける
148  # Points the hand tip downwards.
149  q = quaternion_from_euler(3.14/2.0, 0.0, 0.0)
150  target_pose.orientation.x = q[0]
151  target_pose.orientation.y = q[1]
152  target_pose.orientation.z = q[2]
153  target_pose.orientation.w = q[3]
154  self._right_arm.set_pose_target(target_pose)
155  return self._right_arm.go()
156  elif current_arm == self._LEFT_ARM:
157  # 手先を下に向ける
158  # Points the hand tip downwards.
159  q = quaternion_from_euler(-3.14/2.0, 0.0, 0.0)
160  target_pose.orientation.x = q[0]
161  target_pose.orientation.y = q[1]
162  target_pose.orientation.z = q[2]
163  target_pose.orientation.w = q[3]
164  self._left_arm.set_pose_target(target_pose)
165  return self._left_arm.go()
166  else:
167  return False
168 
169 
170  def _move_arm_to_init_pose(self, current_arm):
171  if current_arm == self._RIGHT_ARM:
172  self._right_arm.set_named_target("r_arm_waist_init_pose")
173  return self._right_arm.go()
174  elif current_arm == self._LEFT_ARM:
175  self._left_arm.set_named_target("l_arm_waist_init_pose")
176  return self._left_arm.go()
177  else:
178  return False
179 
180 
181  def _open_gripper(self, current_arm):
182  if current_arm == self._RIGHT_ARM:
183  self._gripper_goal.command.position = self._GRIPPER_OPEN
184  self._right_gripper.send_goal(self._gripper_goal)
185  return self._right_gripper.wait_for_result(rospy.Duration(1.0))
186  elif current_arm == self._LEFT_ARM:
187  self._gripper_goal.command.position = -self._GRIPPER_OPEN
188  self._left_gripper.send_goal(self._gripper_goal)
189  return self._left_gripper.wait_for_result(rospy.Duration(1.0))
190  else:
191  return False
192 
193 
194  def _close_gripper(self, current_arm):
195  if current_arm == self._RIGHT_ARM:
196  self._gripper_goal.command.position = self._GRIPPER_CLOSE
197  self._right_gripper.send_goal(self._gripper_goal)
198  elif current_arm == self._LEFT_ARM:
199  self._gripper_goal.command.position = -self._GRIPPER_CLOSE
200  self._left_gripper.send_goal(self._gripper_goal)
201  else:
202  return False
203 
204 
205  def initialize_arms(self):
208  self._open_gripper(self._RIGHT_ARM)
209  self._open_gripper(self._LEFT_ARM)
210 
211 
212  def pick_up(self, check_result):
213  # 一番高さが低いオブジェクトを持ち上げる
214  # Lifts the object with the lowest height.
215  rospy.loginfo("PICK UP")
216  result = True
217  # 制御対象を初期化
218  # Initialize control target.
219  self._current_arm = None
220 
221  # オブジェクトがなければ終了
222  # Exits if no object
223  rospy.sleep(1.0)
224  if self.get_num_of_markers() == 0:
225  rospy.logwarn("NO OBJECTS")
226  return False
227 
228  object_pose = self._get_lowest_object_pose()
229 
230  # オブジェクトの位置によって左右のどちらの手で取るかを判定する
231  # Determines whether the object should be taken with the left or right hand depending on its position.
232  if object_pose.position.y < 0:
233  self._current_arm = self._RIGHT_ARM
234  rospy.loginfo("Set right arm")
235  else:
236  self._current_arm = self._LEFT_ARM
237  rospy.loginfo("Set left arm")
238 
239  self._open_gripper(self._current_arm)
240 
241  # Z軸方向のオフセット meters
242  # Offset in Z-axis (meters)
243  APPROACH_OFFSET = 0.10
244  PREPARE_OFFSET = 0.06
245  LEAVE_OFFSET = 0.10
246 
247  # 目標手先姿勢の生成
248  # Generates target hand pose
249  target_pose = Pose()
250  target_pose.position.x = object_pose.position.x
251  target_pose.position.y = object_pose.position.y
252  target_pose.position.z = object_pose.position.z
253 
254  # 掴む準備をする
255  # Prepares to grasp
256  target_pose.position.z = object_pose.position.z + APPROACH_OFFSET
257  if self._move_arm(self._current_arm, target_pose) is False and check_result:
258  rospy.logwarn("Approach failed")
259  result = False
260 
261  else:
262  rospy.sleep(1.0)
263  # ハンドを下げる
264  # Lowers the hand
265  target_pose.position.z = object_pose.position.z + PREPARE_OFFSET
266  if self._move_arm(self._current_arm, target_pose) is False and check_result:
267  rospy.logwarn("Preparation grasping failed")
268  result = False
269 
270  else:
271  rospy.sleep(1.0)
272  # つかむ
273  # Grasps
274  if self._close_gripper(self._current_arm) is False and check_result:
275  rospy.logwarn("Grasping failed")
276  result = False
277 
278  rospy.sleep(1.0)
279  # ハンドを上げる
280  # Raises the hand
281  target_pose.position.z = object_pose.position.z + LEAVE_OFFSET
282  self._move_arm(self._current_arm, target_pose)
283 
284 
285  if result is False:
286  rospy.sleep(1.0)
287  # 失敗したときは安全のため手を広げる
288  # Opens the hand for safety if it fails
289  self._open_gripper(self._current_arm)
290 
291  rospy.sleep(1.0)
292  # 初期位置に戻る
293  # Returns to initial position
295 
296  return result
297 
298 
299  def place_on(self, check_result, target_x=0.3, target_y=0):
300  # 座標x,yにオブジェクトを配置する
301  # Places the object at coordinates x,y
302  rospy.loginfo("PLACE on :" + str(target_x) + ", " + str(target_y))
303  result = True
304 
305  # 制御アームが設定されているかチェック
306  # Checks if the control arm is set
307  if self._current_arm is None:
308  rospy.logwarn("NO ARM SELECTED")
309  return False
310 
311  # Z軸方向のオフセット meters
312  # Offset in Z-axis direction meters.
313  APPROACH_OFFSET = 0.14
314  PREPARE_OFFSET = 0.10
315  LEAVE_OFFSET = 0.14
316 
317  # 目標手先姿勢の生成
318  # Generates target hand pose
319  target_pose = Pose()
320  target_pose.position.x = target_x
321  target_pose.position.y = target_y
322  target_pose.position.z = 0.0
323 
324  # 置く準備をする
325  # Prepares to place
326  target_pose.position.z = APPROACH_OFFSET
327  if self._move_arm(self._current_arm, target_pose) is False and check_result:
328  rospy.logwarn("Approach failed")
329  result = False
330  else:
331  rospy.sleep(1.0)
332  # ハンドを下げる
333  # Lowers the hand
334  target_pose.position.z = PREPARE_OFFSET
335  if self._move_arm(self._current_arm, target_pose) is False and check_result:
336  rospy.logwarn("Preparation release failed")
337  result = False
338  else:
339  rospy.sleep(1.0)
340  # はなす
341  # Release
342  self._open_gripper(self._current_arm)
343  # ハンドを上げる
344  # Raises the hand
345  target_pose.position.z = LEAVE_OFFSET
346  self._move_arm(self._current_arm, target_pose)
347 
348  if result is False:
349  rospy.sleep(1.0)
350  # 失敗したときは安全のため手を広げる
351  # Opens the hand for safety if it fails to move the arm.
352  self._open_gripper(self._current_arm)
353 
354  rospy.sleep(1.0)
355  # 初期位置に戻る
356  # Returns to initial position
358 
359  return result
360 
361 
362  def place_on_highest_object(self, check_result):
363  # 一番高さが高いオブジェクトの上に配置する
364  # Places on top of the highest object
365  rospy.loginfo("PLACE ON HIGHEST OBJECT")
366  result = True
367 
368  # 制御アームが設定されているかチェック
369  # Checks if the control arm is set
370  if self._current_arm is None:
371  rospy.logwarn("NO ARM SELECTED")
372  return False
373 
374  # オブジェクトが他になければデフォルト位置に置く
375  # Places the object in the default position if no other object exists
376  rospy.sleep(1.0)
377  if self.get_num_of_markers() == 0:
378  rospy.logwarn("NO OBJECTS")
379  return self.place_on(check_result)
380 
381  object_pose = self._get_highest_object_pose()
382 
383  # Z軸方向のオフセット meters
384  # Offset in Z-axis direction meters
385  APPROACH_OFFSET = 0.15
386  PREPARE_OFFSET = 0.11
387  LEAVE_OFFSET = 0.15
388 
389  # 目標手先姿勢の生成
390  # Generates target hand pose
391  target_pose = Pose()
392  target_pose.position.x = object_pose.position.x
393  target_pose.position.y = object_pose.position.y
394  target_pose.position.z = object_pose.position.z
395 
396  # 置く準備をする
397  # Prepares to place
398  target_pose.position.z = object_pose.position.z + APPROACH_OFFSET
399  if self._move_arm(self._current_arm, target_pose) is False and check_result:
400  rospy.logwarn("Approach failed")
401  result = False
402  else:
403  rospy.sleep(1.0)
404  # ハンドを下げる
405  # Lowers the hand
406  target_pose.position.z = object_pose.position.z + PREPARE_OFFSET
407  if self._move_arm(self._current_arm, target_pose) is False and check_result:
408  rospy.logwarn("Preparation release failed")
409  result = False
410  else:
411  rospy.sleep(1.0)
412  # はなす
413  # Release
414  self._open_gripper(self._current_arm)
415  # ハンドを上げる
416  # Raises the hand
417  target_pose.position.z = object_pose.position.z + LEAVE_OFFSET
418  self._move_arm(self._current_arm, target_pose)
419 
420  if result is False:
421  rospy.sleep(1.0)
422  # 失敗したときは安全のため手を広げる
423  # Opens the hand for safety if it fails to move the arm.
424  self._open_gripper(self._current_arm)
425 
426  rospy.sleep(1.0)
427  # 初期位置に戻る
428  # Returns to initial position
430 
431  return result
432 
433 
435  # 首の角度を戻す
436  # Moves the neck to 0 degrees
437  neck.set_angle(math.radians(0), math.radians(0), 3.0)
438  # 両腕を初期位置に戻す
439  # Moves both arms to initial position
440  stacker.initialize_arms()
441 
442 
443 def main():
444  r = rospy.Rate(60)
445 
446  rospy.on_shutdown(hook_shutdown)
447 
448  # 首の初期角度 degree
449  # Initial angle of neck in degree
450  INITIAL_YAW_ANGLE = 0
451  INITIAL_PITCH_ANGLE = -70
452  # 首を下に傾けてテーブル上のものを見る
453  # Tilts neck down to see objects on the table
454  neck.set_angle(math.radians(INITIAL_YAW_ANGLE), math.radians(INITIAL_PITCH_ANGLE))
455 
456  PICKING_MODE = 0
457  PLACE_MODE = 1
458  current_mode = PICKING_MODE
459 
460  # 箱の配置位置 meter
461  # Box placement position in meter
462  PLACE_X = 0.3
463  PLACE_Y = 0.0
464 
465  # アームとグリッパが正しく動いたかチェックする
466  # Checks if arm and gripper moved correctly
467  CHECK_RESULT = True
468 
469  while not rospy.is_shutdown():
470  if current_mode == PICKING_MODE:
471  if stacker.get_num_of_markers() > 0:
472  # マーカがあれば、1番高さが低いオブジェクトを掴み上げる
473  # If there is a marker, picks up the object with the lowest height.
474  if stacker.pick_up(CHECK_RESULT) is False:
475  rospy.logwarn("PickUp Failed")
476  else:
477  rospy.loginfo("PickUp Succeeded")
478  current_mode = PLACE_MODE
479  else:
480  rospy.loginfo("NO MARKERS")
481  rospy.sleep(1.0)
482 
483  elif current_mode == PLACE_MODE:
484  if stacker.get_num_of_markers() == 0:
485  # マーカがなければ、指定位置に配置
486  # If there is no marker, places it at the specified position
487  if stacker.place_on(CHECK_RESULT, PLACE_X, PLACE_Y) is False:
488  rospy.logwarn("Place Failed")
489  else:
490  rospy.loginfo("Place Succeeded")
491 
492  else:
493  # マーカがあれば、一番高い位置にあるオブジェクトの上に配置
494  # If there is a marker, places it on top of the highest object
495  if stacker.place_on_highest_object(CHECK_RESULT) is False:
496  rospy.logwarn("Place Failed")
497  else:
498  rospy.loginfo("Place Succeeded")
499 
500  current_mode = PICKING_MODE
501 
502  r.sleep()
503 
504 
505 if __name__ == '__main__':
506  rospy.init_node("box_stacking_example")
507 
508  neck = NeckYawPitch()
509  stacker = Stacker()
510 
511  main()
512 
box_stacking_example.Stacker._move_arm_to_init_pose
def _move_arm_to_init_pose(self, current_arm)
Definition: box_stacking_example.py:170
box_stacking_example.Stacker._GRIPPER_OPEN
float _GRIPPER_OPEN
Definition: box_stacking_example.py:74
box_stacking_example.Stacker._get_lowest_object_pose
def _get_lowest_object_pose(self)
Definition: box_stacking_example.py:109
box_stacking_example.Stacker.initialize_arms
def initialize_arms(self)
Definition: box_stacking_example.py:205
box_stacking_example.Stacker._open_gripper
def _open_gripper(self, current_arm)
Definition: box_stacking_example.py:181
box_stacking_example.Stacker._markers_callback
def _markers_callback(self, msg)
Definition: box_stacking_example.py:103
box_stacking_example.main
def main()
Definition: box_stacking_example.py:443
box_stacking_example.NeckYawPitch.set_angle
def set_angle(self, yaw_angle, pitch_angle, goal_secs=1.0e-9)
Definition: box_stacking_example.py:52
box_stacking_example.Stacker._move_arm
def _move_arm(self, current_arm, target_pose)
Definition: box_stacking_example.py:145
box_stacking_example.NeckYawPitch.__init__
def __init__(self)
Definition: box_stacking_example.py:42
box_stacking_example.Stacker
Definition: box_stacking_example.py:69
box_stacking_example.Stacker._marker_sub
_marker_sub
Definition: box_stacking_example.py:80
box_stacking_example.NeckYawPitch._client
_client
Definition: box_stacking_example.py:43
actionlib::SimpleActionClient
box_stacking_example.Stacker.place_on
def place_on(self, check_result, target_x=0.3, target_y=0)
Definition: box_stacking_example.py:299
box_stacking_example.Stacker._right_arm
_right_arm
Definition: box_stacking_example.py:83
box_stacking_example.Stacker._get_highest_object_pose
def _get_highest_object_pose(self)
Definition: box_stacking_example.py:125
box_stacking_example.NeckYawPitch
Definition: box_stacking_example.py:41
box_stacking_example.Stacker._gripper_goal
_gripper_goal
Definition: box_stacking_example.py:93
box_stacking_example.Stacker._left_gripper
_left_gripper
Definition: box_stacking_example.py:90
box_stacking_example.hook_shutdown
def hook_shutdown()
Definition: box_stacking_example.py:434
box_stacking_example.Stacker._markers
_markers
Definition: box_stacking_example.py:78
box_stacking_example.Stacker._GRIPPER_CLOSE
float _GRIPPER_CLOSE
Definition: box_stacking_example.py:75
box_stacking_example.Stacker._RIGHT_ARM
int _RIGHT_ARM
Definition: box_stacking_example.py:70
box_stacking_example.Stacker.get_num_of_markers
def get_num_of_markers(self)
Definition: box_stacking_example.py:106
box_stacking_example.Stacker._LEFT_ARM
int _LEFT_ARM
Definition: box_stacking_example.py:71
box_stacking_example.Stacker._current_arm
_current_arm
Definition: box_stacking_example.py:100
box_stacking_example.Stacker._right_gripper
_right_gripper
Definition: box_stacking_example.py:85
box_stacking_example.Stacker.pick_up
def pick_up(self, check_result)
Definition: box_stacking_example.py:212
box_stacking_example.Stacker._close_gripper
def _close_gripper(self, current_arm)
Definition: box_stacking_example.py:194
box_stacking_example.Stacker.__init__
def __init__(self)
Definition: box_stacking_example.py:77
box_stacking_example.Stacker.place_on_highest_object
def place_on_highest_object(self, check_result)
Definition: box_stacking_example.py:362
box_stacking_example.Stacker._left_arm
_left_arm
Definition: box_stacking_example.py:88


sciurus17_examples
Author(s): Daisuke Sato , Hiroyuki Nomura
autogenerated on Fri Aug 2 2024 08:37:20