引言

在我们的上一篇文章中,我们探索了如何将ChatGPT集成到myCobot 280机械臂中,实现了一个通过自然语言控制机械臂的系统。我们详细介绍了项目的动机、使用的关键技术如ChatGPT和Google的Speech-to-text服务,以及我们是如何通过pymycobot模块来控制机械臂的。通过将自然语言处理和机械臂控制相结合,我们的项目旨在降低机器人编程的门槛,使得非专业人士也能轻松地进行机器人编程和实验。

接下来,在这篇文章中,我们将讨论在开发这一系统过程中遇到的挑战,我们是如何克服这些挑战的,以及项目未来的扩展可能性。我们的目标是深入了解技术实施的具体问题,并探索该系统未来发展的新方向。

开发当中遇到的困难

在开发集成了ChatGPT的mycobot 280机械臂控制系统的过程中,我面临了几个主要的技术挑战。

1.语音识别的准确性和响应时间

首先,我遇到的挑战是语音识别的准确性和反应时间。尽管使用了Google的Speech-to-text,但在实际应用中,我发现它有时难以准确识别专业术语或在嘈杂环境中捕捉语音指令。可能是因为不太理解底层逻辑运行的一个原理是什么,也不知道如何来正确的使用。此外,从语音输入到文本输出的过程延迟较长,如何来判断这句话是不是说完了,通常响应的时间较久。

在我说完之后,大概会有3s左右的响应时间。

OpenAI API的实用性和地域限制

ChatGPT的API 是整个项目的核心功能点,没有了他就不能实现AI的机械臂控制系统了。在一开始测试代码的时候我用的是WEB版本的ChatGPT,一开始没有考虑到使用API是一个比较大的问题。

因为地区的问题,没有办法直接通过API进行访问OpenAI,会出现网络延迟,不能够使用代理等软件来实现访问。除此之外还得确保网络的稳定性才能够快快速的进行处理。

1.自然语言转指令的处理

如果解决了上边的生成代码的问题,我们将会得到类似于命令行的字符串,需要将它转变成可以编译的代码。一开始只考虑到了单行的命令行

"robot.move_to_zero()"

要将字符串转化成执行的代码可以用到python的getattr(),他是一个内置函数,用于获取对象的属性值。

getattr(object, name[, default])
object:表示要获取属性的对象。
name:表示要获取的属性的名称。
default:可选参数,表示如果指定的属性不存在时返回的默认值。

getattr() 函数会尝试获取指定对象的指定属性的值。如果对象具有该属性,则返回属性的值;如果对象没有指定的属性,但提供了默认值,则返回默认值;如果对象没有指定的属性,并且没有提供默认值,则会引发 AttributeError 异常。

举个例子直接调用类的方法

class Myclass:
    def print_1(self):
        print("halo word")

obj = mycalss()
getattr(obj,"print_1")()

"""
halo word

用这个方法就可以完美解决如何将字符串的形式输出可执行的代码了!

接下来是将字符串转化为可执行代码的过程:

我们收到的字符串是代码的形式例如

"robot.move_to_zero()"

我们要将这一部分进行拆分,分为obj和方法两部分,就要用到python当中的分割的方法。

# 以.为节点分为前后两个部分
command_str = "robot.move_to_zero()"
parts = command_str.split(".")

parts[0] = "robot"
part[1] = "move_to_zero()"
# 去掉括号保留,方法名
method_name = part[1].split("()")[0]

method = getatter(robot,method_name)
method()

#处理转化方法
def execute_command(instance,command_str):
    try:
        #分割对象名和方法
        parts = command_str.split(".")
        if len(parts) != 2 or parts[0] != 'robot':
            print("Invalid command format.")
            return

        method_name = parts[1].split("()")[0] #移除括号

        #使用getattr 安全的获取方法引用
        if hasattr(instance, method_name):
            method = getattr(instance, method_name)
            method()

        else:
            print(f"the method {method_name} does not exist!")

    except Exception as e:
        print(f"An error occurred: {e}")

这样就完成了,能够处理单行的字符串,但是在测试的时候使用产生多行的命令的时候,这个代码就不行了,它会变成一长串,所以这个方法是无效的。

上述三个是我主要遇到的问题,接下来我将一一的进行解答。

解决方案和应对策略

1.优化语音识别

根据我上述描写的识别延迟的问题,我是通过设置时间来优化我的程序。

# 设置timeout为3秒,phrase_time_limit为10秒
audio = recognizer.listen(source, timeout=3, phrase_time_limit=10)

默认设置没有听到声音,一直的进行监听,我设置了时间上的限制10s,也能够保证我在说完话之后较快的一个响应。

接下来完成的功能代码


import speech_recognition as sr

def speech_to_text():
    # 初始化识别器
    recognizer = sr.Recognizer()

    with sr.Microphone() as source:
        print("start speaking...")

        # 监听源,设置timeout和phrase_time_limit
        # timeout:在这段时间内没有检测到声音,则停止监听
        # phrase_time_limit:监听的最大时长
        try:
            audio = recognizer.listen(source, timeout=3, phrase_time_limit=10)
        except sr.WaitTimeoutError:
            print("No speech was detected within the timeout period.")
            return None

        try:
            # 使用Google的语音识别服务
            text = recognizer.recognize_google(audio, language='en-US')
            print("You said: " + text)
            return text
        except sr.UnknownValueError:
            print("Google Speech Recognition could not understand audio")
            return None
        except sr.RequestError as e:
            print(f"Could not request results from Google Speech Recognition service; {e}")
            return None

这目前已经可以满足大部分的需求了,实际的使用情况下来来看,整个的功能还是比较完整的,能够有效的识别出语音内容,特别是让我说数字的时候他主动转化成阿拉伯数字,在进行交互的过程中省了处理数字的问题。

1.自然语言转化优化

如何来解决多行的指令问题呢。

当我们收到,多行的指令就不能跟之前单纯的分离来进行处理了得考虑其他的方式,以下的情况默认ChatGPT生成的指令是下面这种换行行的字符串,没有带注释的(ChatGPT很喜欢写注释)。

"robot.move_to_zero()
robot.grab_position() 
 robot.plus_z_coords(20)"

只要把多个当成一个来看就好了!

# 分割成多行
commands = command_str.strip().split('\n')

#万一里面存在一些空白符,得先进行处理
for cmd in commands:
    cmd = cmd.strip()
    if not cmd:
        continue

# 我们默认obj 是robot,就只需要获取方法名字就可以了
            if cmd.startswith("robot."):
                cmd = cmd[6:]

            # 分割方法名,和参数
            if '(' in cmd and cmd.endswith(")"):
                method_name, args_str = cmd.split('(', 1)
                method_name = method_name.strip() #删除前后空格
                args_str = args_str.rstrip(")") #删除右侧的)
                # 移除可能的空白字符,并按逗号分隔参数
                args = [arg.strip() for arg in args_str.split(',')] if args_str else []

it works!

1.ChatGPT API的问题

关于这个问题,我目前并没能很好的进行解决,大家如果有好的方法可以,私信我跟我沟通,因为地区的问题,并不能够直接的用API获取响应。

项目的扩展功能和未来展望

视觉功能

在本次记录当中,缺少了最重要的一个模块,视觉模块,单独有一个机械臂没有眼睛的话跟瞎子又有什么区别呢。 对于这一部分的开发,会需要花费较大的经历,如果以后有完成一定程度上的开发,我也会及时出来跟大家进行分享。

之前也有看到日本的Shirokuma 开发个类似的项目,用到了ChatGPT4-vision的功能,做了说出目标进行抓取的一个功能。

https://twitter.com/neka_nat/status/1733517151947108717

这个项目也是相当的有意思,给了我不少开发这个项目的想法。

更加智能的“贾维斯”

相信大家的肯定都有看过钢铁侠,随着AI的不断发展,我觉得在不久的将来,肯定会出现一款如同电影当中的机械臂,能够通过交流的方式来帮助你完成一些工作。

近几年也能说是人工智能的突发猛进的几年,AIGC是近期最火热的内容,只要接收到内容就可以生成对应的文本,图像,视频和音频等等。

总结

很期待未来,AI和机器人相结合能够融合到怎样的一个程度,是不是已经能够帮助人类做一定的事情了!如果你有一些好的想法,或者对我的项目修改的意见欢迎随时跟我提出!