Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
demo_picking.py
1 #! /usr/bin/env python3
2 # Copyright 2021 Samsung Research America
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 from geometry_msgs.msg import PoseStamped
17 from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult
18 import rclpy
19 from rclpy.duration import Duration
20 
21 """
22 Basic item picking demo. In this demonstration, the expectation
23 is that there is a person at the item shelf to put the item on the robot
24 and at the pallet jack to remove it
25 (probably with some kind of button for 'got item, robot go do next task').
26 """
27 
28 # Shelf positions for picking
29 shelf_positions = {
30  'shelf_A': [8.21, 1.3, 1.57],
31  'shelf_B': [11.6, 1.3, -1.57],
32  'shelf_C': [12.6, 4.0, -1.57],
33  'shelf_D': [19.0, 4.0, 1.57],
34 }
35 
36 # Shipping destination for picked products
37 shipping_destinations = {
38  'frieght_bay_1': [-6.0, 5.0, 3.14],
39  'frieght_bay_2': [-6.0, 0.0, 3.14],
40  'frieght_bay_3': [-6.0, -5.0, 3.14],
41 }
42 
43 
44 def main() -> None:
45  # Received virtual request for picking item at Shelf A and bring to
46  # worker at the pallet jack 7 for shipping. This request would
47  # contain the shelf ID ('shelf_A') and shipping destination ('frieght_bay_3')
48 
49  request_item_location = 'shelf_A'
50  request_destination = 'frieght_bay_3'
51 
52 
53  rclpy.init()
54 
55  navigator = BasicNavigator()
56 
57  # Set our demo's initial pose
58  initial_pose = PoseStamped()
59  initial_pose.header.frame_id = 'map'
60  initial_pose.header.stamp = navigator.get_clock().now().to_msg()
61  initial_pose.pose.position.x = 0.0
62  initial_pose.pose.position.y = 0.0
63  initial_pose.pose.orientation.z = 0.0
64  initial_pose.pose.orientation.w = 1.0
65  navigator.setInitialPose(initial_pose)
66 
67  # Wait for navigation to fully activate
68  navigator.waitUntilNav2Active()
69 
70  shelf_item_pose = PoseStamped()
71  shelf_item_pose.header.frame_id = 'map'
72  shelf_item_pose.header.stamp = navigator.get_clock().now().to_msg()
73  shelf_item_pose.pose.position.x = shelf_positions[request_item_location][0]
74  shelf_item_pose.pose.position.y = shelf_positions[request_item_location][1]
75  # Simplification of angle handling for demonstration purposes
76  if shelf_positions[request_item_location][2] > 0:
77  shelf_item_pose.pose.orientation.z = 0.707
78  shelf_item_pose.pose.orientation.w = 0.707
79  else:
80  shelf_item_pose.pose.orientation.z = -0.707
81  shelf_item_pose.pose.orientation.w = 0.707
82  print(f'Received request for item picking at {request_item_location}.')
83  go_to_pose_task = navigator.goToPose(shelf_item_pose)
84 
85  # Do something during our route
86  # (e.x. queue up future tasks or detect person for fine-tuned positioning)
87  # Simply print information for workers on the robot's ETA for the demonstration
88  i = 0
89  while not navigator.isTaskComplete(task=go_to_pose_task):
90  i += 1
91  feedback = navigator.getFeedback(task=go_to_pose_task)
92  if feedback and i % 5 == 0:
93  print(
94  'Estimated time of arrival at '
95  + request_item_location
96  + ' for worker: '
97  + '{:.0f}'.format(
98  Duration.from_msg(feedback.estimated_time_remaining).nanoseconds
99  / 1e9
100  )
101  + ' seconds.'
102  )
103 
104  result = navigator.getResult()
105  if result == TaskResult.SUCCEEDED:
106  print(
107  'Got product from '
108  + request_item_location
109  + '! Bringing product to shipping destination ('
110  + request_destination
111  + ')...'
112  )
113  shipping_destination = PoseStamped()
114  shipping_destination.header.frame_id = 'map'
115  shipping_destination.header.stamp = navigator.get_clock().now().to_msg()
116  shipping_destination.pose.position.x = shipping_destinations[
117  request_destination
118  ][0]
119  shipping_destination.pose.position.y = shipping_destinations[
120  request_destination
121  ][1]
122  shipping_destination.pose.orientation.z = 1.0
123  shipping_destination.pose.orientation.w = 0.0
124  go_to_pose_task = navigator.goToPose(shipping_destination)
125 
126  elif result == TaskResult.CANCELED:
127  print(
128  f'Task at {request_item_location} was canceled. Returning to staging point...'
129  )
130  initial_pose.header.stamp = navigator.get_clock().now().to_msg()
131  navigator.goToPose(initial_pose)
132 
133  elif result == TaskResult.FAILED:
134  (error_code, error_msg) = navigator.getTaskError()
135  print(f'Task at {request_item_location} failed!:'
136  f'{error_code}:{error_msg}')
137  exit(-1)
138 
139  while not navigator.isTaskComplete(task=go_to_pose_task):
140  pass
141 
142  exit(0)
143 
144 
145 if __name__ == '__main__':
146  main()