pyaidrone 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyaidrone might be problematic. Click here for more details.
- pyaidrone/AIDrone.py +151 -0
- pyaidrone/__init__.py +0 -0
- pyaidrone/deflib.py +45 -0
- pyaidrone/ikeyevent.py +99 -0
- pyaidrone/packet.py +28 -0
- pyaidrone/parse.py +45 -0
- pyaidrone-1.0.dist-info/METADATA +10 -0
- pyaidrone-1.0.dist-info/RECORD +10 -0
- pyaidrone-1.0.dist-info/WHEEL +5 -0
- pyaidrone-1.0.dist-info/top_level.txt +1 -0
pyaidrone/AIDrone.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import serial
|
|
2
|
+
import binascii
|
|
3
|
+
import math
|
|
4
|
+
from time import sleep
|
|
5
|
+
import random
|
|
6
|
+
from operator import eq
|
|
7
|
+
from threading import Thread
|
|
8
|
+
from serial.tools.list_ports import comports
|
|
9
|
+
from pyaidrone.parse import *
|
|
10
|
+
from pyaidrone.packet import *
|
|
11
|
+
from pyaidrone.deflib import *
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AIDrone(Parse, Packet):
|
|
15
|
+
def __init__(self, receiveCallback = None):
|
|
16
|
+
self.serial = None
|
|
17
|
+
self.isThreadRun = False
|
|
18
|
+
self.parse = Parse(AIDRONE)
|
|
19
|
+
self.makepkt = Packet(AIDRONE)
|
|
20
|
+
self.receiveCallback = receiveCallback
|
|
21
|
+
self.makepkt.clearPacket()
|
|
22
|
+
self.posX = 0
|
|
23
|
+
self.posY = 0
|
|
24
|
+
self.rot = 0
|
|
25
|
+
|
|
26
|
+
def receiveHandler(self):
|
|
27
|
+
while self.isThreadRun:
|
|
28
|
+
readData = self.serial.read(self.serial.in_waiting or 1)
|
|
29
|
+
packet = self.parse.packetArrange(readData)
|
|
30
|
+
if not eq(packet, "None"):
|
|
31
|
+
if self.receiveCallback != None:
|
|
32
|
+
self.receiveCallback(packet)
|
|
33
|
+
self.serial.write(self.makepkt.getPacket())
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def Open(self, portName = "None"):
|
|
37
|
+
if eq(portName, "None"):
|
|
38
|
+
nodes = comports()
|
|
39
|
+
for node in nodes:
|
|
40
|
+
if "CH340" in node.description:
|
|
41
|
+
portName = node.device
|
|
42
|
+
|
|
43
|
+
if eq(portName, "None"):
|
|
44
|
+
print("Can't find Serial Port")
|
|
45
|
+
exit()
|
|
46
|
+
return False
|
|
47
|
+
try:
|
|
48
|
+
self.serial = serial.Serial(port=portName, baudrate=115200, timeout=1)
|
|
49
|
+
if self.serial.isOpen():
|
|
50
|
+
self.isThreadRun = True
|
|
51
|
+
self.thread = Thread(target=self.receiveHandler, args=(), daemon=True)
|
|
52
|
+
self.thread.start()
|
|
53
|
+
print("Connected to", portName)
|
|
54
|
+
return True
|
|
55
|
+
else:
|
|
56
|
+
print("Can't open " + portName)
|
|
57
|
+
exit()
|
|
58
|
+
return False
|
|
59
|
+
except:
|
|
60
|
+
print("Can't open " + portName)
|
|
61
|
+
exit()
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def Close(self):
|
|
66
|
+
self.isThreadRun = False
|
|
67
|
+
sleep(0.2)
|
|
68
|
+
pkt = self.makepkt.getPacket()
|
|
69
|
+
if (pkt[15]&0x80) == 0x80:
|
|
70
|
+
self.makepkt.clearPacket()
|
|
71
|
+
self.setOption(0x8000)
|
|
72
|
+
self.serial.write(self.makepkt.getPacket())
|
|
73
|
+
sleep(0.2)
|
|
74
|
+
self.serial.write(self.makepkt.clearPacket())
|
|
75
|
+
sleep(0.2)
|
|
76
|
+
if self.serial != None:
|
|
77
|
+
if self.serial.isOpen() == True:
|
|
78
|
+
self.serial.close()
|
|
79
|
+
|
|
80
|
+
def setOption(self, option):
|
|
81
|
+
data = option.to_bytes(2, byteorder="little", signed=False)
|
|
82
|
+
self.makepkt.makePacket(14, data)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def takeoff(self):
|
|
86
|
+
alt = 70
|
|
87
|
+
data = alt.to_bytes(2, byteorder="little", signed=False)
|
|
88
|
+
self.makepkt.makePacket(12, data)
|
|
89
|
+
alt = 0x2F
|
|
90
|
+
data = alt.to_bytes(2, byteorder="little", signed=False)
|
|
91
|
+
self.setOption(0x2F)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def landing(self):
|
|
95
|
+
alt = 0
|
|
96
|
+
data = alt.to_bytes(2, byteorder="little", signed=False)
|
|
97
|
+
self.makepkt.makePacket(12, data)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def altitude(self, alt):
|
|
101
|
+
data = alt.to_bytes(2, byteorder="little", signed=False)
|
|
102
|
+
self.makepkt.makePacket(12, data)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def velocity(self, dir=0, vel=100):
|
|
106
|
+
if dir > 3:
|
|
107
|
+
return
|
|
108
|
+
if dir==1 or dir==3:
|
|
109
|
+
vel *= -1;
|
|
110
|
+
data = vel.to_bytes(2, byteorder="little", signed=True)
|
|
111
|
+
if dir==0 or dir==1:
|
|
112
|
+
self.makepkt.makePacket(8, data)
|
|
113
|
+
else:
|
|
114
|
+
self.makepkt.makePacket(6, data)
|
|
115
|
+
self.setOption(0x0F)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def move(self, dir=0, dist=100):
|
|
119
|
+
if dir > 3:
|
|
120
|
+
return
|
|
121
|
+
if dir==1 or dir==3:
|
|
122
|
+
dist *= -1;
|
|
123
|
+
if dir==0 or dir==1:
|
|
124
|
+
self.posX += dist
|
|
125
|
+
data = self.posX.to_bytes(2, byteorder="little", signed=True)
|
|
126
|
+
self.makepkt.makePacket(8, data)
|
|
127
|
+
else:
|
|
128
|
+
self.posY += dist
|
|
129
|
+
data = self.posY.to_bytes(2, byteorder="little", signed=True)
|
|
130
|
+
self.makepkt.makePacket(6, data)
|
|
131
|
+
self.setOption(0x2F)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def rotation(self, rot=90):
|
|
135
|
+
self.rot += rot
|
|
136
|
+
data = self.rot.to_bytes(2, byteorder="little", signed=True)
|
|
137
|
+
self.makepkt.makePacket(10, data)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def motor(self, what, speed):
|
|
141
|
+
speed = DefLib.constrain(speed, 100, 0)
|
|
142
|
+
data = speed.to_bytes(2, byteorder="little", signed=True)
|
|
143
|
+
self.makepkt.makePacket(what*2+6, data)
|
|
144
|
+
self.setOption(0x8000)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def emergency(self):
|
|
148
|
+
self.setOption(0x00)
|
|
149
|
+
self.serial.write(self.makepkt.getPacket())
|
|
150
|
+
|
|
151
|
+
|
pyaidrone/__init__.py
ADDED
|
File without changes
|
pyaidrone/deflib.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
AIDRONE = 1
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
FRONT = 0
|
|
6
|
+
BACK = 1
|
|
7
|
+
RIGHT = 2
|
|
8
|
+
LEFT = 3
|
|
9
|
+
|
|
10
|
+
class DefLib:
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def checksum(self, packet):
|
|
14
|
+
len = packet[4]
|
|
15
|
+
sum = 0
|
|
16
|
+
for n in range(6, len):
|
|
17
|
+
sum += packet[n]
|
|
18
|
+
return sum & 0xFF
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def _print(self, data):
|
|
23
|
+
for n in range(0, len(data)):
|
|
24
|
+
h = hex(data[n])
|
|
25
|
+
# print(h, end=" ")
|
|
26
|
+
print("")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def constrain(self, val , max, min):
|
|
31
|
+
if val > max:
|
|
32
|
+
val = max
|
|
33
|
+
if val < min:
|
|
34
|
+
val = min
|
|
35
|
+
return val
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def comp(self, data):
|
|
40
|
+
data = data&0xFF
|
|
41
|
+
if data < 0:
|
|
42
|
+
return 256 + data
|
|
43
|
+
else:
|
|
44
|
+
return data
|
|
45
|
+
|
pyaidrone/ikeyevent.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from pynput import keyboard
|
|
2
|
+
|
|
3
|
+
class IKeyEvent:
|
|
4
|
+
def on_press(self, key):
|
|
5
|
+
if key == keyboard.Key.enter:
|
|
6
|
+
self.keyEnter = True
|
|
7
|
+
if key == keyboard.Key.space:
|
|
8
|
+
self.keySpace = True
|
|
9
|
+
if key == keyboard.Key.up:
|
|
10
|
+
self.keyUp = True
|
|
11
|
+
if key == keyboard.Key.down:
|
|
12
|
+
self.keyDown = True
|
|
13
|
+
if key == keyboard.Key.right:
|
|
14
|
+
self.keyRight = True
|
|
15
|
+
if key == keyboard.Key.left:
|
|
16
|
+
self.keyLeft = True
|
|
17
|
+
if key == keyboard.KeyCode(char="w"):
|
|
18
|
+
self.keyGoUp = True
|
|
19
|
+
if key == keyboard.KeyCode(char="x"):
|
|
20
|
+
self.keyGoDown = True
|
|
21
|
+
if key == keyboard.KeyCode(char="a"):
|
|
22
|
+
self.keyLTurn = True
|
|
23
|
+
if key == keyboard.KeyCode(char="d"):
|
|
24
|
+
self.keyRTurn = True
|
|
25
|
+
if key == keyboard.Key.esc:
|
|
26
|
+
self.keyEsc = True
|
|
27
|
+
|
|
28
|
+
def on_release(self, key):
|
|
29
|
+
if key == keyboard.Key.enter:
|
|
30
|
+
self.keyEnter = False
|
|
31
|
+
if key == keyboard.Key.space:
|
|
32
|
+
self.keySpace = False
|
|
33
|
+
if key == keyboard.Key.up:
|
|
34
|
+
self.keyUp = False
|
|
35
|
+
if key == keyboard.Key.down:
|
|
36
|
+
self.keyDown = False
|
|
37
|
+
if key == keyboard.Key.right:
|
|
38
|
+
self.keyRight = False
|
|
39
|
+
if key == keyboard.Key.left:
|
|
40
|
+
self.keyLeft = False
|
|
41
|
+
if key == keyboard.KeyCode(char="w"):
|
|
42
|
+
self.keyGoUp = False
|
|
43
|
+
if key == keyboard.KeyCode(char="x"):
|
|
44
|
+
self.keyGoDown = False
|
|
45
|
+
if key == keyboard.KeyCode(char="a"):
|
|
46
|
+
self.keyLTurn = False
|
|
47
|
+
if key == keyboard.KeyCode(char="d"):
|
|
48
|
+
self.keyRTurn = False
|
|
49
|
+
if key == keyboard.Key.esc:
|
|
50
|
+
self.keyEsc = False
|
|
51
|
+
|
|
52
|
+
def __init__(self):
|
|
53
|
+
self.keyEnter = False
|
|
54
|
+
self.keySpace = False
|
|
55
|
+
self.keyUp = False
|
|
56
|
+
self.keyDown = False
|
|
57
|
+
self.keyLeft = False
|
|
58
|
+
self.keyRight = False
|
|
59
|
+
self.keyGoUp = False
|
|
60
|
+
self.keyGoDown = False
|
|
61
|
+
self.keyLTurn= False
|
|
62
|
+
self.keyRTurn = False
|
|
63
|
+
self.keyEsc = False
|
|
64
|
+
|
|
65
|
+
listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
|
|
66
|
+
listener.start()
|
|
67
|
+
|
|
68
|
+
def isKeyEnterPressed(self):
|
|
69
|
+
return self.keyEnter
|
|
70
|
+
|
|
71
|
+
def isKeySpacePressed(self):
|
|
72
|
+
return self.keySpace
|
|
73
|
+
|
|
74
|
+
def isKeyUpPressed(self):
|
|
75
|
+
return self.keyUp
|
|
76
|
+
|
|
77
|
+
def isKeyDownPressed(self):
|
|
78
|
+
return self.keyDown
|
|
79
|
+
|
|
80
|
+
def isKeyLeftPressed(self):
|
|
81
|
+
return self.keyLeft
|
|
82
|
+
|
|
83
|
+
def isKeyRightPressed(self):
|
|
84
|
+
return self.keyRight
|
|
85
|
+
|
|
86
|
+
def isKeyWPressed(self):
|
|
87
|
+
return self.keyGoUp
|
|
88
|
+
|
|
89
|
+
def isKeyXPressed(self):
|
|
90
|
+
return self.keyGoDown
|
|
91
|
+
|
|
92
|
+
def isKeyAPressed(self):
|
|
93
|
+
return self.keyLTurn
|
|
94
|
+
|
|
95
|
+
def isKeyDPressed(self):
|
|
96
|
+
return self.keyRTurn
|
|
97
|
+
|
|
98
|
+
def isKeyEscPressed(self):
|
|
99
|
+
return self.keyEsc
|
pyaidrone/packet.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from pyirbrain.deflib import *
|
|
2
|
+
|
|
3
|
+
class Packet:
|
|
4
|
+
def __init__(self, model = AIRONE):
|
|
5
|
+
self.model = model
|
|
6
|
+
self.packet = bytearray(20)
|
|
7
|
+
if self.model == AIRONE:
|
|
8
|
+
self.packet[0:5] = [0x26, 0xA8, 0x14, 0xB1, 0x14]
|
|
9
|
+
|
|
10
|
+
def getPacket(self):
|
|
11
|
+
return self.packet
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def makePacket(self, start, data):
|
|
15
|
+
for n in range(start, start+len(data)):
|
|
16
|
+
self.packet[n] = data[n-start]
|
|
17
|
+
self.packet[5] = DefLib.checksum(self.packet)
|
|
18
|
+
# DefLib._print(self.packet)
|
|
19
|
+
return self.packet
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def clearPacket(self):
|
|
23
|
+
for n in range(5, 20):
|
|
24
|
+
self.packet[n] = 0
|
|
25
|
+
if self.model == AIRONE:
|
|
26
|
+
self.packet[5] = self.packet[14] = 0x01
|
|
27
|
+
self.packet[16] = self.packet[18] = 0x64
|
|
28
|
+
return self.packet
|
pyaidrone/parse.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from pyirbrain.deflib import *
|
|
2
|
+
|
|
3
|
+
class Parse:
|
|
4
|
+
def __init__(self, model=AIDRONE):
|
|
5
|
+
self.model = model
|
|
6
|
+
self.packet = bytearray(20)
|
|
7
|
+
self.offset = 0
|
|
8
|
+
self.type = 0
|
|
9
|
+
self.packetLen = 20
|
|
10
|
+
self.headMatchCnt = 0
|
|
11
|
+
if self.model == AIDRONE:
|
|
12
|
+
self.head = (0x26, 0xA8, 0x14, 0xA0)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def findHeader(self, ch):
|
|
16
|
+
if self.headMatchCnt==3:
|
|
17
|
+
ch = ch&0xF0
|
|
18
|
+
if ch == self.head[self.headMatchCnt]:
|
|
19
|
+
self.headMatchCnt += 1
|
|
20
|
+
else:
|
|
21
|
+
self.headMatchCnt = 0
|
|
22
|
+
if self.headMatchCnt==4:
|
|
23
|
+
self.headMatchCnt = 0
|
|
24
|
+
self.offset = 4
|
|
25
|
+
self.packetLen = 20
|
|
26
|
+
return True
|
|
27
|
+
else:
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
def packetArrange(self, data):
|
|
31
|
+
for n in range(0, len(data)):
|
|
32
|
+
if self.findHeader(data[n]) == True:
|
|
33
|
+
self.type = data[n]&0x0F
|
|
34
|
+
elif self.offset>0:
|
|
35
|
+
self.packet[self.offset] = data[n]
|
|
36
|
+
if self.offset == 4:
|
|
37
|
+
self.packetLen = data[n]
|
|
38
|
+
self.offset += 1
|
|
39
|
+
if self.offset == self.packetLen:
|
|
40
|
+
self.offset = 0
|
|
41
|
+
chksum = DefLib.checksum(self.packet)
|
|
42
|
+
if chksum == self.packet[5]:
|
|
43
|
+
return self.packet
|
|
44
|
+
return "None"
|
|
45
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pyaidrone/AIDrone.py,sha256=p0-JQtpzmv_TCk1EY9lmkoa8JCJ43Q8ByBVwkgM0QOY,4562
|
|
2
|
+
pyaidrone/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
pyaidrone/deflib.py,sha256=ZeA_qfnhuXEIhJHUMNSKkCkBEaWuoIS5X7ZqjTo9Sx4,735
|
|
4
|
+
pyaidrone/ikeyevent.py,sha256=ZpRiFu71GhW2XQgyiXzCvb2FYoLU8bH4fVeaKoGEMqM,2866
|
|
5
|
+
pyaidrone/packet.py,sha256=sA7v9MbptPVxCm1_Lah1vHnoeQdrWY87NH-C5CP4Gz8,810
|
|
6
|
+
pyaidrone/parse.py,sha256=J8FOblxPhWw9VpovaBLgltkL7YVX0HXLZHTzH6519G8,1363
|
|
7
|
+
pyaidrone-1.0.dist-info/METADATA,sha256=QBFVuZgu0Qa5Tc9UJadDQA31xLlaDI4jqmED0NE82KU,237
|
|
8
|
+
pyaidrone-1.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
9
|
+
pyaidrone-1.0.dist-info/top_level.txt,sha256=YLnJwG3F2TdfFcg6r7jcx02fekcXHF_GC0nv12hJGT8,10
|
|
10
|
+
pyaidrone-1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyaidrone
|