Skip to content

Commit fae4b5a

Browse files
committed
feat: upgrade aeloes action imatation extension to v2
1 parent 73b9ce3 commit fae4b5a

File tree

2 files changed

+140
-1
lines changed

2 files changed

+140
-1
lines changed
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import time
2+
import math
3+
import queue
4+
import serial
5+
import serial.tools.list_ports
6+
from codelab_adapter.core_extension import Extension
7+
8+
9+
def auto_detect_port():
10+
device_desc = 'STM32 Virtual COM Port'
11+
vid_pid = '0483:5740'
12+
ports = serial.tools.list_ports.comports()
13+
for port, desc, hwid in sorted(ports):
14+
print("port: {} desc: {} hwid: {}".format(port, desc, hwid))
15+
if device_desc in desc and vid_pid in hwid:
16+
return port
17+
assert False, 'Aelos usb device not found!'
18+
19+
20+
def arm_pose(line):
21+
max_limit = 175
22+
min_limit = 15
23+
line = line.replace('aelos_armpose:', '')
24+
coors = line.split(' ')
25+
coors = list(map(lambda x: float(x), coors))
26+
x_ls, y_ls, x_le, y_le, x_lw, y_lw = coors[0], coors[1], coors[2], coors[3], coors[4], coors[5]
27+
x_rs, y_rs, x_re, y_re, x_rw, y_rw = coors[6], coors[7], coors[8], coors[9], coors[10], coors[11]
28+
lse = math.sqrt((x_ls - x_le)**2 + (y_ls - y_le)**2)
29+
lew = math.sqrt((x_le - x_lw)**2 + (y_le - y_lw)**2)
30+
lsw = math.sqrt((x_ls - x_lw)**2 + (y_ls - y_lw)**2)
31+
rse = math.sqrt((x_rs - x_re)**2 + (y_rs - y_re)**2)
32+
rew = math.sqrt((x_re - x_rw)**2 + (y_re - y_rw)**2)
33+
rsw = math.sqrt((x_rs - x_rw)**2 + (y_rs - y_rw)**2)
34+
# left hand
35+
l_shoulder = math.asin(abs(x_le - x_ls) / lse) / math.pi * 180
36+
l_shoulder = l_shoulder if y_le < y_ls else 180 - l_shoulder
37+
l_elbow = math.acos((lse**2 + lew**2 - lsw**2) /
38+
(2*lse*lew)) / math.pi * 180
39+
l_elbow = l_elbow - 90
40+
if y_lw > y_le:
41+
l_elbow = 180 - l_elbow
42+
l_elbow = l_elbow if l_elbow < max_limit else max_limit
43+
else:
44+
l_elbow = l_elbow if l_elbow > min_limit else min_limit
45+
# right hand
46+
r_shoulder = math.asin(abs(x_re - x_rs) / rse) / math.pi * 180
47+
r_shoulder = r_shoulder if y_re < y_rs else 180 - r_shoulder
48+
r_elbow = math.acos((rse**2 + rew**2 - rsw**2) /
49+
(2*rse*rew)) / math.pi * 180
50+
r_elbow = r_elbow - 90
51+
if y_rw > y_re:
52+
r_elbow = 180 - r_elbow
53+
r_elbow = r_elbow if r_elbow < max_limit else max_limit
54+
else:
55+
r_elbow = r_elbow if r_elbow > min_limit else min_limit
56+
57+
r_shoulder = 190 - r_shoulder
58+
r_elbow = 190 - r_elbow
59+
return int(l_shoulder), int(l_elbow), int(r_shoulder), int(r_elbow)
60+
61+
62+
class WiredUsb:
63+
def __init__(self, port=None):
64+
self.port = port
65+
self.dongle = self.open_port(self.port)
66+
67+
def open_port(self, port):
68+
if port is None:
69+
port = auto_detect_port()
70+
return serial.Serial(port, 9600)
71+
72+
def send(self, data):
73+
self.dongle.write(bytes(data))
74+
75+
def read(self):
76+
self.dongle.read_all()
77+
78+
def set_channel(self, channel):
79+
self.send([0x29, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, channel])
80+
81+
def online_mode(self):
82+
self.send([0xcc])
83+
time.sleep(0.5)
84+
self.send([0x83])
85+
86+
def set_angles(self, data):
87+
assert len(data) == 16
88+
prefix = [0x91, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00]
89+
self.send(prefix + data)
90+
91+
def set_arms(self, l_shoulder, l_elbow, r_shoulder, r_elbow):
92+
pose = [80, 30, 100, 100, 93, 55, 124, 100,
93+
120, 170, 100, 100, 107, 145, 76, 100]
94+
pose[0] = l_elbow
95+
pose[1] = l_shoulder
96+
pose[8] = r_elbow
97+
pose[9] = r_shoulder
98+
self.set_angles(pose)
99+
100+
def arm_imitate(self, line):
101+
l_shoulder, l_elbow, r_shoulder, r_elbow = arm_pose(line)
102+
self.set_arms(l_shoulder, l_elbow, r_shoulder, r_elbow)
103+
104+
105+
class LejuAelosEduOnlineExtension(Extension):
106+
107+
def __init__(self):
108+
super().__init__()
109+
self.EXTENSION_ID = "eim/leju/aelosonline"
110+
self.q = queue.Queue(maxsize=1)
111+
self.wired = WiredUsb()
112+
self.wired.online_mode()
113+
114+
def extension_message_handle(self, topic, payload):
115+
self.q.put(payload)
116+
117+
def run(self):
118+
while self._running:
119+
time.sleep(0.01)
120+
if not self.q.empty():
121+
payload = self.q.get()
122+
python_code = payload["content"]
123+
try:
124+
output = eval(python_code, {"__builtins__": None}, {
125+
"wired": self.wired
126+
})
127+
except Exception as e:
128+
output = e
129+
print(python_code)
130+
131+
# payload["content"] = str(output)
132+
# message = {"payload": payload}
133+
# self.publish(message)
134+
135+
136+
export = LejuAelosEduOnlineExtension
137+
138+
if __name__ == "__main__":
139+
LejuAelosEduOnlineExtension().run()

servers_v2/yeelight_server.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class YeelightNode(AdapterNode):
5858
def __init__(self):
5959
super().__init__()
6060
self.EXTENSION_ID = "eim/yeelight" # default: eim
61-
self.q = queue.Queue()
61+
self.q = queue.Queue(maxsize=1)
6262
self.bulb_ctl = YeeLightController()
6363

6464
def extension_message_handle(self, topic, payload):

0 commit comments

Comments
 (0)