野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 374|回复: 1

[经验\资料] 野火【鲁班猫】卡片电脑创意氛围赛(第二期)基于LubanCat...

[复制链接]
发表于 2023-11-30 22:18:01 | 显示全部楼层 |阅读模式
本帖最后由 ChenChenRui 于 2023-11-30 22:20 编辑

大规模预训练语言模型(Large Language Model, LLM)的出现推动了机器人领域的发展。这些模型通过在大规模文本数据上进行预训练,可以学习到丰富的语言知识和语义表示。然后,这些模型可以通过微调来适应特定的任务或领域。自然语言是一种大众掌握的技能。通过使用自然语言与计算机交互,降低了新手的使用难度,直观有效,降低了学习成本。本项目以机械臂为大语言模型的身体,实现具身智能。
1. 什么是具身智能?
具身智能通过在物理世界和数字世界的学习和进化,达到理解世界、互动交互并完成任务的目标。
具身智能是由“本体”和“智能体”耦合而成且能够在复杂环境中执行任务的智能系统。一般认为,具身智能具有如下的几个核心要素:
第一是本体,作为实际的执行者,是在物理或者虚拟世界进行感知和任务执行的机构。
本体通常是具有物理实体的机器人,可以有多种形态。本体的能力边界会限制智能体的能力发挥,本体具备环境感知能力、运动能力和操作执行能力,是连接数字世界和物理世界的载体,本项目采用三轴步进机械臂。
具身智能的第二个要素是智能体(EmbodiedAgents),是具身于本体之上的智能核心,负责感知、理解、决策、控制等的核心工作。
智能体可以感知复杂环境,理解环境所包含的语义信息,能够和环境进行交互;可以理解具体任务,并且根据环境的变化和目标状态做出决策,进而控制本体完成任务。
本项目的方案
硬件方面:
鲁班猫4、usb摄像头、usb音频模块、机械臂及其控制器
机械臂为三轴步进机械臂。控制器为stm32,接收串口指令完成运动学正逆解以及圆弧直线插补等算法。
上位机为鲁班猫4通过串口与stm32连接,完成对机械臂的控制以及连接usb摄像头和usb音频获取环境。
软件方面:
基于ChatGPT的强大自然语言理解和推理能力,生成控制机器人的相关代码并通过串口向机械臂发送指令,利用usb摄像头获取环境和物体信息,以及通过usb音频模块获取人类指令并向人类反馈状态。
物体定位:采用opencv
OpenCV是一个开源的计算机视觉和机器学习软件库,由英特尔公司发起并开发。它提供了丰富的图像处理和计算机视觉的功能,涵盖了从基本的图像操作、图像处理到目标检测、人脸识别等高级功能。OpenCV广泛应用于各种领域,包括医学图像处理、安防监控、自动驾驶、机器人技术等。
      本项目采用将采集到的图片先进行仿射变换完成投影到xy平面后再转换到hsv颜色空间后寻找物体轮廓和定位。
  1. <blockquote>import cv2
复制代码
语言转文字为调用讯飞api
  1. import base64
  2. import hashlib
  3. import hmac
  4. import json
  5. import os
  6. import time

  7. import requests

  8. lfasr_host = 'http://raasr.xfyun.cn/api'

  9. # 请求的接口名
  10. api_prepare = '/prepare'
  11. api_upload = '/upload'
  12. api_merge = '/merge'
  13. api_get_progress = '/getProgress'
  14. api_get_result = '/getResult'
  15. # 文件分片大小10M
  16. file_piece_sice = 10485760

  17. # ——————————————————转写可配置参数————————————————
  18. # 参数可在官网界面(https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html)查看,根据需求可自行在gene_params方法里添加修改
  19. # 转写类型
  20. lfasr_type = 0
  21. # 是否开启分词
  22. has_participle = 'false'
  23. has_seperate = 'true'
  24. # 多候选词个数
  25. max_alternatives = 0
  26. # 子用户标识
  27. suid = ''


  28. class SliceIdGenerator:
  29.     """slice id生成器"""

  30.     def __init__(self):
  31.         self.__ch = 'aaaaaaaaa`'

  32.     def getNextSliceId(self):
  33.         ch = self.__ch
  34.         j = len(ch) - 1
  35.         while j >= 0:
  36.             cj = ch[j]
  37.             if cj != 'z':
  38.                 ch = ch[:j] + chr(ord(cj) + 1) + ch[j + 1:]
  39.                 break
  40.             else:
  41.                 ch = ch[:j] + 'a' + ch[j + 1:]
  42.                 j = j - 1
  43.         self.__ch = ch
  44.         return self.__ch


  45. class RequestApi(object):
  46.     def __init__(self, appid, secret_key, upload_file_path):
  47.         self.appid = appid
  48.         self.secret_key = secret_key
  49.         self.upload_file_path = upload_file_path

  50.     # 根据不同的apiname生成不同的参数,本示例中未使用全部参数您可在官网(https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html)查看后选择适合业务场景的进行更换
  51.     def gene_params(self, apiname, taskid=None, slice_id=None):
  52.         appid = self.appid
  53.         secret_key = self.secret_key
  54.         upload_file_path = self.upload_file_path
  55.         ts = str(int(time.time()))
  56.         m2 = hashlib.md5()
  57.         m2.update((appid + ts).encode('utf-8'))
  58.         md5 = m2.hexdigest()
  59.         md5 = bytes(md5, encoding='utf-8')
  60.         # 以secret_key为key, 上面的md5为msg, 使用hashlib.sha1加密结果为signa
  61.         signa = hmac.new(secret_key.encode('utf-8'), md5, hashlib.sha1).digest()
  62.         signa = base64.b64encode(signa)
  63.         signa = str(signa, 'utf-8')
  64.         file_len = os.path.getsize(upload_file_path)
  65.         file_name = os.path.basename(upload_file_path)
  66.         param_dict = {}

  67.         if apiname == api_prepare:
  68.             # slice_num是指分片数量,如果您使用的音频都是较短音频也可以不分片,直接将slice_num指定为1即可
  69.             slice_num = int(file_len / file_piece_sice) + (0 if (file_len % file_piece_sice == 0) else 1)
  70.             param_dict['app_id'] = appid
  71.             param_dict['signa'] = signa
  72.             param_dict['ts'] = ts
  73.             param_dict['file_len'] = str(file_len)
  74.             param_dict['file_name'] = file_name
  75.             param_dict['slice_num'] = str(slice_num)
  76.         elif apiname == api_upload:
  77.             param_dict['app_id'] = appid
  78.             param_dict['signa'] = signa
  79.             param_dict['ts'] = ts
  80.             param_dict['task_id'] = taskid
  81.             param_dict['slice_id'] = slice_id
  82.         elif apiname == api_merge:
  83.             param_dict['app_id'] = appid
  84.             param_dict['signa'] = signa
  85.             param_dict['ts'] = ts
  86.             param_dict['task_id'] = taskid
  87.             param_dict['file_name'] = file_name
  88.         elif apiname == api_get_progress or apiname == api_get_result:
  89.             param_dict['app_id'] = appid
  90.             param_dict['signa'] = signa
  91.             param_dict['ts'] = ts
  92.             param_dict['task_id'] = taskid
  93.         return param_dict

  94.     # 请求和结果解析,结果中各个字段的含义可参考:https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html
  95.     def gene_request(self, apiname, data, files=None, headers=None):
  96.         response = requests.post(lfasr_host + apiname, data=data, files=files, headers=headers)
  97.         result = json.loads(response.text)
  98.         if result["ok"] == 0:
  99.             print("{} success:".format(apiname) + str(result))
  100.             return result
  101.         else:
  102.             print("{} error:".format(apiname) + str(result))
  103.             exit(0)
  104.             return result

  105.     # 预处理
  106.     def prepare_request(self):
  107.         return self.gene_request(apiname=api_prepare,
  108.                                  data=self.gene_params(api_prepare))

  109.     # 上传
  110.     def upload_request(self, taskid, upload_file_path):
  111.         file_object = open(upload_file_path, 'rb')
  112.         try:
  113.             index = 1
  114.             sig = SliceIdGenerator()
  115.             while True:
  116.                 content = file_object.read(file_piece_sice)
  117.                 if not content or len(content) == 0:
  118.                     break
  119.                 files = {
  120.                     "filename": self.gene_params(api_upload).get("slice_id"),
  121.                     "content": content
  122.                 }
  123.                 response = self.gene_request(api_upload,
  124.                                              data=self.gene_params(api_upload, taskid=taskid,
  125.                                                                    slice_id=sig.getNextSliceId()),
  126.                                              files=files)
  127.                 if response.get('ok') != 0:
  128.                     # 上传分片失败
  129.                     print('upload slice fail, response: ' + str(response))
  130.                     return False
  131.                 print('upload slice ' + str(index) + ' success')
  132.                 index += 1
  133.         finally:
  134.             'file index:' + str(file_object.tell())
  135.             file_object.close()
  136.         return True

  137.     # 合并
  138.     def merge_request(self, taskid):
  139.         return self.gene_request(api_merge, data=self.gene_params(api_merge, taskid=taskid))

  140.     # 获取进度
  141.     def get_progress_request(self, taskid):
  142.         return self.gene_request(api_get_progress, data=self.gene_params(api_get_progress, taskid=taskid))

  143.     # 获取结果
  144.     def get_result_request(self, taskid):
  145.         return self.gene_request(api_get_result, data=self.gene_params(api_get_result, taskid=taskid))

  146.     def all_api_request(self):
  147.         # 1. 预处理
  148.         pre_result = self.prepare_request()
  149.         taskid = pre_result["data"]
  150.         # 2 . 分片上传
  151.         self.upload_request(taskid=taskid, upload_file_path=self.upload_file_path)
  152.         # 3 . 文件合并
  153.         self.merge_request(taskid=taskid)
  154.         # 4 . 获取任务进度
  155.         while True:
  156.             # 每隔20秒获取一次任务进度
  157.             progress = self.get_progress_request(taskid)
  158.             progress_dic = progress
  159.             if progress_dic['err_no'] != 0 and progress_dic['err_no'] != 26605:
  160.                 print('task error: ' + progress_dic['failed'])
  161.                 return
  162.             else:
  163.                 data = progress_dic['data']
  164.                 task_status = json.loads(data)
  165.                 if task_status['status'] == 9:
  166.                     print('task ' + taskid + ' finished')
  167.                     break
  168.                 print('The task ' + taskid + ' is in processing, task status: ' + str(data))

  169.             # 每次获取进度间隔20S
  170.             time.sleep(20)
  171.         # 5 . 获取结果
  172.         res = self.get_result_request(taskid=taskid)
  173.         # 保存到txt
  174.         data = res['data'].strip('[').strip(']')
  175.         for d in eval(data):
  176.             a = d['onebest']
  177.             fw.write(a + '\n') # 逐行保存


  178. # 注意:如果出现requests模块报错:"NoneType" object has no attribute 'read', 请尝试将requests模块更新到2.20.0或以上版本(本demo测试版本为2.20.0)
  179. # 输入讯飞开放平台的appid,secret_key和待转写的文件路径
  180. if __name__ == '__main__':
  181.     # 单个语音文件解析并保存
  182.     root = "D:/xxxx/"
  183.     filename = "xxxx" # mp3文件名,需修改
  184.     speechpath = root +filename
  185.     save_path = speechpath + '.txt' # txt与mp3同名,并保存在同一路径下
  186.     fw = open(save_path, 'w')

  187.     # 解析语音并保存到txt
  188.     api = RequestApi(appid="xxx", secret_key="xxx", upload_file_path=speechpath+".mp3")
  189.     api.all_api_request()
复制代码
因为此项目还在参加比赛,所以未公开整个工程和大语言模型部分。等后续比赛结束整理资料后再开源。


野火论坛202311302211542247..png
微信图片_20231130215859.jpg
微信图片_20231130215825.jpg
回复

使用道具 举报

发表于 2023-12-2 16:33:51 | 显示全部楼层
真不错  
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-4-28 23:26 , Processed in 0.144847 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表