66from sensor_msgs .msg import BatteryState , NavSatFix , Image , NavSatStatus
77from geometry_msgs .msg import PoseStamped , TwistStamped , Pose , Point , Quaternion , Twist , Vector3
88from cv_bridge import CvBridge
9+ import tf
910from tf .transformations import quaternion_from_euler
1011
1112import cv2
@@ -27,6 +28,18 @@ def process_mask(mask):
2728 return 1991 # vx vy vz yaw_rate
2829
2930
31+ class TelloConstraints :
32+ MIN_SPEED = 10
33+ MAX_SPEED = 100
34+
35+ def constraint_speed (self , s ):
36+ '''
37+ s: speed (cm/s)
38+ '''
39+ return self .MIN_SPEED if s < self .MIN_SPEED else self .MAX_SPEED if s > self .MAX_SPEED else s
40+
41+
42+
3043class TelloConnectionError (Exception ):
3144 pass
3245
@@ -35,11 +48,13 @@ class TelloConnectionError(Exception):
3548class TelloDriver :
3649 STILL_ALIVE_RATE = 10 # sec
3750 PUB_RATE = 100000000 # nsec --> 0.1 secs
51+ TF_RATE = 100000000 # nsec --> 0.1 secs
3852 RESP_TIMEOUT = 7 # sec
3953 CMD_ADDRESS = ('192.168.10.1' , 8889 )
4054 STATE_ADDRESS = ('0.0.0.0' , 8890 )
4155 VIDEO_ADDRESS = ('0.0.0.0' , 11111 )
4256 LOCAL_ADDRESS = ('0.0.0.0' , 9000 )
57+ CONSTRAINTS = TelloConstraints ()
4358
4459 def __init__ (self , emergency_disabled = False ):
4560 self .sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
@@ -63,6 +78,7 @@ def __init__(self, emergency_disabled=False):
6378 self .__vy = 0.0 # cm/s
6479 self .__vz = 0.0 # cm/s
6580 self .__yaw_rate = 0.0 # degrees/s
81+ self .__speed = 100.0 # cm/s (DEFAULT VALUE)
6682
6783 self .state_pub = rospy .Publisher ('mavros/state' , State , queue_size = 10 )
6884 self .ext_state_pub = rospy .Publisher ('mavros/extended_state' , ExtendedState , queue_size = 10 )
@@ -108,14 +124,20 @@ def __init__(self, emergency_disabled=False):
108124 rospy .logerr (ex )
109125 self .shutdown ()
110126
111- rospy .Timer (rospy .Duration (nsecs = self .PUB_RATE ), self .send_data )
127+ self .pub_timer = rospy .Timer (rospy .Duration (nsecs = self .PUB_RATE ), self .send_data )
128+
129+ self .tb_map = tf .TransformBroadcaster ()
130+ self .tb_map_timer = rospy .Timer (rospy .Duration (nsecs = self .TF_RATE ), self .br_map2ned )
131+ self .tb_base = tf .TransformBroadcaster ()
132+ self .tb_base_timer = rospy .Timer (rospy .Duration (nsecs = self .TF_RATE ), self .br_base2frd )
133+
112134 if emergency_disabled :
113- rospy .Timer (rospy .Duration (secs = self .STILL_ALIVE_RATE ), self .__still_alive )
135+ self . still_alive_timer = rospy .Timer (rospy .Duration (secs = self .STILL_ALIVE_RATE ), self .__still_alive )
114136
115137 def __still_alive (self , event ):
116138 self .__send_cmd ("battery?" )
117139
118- def __send_cmd (self , cmd , blocking = True , timeout = RESP_TIMEOUT ):
140+ def __send_cmd (self , cmd , reading = False , blocking = True , timeout = RESP_TIMEOUT ):
119141 print ("Sending... {}" .format (cmd )) # DEBUG
120142 self .sock .sendto (cmd .encode (encoding = "utf-8" ), self .CMD_ADDRESS )
121143
@@ -128,6 +150,8 @@ def __send_cmd(self, cmd, blocking=True, timeout=RESP_TIMEOUT):
128150 time .sleep (0.1 ) # waits a bit
129151
130152 resp = self .__responses .pop (0 ).decode ("utf-8" )
153+ if reading :
154+ return resp
131155 if resp .lower () == "ok" :
132156 return True
133157 else :
@@ -213,12 +237,35 @@ def tello_land(self, req):
213237 else :
214238 return False , 1
215239
240+ def tello_change_speed (self , speed ):
241+ '''speed in m/s'''
242+ speed = self .CONSTRAINTS .constraint_speed (speed * 100 ) # to cm/s
243+
244+ if self .__send_cmd ("speed {}" .format (str (speed ))):
245+ rospy .loginfo ("Tello speed updated to " + str (speed ))
246+ rospy .set_param ("/tello/speed" , speed )
247+ return True
248+ else :
249+ return False
250+
216251 def tello_param_set (self , req ):
217252 # string param_id
218253 # mavros_msgs/ParamValue value
219254 # ----
220255 # bool success
221256 # mavros_msgs/ParamValue value
257+
258+ if req .param_id == "MPC_XY_VEL_MAX" :
259+ if req .value .integer != 0 :
260+ speed = req .value .integer
261+ elif req .value .real != 0.0 :
262+ speed = req .value .real
263+ else :
264+ speed = 0
265+
266+ self .tello_change_speed (int (speed ))
267+ return True , req .value
268+
222269 return False , ParamValue (integer = 0 , real = 0.0 )
223270
224271 def tello_param_get (self , req ):
@@ -292,9 +339,9 @@ def setpoint_cb(self, msg):
292339 self .__x += target_x
293340
294341 if x > 0 :
295- self .__send_cmd ("forward {}" .format (abs (x )), False ) # cm
342+ self .__send_cmd ("forward {}" .format (abs (x )), blocking = False ) # cm
296343 elif x < 0 :
297- self .__send_cmd ("back {}" .format (abs (x )), False ) # cm
344+ self .__send_cmd ("back {}" .format (abs (x )), blocking = False ) # cm
298345 else :
299346 pass # already at target x
300347 # print("Already at target x")
@@ -310,9 +357,9 @@ def setpoint_cb(self, msg):
310357 cmd_right = "right" if is_frd else "left"
311358 cmd_left = "left" if is_frd else "right"
312359 if y > 0 :
313- self .__send_cmd (cmd_right + " {}" .format (abs (y )), False ) # cm
360+ self .__send_cmd (cmd_right + " {}" .format (abs (y )), blocking = False ) # cm
314361 elif y < 0 :
315- self .__send_cmd (cmd_left + " {}" .format (abs (y )), False ) # cm
362+ self .__send_cmd (cmd_left + " {}" .format (abs (y )), blocking = False ) # cm
316363 else :
317364 pass # already at target y
318365 # print("Already at target y")
@@ -328,9 +375,9 @@ def setpoint_cb(self, msg):
328375 cmd_down = "down" if is_frd else "up"
329376 cmd_up = "up" if is_frd else "down"
330377 if z > 0 :
331- self .__send_cmd (cmd_down + " {}" .format (abs (z )), False ) # cm
378+ self .__send_cmd (cmd_down + " {}" .format (abs (z )), blocking = False ) # cm
332379 elif z < 0 :
333- self .__send_cmd (cmd_up + " {}" .format (abs (z )), False ) # cm
380+ self .__send_cmd (cmd_up + " {}" .format (abs (z )), blocking = False ) # cm
334381 else :
335382 pass # already at target z
336383 # print("Already at target z")
@@ -377,9 +424,9 @@ def setpoint_cb(self, msg):
377424 self .__yaw += target_yaw
378425
379426 if yaw > 0 :
380- self .__send_cmd ("cw {}" .format (abs (yaw )), False ) # degrees
427+ self .__send_cmd ("cw {}" .format (abs (yaw )), blocking = False ) # degrees
381428 elif yaw < 0 :
382- self .__send_cmd ("ccw {}" .format (abs (yaw )), False ) # degrees
429+ self .__send_cmd ("ccw {}" .format (abs (yaw )), blocking = False ) # degrees
383430 else :
384431 pass # already at target yaw
385432 # print("Already at target yaw")
@@ -549,6 +596,12 @@ def rcv_video(self):
549596 cap .release ()
550597 cv2 .destroyAllWindows ()
551598
599+ def br_map2ned (self , event ):
600+ self .tb_map .sendTransform ((0 ,0 ,0 ), (0.707 , 0.707 , 0.000 , 0.000 ), rospy .Time .now (), "map_ned" , "map" )
601+
602+ def br_base2frd (self , event ):
603+ self .tb_base .sendTransform ((0 ,0 ,0 ), (1 , 0 , 0 , 0 ), rospy .Time .now (), "base_link_frd" , "base_link" )
604+
552605 def shutdown (self ):
553606 if self .__is_flying :
554607 self .tello_land (CommandTOL ())
@@ -571,6 +624,15 @@ def shutdown(self):
571624 if self .video_handler .is_alive ():
572625 self .video_handler .join ()
573626
627+ try :
628+ self .pub_timer .shutdown ()
629+ self .tb_map_timer .shutdown ()
630+ self .tb_base_timer .shutdown ()
631+ if self .__emergency_disabled :
632+ self .still_alive_timer .shutdown ()
633+ except AttributeError :
634+ pass
635+
574636 rospy .loginfo ("Tello driver shutting down" )
575637
576638 def __del__ (self ):
0 commit comments