Hello Tello Pilot!
Join our DJI Tello community & remove this banner.
Sign up

SWARM of 2 Tello Drones (Simple Tello / Non-EDU Version)

a4aleem

New member
Joined
Oct 29, 2021
Messages
3
Reaction score
1
All I do is, connect both Tellos' to different wifi dongles and send commands via socket programming, the operating system I am on is, Ubuntu 18.04 below is the code...

import socket
import time

drone_1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
drone_1.setsockopt(socket.SOL_SOCKET, 25, 'wlxd03745aa6775'.encode()) #'wlxd03745aa6775' it will be different to your wifi dongle (check yours' using ifconfig command in Linux / Ubuntu OS).

drone_2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
drone_2.setsockopt(socket.SOL_SOCKET, 25, 'wlxd03745ab21eb'.encode())

drone_1.sendto('command'.encode(), 0, ('192.168.10.1', 8889))
drone_2.sendto('command'.encode(), 0, ('192.168.10.1', 8889))

#%%Code to takeoff:
drone_1.sendto('takeoff'.encode(), 0, ('192.168.10.1', 8889))
drone_2.sendto('takeoff'.encode(), 0, ('192.168.10.1', 8889))

#%%Code to land:
drone_1.sendto('land'.encode(), 0, ('192.168.10.1', 8889))
drone_2.sendto('land'.encode(), 0, ('192.168.10.1', 8889))
 

Attachments

  • vlcsnap-2021-10-30-18h32m46s944.png
    vlcsnap-2021-10-30-18h32m46s944.png
    262.6 KB · Views: 18
  • Tello_SWARM_Code.zip
    375 bytes · Views: 8
  • Test Flight Videos.zip
    9.5 MB · Views: 8

martinpi

Well-known member
Joined
Dec 15, 2019
Messages
110
Reaction score
53
Location
Vienna. Austria
Website
martinpi.at
Thanks a lot!
I own a normal Tello and an EDU, and I thought about doing a swarm using a second wifi dongle. It should work by setting the EDU into station mode, but your solution is a lot easier.
And it opens up swarm programming for non-EDU users.

Does anyone know how to get the equiivalent of "wlxd03745aa6775" under Windows?
When looking up ip addresses etc, I use ipconfig, but this does not show anythong that looks similar to wlxd03745aa6775
 

martinpi

Well-known member
Joined
Dec 15, 2019
Messages
110
Reaction score
53
Location
Vienna. Austria
Website
martinpi.at
I made it!

1) It really works under Linux only (tested on Raspberry Pi). When I try it under Windows, setsockopt reports an illegal argument.
2) I did not find any documentation on option name 25, but it works
3) The option value is the name of the network adapter. wlan0 and wlan1 on the raspi. I was confused because your wlxd03745aa6775 looks like adapter name + MAC address.

I modified the Tello3.py, so that all commands go to both Tello's.
In the terminal window, the dialog gets a little mixed up because my debug messages interfere with the lines.
So the screenshot looks a bit funny, but basically it works.

Thanks again for sharing!
 

Attachments

  • first-swarm-flight.jpg
    first-swarm-flight.jpg
    129 KB · Views: 8

martinpi

Well-known member
Joined
Dec 15, 2019
Messages
110
Reaction score
53
Location
Vienna. Austria
Website
martinpi.at
I tried to attach the python file, but it is not shown here.
So I copy&paste the code here. It is definitely far from perfect, just a proof of concept.


Code:
# tello demo by Ryze Robotics, modified by Martin Piehslinger


import threading
import socket
import sys
import time


#-----------------------------------------------------------------------------------
def recv1():
    global TimeSent
    global Ready
    global Running
    global DataDecoded
    
    print ("Tello recv task 1 started")
    count = 0
    while Running:
        RecvError = False
        try:
            data, server = sock1.recvfrom(1518)
        except Exception as e:
            RecvError = True
            if (str(e) == 'timed out'):
                print (".", end = "") # python2 users, please remove this line
                pass
            else:
                log ('\n------------------- Exception: ' + str(e) + '\n')
                break
        if (not RecvError):
            Time = (time.time() - TimeSent)
            DataDecoded = data.decode(encoding="utf-8")
            print('-1-:' + DataDecoded)
            Ready = True




    print ("recv ended")
#-----------------------------------------------------------------------------------
def recv2():
    global TimeSent
    global Ready
    global Running
    global DataDecoded
    
    print ("Tello recv task 2 started")
    count = 0
    while Running:
        RecvError = False
        try:
            data, server = sock2.recvfrom(1518)
        except Exception as e:
            RecvError = True
            if (str(e) == 'timed out'):
                print (".", end = "") # python2 users, please remove this line
                pass
            else:
                log ('\n------------------- Exception: ' + str(e) + '\n')
                break
        if (not RecvError):
            Time = (time.time() - TimeSent)
            DataDecoded = data.decode(encoding="utf-8")
            print('-2-:' + DataDecoded)
            Ready = True




    print ("recv ended")
#-----------------------------------------------------------------------------------


host = ''
port = 9000
locaddr = (host,port)




# Create a UDP socket
sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock1.setsockopt(socket.SOL_SOCKET, 25, 'wlan0'.encode())
sock1.settimeout (1)


sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock2.setsockopt(socket.SOL_SOCKET, 25, 'wlan1'.encode())
sock2.settimeout (1)


tello_address = ('192.168.10.1', 8889)


sock1.bind(locaddr)
sock2.bind(locaddr)
TimeSend = 0
Ready = True






print ('\r\n\r\nTello Python3 Demo.\r\n')


print ('Tello: command takeoff land flip forward back left right \r\n       up down cw ccw speed speed? battery?\r\n')


print ('end -- quit demo.\r\n')


Running = True
DataDecoded = ""


#recvThread create
recvThread1 = threading.Thread(target=recv1)
recvThread1.start()


#recvThread create
recvThread2 = threading.Thread(target=recv2)
recvThread2.start()


while Running:
    if (Ready):
        try:
            msg = input(">");


            if not msg:
                break 


            if 'end' in msg:
                print ('...')
                # sock1.close() 
                Running = False
                break


            # Send data
            Ready = False
            msg = msg.encode(encoding="utf-8")
            sent = sock1.sendto(msg, tello_address)
            sent = sock2.sendto(msg, tello_address)
            TimeSent = time.time()
            print (str(sent) + ' bytes sent')
        except KeyboardInterrupt:
            print ('\n . . .\n')
            # sock1.close() 
            break


TimeShutdown = 2
print ("Will shut down in " + str(TimeShutdown) + " seconds")
time.sleep (TimeShutdown) # give recv task some time to end
sock1.close() 
sock2.close() 
print ("Thank you for using Tello")
 

Hacky

Well-known member
Joined
Jul 19, 2021
Messages
167
Reaction score
69
Location
Germany
As we saw already in earlier threads, this approach allows to send selective commands to the different Tellos by selecting the corresponding network interface. For simple formations based on the standard "go to" or "curve" commands, this is sufficient.

The follow-up question is, if you can also seperate data coming from the Tellos like telemetry (on UDP port 8890) or video streams. By default, the python UDP code returns the packet and the IP which has been received but not the network interface, right? As the IP of the Tellos is the same in this situation, I see no way to differentiate.
 

martinpi

Well-known member
Joined
Dec 15, 2019
Messages
110
Reaction score
53
Location
Vienna. Austria
Website
martinpi.at
As we saw already in earlier threads, this approach allows to send selective commands to the different Tellos by selecting the corresponding network interface. For simple formations based on the standard "go to" or "curve" commands, this is sufficient.

The follow-up question is, if you can also seperate data coming from the Tellos like telemetry (on UDP port 8890) or video streams. By default, the python UDP code returns the packet and the IP which has been received but not the network interface, right? As the IP of the Tellos is the same in this situation, I see no way to differentiate.
Well, I have not yet tried the receive side, but as you have two (or more) sockets tied to two different network interfaces (or more), you should be able to separate the incoming streams.
When sending commands, it is the same situation: Both (or all, if you connect to more than two) Tellos have the same IP address.
 

martinpi

Well-known member
Joined
Dec 15, 2019
Messages
110
Reaction score
53
Location
Vienna. Austria
Website
martinpi.at
It works fine on the Raspberry Pi.

When I tried my script on a notebook running Mint 19.10, I experienced a strange situation:
I was able to talk to both Tello's like sending "command" or "battery?". The both replied.
But when I wanted to takeoff or send "rc -100 -100 -100 100" to start the motors, nothing happened.
No movement, no reply.

I tried "land" which should produce at least an "error" message when I am not flying, but again, nothing.

Back on the Raspi, again the same.

Tried the official Tello App on the phone (with only one Tello, of course), got the message that Tello is not connected. Although it was.

Tried the Tello FPV app by Volatello, Tello flew.
Second Tello, it flew too.
Back on the Raspi, everything works as before.

Unfortunately I cannot try Mint again because I crashed the System. It is an old Asus eeePC which was obviously overloaded with Mint and XFCE desktop (which should be lightweight). I tried to install Ubuntu Light, which was unsuccessful, and the eeePC does not boot.
But still, sending "battery?" should not be much different from sending "takeoff".

Any clues?
 

New Threads

Members online

No members online now.

Forum statistics

Threads
5,285
Messages
38,079
Members
14,588
Latest member
rdmitre