Skip to content

Commit ee3133e

Browse files
committed
* update demo projects
1 parent 6e356a7 commit ee3133e

File tree

8 files changed

+618
-59
lines changed

8 files changed

+618
-59
lines changed

projects/demo_block_tracking/main.py

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
SERVO_PORT_NAME = '/dev/ttyS4' # 舵机串口号
99
SERVO_BAUDRATE = 115200 # 舵机的波特率
1010
SERVO_ID = [1, 2] # 舵机ID,依次是pitch,roll,yaw
11-
SERVO_MIN_POSITION = [1650, 0] # 舵机位置最小值
12-
SERVO_MAX_POSITION = [2446, 4096] # 舵机位置最大值
11+
SERVO_MIN_POSITION = [1650, 787] # 舵机位置最小值
12+
SERVO_MAX_POSITION = [2446, 3496] # 舵机位置最大值
1313
value_per_angle = 4096 / 270
1414
SERVO_ANGLE = [0, 0] # 舵机旋转的角度范围
1515
for i, _ in enumerate(SERVO_ANGLE):
@@ -31,8 +31,8 @@
3131
blobs_area_threshold = 500 # blob最小面积
3232
blobs_pixels_threshold = 500 # blob最小像素点
3333

34-
pitch_pid = [0.45, 0.00001, 0.000, 0] # [P I D I_max]
35-
roll_pid = [0.6, 0.01, 0.000, 0] # [P I D I_max]
34+
pitch_pid = [0.5, 0.01, 0.000, 0] # [P I D I_max]
35+
roll_pid = [0.8, 0.01, 0.000, 0] # [P I D I_max]
3636

3737
manual_wb_enable = True # 使能手动白平衡,保证找色块时颜色不会随色温变化
3838
wb_gain_list = [0.0682, 0, 0, 0.04897] # 手动白平衡增益参数
@@ -75,7 +75,7 @@ def rgb_list_to_lab_list(rgb_list):
7575

7676
class App:
7777
def __init__(self, gimbal: servos.Gimbal):
78-
self.cam = camera.Camera(640, 360)
78+
self.cam = camera.Camera(640, 360, fps=60)
7979
self.disp = display.Display()
8080
self.ts = touchscreen.TouchScreen()
8181
self.img_exit = image.load("./assets/exit.jpg").resize(40, 40)
@@ -154,7 +154,7 @@ def run(self):
154154
obj_x = b.cx()
155155
obj_y = b.cy()
156156

157-
print(b.cx(), b.cy())
157+
# print(b.cx(), b.cy())
158158
for i in range(4):
159159
img.draw_line(corners[i][0], corners[i][1], corners[(i + 1) % 4][0], corners[(i + 1) % 4][1], image.COLOR_RED, 4)
160160

@@ -163,7 +163,7 @@ def run(self):
163163
center_y = img_h / 2
164164
angle_x = (obj_x - center_x) / img_w * CAMERA_FOV_H
165165
angle_y = (obj_y - center_y) / img_h * CAMERA_FOV_V
166-
print(f'angle_x:{angle_x:.2f} fov_h:{CAMERA_FOV_H:.2f}', f'angle_y:{angle_y:.2f} fov_v:{CAMERA_FOV_V:.2f}')
166+
# print(f'angle_x:{angle_x:.2f} fov_h:{CAMERA_FOV_H:.2f}', f'angle_y:{angle_y:.2f} fov_v:{CAMERA_FOV_V:.2f}')
167167

168168
# # 偏移的角度映射到舵机偏移的百分比
169169
# pitch_error = (angle_y + SERVO_ANGLE[0] / 2) / SERVO_ANGLE[0] * 100
@@ -173,7 +173,7 @@ def run(self):
173173
pitch_error = angle_y * value_per_angle
174174
roll_error = angle_x * value_per_angle
175175

176-
print(f'pitch_error:{pitch_error:.2f} pitch_angle_range:{SERVO_ANGLE[0]:.2f} roll_error:{roll_error:.2f} roll_angle_range:{SERVO_ANGLE[1]:.2f}')
176+
# print(f'pitch_error:{pitch_error:.2f} pitch_angle_range:{SERVO_ANGLE[0]:.2f} roll_error:{roll_error:.2f} roll_angle_range:{SERVO_ANGLE[1]:.2f}')
177177
gimbal.run(pitch_error, roll_error, pitch_reverse = pitch_reverse, roll_reverse=roll_reverse)
178178

179179
if self.need_exit:
@@ -194,59 +194,52 @@ def run(self):
194194
pid_roll = servos.PID(p=roll_pid[0], i=roll_pid[1], d=roll_pid[2], imax=roll_pid[3])
195195
gimbal = servos.Gimbal(s, pid_pitch, pid_roll)
196196

197+
def print_pid(s, id: int):
198+
print(f'ID:{id} position p:{s.uservo.get_position_p(id)} i:{s.uservo.get_position_i(id)} d:{s.uservo.get_position_d(id)}')
199+
print(f'ID:{id} speed p:{s.uservo.get_speed_p(id)} i:{s.uservo.get_speed_i(id)} d:{s.uservo.get_speed_d(id)}')
200+
201+
def print_max_min_angle(s, id: int):
202+
print(f'ID:{id} min {s.uservo.get_lower_angle(id)} max:{s.uservo.get_upper_angle(id)}')
203+
204+
print_pid(s, 1)
205+
print_pid(s, 2)
206+
print_max_min_angle(s, 1)
207+
print_max_min_angle(s, 2)
208+
197209
if test_get_position_enable:
198210
s.test_position()
199211
elif test_set_pitch_position_enable:
200-
s.uservo.set_position(1, 2048)
201-
while True:
202-
pos = s.uservo.get_position(1)
203-
if pos:
204-
if pos > 2000 and pos < 3100:
205-
break
206-
time.sleep_ms(1)
207-
208-
t = time.ticks_us()
209-
s.uservo.set_position(1, 2548)
210-
while True:
211-
pos = s.uservo.get_position(1)
212-
if pos:
213-
if pos > 2548-50 and pos < 2548+50:
214-
break
215-
time.sleep_ms(1)
216-
print('cost', time.ticks_us() - t)
217-
elif test_set_roll_position_enable:
218-
id = 2
219-
angle = 120
220-
start_position = 1024
221-
dst_position = start_position + angle / 270 * 4096
222-
s.uservo.set_position(id, start_position)
223-
224-
while True:
225-
pos = s.uservo.get_position(id)
226-
if pos:
227-
if pos > start_position - 25 and pos < start_position + 25:
228-
break
229-
print('wait start position, dst position', dst_position,'curr position', pos)
230-
time.sleep_ms(100)
231-
232-
t = time.ticks_us()
233-
s.uservo.set_position(id, dst_position)
234-
print('run set_position cost', time.ticks_us() - t)
235-
236-
t = time.ticks_us()
237-
while True:
238-
pos = s.uservo.get_position(id)
239-
if pos:
240-
if pos > dst_position-25 and pos < dst_position+100:
241-
break
242-
print('wait dst position, dst position', dst_position,'curr position', pos)
243-
# time.sleep_ms(1)
244-
print('wait cost', time.ticks_us() - t)
212+
id = SERVO_ID[0]
213+
while not app.need_exit():
214+
for position in range(SERVO_MIN_POSITION[id-1], SERVO_MAX_POSITION[id-1], 10):
215+
s.uservo.set_position(id, position)
216+
217+
pos = s.uservo.get_position(id)
218+
print(f'id:{id} position:{pos}')
219+
time.sleep_ms(10)
220+
221+
for position in range(SERVO_MAX_POSITION[id-1], SERVO_MIN_POSITION[id-1], -10):
222+
s.uservo.set_position(id, position)
245223

224+
pos = s.uservo.get_position(id)
225+
print(f'id:{id} position:{pos}')
226+
time.sleep_ms(10)
227+
elif test_set_roll_position_enable:
228+
id = SERVO_ID[1]
246229
while not app.need_exit():
247-
pos = s.uservo.get_position(id)
248-
print(pos)
249-
time.sleep_ms(1000)
230+
for position in range(SERVO_MIN_POSITION[id-1], SERVO_MAX_POSITION[id-1], 10):
231+
s.uservo.set_position(id, position)
232+
233+
pos = s.uservo.get_position(id)
234+
print(f'id:{id} set:{position} get:{pos}')
235+
time.sleep_ms(10)
236+
237+
for position in range(SERVO_MAX_POSITION[id-1], SERVO_MIN_POSITION[id-1], -10):
238+
s.uservo.set_position(id, position)
239+
240+
pos = s.uservo.get_position(id)
241+
print(f'id:{id} set:{position} get:{pos}')
242+
time.sleep_ms(10)
250243
else:
251244
a = App(gimbal)
252245
a.run()

projects/demo_block_tracking/servos.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ def __init__(self, id_list:list, device_name:str, baudrate:int, min_position_lis
1818
self.uart = uart.UART(device_name, baudrate)
1919
self.uservo = UartServoManager(self.uart, servo_id_list=id_list)
2020
self.id_list = id_list
21-
for id in id_list:
21+
for idx, id in enumerate(id_list):
2222
self.uservo.torque_enable(id, True)
2323
self.uservo.set_position(id, 2048, True)
24+
# self.uservo.set_lower_angle(id, min_position_list[idx])
25+
# self.uservo.set_upper_angle(id, max_position_list[idx])
26+
2427
self.max_position_list = max_position_list
2528
self.min_position_list = min_position_list
2629
if len(self.id_list) != len(self.max_position_list) != len(self.min_position_list):
@@ -40,7 +43,7 @@ def set_pitch(self, inc:float):
4043
position = position if position >= self.min_position_list[0] else self.min_position_list[0]
4144
position = position if position <= self.max_position_list[0] else self.max_position_list[0]
4245
self.uservo.set_position(self.pitch_id, position)
43-
print(f'set pitch inc:{inc:.2f}', f'position:{position:.2f}', f'range:[{self.min_position_list[0]},{self.max_position_list[0]}]')
46+
# print(f'set pitch inc:{inc:.2f}', f'position:{position:.2f}', f'range:[{self.min_position_list[0]},{self.max_position_list[0]}]')
4447

4548
def set_roll(self, inc:float):
4649
if inc == 0:
@@ -52,7 +55,7 @@ def set_roll(self, inc:float):
5255
position = position if position >= self.min_position_list[1] else self.min_position_list[1]
5356
position = position if position <= self.max_position_list[1] else self.max_position_list[1]
5457
self.uservo.set_position(self.roll_id, position)
55-
print(f'set roll inc:{inc:.2f}', f'position:{position:.2f}', f'range:[{self.min_position_list[1]},{self.max_position_list[1]}]')
58+
# print(f'set roll inc:{inc:.2f}', f'position:{position:.2f}', f'range:[{self.min_position_list[1]},{self.max_position_list[1]}]')
5659

5760
def set_yaw(self, inc:float):
5861
if inc == 0:

projects/demo_block_tracking/src/uart_servo.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,82 @@ def write_data_by_name(self, servo_id, data_name, value):
237237
param_bytes = struct.pack(f">{dtype}", value)
238238
self.write_data(servo_id, data_address, param_bytes)
239239

240+
def set_id(self, new_servo_id):
241+
'''设置舵机ID'''
242+
self.write_data_by_name(0xfe, 'SERVO_ID', new_servo_id)
243+
244+
def get_id(self):
245+
'''获取舵机ID'''
246+
return self.read_data_by_name(0xfe, 'SERVO_ID')
247+
248+
def set_position_p(self, servo_id, value):
249+
'''设置位置环 P参数'''
250+
self.write_data_by_name(servo_id, "CONTROL_P_KP", value)
251+
252+
def get_position_p(self, servo_id):
253+
'''获取位置环 P参数'''
254+
return self.read_data_by_name(servo_id, 'CONTROL_P_KP')
255+
256+
def set_position_i(self, servo_id, value):
257+
'''设置位置环 I参数'''
258+
self.write_data_by_name(servo_id, "CONTROL_P_KI", value)
259+
260+
def get_position_i(self, servo_id):
261+
'''获取位置环 I参数'''
262+
return self.read_data_by_name(servo_id, 'CONTROL_P_KI')
263+
264+
def set_position_d(self, servo_id, value):
265+
'''设置位置环 D参数'''
266+
self.write_data_by_name(servo_id, "CONTROL_P_KD", value)
267+
268+
def get_position_d(self, servo_id):
269+
'''获取位置环 D参数'''
270+
return self.read_data_by_name(servo_id, 'CONTROL_P_KD')
271+
272+
def set_position_p(self, servo_id, value):
273+
'''设置位置环 P参数'''
274+
self.write_data_by_name(servo_id, "CONTROL_P_KP", value)
275+
276+
def set_speed_p(self, servo_id, value):
277+
'''设置速度环 P参数'''
278+
self.write_data_by_name(servo_id, "CONTROL_V_KP", value)
279+
280+
def get_speed_p(self, servo_id):
281+
'''获取速度环 P参数'''
282+
return self.read_data_by_name(servo_id, 'CONTROL_V_KP')
283+
284+
def set_speed_i(self, servo_id, value):
285+
'''设置速度环 I参数'''
286+
self.write_data_by_name(servo_id, "CONTROL_V_KI", value)
287+
288+
def get_speed_i(self, servo_id):
289+
'''获取速度环 I参数'''
290+
return self.read_data_by_name(servo_id, 'CONTROL_V_KI')
291+
292+
def set_speed_d(self, servo_id, value):
293+
'''设置速度环 D参数'''
294+
self.write_data_by_name(servo_id, "CONTROL_V_KD", value)
295+
296+
def get_speed_d(self, servo_id):
297+
'''获取速度环 D参数'''
298+
return self.read_data_by_name(servo_id, 'CONTROL_V_KD')
299+
300+
def set_lower_angle(self, servo_id, value):
301+
'''设置舵机角度下限'''
302+
self.write_data_by_name(servo_id, "ANGLE_LOWERB", value)
303+
304+
def get_lower_angle(self, servo_id):
305+
'''获取舵机角度下限'''
306+
return self.read_data_by_name(servo_id, 'ANGLE_LOWERB')
307+
308+
def set_upper_angle(self, servo_id, value):
309+
'''设置舵机角度上限'''
310+
self.write_data_by_name(servo_id, "ANGLE_UPPERB", value)
311+
312+
def get_upper_angle(self, servo_id):
313+
'''获取舵机角度上限'''
314+
return self.read_data_by_name(servo_id, 'ANGLE_UPPERB')
315+
240316
def get_legal_position(self, position):
241317
'''获取合法的位置'''
242318
position = int(position)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
deps
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# README
2+
3+
通过视觉检测到姿态变化, 来完成地铁跑酷需要的动作. 支持maixcam/maixcam2, 以下统称为设备
4+
5+
## 使用方法
6+
7+
### 配置游戏环境
8+
9+
10+
1. 将设备的usb接口连接到电脑
11+
2. 打设备的HID Mouse功能, 打开方法是在设置应用->USB设置->选择device->勾选HID Mouse->点击确定
12+
3. 在电脑上打开地铁跑酷游戏. 可以点击[这里](https://subtlexp.github.io/Subway-Surfers)用浏览器玩地铁跑酷
13+
14+
### 开始游戏
15+
16+
1. 打开应用后, 确保画面中存在玩家的膝盖到头部的区域
17+
2. 玩家初始时需要站直, 肩膀保持自然水平, 裁判将设备对准玩家后点击BOOT键进行校准, 校准完成后设备会立即检测玩家姿态并操作鼠标.这时候在电脑上点击游戏开始
18+
3. 玩家的操作方式是:
19+
- 向左旋转肩膀, 表示左移一次
20+
- 向右旋转肩膀, 表示右转一次
21+
- 跳跃, 表示跳跃一次
22+
- 蹲下, 表示蹲下一次
23+
注意:
24+
1. 判断左移和右移的标准是肩膀向左或者向右旋转的角度, 一般旋转角度超过10度后认为有效. 旋转后需要立马回正
25+
2. 跳越和蹲下时由于身体需要一定时间反映, 因此有一定延时, 需要提前做预判动作
26+
27+
28+
Complete the actions required for Subway Surfers by detecting posture changes through visual detection. Supports maixcam/maixcam2, collectively referred to as the device below.
29+
30+
## Usage
31+
### Setting Up the Game Environment
32+
1. Connect the device's USB interface to the computer.
33+
2. Enable the HID Mouse function of the device. To do this, go to the Settings app -> USB Settings -> Select device -> Check HID Mouse -> Click OK.
34+
3. Open the Subway Surfers game on the computer. You can click [here](https://subtlexp.github.io/Subway-Surfers) to play Subway Surfers in your browser.
35+
36+
### Starting the Game
37+
1. After opening the application, ensure that the area from the player's knees to the head is visible in the frame.
38+
2. The player should initially stand straight with their shoulders naturally level. The referee should aim the device at the player and press the BOOT key to calibrate. Once calibration is complete, the device will immediately detect the player's posture and control the mouse. At this point, click to start the game on the computer.
39+
3. The player's controls are as follows:
40+
- Rotate the shoulders to the left to move left once.
41+
- Rotate the shoulders to the right to move right once.
42+
- Jump to perform a jump.
43+
- Crouch to perform a crouch.
44+
45+
Note:
46+
1. The criteria for determining left and right movement are the angles of shoulder rotation to the left or right. Generally, a rotation angle exceeding 10 degrees is considered valid. After rotating, return to the original position immediately.
47+
2. Due to the time required for the body to react, there is a certain delay when jumping and crouching. Preemptive actions are necessary.
32.9 KB
Loading
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
id: subway_surfers
2+
name: Subway Surfers
3+
version: 1.0.0
4+
author: sipeed
5+
icon: app.png
6+
desc: subway_surfers
7+
files:
8+
- main.py
9+
- README.md

0 commit comments

Comments
 (0)