joystick_and_video.py
Go to the documentation of this file.
1 """
2 tellopy sample using joystick and video palyer
3 
4  - you can use PS3/PS4/XONE joystick to controll DJI Tello with tellopy module
5  - you must install mplayer to replay the video
6  - Xbox One Controllers were only tested on Mac OS with the 360Controller Driver.
7  get it here -> https://github.com/360Controller/360Controller'''
8 """
9 
10 import time
11 import sys
12 import tellopy
13 import pygame
14 import pygame.locals
15 from subprocess import Popen, PIPE
16 import threading
17 import av
18 import cv2.cv2 as cv2 # for avoidance of pylint error
19 import numpy
20 import time
21 import traceback
22 
23 
25  # d-pad
26  UP = 4 # UP
27  DOWN = 6 # DOWN
28  ROTATE_LEFT = 7 # LEFT
29  ROTATE_RIGHT = 5 # RIGHT
30 
31  # bumper triggers
32  TAKEOFF = 11 # R1
33  LAND = 10 # L1
34  # UNUSED = 9 #R2
35  # UNUSED = 8 #L2
36 
37  # buttons
38  FORWARD = 12 # TRIANGLE
39  BACKWARD = 14 # CROSS
40  LEFT = 15 # SQUARE
41  RIGHT = 13 # CIRCLE
42 
43  # axis
44  LEFT_X = 0
45  LEFT_Y = 1
46  RIGHT_X = 2
47  RIGHT_Y = 3
48  LEFT_X_REVERSE = 1.0
49  LEFT_Y_REVERSE = -1.0
50  RIGHT_X_REVERSE = 1.0
51  RIGHT_Y_REVERSE = -1.0
52  DEADZONE = 0.1
53 
54 
56  # d-pad
57  UP = -1 # UP
58  DOWN = -1 # DOWN
59  ROTATE_LEFT = -1 # LEFT
60  ROTATE_RIGHT = -1 # RIGHT
61 
62  # bumper triggers
63  TAKEOFF = 5 # R1
64  LAND = 4 # L1
65  # UNUSED = 7 #R2
66  # UNUSED = 6 #L2
67 
68  # buttons
69  FORWARD = 3 # TRIANGLE
70  BACKWARD = 1 # CROSS
71  LEFT = 0 # SQUARE
72  RIGHT = 2 # CIRCLE
73 
74  # axis
75  LEFT_X = 0
76  LEFT_Y = 1
77  RIGHT_X = 2
78  RIGHT_Y = 3
79  LEFT_X_REVERSE = 1.0
80  LEFT_Y_REVERSE = -1.0
81  RIGHT_X_REVERSE = 1.0
82  RIGHT_Y_REVERSE = -1.0
83  DEADZONE = 0.08
84 
85 
87  # d-pad
88  UP = -1 # UP
89  DOWN = -1 # DOWN
90  ROTATE_LEFT = -1 # LEFT
91  ROTATE_RIGHT = -1 # RIGHT
92 
93  # bumper triggers
94  TAKEOFF = 5 # R1
95  LAND = 4 # L1
96  # UNUSED = 7 #R2
97  # UNUSED = 6 #L2
98 
99  # buttons
100  FORWARD = 3 # TRIANGLE
101  BACKWARD = 1 # CROSS
102  LEFT = 0 # SQUARE
103  RIGHT = 2 # CIRCLE
104 
105  # axis
106  LEFT_X = 0
107  LEFT_Y = 1
108  RIGHT_X = 3
109  RIGHT_Y = 4
110  LEFT_X_REVERSE = 1.0
111  LEFT_Y_REVERSE = -1.0
112  RIGHT_X_REVERSE = 1.0
113  RIGHT_Y_REVERSE = -1.0
114  DEADZONE = 0.08
115 
117  # d-pad
118  UP = -1 # UP
119  DOWN = -1 # DOWN
120  ROTATE_LEFT = -1 # LEFT
121  ROTATE_RIGHT = -1 # RIGHT
122 
123  # bumper triggers
124  TAKEOFF = 5 # R1
125  LAND = 4 # L1
126  # UNUSED = 7 #R2
127  # UNUSED = 6 #L2
128 
129  # buttons
130  FORWARD = 3 # Y
131  BACKWARD = 0 # B
132  LEFT = 2 # X
133  RIGHT = 1 # A
134 
135  # axis
136  LEFT_X = 0
137  LEFT_Y = 1
138  RIGHT_X = 3
139  RIGHT_Y = 4
140  LEFT_X_REVERSE = 1.0
141  LEFT_Y_REVERSE = -1.0
142  RIGHT_X_REVERSE = 1.0
143  RIGHT_Y_REVERSE = -1.0
144  DEADZONE = 0.08
145 
147  # d-pad
148  UP = 0 # UP
149  DOWN = 1 # DOWN
150  ROTATE_LEFT = 2 # LEFT
151  ROTATE_RIGHT = 3 # RIGHT
152 
153  # bumper triggers
154  TAKEOFF = 9 # RB
155  LAND = 8 # LB
156  # UNUSED = 7 #RT
157  # UNUSED = 6 #LT
158 
159  # buttons
160  FORWARD = 14 # Y
161  BACKWARD = 11 # A
162  LEFT = 13 # X
163  RIGHT = 12 # B
164 
165  # axis
166  LEFT_X = 0
167  LEFT_Y = 1
168  RIGHT_X = 2
169  RIGHT_Y = 3
170  LEFT_X_REVERSE = 1.0
171  LEFT_Y_REVERSE = -1.0
172  RIGHT_X_REVERSE = 1.0
173  RIGHT_Y_REVERSE = -1.0
174  DEADZONE = 0.09
175 
176 
178  # d-pad
179  UP = -1 # UP
180  DOWN = -1 # DOWN
181  ROTATE_LEFT = -1 # LEFT
182  ROTATE_RIGHT = -1 # RIGHT
183 
184  # bumper triggers
185  TAKEOFF = 12 # left switch
186  LAND = 12 # left switch
187  # UNUSED = 7 #RT
188  # UNUSED = 6 #LT
189 
190  # buttons
191  FORWARD = -1
192  BACKWARD = -1
193  LEFT = -1
194  RIGHT = -1
195 
196  # axis
197  LEFT_X = 3
198  LEFT_Y = 0
199  RIGHT_X = 1
200  RIGHT_Y = 2
201  LEFT_X_REVERSE = 1.0
202  LEFT_Y_REVERSE = 1.0
203  RIGHT_X_REVERSE = 1.0
204  RIGHT_Y_REVERSE = 1.0
205  DEADZONE = 0.01
206 
207 
208 prev_flight_data = None
209 run_recv_thread = True
210 new_image = None
211 flight_data = None
212 log_data = None
213 buttons = None
214 speed = 100
215 throttle = 0.0
216 yaw = 0.0
217 pitch = 0.0
218 roll = 0.0
219 
220 def handler(event, sender, data, **args):
221  global prev_flight_data
222  global flight_data
223  global log_data
224  drone = sender
225  if event is drone.EVENT_FLIGHT_DATA:
226  if prev_flight_data != str(data):
227  print(data)
228  prev_flight_data = str(data)
229  flight_data = data
230  elif event is drone.EVENT_LOG_DATA:
231  log_data = data
232  else:
233  print('event="%s" data=%s' % (event.getname(), str(data)))
234 
235 
236 def update(old, new, max_delta=0.3):
237  if abs(old - new) <= max_delta:
238  res = new
239  else:
240  res = 0.0
241  return res
242 
243 
244 def handle_input_event(drone, e):
245  global speed
246  global throttle
247  global yaw
248  global pitch
249  global roll
250  if e.type == pygame.locals.JOYAXISMOTION:
251  # ignore small input values (Deadzone)
252  if -buttons.DEADZONE <= e.value and e.value <= buttons.DEADZONE:
253  e.value = 0.0
254  if e.axis == buttons.LEFT_Y:
255  throttle = update(throttle, e.value * buttons.LEFT_Y_REVERSE)
256  drone.set_throttle(throttle)
257  if e.axis == buttons.LEFT_X:
258  yaw = update(yaw, e.value * buttons.LEFT_X_REVERSE)
259  drone.set_yaw(yaw)
260  if e.axis == buttons.RIGHT_Y:
261  pitch = update(pitch, e.value *
262  buttons.RIGHT_Y_REVERSE)
263  drone.set_pitch(pitch)
264  if e.axis == buttons.RIGHT_X:
265  roll = update(roll, e.value * buttons.RIGHT_X_REVERSE)
266  drone.set_roll(roll)
267  elif e.type == pygame.locals.JOYHATMOTION:
268  if e.value[0] < 0:
269  drone.counter_clockwise(speed)
270  if e.value[0] == 0:
271  drone.clockwise(0)
272  if e.value[0] > 0:
273  drone.clockwise(speed)
274  if e.value[1] < 0:
275  drone.down(speed)
276  if e.value[1] == 0:
277  drone.up(0)
278  if e.value[1] > 0:
279  drone.up(speed)
280  elif e.type == pygame.locals.JOYBUTTONDOWN:
281  if e.button == buttons.LAND:
282  drone.land()
283  elif e.button == buttons.UP:
284  drone.up(speed)
285  elif e.button == buttons.DOWN:
286  drone.down(speed)
287  elif e.button == buttons.ROTATE_RIGHT:
288  drone.clockwise(speed)
289  elif e.button == buttons.ROTATE_LEFT:
290  drone.counter_clockwise(speed)
291  elif e.button == buttons.FORWARD:
292  drone.forward(speed)
293  elif e.button == buttons.BACKWARD:
294  drone.backward(speed)
295  elif e.button == buttons.RIGHT:
296  drone.right(speed)
297  elif e.button == buttons.LEFT:
298  drone.left(speed)
299  elif e.type == pygame.locals.JOYBUTTONUP:
300  if e.button == buttons.TAKEOFF:
301  if throttle != 0.0:
302  print('###')
303  print('### throttle != 0.0 (This may hinder the drone from taking off)')
304  print('###')
305  drone.takeoff()
306  elif e.button == buttons.UP:
307  drone.up(0)
308  elif e.button == buttons.DOWN:
309  drone.down(0)
310  elif e.button == buttons.ROTATE_RIGHT:
311  drone.clockwise(0)
312  elif e.button == buttons.ROTATE_LEFT:
313  drone.counter_clockwise(0)
314  elif e.button == buttons.FORWARD:
315  drone.forward(0)
316  elif e.button == buttons.BACKWARD:
317  drone.backward(0)
318  elif e.button == buttons.RIGHT:
319  drone.right(0)
320  elif e.button == buttons.LEFT:
321  drone.left(0)
322 
323 def draw_text(image, text, row):
324  font = cv2.FONT_HERSHEY_SIMPLEX
325  font_scale = 0.5
326  font_size = 24
327  font_color = (255,255,255)
328  bg_color = (0,0,0)
329  d = 2
330  height, width = image.shape[:2]
331  left_mergin = 10
332  if row < 0:
333  pos = (left_mergin, height + font_size * row + 1)
334  else:
335  pos = (left_mergin, font_size * (row + 1))
336  cv2.putText(image, text, pos, font, font_scale, bg_color, 6)
337  cv2.putText(image, text, pos, font, font_scale, font_color, 1)
338 
339 def recv_thread(drone):
340  global run_recv_thread
341  global new_image
342  global flight_data
343  global log_data
344 
345  print('start recv_thread()')
346  try:
347  container = av.open(drone.get_video_stream())
348  # skip first 300 frames
349  frame_skip = 300
350  while True:
351  for frame in container.decode(video=0):
352  if 0 < frame_skip:
353  frame_skip = frame_skip - 1
354  continue
355  start_time = time.time()
356  image = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
357 
358  if flight_data:
359  draw_text(image, 'TelloPy: joystick_and_video ' + str(flight_data), 0)
360  if log_data:
361  draw_text(image, 'MVO: ' + str(log_data.mvo), -3)
362  draw_text(image, ('IMU: ' + str(log_data.imu))[0:52], -2)
363  draw_text(image, ' ' + ('IMU: ' + str(log_data.imu))[52:], -1)
364  new_image = image
365  if frame.time_base < 1.0/60:
366  time_base = 1.0/60
367  else:
368  time_base = frame.time_base
369  frame_skip = int((time.time() - start_time)/time_base)
370  except Exception as ex:
371  exc_type, exc_value, exc_traceback = sys.exc_info()
372  traceback.print_exception(exc_type, exc_value, exc_traceback)
373  print(ex)
374 
375 def main():
376  global buttons
377  global run_recv_thread
378  global new_image
379  pygame.init()
380  pygame.joystick.init()
381  current_image = None
382 
383  try:
384  js = pygame.joystick.Joystick(0)
385  js.init()
386  js_name = js.get_name()
387  print('Joystick name: ' + js_name)
388  if js_name in ('Wireless Controller', 'Sony Computer Entertainment Wireless Controller'):
389  buttons = JoystickPS4
390  elif js_name == 'Sony Interactive Entertainment Wireless Controller':
391  buttons = JoystickPS4ALT
392  elif js_name in ('PLAYSTATION(R)3 Controller', 'Sony PLAYSTATION(R)3 Controller'):
393  buttons = JoystickPS3
394  elif js_name in ('Logitech Gamepad F310'):
395  buttons = JoystickF310
396  elif js_name == 'Xbox One Wired Controller':
397  buttons = JoystickXONE
398  elif js_name == 'FrSky Taranis Joystick':
399  buttons = JoystickTARANIS
400  except pygame.error:
401  pass
402 
403  if buttons is None:
404  print('no supported joystick found')
405  return
406 
407  drone = tellopy.Tello()
408  drone.connect()
409  drone.subscribe(drone.EVENT_FLIGHT_DATA, handler)
410  drone.subscribe(drone.EVENT_LOG_DATA, handler)
411  threading.Thread(target=recv_thread, args=[drone]).start()
412 
413  try:
414  while 1:
415  # loop with pygame.event.get() is too much tight w/o some sleep
416  time.sleep(0.01)
417  for e in pygame.event.get():
418  handle_input_event(drone, e)
419  if current_image is not new_image:
420  cv2.imshow('Tello', new_image)
421  current_image = new_image
422  cv2.waitKey(1)
423  except KeyboardInterrupt as e:
424  print(e)
425  except Exception as e:
426  exc_type, exc_value, exc_traceback = sys.exc_info()
427  traceback.print_exception(exc_type, exc_value, exc_traceback)
428  print(e)
429 
430  run_recv_thread = False
431  cv2.destroyAllWindows()
432  drone.quit()
433  exit(1)
434 
435 
436 if __name__ == '__main__':
437  main()
def update(old, new, max_delta=0.3)
def handler(event, sender, data, args)


tello_driver
Author(s): Jordy van Appeven
autogenerated on Wed May 13 2020 03:34:54