first commit
commit
68acc666fc
|
@ -0,0 +1,15 @@
|
|||
# API_KEY.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 各种开放平台的KEY,不要外传
|
||||
|
||||
# 零一万物大模型开放平台
|
||||
# https://platform.lingyiwanwu.com
|
||||
YI_KEY = "f8144ffaff7c459791XXXXXXXXX"
|
||||
|
||||
# 百度智能云千帆ModelBuilder
|
||||
# https://qianfan.cloud.baidu.com
|
||||
QIANFAN_ACCESS_KEY = "ALTAKRELRxSXXXXXXXXXX"
|
||||
QIANFAN_SECRET_KEY = "3737d9da82de4f2XXXXXXXXXX"
|
||||
|
||||
# 百度智能云千帆AppBuilder-SDK
|
||||
APPBUILDER_TOKEN = "bce-v3/ALTAK-7jr20xkZl4cDmhbQKA4ml/f560e5dc3XXXXXXX059XXXXXXXXX"
|
|
@ -0,0 +1,121 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "c8a0febf-1001-4a87-b873-06bc1471187c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 语音控制智能体\n",
|
||||
"\n",
|
||||
"同济子豪兄 2024-5-23"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "bb2091f1-1d00-40bc-9432-9d7cd3d9157e",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 首先要做\n",
|
||||
"\n",
|
||||
"- 音频输出选择HDMI显示屏\n",
|
||||
"\n",
|
||||
"- 找到麦克风设备号\n",
|
||||
"\n",
|
||||
"- 手眼标定"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e2c144d1-059c-40d1-b69b-8485cb6686c5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 智能体Agent能够调用的函数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "1b933878-c06f-426d-8ca3-d4b5ddade0ac",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 函数一:归零\n",
|
||||
"# back_zero()\n",
|
||||
"\n",
|
||||
"# 函数二:放松机械臂\n",
|
||||
"# relax_arms()\n",
|
||||
"\n",
|
||||
"# 函数三:摇头\n",
|
||||
"# head_shake()\n",
|
||||
"\n",
|
||||
"# 函数四:点头\n",
|
||||
"# head_nod()\n",
|
||||
"\n",
|
||||
"# 函数五:跳舞\n",
|
||||
"# head_dance()\n",
|
||||
"\n",
|
||||
"# 函数六:开启吸泵\n",
|
||||
"# pump_on()\n",
|
||||
"\n",
|
||||
"# 函数七:关闭吸泵\n",
|
||||
"# pump_off()\n",
|
||||
"\n",
|
||||
"# 函数八:移动到指定坐标\n",
|
||||
"# move_to_coords(X=150, Y=-120)\n",
|
||||
"\n",
|
||||
"# 函数九:指定关节旋转\n",
|
||||
"# single_joint_move(1, 60)\n",
|
||||
"\n",
|
||||
"# 函数十:移动至俯视姿态\n",
|
||||
"# move_to_top_view()\n",
|
||||
"\n",
|
||||
"# 函数十一:拍一张俯视图\n",
|
||||
"# top_view_shot()\n",
|
||||
"\n",
|
||||
"# 函数十二:开启摄像头\n",
|
||||
"# check_camera()\n",
|
||||
"\n",
|
||||
"# 函数十三:LED灯变颜色\n",
|
||||
"# llm_led('帮我把LED灯的颜色改为贝加尔湖的颜色')\n",
|
||||
"\n",
|
||||
"# 函数十四:移动物体\n",
|
||||
"# vlm_move(PROMPT='帮我把红色方块放在小猪佩奇上')\n",
|
||||
"\n",
|
||||
"# 函数十五:拖动示教\n",
|
||||
"# drag_teach()\n",
|
||||
"\n",
|
||||
"# 函数十六:休息等待\n",
|
||||
"# time.sleep()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d1d0c3be-3080-4543-a943-adb10e19e79b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.14"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
# agent_go.py
|
||||
# 同济子豪兄 2024-5-27
|
||||
# 看懂“图像”、听懂“人话”、指哪打哪的机械臂
|
||||
# 机械臂+大模型+多模态+语音识别=具身智能体Agent
|
||||
|
||||
print('\n听得懂人话、看得懂图像、拎得清动作的具身智能机械臂!')
|
||||
print('同济子豪兄 2024-5-27 \n')
|
||||
|
||||
# 导入常用函数
|
||||
from utils_asr import * # 录音+语音识别
|
||||
from utils_robot import * # 连接机械臂
|
||||
from utils_llm import * # 大语言模型API
|
||||
from utils_led import * # 控制LED灯颜色
|
||||
from utils_camera import * # 摄像头
|
||||
from utils_robot import * # 机械臂运动
|
||||
from utils_pump import * # GPIO、吸泵
|
||||
from utils_vlm_move import * # 多模态大模型识别图像,吸泵吸取并移动物体
|
||||
from utils_drag_teaching import * # 拖动示教
|
||||
from utils_agent import * # 智能体Agent编排
|
||||
from utils_tts import * # 语音合成模块
|
||||
|
||||
# print('播放欢迎词')
|
||||
pump_off()
|
||||
# back_zero()
|
||||
play_wav('asset/welcome.wav')
|
||||
|
||||
|
||||
def agent_play():
|
||||
'''
|
||||
主函数,语音控制机械臂智能体编排动作
|
||||
'''
|
||||
# 归零
|
||||
back_zero()
|
||||
|
||||
# print('测试摄像头')
|
||||
# check_camera()
|
||||
|
||||
# 输入指令
|
||||
# 先回到原点,再把LED灯改为墨绿色,然后把绿色方块放在篮球上
|
||||
start_record_ok = input('是否开启录音,输入数字录音指定时长,按k打字输入,按c输入默认指令\n')
|
||||
if str.isnumeric(start_record_ok):
|
||||
DURATION = int(start_record_ok)
|
||||
record(DURATION=DURATION) # 录音
|
||||
order = speech_recognition() # 语音识别
|
||||
elif start_record_ok == 'k':
|
||||
order = input('请输入指令')
|
||||
elif start_record_ok == 'c':
|
||||
order = '先归零,再摇头,然后把绿色方块放在篮球上'
|
||||
else:
|
||||
print('无指令,退出')
|
||||
# exit()
|
||||
raise NameError('无指令,退出')
|
||||
|
||||
# 智能体Agent编排动作
|
||||
agent_plan_output = eval(agent_plan(order))
|
||||
|
||||
print('智能体编排动作如下\n', agent_plan_output)
|
||||
# plan_ok = input('是否继续?按c继续,按q退出')
|
||||
plan_ok = 'c'
|
||||
if plan_ok == 'c':
|
||||
response = agent_plan_output['response'] # 获取机器人想对我说的话
|
||||
print('开始语音合成')
|
||||
tts(response) # 语音合成,导出wav音频文件
|
||||
play_wav('temp/tts.wav') # 播放语音合成音频文件
|
||||
for each in agent_plan_output['function']: # 运行智能体规划编排的每个函数
|
||||
print('开始执行动作', each)
|
||||
eval(each)
|
||||
elif plan_ok =='q':
|
||||
# exit()
|
||||
raise NameError('按q退出')
|
||||
|
||||
# agent_play()
|
||||
if __name__ == '__main__':
|
||||
agent_play()
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
# camera_check.py
|
||||
# 调用摄像头实时画面,按q键退出
|
||||
# 同济子豪兄 2024-5-13
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
cap = cv2.VideoCapture(0)
|
||||
|
||||
while(True):
|
||||
ret, frame = cap.read()
|
||||
|
||||
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
cv2.imshow('frame', frame)
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
|
||||
cap.release()
|
||||
cv2.destroyAllWindows()
|
|
@ -0,0 +1,16 @@
|
|||
# sound_check.py
|
||||
# 快速检查语音相关的所有功能:麦克风、录音、扬声器播放声音、语音识别、语音合成
|
||||
# 同济子豪兄 2024-7-15
|
||||
|
||||
from utils_asr import * # 录音+语音识别
|
||||
from utils_tts import * # 语音合成模块
|
||||
print('开始录音5秒')
|
||||
record(DURATION=5) # 录音
|
||||
print('播放录音')
|
||||
play_wav('temp/speech_record.wav')
|
||||
speech_result = speech_recognition()
|
||||
print('开始语音合成')
|
||||
tts(speech_result)
|
||||
print('播放语音合成音频')
|
||||
play_wav('temp/tts.wav')
|
||||
|
|
@ -0,0 +1,842 @@
|
|||
[
|
||||
[
|
||||
2158,
|
||||
2046,
|
||||
1786,
|
||||
1747,
|
||||
1807,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2046,
|
||||
1786,
|
||||
1744,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2047,
|
||||
1786,
|
||||
1743,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2051,
|
||||
1781,
|
||||
1730,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2051,
|
||||
1780,
|
||||
1711,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2061,
|
||||
1780,
|
||||
1683,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2104,
|
||||
1780,
|
||||
1623,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2153,
|
||||
1780,
|
||||
1562,
|
||||
1816,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2185,
|
||||
1780,
|
||||
1522,
|
||||
1819,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2158,
|
||||
2221,
|
||||
1780,
|
||||
1492,
|
||||
1820,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2159,
|
||||
2269,
|
||||
1780,
|
||||
1454,
|
||||
1820,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2159,
|
||||
2324,
|
||||
1780,
|
||||
1406,
|
||||
1820,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2160,
|
||||
2382,
|
||||
1780,
|
||||
1358,
|
||||
1820,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2160,
|
||||
2442,
|
||||
1782,
|
||||
1309,
|
||||
1819,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2162,
|
||||
2488,
|
||||
1780,
|
||||
1251,
|
||||
1817,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2160,
|
||||
2538,
|
||||
1780,
|
||||
1204,
|
||||
1814,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2159,
|
||||
2596,
|
||||
1784,
|
||||
1176,
|
||||
1808,
|
||||
1326
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2638,
|
||||
1780,
|
||||
1128,
|
||||
1814,
|
||||
1324
|
||||
],
|
||||
[
|
||||
2160,
|
||||
2718,
|
||||
1780,
|
||||
1044,
|
||||
1855,
|
||||
1300
|
||||
],
|
||||
[
|
||||
2159,
|
||||
2781,
|
||||
1780,
|
||||
990,
|
||||
1926,
|
||||
1251
|
||||
],
|
||||
[
|
||||
2162,
|
||||
2821,
|
||||
1782,
|
||||
989,
|
||||
1958,
|
||||
1176
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2844,
|
||||
1780,
|
||||
992,
|
||||
1970,
|
||||
1131
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2874,
|
||||
1783,
|
||||
979,
|
||||
1983,
|
||||
1097
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2904,
|
||||
1784,
|
||||
941,
|
||||
2010,
|
||||
1061
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2912,
|
||||
1785,
|
||||
932,
|
||||
2023,
|
||||
1055
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2913,
|
||||
1808,
|
||||
948,
|
||||
2025,
|
||||
1055
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2936,
|
||||
1901,
|
||||
1038,
|
||||
2025,
|
||||
1055
|
||||
],
|
||||
[
|
||||
2163,
|
||||
2988,
|
||||
2051,
|
||||
1131,
|
||||
2028,
|
||||
1055
|
||||
],
|
||||
[
|
||||
2164,
|
||||
3039,
|
||||
2210,
|
||||
1247,
|
||||
2030,
|
||||
1055
|
||||
],
|
||||
[
|
||||
2188,
|
||||
3076,
|
||||
2352,
|
||||
1365,
|
||||
2022,
|
||||
1051
|
||||
],
|
||||
[
|
||||
2229,
|
||||
3100,
|
||||
2468,
|
||||
1467,
|
||||
1990,
|
||||
1030
|
||||
],
|
||||
[
|
||||
2253,
|
||||
3118,
|
||||
2559,
|
||||
1543,
|
||||
1979,
|
||||
1007
|
||||
],
|
||||
[
|
||||
2260,
|
||||
3139,
|
||||
2632,
|
||||
1584,
|
||||
1980,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2260,
|
||||
3162,
|
||||
2705,
|
||||
1613,
|
||||
1985,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2273,
|
||||
3189,
|
||||
2786,
|
||||
1658,
|
||||
1990,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2313,
|
||||
3215,
|
||||
2868,
|
||||
1715,
|
||||
1969,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2362,
|
||||
3233,
|
||||
2949,
|
||||
1786,
|
||||
1953,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2422,
|
||||
3247,
|
||||
3025,
|
||||
1845,
|
||||
1922,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2473,
|
||||
3265,
|
||||
3095,
|
||||
1868,
|
||||
1876,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2516,
|
||||
3293,
|
||||
3168,
|
||||
1874,
|
||||
1855,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2552,
|
||||
3332,
|
||||
3252,
|
||||
1902,
|
||||
1842,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2591,
|
||||
3372,
|
||||
3335,
|
||||
1938,
|
||||
1842,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2635,
|
||||
3397,
|
||||
3389,
|
||||
1969,
|
||||
1912,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2694,
|
||||
3401,
|
||||
3401,
|
||||
2025,
|
||||
2010,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2756,
|
||||
3400,
|
||||
3401,
|
||||
2051,
|
||||
2000,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2808,
|
||||
3397,
|
||||
3401,
|
||||
2054,
|
||||
2011,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2855,
|
||||
3396,
|
||||
3401,
|
||||
2039,
|
||||
2044,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2896,
|
||||
3396,
|
||||
3401,
|
||||
2003,
|
||||
2062,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2930,
|
||||
3396,
|
||||
3401,
|
||||
1982,
|
||||
2090,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2971,
|
||||
3396,
|
||||
3401,
|
||||
1980,
|
||||
2109,
|
||||
1006
|
||||
],
|
||||
[
|
||||
3004,
|
||||
3395,
|
||||
3401,
|
||||
1994,
|
||||
2110,
|
||||
1006
|
||||
],
|
||||
[
|
||||
3005,
|
||||
3355,
|
||||
3398,
|
||||
2067,
|
||||
2110,
|
||||
1006
|
||||
],
|
||||
[
|
||||
3004,
|
||||
3246,
|
||||
3385,
|
||||
2248,
|
||||
2107,
|
||||
1006
|
||||
],
|
||||
[
|
||||
3004,
|
||||
3118,
|
||||
3320,
|
||||
2402,
|
||||
2103,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2995,
|
||||
3026,
|
||||
3209,
|
||||
2386,
|
||||
2103,
|
||||
1006
|
||||
],
|
||||
[
|
||||
2979,
|
||||
2953,
|
||||
3081,
|
||||
2351,
|
||||
2104,
|
||||
999
|
||||
],
|
||||
[
|
||||
2978,
|
||||
2889,
|
||||
2925,
|
||||
2312,
|
||||
2077,
|
||||
999
|
||||
],
|
||||
[
|
||||
2962,
|
||||
2835,
|
||||
2746,
|
||||
2207,
|
||||
2053,
|
||||
999
|
||||
],
|
||||
[
|
||||
2939,
|
||||
2774,
|
||||
2557,
|
||||
2037,
|
||||
2006,
|
||||
999
|
||||
],
|
||||
[
|
||||
2904,
|
||||
2716,
|
||||
2372,
|
||||
1904,
|
||||
1966,
|
||||
999
|
||||
],
|
||||
[
|
||||
2867,
|
||||
2658,
|
||||
2221,
|
||||
1829,
|
||||
1951,
|
||||
999
|
||||
],
|
||||
[
|
||||
2808,
|
||||
2604,
|
||||
2130,
|
||||
1790,
|
||||
1952,
|
||||
999
|
||||
],
|
||||
[
|
||||
2714,
|
||||
2583,
|
||||
2115,
|
||||
1800,
|
||||
2007,
|
||||
999
|
||||
],
|
||||
[
|
||||
2610,
|
||||
2544,
|
||||
2114,
|
||||
1905,
|
||||
2063,
|
||||
993
|
||||
],
|
||||
[
|
||||
2552,
|
||||
2497,
|
||||
2088,
|
||||
2001,
|
||||
2095,
|
||||
894
|
||||
],
|
||||
[
|
||||
2546,
|
||||
2435,
|
||||
1960,
|
||||
1971,
|
||||
2055,
|
||||
802
|
||||
],
|
||||
[
|
||||
2541,
|
||||
2351,
|
||||
1743,
|
||||
1820,
|
||||
2001,
|
||||
802
|
||||
],
|
||||
[
|
||||
2498,
|
||||
2251,
|
||||
1493,
|
||||
1628,
|
||||
1966,
|
||||
802
|
||||
],
|
||||
[
|
||||
2426,
|
||||
2152,
|
||||
1272,
|
||||
1459,
|
||||
1947,
|
||||
802
|
||||
],
|
||||
[
|
||||
2342,
|
||||
2056,
|
||||
1121,
|
||||
1377,
|
||||
1902,
|
||||
805
|
||||
],
|
||||
[
|
||||
2268,
|
||||
1961,
|
||||
1038,
|
||||
1387,
|
||||
1839,
|
||||
829
|
||||
],
|
||||
[
|
||||
2215,
|
||||
1865,
|
||||
1004,
|
||||
1452,
|
||||
1799,
|
||||
855
|
||||
],
|
||||
[
|
||||
2174,
|
||||
1775,
|
||||
984,
|
||||
1531,
|
||||
1756,
|
||||
921
|
||||
],
|
||||
[
|
||||
2122,
|
||||
1702,
|
||||
947,
|
||||
1551,
|
||||
1724,
|
||||
999
|
||||
],
|
||||
[
|
||||
2058,
|
||||
1626,
|
||||
881,
|
||||
1542,
|
||||
1714,
|
||||
1020
|
||||
],
|
||||
[
|
||||
2005,
|
||||
1525,
|
||||
783,
|
||||
1516,
|
||||
1717,
|
||||
1023
|
||||
],
|
||||
[
|
||||
1960,
|
||||
1413,
|
||||
675,
|
||||
1483,
|
||||
1723,
|
||||
1038
|
||||
],
|
||||
[
|
||||
1922,
|
||||
1301,
|
||||
576,
|
||||
1469,
|
||||
1719,
|
||||
1089
|
||||
],
|
||||
[
|
||||
1898,
|
||||
1192,
|
||||
498,
|
||||
1477,
|
||||
1704,
|
||||
1139
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1102,
|
||||
438,
|
||||
1493,
|
||||
1681,
|
||||
1146
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1054,
|
||||
399,
|
||||
1497,
|
||||
1662,
|
||||
1146
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1051,
|
||||
393,
|
||||
1482,
|
||||
1657,
|
||||
1146
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1064,
|
||||
395,
|
||||
1422,
|
||||
1656,
|
||||
1145
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1118,
|
||||
398,
|
||||
1343,
|
||||
1647,
|
||||
1145
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1204,
|
||||
410,
|
||||
1242,
|
||||
1649,
|
||||
1139
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1301,
|
||||
480,
|
||||
1214,
|
||||
1661,
|
||||
1127
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1395,
|
||||
603,
|
||||
1250,
|
||||
1685,
|
||||
1124
|
||||
],
|
||||
[
|
||||
1893,
|
||||
1497,
|
||||
755,
|
||||
1317,
|
||||
1717,
|
||||
1111
|
||||
],
|
||||
[
|
||||
1894,
|
||||
1609,
|
||||
918,
|
||||
1377,
|
||||
1757,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
1726,
|
||||
1084,
|
||||
1418,
|
||||
1803,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
1840,
|
||||
1252,
|
||||
1464,
|
||||
1850,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
1928,
|
||||
1412,
|
||||
1538,
|
||||
1895,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
1989,
|
||||
1559,
|
||||
1636,
|
||||
1939,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
2025,
|
||||
1690,
|
||||
1740,
|
||||
1976,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2050,
|
||||
1799,
|
||||
1839,
|
||||
2003,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2057,
|
||||
1868,
|
||||
1944,
|
||||
2019,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2053,
|
||||
1887,
|
||||
2032,
|
||||
2055,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2052,
|
||||
1884,
|
||||
2061,
|
||||
2086,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2056,
|
||||
1883,
|
||||
2126,
|
||||
2135,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2057,
|
||||
1883,
|
||||
2207,
|
||||
2155,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2053,
|
||||
1886,
|
||||
2218,
|
||||
2152,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2052,
|
||||
1886,
|
||||
2218,
|
||||
2154,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2050,
|
||||
1887,
|
||||
2175,
|
||||
2147,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1898,
|
||||
2055,
|
||||
1883,
|
||||
2081,
|
||||
2117,
|
||||
1107
|
||||
],
|
||||
[
|
||||
1897,
|
||||
2057,
|
||||
1882,
|
||||
2072,
|
||||
2107,
|
||||
1107
|
||||
]
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
|
@ -0,0 +1,75 @@
|
|||
# utils_agent.py
|
||||
# 同济子豪兄 2024-5-23
|
||||
# Agent智能体相关函数
|
||||
|
||||
from utils_llm import *
|
||||
|
||||
AGENT_SYS_PROMPT = '''
|
||||
你是我的机械臂助手,机械臂内置了一些函数,请你根据我的指令,以json形式输出要运行的对应函数和你给我的回复
|
||||
|
||||
【以下是所有内置函数介绍】
|
||||
机械臂位置归零,所有关节回到原点:back_zero()
|
||||
放松机械臂,所有关节都可以自由手动拖拽活动:relax_arms()
|
||||
做出摇头动作:head_shake()
|
||||
做出点头动作:head_nod()
|
||||
做出跳舞动作:head_dance()
|
||||
打开吸泵:pump_on()
|
||||
关闭吸泵:pump_off()
|
||||
移动到指定XY坐标,比如移动到X坐标150,Y坐标-120:move_to_coords(X=150, Y=-120)
|
||||
指定关节旋转,比如关节1旋转到60度,总共有6个关节:single_joint_move(1, 60)
|
||||
移动至俯视姿态:move_to_top_view()
|
||||
拍一张俯视图:top_view_shot()
|
||||
开启摄像头,在屏幕上实时显示摄像头拍摄的画面:check_camera()
|
||||
LED灯改变颜色,比如:llm_led('帮我把LED灯的颜色改为贝加尔湖的颜色')
|
||||
将一个物体移动到另一个物体的位置上,比如:vlm_move('帮我把红色方块放在小猪佩奇上')
|
||||
拖动示教,我可以拽着机械臂运动,然后机械臂模仿复现出一样的动作:drag_teach()
|
||||
休息等待,比如等待两秒:time.sleep(2)
|
||||
|
||||
【输出json格式】
|
||||
你直接输出json即可,从{开始,不要输出包含```json的开头或结尾
|
||||
在'function'键中,输出函数名列表,列表中每个元素都是字符串,代表要运行的函数名称和参数。每个函数既可以单独运行,也可以和其他函数先后运行。列表元素的先后顺序,表示执行函数的先后顺序
|
||||
在'response'键中,根据我的指令和你编排的动作,以第一人称输出你回复我的话,不要超过20个字,可以幽默和发散,用上歌词、台词、互联网热梗、名场面。比如李云龙的台词、甄嬛传的台词、练习时长两年半。
|
||||
|
||||
【以下是一些具体的例子】
|
||||
我的指令:回到原点。你输出:{'function':['back_zero()'], 'response':'回家吧,回到最初的美好'}
|
||||
我的指令:先回到原点,然后跳舞。你输出:{'function':['back_zero()', 'head_dance()'], 'response':'我的舞姿,练习时长两年半'}
|
||||
我的指令:先回到原点,然后移动到180, -90坐标。你输出:{'function':['back_zero()', 'move_to_coords(X=180, Y=-90)'], 'response':'精准不,老子打的就是精锐'}
|
||||
我的指令:先打开吸泵,再把关节2旋转到30度。你输出:{'function':['pump_on()', single_joint_move(2, 30)], 'response':'你之前做的指星笔,就是通过关节2调俯仰角'}
|
||||
我的指令:移动到X为160,Y为-30的地方。你输出:{'function':['move_to_coords(X=160, Y=-30)'], 'response':'坐标移动已完成'}
|
||||
我的指令:拍一张俯视图,然后把LED灯的颜色改为黄金的颜色。你输出:{'function':['top_view_shot()', llm_led('把LED灯的颜色改为黄金的颜色')], 'response':'人工智能未来比黄金值钱,你信不信'}
|
||||
我的指令:帮我把绿色方块放在小猪佩奇上面。你输出:{'function':[vlm_move('帮我把绿色方块放在小猪佩奇上面')], 'response':'它的弟弟乔治呢?'}
|
||||
我的指令:帮我把红色方块放在李云龙的脸上。你输出:{'function':[vlm_move('帮我把红色方块放在李云龙的脸上')], 'response':'你他娘的真是个天才'}
|
||||
我的指令:关闭吸泵,打开摄像头。你输出:{'function':[pump_off(), check_camera()], 'response':'你是我的眼,带我阅读浩瀚的书海'}
|
||||
我的指令:先归零,再把LED灯的颜色改为墨绿色。你输出:{'function':[back_zero(), llm_led('把LED灯的颜色改为墨绿色')], 'response':'这种墨绿色,很像蜀南竹海的竹子'}
|
||||
我的指令:我拽着你运动,然后你模仿复现出这个运动。你输出:{'function':['drag_teach()'], 'response':'你有本事拽一个鸡你太美'}
|
||||
我的指令:开启拖动示教。你输出:{'function':['drag_teach()'], 'response':'你要我模仿我自己?'}
|
||||
我的指令:先回到原点,等待三秒,再打开吸泵,把LED灯的颜色改成中国红,最后把绿色方块移动到摩托车上。你输出:{'function':['back_zero()', 'time.sleep(3)', 'pump_on()', llm_led('把LED灯的颜色改为中国红色', vlm_move('把绿色方块移动到摩托车上'))], 'response':'如果奇迹有颜色,那一定是中国红'}
|
||||
|
||||
【一些李云龙相关的台词,如果和李云龙相关,可以在response中提及对应的台词】
|
||||
学习?学个屁
|
||||
给你半斤地瓜烧
|
||||
老子打的就是精锐
|
||||
二营长,你的意大利炮呢
|
||||
你他娘的真是个天才
|
||||
咱老李也是十里八乡的俊后生
|
||||
不报此仇,我李云龙誓不为人
|
||||
你猜旅长怎么说
|
||||
逢敌必亮剑,绝不含糊!
|
||||
老子当初怎么教他打枪,现在就教他怎么打仗!
|
||||
你咋就不敢跟旅长干一架呢?
|
||||
你猪八戒戴眼镜充什么大学生啊?
|
||||
我李云龙八岁习武,南拳北腿略知一二。
|
||||
死,也要死在冲锋的路上!
|
||||
|
||||
|
||||
【一些小猪佩奇相关的台词】
|
||||
这是我的弟弟乔治
|
||||
|
||||
【我现在的指令是】
|
||||
'''
|
||||
|
||||
def agent_plan(AGENT_PROMPT='先回到原点,再把LED灯改为墨绿色,然后把绿色方块放在篮球上'):
|
||||
print('Agent智能体编排动作')
|
||||
PROMPT = AGENT_SYS_PROMPT + AGENT_PROMPT
|
||||
agent_plan = llm_yi(PROMPT)
|
||||
return agent_plan
|
|
@ -0,0 +1,150 @@
|
|||
# utils_asr.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 录音+语音识别
|
||||
|
||||
print('导入录音+语音识别模块')
|
||||
|
||||
import pyaudio
|
||||
import wave
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
from API_KEY import *
|
||||
|
||||
# 确定麦克风索引号
|
||||
# import sounddevice as sd
|
||||
# print(sd.query_devices())
|
||||
|
||||
def record(MIC_INDEX=0, DURATION=5):
|
||||
'''
|
||||
调用麦克风录音,需用arecord -l命令获取麦克风ID
|
||||
DURATION,录音时长
|
||||
'''
|
||||
print('开始 {} 秒录音'.format(DURATION))
|
||||
os.system('sudo arecord -D "plughw:{}" -f dat -c 1 -r 16000 -d {} temp/speech_record.wav'.format(MIC_INDEX, DURATION))
|
||||
print('录音结束')
|
||||
|
||||
def record_auto(MIC_INDEX=1):
|
||||
'''
|
||||
开启麦克风录音,保存至'temp/speech_record.wav'音频文件
|
||||
音量超过阈值自动开始录音,低于阈值一段时间后自动停止录音
|
||||
MIC_INDEX:麦克风设备索引号
|
||||
'''
|
||||
|
||||
CHUNK = 1024 # 采样宽度
|
||||
RATE = 16000 # 采样率
|
||||
|
||||
QUIET_DB = 2000 # 分贝阈值,大于则开始录音,否则结束
|
||||
delay_time = 1 # 声音降至分贝阈值后,经过多长时间,自动终止录音
|
||||
|
||||
FORMAT = pyaudio.paInt16
|
||||
CHANNELS = 1 if sys.platform == 'darwin' else 2 # 采样通道数
|
||||
|
||||
# 初始化录音
|
||||
p = pyaudio.PyAudio()
|
||||
stream = p.open(format=FORMAT,
|
||||
channels=CHANNELS,
|
||||
rate=RATE,
|
||||
input=True,
|
||||
frames_per_buffer=CHUNK,
|
||||
input_device_index=MIC_INDEX
|
||||
)
|
||||
|
||||
frames = [] # 所有音频帧
|
||||
|
||||
flag = False # 是否已经开始录音
|
||||
quiet_flag = False # 当前音量小于阈值
|
||||
|
||||
temp_time = 0 # 当前时间是第几帧
|
||||
last_ok_time = 0 # 最后正常是第几帧
|
||||
START_TIME = 0 # 开始录音是第几帧
|
||||
END_TIME = 0 # 结束录音是第几帧
|
||||
|
||||
print('可以说话啦!')
|
||||
|
||||
while True:
|
||||
|
||||
# 获取当前chunk的声音
|
||||
data = stream.read(CHUNK, exception_on_overflow=False)
|
||||
frames.append(data)
|
||||
# 获取当前chunk的音量分贝值
|
||||
temp_volume = np.max(np.frombuffer(data, dtype=np.short))
|
||||
|
||||
if temp_volume > QUIET_DB and flag==False:
|
||||
print("音量高于阈值,开始录音")
|
||||
flag =True
|
||||
START_TIME = temp_time
|
||||
last_ok_time = temp_time
|
||||
|
||||
if flag: # 录音中的各种情况
|
||||
|
||||
if(temp_volume < QUIET_DB and quiet_flag==False):
|
||||
print("录音中,当前音量低于阈值")
|
||||
quiet_flag = True
|
||||
last_ok_time = temp_time
|
||||
|
||||
if(temp_volume > QUIET_DB):
|
||||
# print('录音中,当前音量高于阈值,正常录音')
|
||||
quiet_flag = False
|
||||
last_ok_time = temp_time
|
||||
|
||||
if(temp_time > last_ok_time + delay_time*15 and quiet_flag==True):
|
||||
print("音量低于阈值{:.2f}秒后,检测当前音量".format(delay_time))
|
||||
if(quiet_flag and temp_volume < QUIET_DB):
|
||||
print("当前音量仍然小于阈值,录音结束")
|
||||
END_TIME = temp_time
|
||||
break
|
||||
else:
|
||||
print("当前音量重新高于阈值,继续录音中")
|
||||
quiet_flag = False
|
||||
last_ok_time = temp_time
|
||||
|
||||
# print('当前帧 {} 音量 {}'.format(temp_time+1, temp_volume))
|
||||
temp_time += 1
|
||||
if temp_time > 150: # 超时直接退出
|
||||
END_TIME = temp_time
|
||||
print('超时,录音结束')
|
||||
break
|
||||
|
||||
# 停止录音
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
p.terminate()
|
||||
|
||||
# 导出wav音频文件
|
||||
output_path = 'temp/speech_record.wav'
|
||||
wf = wave.open(output_path, 'wb')
|
||||
wf.setnchannels(CHANNELS)
|
||||
wf.setsampwidth(p.get_sample_size(FORMAT))
|
||||
wf.setframerate(RATE)
|
||||
wf.writeframes(b''.join(frames[START_TIME-2:END_TIME]))
|
||||
wf.close()
|
||||
print('保存录音文件', output_path)
|
||||
|
||||
import appbuilder
|
||||
# 配置密钥
|
||||
os.environ["APPBUILDER_TOKEN"] = APPBUILDER_TOKEN
|
||||
asr = appbuilder.ASR() # 语音识别组件
|
||||
def speech_recognition(audio_path='temp/speech_record.wav'):
|
||||
'''
|
||||
AppBuilder-SDK语音识别组件
|
||||
'''
|
||||
print('开始语音识别')
|
||||
# 载入wav音频文件
|
||||
with wave.open(audio_path, 'rb') as wav_file:
|
||||
|
||||
# 获取音频文件的基本信息
|
||||
num_channels = wav_file.getnchannels()
|
||||
sample_width = wav_file.getsampwidth()
|
||||
framerate = wav_file.getframerate()
|
||||
num_frames = wav_file.getnframes()
|
||||
|
||||
# 获取音频数据
|
||||
frames = wav_file.readframes(num_frames)
|
||||
|
||||
# 向API发起请求
|
||||
content_data = {"audio_format": "wav", "raw_audio": frames, "rate": 16000}
|
||||
message = appbuilder.Message(content_data)
|
||||
speech_result = asr.run(message).content['result'][0]
|
||||
print('语音识别结果:', speech_result)
|
||||
return speech_result
|
|
@ -0,0 +1,25 @@
|
|||
# utils_camera.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 开启摄像头,调用摄像头实时画面,按q键退出
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
def check_camera():
|
||||
'''
|
||||
开启摄像头,调用摄像头实时画面,按q键退出
|
||||
'''
|
||||
print('开启摄像头')
|
||||
cap = cv2.VideoCapture(0)
|
||||
|
||||
while(True):
|
||||
ret, frame = cap.read()
|
||||
|
||||
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
cv2.imshow('frame', frame)
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
|
||||
cap.release()
|
||||
cv2.destroyAllWindows()
|
|
@ -0,0 +1,186 @@
|
|||
# utils_drag_teaching.py
|
||||
# 同济子豪兄 2024-5-23
|
||||
# 拖动示教
|
||||
|
||||
print('导入拖动示教模块')
|
||||
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import termios
|
||||
import tty
|
||||
import threading
|
||||
import json
|
||||
|
||||
from pymycobot.mycobot import MyCobot
|
||||
from pymycobot import PI_PORT, PI_BAUD
|
||||
|
||||
# 连接机械臂
|
||||
mc = MyCobot(PI_PORT, PI_BAUD, debug=False)
|
||||
|
||||
class Raw(object):
|
||||
"""Set raw input mode for device"""
|
||||
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
self.fd = self.stream.fileno()
|
||||
|
||||
def __enter__(self):
|
||||
self.original_stty = termios.tcgetattr(self.stream)
|
||||
tty.setcbreak(self.stream)
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
termios.tcsetattr(self.stream, termios.TCSANOW, self.original_stty)
|
||||
|
||||
|
||||
class Helper(object):
|
||||
def __init__(self) -> None:
|
||||
self.w, self.h = os.get_terminal_size()
|
||||
|
||||
def echo(self, msg):
|
||||
print("\r{}".format(" " * self.w), end="")
|
||||
print("\r{}".format(msg), end="")
|
||||
|
||||
|
||||
class TeachingTest(Helper):
|
||||
def __init__(self, mycobot) -> None:
|
||||
super().__init__()
|
||||
self.mc = mycobot
|
||||
self.recording = False
|
||||
self.playing = False
|
||||
self.record_list = []
|
||||
self.record_t = None
|
||||
self.play_t = None
|
||||
|
||||
def record(self):
|
||||
self.record_list = []
|
||||
self.recording = True
|
||||
self.mc.set_fresh_mode(0)
|
||||
def _record():
|
||||
start_t = time.time()
|
||||
|
||||
while self.recording:
|
||||
angles = self.mc.get_encoders()
|
||||
if angles:
|
||||
self.record_list.append(angles)
|
||||
time.sleep(0.1)
|
||||
print("\r {}".format(time.time() - start_t), end="")
|
||||
|
||||
self.echo("开始录制动作")
|
||||
self.record_t = threading.Thread(target=_record, daemon=True)
|
||||
self.record_t.start()
|
||||
|
||||
def stop_record(self):
|
||||
if self.recording:
|
||||
self.recording = False
|
||||
self.record_t.join()
|
||||
self.echo("停止录制动作")
|
||||
|
||||
def play(self):
|
||||
self.echo("开始回放动作")
|
||||
for angles in self.record_list:
|
||||
# print(angles)
|
||||
self.mc.set_encoders(angles, 80)
|
||||
time.sleep(0.1)
|
||||
self.echo("回放结束\n")
|
||||
|
||||
def loop_play(self):
|
||||
self.playing = True
|
||||
|
||||
def _loop():
|
||||
len_ = len(self.record_list)
|
||||
i = 0
|
||||
while self.playing:
|
||||
idx_ = i % len_
|
||||
i += 1
|
||||
self.mc.set_encoders(self.record_list[idx_], 80)
|
||||
time.sleep(0.1)
|
||||
|
||||
self.echo("开始循环回放")
|
||||
self.play_t = threading.Thread(target=_loop, daemon=True)
|
||||
self.play_t.start()
|
||||
|
||||
def stop_loop_play(self):
|
||||
if self.playing:
|
||||
self.playing = False
|
||||
self.play_t.join()
|
||||
self.echo("停止循环回放")
|
||||
|
||||
def save_to_local(self):
|
||||
if not self.record_list:
|
||||
self.echo("No data should save.")
|
||||
return
|
||||
|
||||
save_path = os.path.dirname(__file__) + "/temp/record.txt"
|
||||
with open(save_path, "w") as f:
|
||||
json.dump(self.record_list, f, indent=2)
|
||||
self.echo("回放动作导出至: {}".format(save_path))
|
||||
|
||||
def load_from_local(self):
|
||||
|
||||
with open(os.path.dirname(__file__) + "/temp/record.txt", "r") as f:
|
||||
try:
|
||||
data = json.load(f)
|
||||
self.record_list = data
|
||||
self.echo("载入本地动作数据成功")
|
||||
except Exception:
|
||||
self.echo("Error: invalid data.")
|
||||
|
||||
def print_menu(self):
|
||||
print(
|
||||
"""\
|
||||
\r 拖动示教 同济子豪兄
|
||||
\r q: 退出
|
||||
\r r: 开始录制动作
|
||||
\r c: 停止录制动作
|
||||
\r p: 回放动作
|
||||
\r P: 循环回放/停止循环回放
|
||||
\r s: 将录制的动作保存到本地
|
||||
\r l: 从本地读取录制好的动作
|
||||
\r f: 放松机械臂
|
||||
\r----------------------------------
|
||||
"""
|
||||
)
|
||||
|
||||
def start(self):
|
||||
self.print_menu()
|
||||
|
||||
while not False:
|
||||
with Raw(sys.stdin):
|
||||
key = sys.stdin.read(1)
|
||||
if key == "q":
|
||||
break
|
||||
elif key == "r": # recorder
|
||||
self.record()
|
||||
elif key == "c": # stop recorder
|
||||
self.stop_record()
|
||||
elif key == "p": # play
|
||||
self.play()
|
||||
elif key == "P": # loop play
|
||||
if not self.playing:
|
||||
self.loop_play()
|
||||
else:
|
||||
self.stop_loop_play()
|
||||
elif key == "s": # save to local
|
||||
self.save_to_local()
|
||||
elif key == "l": # load from local
|
||||
self.load_from_local()
|
||||
elif key == "f": # free move
|
||||
self.mc.release_all_servos()
|
||||
self.echo("Released")
|
||||
else:
|
||||
print(key)
|
||||
continue
|
||||
|
||||
def drag_teach():
|
||||
|
||||
print('机械臂归零')
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
time.sleep(3)
|
||||
|
||||
recorder = TeachingTest(mc)
|
||||
recorder.start()
|
||||
|
||||
print('机械臂归零')
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
time.sleep(3)
|
|
@ -0,0 +1,41 @@
|
|||
# utils_led.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 大模型控制LED灯颜色
|
||||
|
||||
from utils_llm import llm_qianfan, llm_yi
|
||||
from utils_robot import mc
|
||||
|
||||
print('导入LED灯控制模块')
|
||||
|
||||
# 备选颜色
|
||||
# 贝加尔湖、中国红、大海、绿叶、金子、蓝宝石、小猪佩奇、墨绿色、黑色
|
||||
|
||||
# 系统提示词
|
||||
SYS_PROMPT = '我即将说的这句话中包含一个目标物体,帮我把这个物体的一种可能的颜色,以0-255的RGB像素值形式返回给我,整理成元组格式,例如(255, 30, 60),直接回复元组本身,以括号开头,不要回复任何中文内容,下面是这句话:'
|
||||
|
||||
def llm_led(PROMPT_LED='帮我把LED灯的颜色改为贝加尔湖的颜色'):
|
||||
'''
|
||||
大模型控制LED灯颜色
|
||||
'''
|
||||
|
||||
PROMPT = SYS_PROMPT + PROMPT_LED
|
||||
|
||||
n = 1
|
||||
while n < 5:
|
||||
try:
|
||||
# 调用大模型API
|
||||
# response = llm_qianfan(PROMPT)
|
||||
response = llm_yi(PROMPT)
|
||||
|
||||
# 提取颜色
|
||||
rgb_tuple = eval(response)
|
||||
|
||||
# 设置LED灯的RGB颜色
|
||||
mc.set_color(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2])
|
||||
print('LED灯颜色修改成功', rgb_tuple)
|
||||
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print('大模型返回json结构错误,再尝试一次', e)
|
||||
n += 1
|
|
@ -0,0 +1,59 @@
|
|||
# utils_llm.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 调用大语言模型API
|
||||
|
||||
print('导入大模型API模块')
|
||||
|
||||
|
||||
import os
|
||||
|
||||
import qianfan
|
||||
def llm_qianfan(PROMPT='你好,你是谁?'):
|
||||
'''
|
||||
百度智能云千帆大模型平台API
|
||||
'''
|
||||
|
||||
# 传入 ACCESS_KEY 和 SECRET_KEY
|
||||
os.environ["QIANFAN_ACCESS_KEY"] = QIANFAN_ACCESS_KEY
|
||||
os.environ["QIANFAN_SECRET_KEY"] = QIANFAN_SECRET_KEY
|
||||
|
||||
# 选择大语言模型
|
||||
MODEL = "ERNIE-Bot-4"
|
||||
# MODEL = "ERNIE Speed"
|
||||
# MODEL = "ERNIE-Lite-8K"
|
||||
# MODEL = 'ERNIE-Tiny-8K'
|
||||
|
||||
chat_comp = qianfan.ChatCompletion(model=MODEL)
|
||||
|
||||
# 输入给大模型
|
||||
resp = chat_comp.do(
|
||||
messages=[{"role": "user", "content": PROMPT}],
|
||||
top_p=0.8,
|
||||
temperature=0.3,
|
||||
penalty_score=1.0
|
||||
)
|
||||
|
||||
response = resp["result"]
|
||||
return response
|
||||
|
||||
import openai
|
||||
from openai import OpenAI
|
||||
from API_KEY import *
|
||||
def llm_yi(PROMPT='你好,你是谁?'):
|
||||
'''
|
||||
零一万物大模型API
|
||||
'''
|
||||
|
||||
API_BASE = "https://api.lingyiwanwu.com/v1"
|
||||
API_KEY = YI_KEY
|
||||
|
||||
MODEL = 'yi-large'
|
||||
# MODEL = 'yi-medium'
|
||||
# MODEL = 'yi-spark'
|
||||
|
||||
# 访问大模型API
|
||||
client = OpenAI(api_key=API_KEY, base_url=API_BASE)
|
||||
completion = client.chat.completions.create(model=MODEL, messages=[{"role": "user", "content": PROMPT}])
|
||||
result = completion.choices[0].message.content.strip()
|
||||
return result
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# utils_pump.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# GPIO引脚、吸泵相关函数
|
||||
|
||||
print('导入吸泵控制模块')
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
# 初始化GPIO
|
||||
GPIO.setwarnings(False) # 不打印 warning 信息
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(20, GPIO.OUT)
|
||||
GPIO.setup(21, GPIO.OUT)
|
||||
GPIO.output(20, 1) # 关闭吸泵电磁阀
|
||||
|
||||
def pump_on():
|
||||
'''
|
||||
开启吸泵
|
||||
'''
|
||||
print(' 开启吸泵')
|
||||
GPIO.output(20, 0)
|
||||
|
||||
def pump_off():
|
||||
'''
|
||||
关闭吸泵,吸泵放气,释放物体
|
||||
'''
|
||||
print(' 关闭吸泵')
|
||||
GPIO.output(20, 1) # 关闭吸泵电磁阀
|
||||
time.sleep(0.05)
|
||||
GPIO.output(21, 0) # 打开泄气阀门
|
||||
time.sleep(0.2)
|
||||
GPIO.output(21, 1)
|
||||
time.sleep(0.05)
|
||||
GPIO.output(21, 0) # 再一次泄气,确保物体释放
|
||||
time.sleep(0.2)
|
||||
GPIO.output(21, 1)
|
||||
time.sleep(0.05)
|
|
@ -0,0 +1,222 @@
|
|||
# utils_robot.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 启动并连接机械臂,导入各种工具包
|
||||
|
||||
print('导入机械臂连接模块')
|
||||
|
||||
from pymycobot.mycobot import MyCobot
|
||||
from pymycobot import PI_PORT, PI_BAUD
|
||||
import cv2
|
||||
import numpy as np
|
||||
import time
|
||||
from utils_pump import *
|
||||
|
||||
# 连接机械臂
|
||||
mc = MyCobot(PI_PORT, PI_BAUD)
|
||||
# 设置运动模式为插补
|
||||
mc.set_fresh_mode(0)
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
# 初始化GPIO
|
||||
GPIO.setwarnings(False) # 不打印 warning 信息
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(20, GPIO.OUT)
|
||||
GPIO.setup(21, GPIO.OUT)
|
||||
GPIO.output(20, 1) # 关闭吸泵电磁阀
|
||||
|
||||
def back_zero():
|
||||
'''
|
||||
机械臂归零
|
||||
'''
|
||||
print('机械臂归零')
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
time.sleep(3)
|
||||
|
||||
def relax_arms():
|
||||
print('放松机械臂关节')
|
||||
mc.release_all_servos()
|
||||
|
||||
def head_shake():
|
||||
# 左右摆头
|
||||
mc.send_angles([0.87,(-50.44),47.28,0.35,(-0.43),(-0.26)],70)
|
||||
time.sleep(1)
|
||||
for count in range(2):
|
||||
mc.send_angle(5, 30, 80)
|
||||
time.sleep(0.5)
|
||||
mc.send_angle(5, -30,80)
|
||||
time.sleep(0.5)
|
||||
# mc.send_angles([0.87,(-50.44),47.28,0.35,(-0.43),(-0.26)],70)
|
||||
# time.sleep(1)
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
time.sleep(2)
|
||||
|
||||
def head_dance():
|
||||
# 跳舞
|
||||
mc.send_angles([0.87,(-50.44),47.28,0.35,(-0.43),(-0.26)],70)
|
||||
time.sleep(1)
|
||||
for count in range(1):
|
||||
mc.send_angles([(-0.17),(-94.3),118.91,(-39.9),59.32,(-0.52)],80)
|
||||
time.sleep(1.2)
|
||||
mc.send_angles([67.85,(-3.42),(-116.98),106.52,23.11,(-0.52)],80)
|
||||
time.sleep(1.7)
|
||||
mc.send_angles([(-38.14),(-115.04),116.63,69.69,3.25,(-11.6)],80)
|
||||
time.sleep(1.7)
|
||||
mc.send_angles([2.72,(-26.19),140.27,(-110.74),(-6.15),(-11.25)],80)
|
||||
time.sleep(1)
|
||||
mc.send_angles([0,0,0,0,0,0],80)
|
||||
|
||||
def head_nod():
|
||||
# 点头
|
||||
mc.send_angles([0.87,(-50.44),47.28,0.35,(-0.43),(-0.26)],70)
|
||||
for count in range(2):
|
||||
mc.send_angle(4, 13, 70)
|
||||
time.sleep(0.5)
|
||||
mc.send_angle(4, -20, 70)
|
||||
time.sleep(1)
|
||||
mc.send_angle(4,13,70)
|
||||
time.sleep(0.5)
|
||||
mc.send_angles([0.87,(-50.44),47.28,0.35,(-0.43),(-0.26)],70)
|
||||
|
||||
def move_to_coords(X=150, Y=-130, HEIGHT_SAFE=230):
|
||||
print('移动至指定坐标:X {} Y {}'.format(X, Y))
|
||||
mc.send_coords([X, Y, HEIGHT_SAFE, 0, 180, 90], 20, 0)
|
||||
time.sleep(4)
|
||||
|
||||
def single_joint_move(joint_index, angle):
|
||||
print('关节 {} 旋转至 {} 度'.format(joint_index, angle))
|
||||
mc.send_angle(joint_index, angle, 40)
|
||||
time.sleep(2)
|
||||
|
||||
def move_to_top_view():
|
||||
print('移动至俯视姿态')
|
||||
mc.send_angles([-62.13, 8.96, -87.71, -14.41, 2.54, -16.34], 10)
|
||||
time.sleep(3)
|
||||
|
||||
def top_view_shot(check=False):
|
||||
'''
|
||||
拍摄一张图片并保存
|
||||
check:是否需要人工看屏幕确认拍照成功,再在键盘上按q键确认继续
|
||||
'''
|
||||
print(' 移动至俯视姿态')
|
||||
move_to_top_view()
|
||||
|
||||
# 获取摄像头,传入0表示获取系统默认摄像头
|
||||
cap = cv2.VideoCapture(0)
|
||||
# 打开cap
|
||||
cap.open(0)
|
||||
time.sleep(0.3)
|
||||
success, img_bgr = cap.read()
|
||||
|
||||
# 保存图像
|
||||
print(' 保存至temp/vl_now.jpg')
|
||||
cv2.imwrite('temp/vl_now.jpg', img_bgr)
|
||||
|
||||
# 屏幕上展示图像
|
||||
cv2.destroyAllWindows() # 关闭所有opencv窗口
|
||||
cv2.imshow('zihao_vlm', img_bgr)
|
||||
|
||||
if check:
|
||||
print('请确认拍照成功,按c键继续,按q键退出')
|
||||
while(True):
|
||||
key = cv2.waitKey(10) & 0xFF
|
||||
if key == ord('c'): # 按c键继续
|
||||
break
|
||||
if key == ord('q'): # 按q键退出
|
||||
# exit()
|
||||
cv2.destroyAllWindows() # 关闭所有opencv窗口
|
||||
raise NameError('按q退出')
|
||||
else:
|
||||
if cv2.waitKey(10) & 0xFF == None:
|
||||
pass
|
||||
|
||||
# 关闭摄像头
|
||||
cap.release()
|
||||
# 关闭图像窗口
|
||||
# cv2.destroyAllWindows()
|
||||
|
||||
def eye2hand(X_im=160, Y_im=120):
|
||||
'''
|
||||
输入目标点在图像中的像素坐标,转换为机械臂坐标
|
||||
'''
|
||||
|
||||
# 整理两个标定点的坐标
|
||||
cali_1_im = [130, 290] # 左下角,第一个标定点的像素坐标,要手动填!
|
||||
cali_1_mc = [-21.8, -197.4] # 左下角,第一个标定点的机械臂坐标,要手动填!
|
||||
cali_2_im = [640, 0] # 右上角,第二个标定点的像素坐标
|
||||
cali_2_mc = [215, -59.1] # 右上角,第二个标定点的机械臂坐标,要手动填!
|
||||
|
||||
X_cali_im = [cali_1_im[0], cali_2_im[0]] # 像素坐标
|
||||
X_cali_mc = [cali_1_mc[0], cali_2_mc[0]] # 机械臂坐标
|
||||
Y_cali_im = [cali_2_im[1], cali_1_im[1]] # 像素坐标,先小后大
|
||||
Y_cali_mc = [cali_2_mc[1], cali_1_mc[1]] # 机械臂坐标,先大后小
|
||||
|
||||
# X差值
|
||||
X_mc = int(np.interp(X_im, X_cali_im, X_cali_mc))
|
||||
|
||||
# Y差值
|
||||
Y_mc = int(np.interp(Y_im, Y_cali_im, Y_cali_mc))
|
||||
|
||||
return X_mc, Y_mc
|
||||
|
||||
# 吸泵吸取并移动物体
|
||||
def pump_move(mc, XY_START=[230,-50], HEIGHT_START=90, XY_END=[100,220], HEIGHT_END=100, HEIGHT_SAFE=220):
|
||||
|
||||
'''
|
||||
用吸泵,将物体从起点吸取移动至终点
|
||||
|
||||
mc:机械臂实例
|
||||
XY_START:起点机械臂坐标
|
||||
HEIGHT_START:起点高度,方块用90,药盒子用70
|
||||
XY_END:终点机械臂坐标
|
||||
HEIGHT_END:终点高度
|
||||
HEIGHT_SAFE:搬运途中安全高度
|
||||
'''
|
||||
|
||||
# 初始化GPIO
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(20, GPIO.OUT)
|
||||
GPIO.setup(21, GPIO.OUT)
|
||||
|
||||
# 设置运动模式为插补
|
||||
mc.set_fresh_mode(0)
|
||||
|
||||
# # 机械臂归零
|
||||
# print(' 机械臂归零')
|
||||
# mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
# time.sleep(4)
|
||||
|
||||
# 吸泵移动至物体上方
|
||||
print(' 吸泵移动至物体上方')
|
||||
mc.send_coords([XY_START[0], XY_START[1], HEIGHT_SAFE, 0, 180, 90], 20, 0)
|
||||
time.sleep(4)
|
||||
|
||||
# 开启吸泵
|
||||
pump_on()
|
||||
|
||||
# 吸泵向下吸取物体
|
||||
print(' 吸泵向下吸取物体')
|
||||
mc.send_coords([XY_START[0], XY_START[1], HEIGHT_START, 0, 180, 90], 15, 0)
|
||||
time.sleep(4)
|
||||
|
||||
# 升起物体
|
||||
print(' 升起物体')
|
||||
mc.send_coords([XY_START[0], XY_START[1], HEIGHT_SAFE, 0, 180, 90], 15, 0)
|
||||
time.sleep(4)
|
||||
|
||||
# 搬运物体至目标上方
|
||||
print(' 搬运物体至目标上方')
|
||||
mc.send_coords([XY_END[0], XY_END[1], HEIGHT_SAFE, 0, 180, 90], 15, 0)
|
||||
time.sleep(4)
|
||||
|
||||
# 向下放下物体
|
||||
print(' 向下放下物体')
|
||||
mc.send_coords([XY_END[0], XY_END[1], HEIGHT_END, 0, 180, 90], 20, 0)
|
||||
time.sleep(3)
|
||||
|
||||
# 关闭吸泵
|
||||
pump_off()
|
||||
|
||||
# 机械臂归零
|
||||
print(' 机械臂归零')
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 40)
|
||||
time.sleep(3)
|
|
@ -0,0 +1,60 @@
|
|||
# utils_tts.py
|
||||
# 同济子豪兄 2024-5-23
|
||||
# 语音合成
|
||||
|
||||
print('导入语音合成模块')
|
||||
|
||||
import os
|
||||
import appbuilder
|
||||
from API_KEY import *
|
||||
import pyaudio
|
||||
import wave
|
||||
|
||||
tts_ab = appbuilder.TTS()
|
||||
|
||||
def tts(TEXT='我是同济子豪兄的麒麟臂', tts_wav_path = 'temp/tts.wav'):
|
||||
'''
|
||||
语音合成TTS,生成wav音频文件
|
||||
'''
|
||||
inp = appbuilder.Message(content={"text": TEXT})
|
||||
out = tts_ab.run(inp, model="paddlespeech-tts", audio_type="wav")
|
||||
# out = tts_ab.run(inp, audio_type="wav")
|
||||
with open(tts_wav_path, "wb") as f:
|
||||
f.write(out.content["audio_binary"])
|
||||
# print("TTS语音合成,导出wav音频文件至:{}".format(tts_wav_path))
|
||||
|
||||
def play_wav(wav_file='asset/welcome.wav'):
|
||||
'''
|
||||
播放wav音频文件
|
||||
'''
|
||||
prompt = 'aplay -t wav {} -q'.format(wav_file)
|
||||
os.system(prompt)
|
||||
|
||||
# def play_wav(wav_file='temp/tts.wav'):
|
||||
# '''
|
||||
# 播放wav文件
|
||||
# '''
|
||||
# wf = wave.open(wav_file, 'rb')
|
||||
|
||||
# # 实例化PyAudio
|
||||
# p = pyaudio.PyAudio()
|
||||
|
||||
# # 打开流
|
||||
# stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
|
||||
# channels=wf.getnchannels(),
|
||||
# rate=wf.getframerate(),
|
||||
# output=True)
|
||||
|
||||
# chunk_size = 1024
|
||||
# # 读取数据
|
||||
# data = wf.readframes(chunk_size)
|
||||
|
||||
# # 播放音频
|
||||
# while data != b'':
|
||||
# stream.write(data)
|
||||
# data = wf.readframes(chunk_size)
|
||||
|
||||
# # 停止流,关闭流和PyAudio
|
||||
# stream.stop_stream()
|
||||
# stream.close()
|
||||
# p.terminate()
|
|
@ -0,0 +1,158 @@
|
|||
# utils_vlm.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 多模态大模型、可视化
|
||||
|
||||
print('导入视觉大模型模块')
|
||||
import time
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from PIL import ImageFont, ImageDraw
|
||||
# 导入中文字体,指定字号
|
||||
font = ImageFont.truetype('asset/SimHei.ttf', 26)
|
||||
|
||||
from API_KEY import *
|
||||
|
||||
# 系统提示词
|
||||
SYSTEM_PROMPT = '''
|
||||
我即将说一句给机械臂的指令,你帮我从这句话中提取出起始物体和终止物体,并从这张图中分别找到这两个物体左上角和右下角的像素坐标,输出json数据结构。
|
||||
|
||||
例如,如果我的指令是:请帮我把红色方块放在房子简笔画上。
|
||||
你输出这样的格式:
|
||||
{
|
||||
"start":"红色方块",
|
||||
"start_xyxy":[[102,505],[324,860]],
|
||||
"end":"房子简笔画",
|
||||
"end_xyxy":[[300,150],[476,310]]
|
||||
}
|
||||
|
||||
只回复json本身即可,不要回复其它内容
|
||||
|
||||
我现在的指令是:
|
||||
'''
|
||||
|
||||
# Yi-Vision调用函数
|
||||
import openai
|
||||
from openai import OpenAI
|
||||
import base64
|
||||
def yi_vision_api(PROMPT='帮我把红色方块放在钢笔上', img_path='temp/vl_now.jpg'):
|
||||
|
||||
'''
|
||||
零一万物大模型开放平台,yi-vision视觉语言多模态大模型API
|
||||
'''
|
||||
|
||||
client = OpenAI(
|
||||
api_key=YI_KEY,
|
||||
base_url="https://api.lingyiwanwu.com/v1"
|
||||
)
|
||||
|
||||
# 编码为base64数据
|
||||
with open(img_path, 'rb') as image_file:
|
||||
image = 'data:image/jpeg;base64,' + base64.b64encode(image_file.read()).decode('utf-8')
|
||||
|
||||
# 向大模型发起请求
|
||||
completion = client.chat.completions.create(
|
||||
model="yi-vision",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": SYSTEM_PROMPT + PROMPT
|
||||
},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": image
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
# 解析大模型返回结果
|
||||
result = eval(completion.choices[0].message.content.strip())
|
||||
print(' 大模型调用成功!')
|
||||
|
||||
return result
|
||||
|
||||
def post_processing_viz(result, img_path, check=False):
|
||||
|
||||
'''
|
||||
视觉大模型输出结果后处理和可视化
|
||||
check:是否需要人工看屏幕确认可视化成功,按键继续或退出
|
||||
'''
|
||||
|
||||
# 后处理
|
||||
img_bgr = cv2.imread(img_path)
|
||||
img_h = img_bgr.shape[0]
|
||||
img_w = img_bgr.shape[1]
|
||||
# 缩放因子
|
||||
FACTOR = 999
|
||||
# 起点物体名称
|
||||
START_NAME = result['start']
|
||||
# 终点物体名称
|
||||
END_NAME = result['end']
|
||||
# 起点,左上角像素坐标
|
||||
START_X_MIN = int(result['start_xyxy'][0][0] * img_w / FACTOR)
|
||||
START_Y_MIN = int(result['start_xyxy'][0][1] * img_h / FACTOR)
|
||||
# 起点,右下角像素坐标
|
||||
START_X_MAX = int(result['start_xyxy'][1][0] * img_w / FACTOR)
|
||||
START_Y_MAX = int(result['start_xyxy'][1][1] * img_h / FACTOR)
|
||||
# 起点,中心点像素坐标
|
||||
START_X_CENTER = int((START_X_MIN + START_X_MAX) / 2)
|
||||
START_Y_CENTER = int((START_Y_MIN + START_Y_MAX) / 2)
|
||||
# 终点,左上角像素坐标
|
||||
END_X_MIN = int(result['end_xyxy'][0][0] * img_w / FACTOR)
|
||||
END_Y_MIN = int(result['end_xyxy'][0][1] * img_h / FACTOR)
|
||||
# 终点,右下角像素坐标
|
||||
END_X_MAX = int(result['end_xyxy'][1][0] * img_w / FACTOR)
|
||||
END_Y_MAX = int(result['end_xyxy'][1][1] * img_h / FACTOR)
|
||||
# 终点,中心点像素坐标
|
||||
END_X_CENTER = int((END_X_MIN + END_X_MAX) / 2)
|
||||
END_Y_CENTER = int((END_Y_MIN + END_Y_MAX) / 2)
|
||||
|
||||
# 可视化
|
||||
# 画起点物体框
|
||||
img_bgr = cv2.rectangle(img_bgr, (START_X_MIN, START_Y_MIN), (START_X_MAX, START_Y_MAX), [0, 0, 255], thickness=3)
|
||||
# 画起点中心点
|
||||
img_bgr = cv2.circle(img_bgr, [START_X_CENTER, START_Y_CENTER], 6, [0, 0, 255], thickness=-1)
|
||||
# 画终点物体框
|
||||
img_bgr = cv2.rectangle(img_bgr, (END_X_MIN, END_Y_MIN), (END_X_MAX, END_Y_MAX), [255, 0, 0], thickness=3)
|
||||
# 画终点中心点
|
||||
img_bgr = cv2.circle(img_bgr, [END_X_CENTER, END_Y_CENTER], 6, [255, 0, 0], thickness=-1)
|
||||
# 写中文物体名称
|
||||
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # BGR 转 RGB
|
||||
img_pil = Image.fromarray(img_rgb) # array 转 pil
|
||||
draw = ImageDraw.Draw(img_pil)
|
||||
# 写起点物体中文名称
|
||||
draw.text((START_X_MIN, START_Y_MIN-32), START_NAME, font=font, fill=(255, 0, 0, 1)) # 文字坐标,中文字符串,字体,rgba颜色
|
||||
# 写终点物体中文名称
|
||||
draw.text((END_X_MIN, END_Y_MIN-32), END_NAME, font=font, fill=(0, 0, 255, 1)) # 文字坐标,中文字符串,字体,rgba颜色
|
||||
img_bgr = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) # RGB转BGR
|
||||
# 保存可视化效果图
|
||||
cv2.imwrite('temp/vl_now_viz.jpg', img_bgr)
|
||||
|
||||
formatted_time = time.strftime("%Y%m%d%H%M", time.localtime())
|
||||
cv2.imwrite('visualizations/{}.jpg'.format(formatted_time), img_bgr)
|
||||
|
||||
# 在屏幕上展示可视化效果图
|
||||
cv2.imshow('zihao_vlm', img_bgr)
|
||||
|
||||
if check:
|
||||
print(' 请确认可视化成功,按c键继续,按q键退出')
|
||||
while(True):
|
||||
key = cv2.waitKey(10) & 0xFF
|
||||
if key == ord('c'): # 按c键继续
|
||||
break
|
||||
if key == ord('q'): # 按q键退出
|
||||
# exit()
|
||||
cv2.destroyAllWindows() # 关闭所有opencv窗口
|
||||
raise NameError('按q退出')
|
||||
else:
|
||||
if cv2.waitKey(1) & 0xFF == None:
|
||||
pass
|
||||
|
||||
return START_X_CENTER, START_Y_CENTER, END_X_CENTER, END_Y_CENTER
|
|
@ -0,0 +1,84 @@
|
|||
# utils_vlm_move.py
|
||||
# 同济子豪兄 2024-5-22
|
||||
# 输入指令,多模态大模型识别图像,吸泵吸取并移动物体
|
||||
|
||||
# print('神行太保:能看懂“图像”、听懂“人话”的机械臂')
|
||||
|
||||
from utils_robot import *
|
||||
from utils_asr import *
|
||||
from utils_vlm import *
|
||||
|
||||
import time
|
||||
|
||||
def vlm_move(PROMPT='帮我把绿色方块放在小猪佩奇上', input_way='keyboard'):
|
||||
'''
|
||||
多模态大模型识别图像,吸泵吸取并移动物体
|
||||
input_way:speech语音输入,keyboard键盘输入
|
||||
'''
|
||||
|
||||
print('多模态大模型识别图像,吸泵吸取并移动物体')
|
||||
|
||||
# 机械臂归零
|
||||
print('机械臂归零')
|
||||
mc.send_angles([0, 0, 0, 0, 0, 0], 50)
|
||||
time.sleep(3)
|
||||
|
||||
## 第一步:完成手眼标定
|
||||
print('第一步:完成手眼标定')
|
||||
|
||||
## 第二步:发出指令
|
||||
# PROMPT_BACKUP = '帮我把绿色方块放在小猪佩奇上' # 默认指令
|
||||
|
||||
# if input_way == 'keyboard':
|
||||
# PROMPT = input('第二步:输入指令')
|
||||
# if PROMPT == '':
|
||||
# PROMPT = PROMPT_BACKUP
|
||||
# elif input_way == 'speech':
|
||||
# record() # 录音
|
||||
# PROMPT = speech_recognition() # 语音识别
|
||||
print('第二步,给出的指令是:', PROMPT)
|
||||
|
||||
## 第三步:拍摄俯视图
|
||||
print('第三步:拍摄俯视图')
|
||||
top_view_shot(check=False)
|
||||
|
||||
## 第四步:将图片输入给多模态视觉大模型
|
||||
print('第四步:将图片输入给多模态视觉大模型')
|
||||
img_path = 'temp/vl_now.jpg'
|
||||
|
||||
n = 1
|
||||
while n < 5:
|
||||
try:
|
||||
print(' 尝试第 {} 次访问多模态大模型'.format(n))
|
||||
result = yi_vision_api(PROMPT, img_path='temp/vl_now.jpg')
|
||||
print(' 多模态大模型调用成功!')
|
||||
print(result)
|
||||
break
|
||||
except Exception as e:
|
||||
print(' 多模态大模型返回数据结构错误,再尝试一次', e)
|
||||
n += 1
|
||||
|
||||
## 第五步:视觉大模型输出结果后处理和可视化
|
||||
print('第五步:视觉大模型输出结果后处理和可视化')
|
||||
START_X_CENTER, START_Y_CENTER, END_X_CENTER, END_Y_CENTER = post_processing_viz(result, img_path, check=True)
|
||||
|
||||
## 第六步:手眼标定转换为机械臂坐标
|
||||
print('第六步:手眼标定,将像素坐标转换为机械臂坐标')
|
||||
# 起点,机械臂坐标
|
||||
START_X_MC, START_Y_MC = eye2hand(START_X_CENTER, START_Y_CENTER)
|
||||
# 终点,机械臂坐标
|
||||
END_X_MC, END_Y_MC = eye2hand(END_X_CENTER, END_Y_CENTER)
|
||||
|
||||
## 第七步:吸泵吸取移动物体
|
||||
print('第七步:吸泵吸取移动物体')
|
||||
pump_move(mc=mc, XY_START=[START_X_MC, START_Y_MC], XY_END=[END_X_MC, END_Y_MC])
|
||||
|
||||
## 第八步:收尾
|
||||
print('第八步:任务完成')
|
||||
GPIO.cleanup() # 释放GPIO pin channel
|
||||
cv2.destroyAllWindows() # 关闭所有opencv窗口
|
||||
# exit()
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
Loading…
Reference in New Issue