赞
踩
电脑端: ubuntu22.04实体机作为上位机
ROS版本:ros2-humble
实体机器人: STM32 + 思岚A1激光雷达
科大讯飞语音SDK 讯飞开放平台-以语音交互为核心的人工智能开放平台
(1)进入官网的控制台
(2)在左侧导航栏中选择 语音识别-> 语音听写
(3)下载语音模块
新建一个工作空间,里面新建两个文件夹 src voice_ros2
将SDK压缩包解压后的文件,放入voice_ros2中,进入sample目录的iat_online_record_sample目录下,运行下面的命令
source 64bit_make.sh
在bin目录下执行对应的可执行文件了
./iat_online_record_sample
如果遇到下列问题:error while loading shared libraries: libmsc.so: cannot open shared object file: No such file or directory
就把在终端中进入下列目录中
执行命令:
- sudo cp libmsc.so /usr/local/lib
- sudo ldconfig
src 文件夹中放的是 两个功能包,base 中是stm32的ROS2驱动包,teleop_twist_keyboard是github上下载的键盘控制节点功能包,地址如下:
GitHub - ros2/teleop_twist_keyboard at ardent
这个目录下的文件是SDK解压后的文件,其中 红框中的voice.py是也单独编写的文件
- import subprocess
- import multiprocessing
- import time
-
- def run_iat_online_record_sample(queue):
- process = subprocess.Popen(["./bin/iat_online_record_sample"],
- stdout=subprocess.PIPE,
- stdin=subprocess.PIPE,
- stderr=subprocess.PIPE,
- )
-
- # Communicate with the process
- stdout, _ = process.communicate(input=b"0\n1\n")
-
- # Put the result into the queue
- queue.put(stdout.decode('utf-8'))
-
- def main():
- while True:
- # Create a queue for communication between processes
- queue = multiprocessing.Queue()
-
- # Start the process
- process = multiprocessing.Process(target=run_iat_online_record_sample, args=(queue,))
- process.start()
-
- # Wait for the process to finish and get the result from the queue
- process.join()
- result = queue.get()
-
- # Print the result
- print("Result:", result)
-
- # Save the result to a text file, clearing the file first
- with open("result.txt", "w") as f:
- f.write(result)
-
- # Ask user whether to continue recognition
- continue_recognition = input("是否继续识别? (0: 结束, 1: 继续): ")
- if continue_recognition == "0":
- break
-
- if __name__ == "__main__":
- main()
这个文件运行后会在当前目录生成一个result.txt文件,如下图,这个文件的内容每次识别之后都会更新,键盘节点就是通过获取这个文件的数据来通过语音控制机器人移动的
在键盘控制的代码前添加读取文件数据的代码
这里将刚刚识别到的语音过滤后存储在voice_command[0]中,以供后续使用,下面会通过判断voice_command[0]中的值来进行不同的操作
- import sys
- import threading
- import time
- import os
- from std_msgs.msg import String
- import geometry_msgs.msg
- import rclpy
-
- if sys.platform == 'win32':
- import msvcrt
- else:
- import termios
- import tty
-
- msg = """
- This node takes keypresses from the keyboard and publishes them
- as Twist/TwistStamped messages. It works best with a US keyboard layout.
- ---------------------------
- Moving around:
- u i o
- j k l
- m , .
- For Holonomic mode (strafing), hold down the shift key:
- ---------------------------
- U I O
- J K L
- M < >
- t : up (+z)
- b : down (-z)
- anything else : stop
- q/z : increase/decrease max speeds by 10%
- w/x : increase/decrease only linear speed by 10%
- e/c : increase/decrease only angular speed by 10%
- CTRL-C to quit
- """
-
- moveBindings = {
- 'i': (1, 0, 0, 0),
- 'o': (1, 0, 0, -1),
- 'j': (0, 0, 0, 1),
- 'l': (0, 0, 0, -1),
- 'u': (1, 0, 0, 1),
- ',': (-1, 0, 0, 0),
- '.': (-1, 0, 0, 1),
- 'm': (-1, 0, 0, -1),
- 'O': (1, -1, 0, 0),
- 'I': (1, 0, 0, 0),
- 'J': (0, 1, 0, 0),
- 'L': (0, -1, 0, 0),
- 'U': (1, 1, 0, 0),
- '<': (-1, 0, 0, 0),
- '>': (-1, -1, 0, 0),
- 'M': (-1, 1, 0, 0),
- 't': (0, 0, 1, 0),
- 'b': (0, 0, -1, 0),
- }
-
- speedBindings = {
- 'q': (1.1, 1.1),
- 'z': (.9, .9),
- 'w': (1.1, 1),
- 'x': (.9, 1),
- 'e': (1, 1.1),
- 'c': (1, .9),
- }
-
-
- def getKey(settings):
- if sys.platform == 'win32':
- # getwch() returns a string on Windows
- key = msvcrt.getwch()
- else:
- tty.setraw(sys.stdin.fileno())
- # sys.stdin.read() returns a string on Linux
- key = sys.stdin.read(1)
- termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
- return key
-
-
- def saveTerminalSettings():
- if sys.platform == 'win32':
- return None
- return termios.tcgetattr(sys.stdin)
-
-
- def restoreTerminalSettings(old_settings):
- if sys.platform == 'win32':
- return
- termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
-
-
- def vels(speed, turn):
- return 'currently:\tspeed %s\tturn %s ' % (speed, turn)
-
-
- def main():
- settings = saveTerminalSettings()
-
- rclpy.init()
-
- node = rclpy.create_node('teleop_twist_keyboard')
-
- # parameters
- stamped = node.declare_parameter('stamped', False).value
- frame_id = node.declare_parameter('frame_id', '').value
- if not stamped and frame_id:
- raise Exception("'frame_id' can only be set when 'stamped' is True")
-
- if stamped:
- TwistMsg = geometry_msgs.msg.TwistStamped
- else:
- TwistMsg = geometry_msgs.msg.Twist
-
- pub = node.create_publisher(TwistMsg, 'cmd_vel', 10)
-
- voice_command = [None] # Initializing as a list
-
- spinner = threading.Thread(target=rclpy.spin, args=(node,))
- spinner.start()
-
- speed = 0.5
- turn = 1.0
- x = 0.0
- y = 0.0
- z = 0.0
- th = 0.0
- status = 0.0
-
- twist_msg = TwistMsg()
-
- if stamped:
- twist = twist_msg.twist
- twist_msg.header.stamp = node.get_clock().now().to_msg()
- twist_msg.header.frame_id = frame_id
- else:
- twist = twist_msg
-
- try:
- print(msg)
- print(vels(speed, turn))
- while True:
- print("当前工作路径:", os.getcwd())
- with open('./voice_ros2/result.txt', 'r') as f:
- # with open('/home/lsg/xufen3_ws/voice_ros2/result.txt', 'r') as f:
- for line in f:
- if line.startswith('Result: ['):
- start = line.find('[')
- end = line.find(']')
- if start != -1 and end != -1:
- voice_command[0] = line[start + 1:end].strip()
- print("voice_command", voice_command[0])
- # Clearing the content of result.txt
- open('./voice_ros2/result.txt', 'w').close()
- # open('/home/lsg/xufen3_ws/voice_ros2/result.txt', 'w').close()
- break
-
- key = getKey(settings)
- # print("键盘控制按键输出", key)
- if key in moveBindings.keys():
- x = moveBindings[key][0]
- y = moveBindings[key][1]
- z = moveBindings[key][2]
- th = moveBindings[key][3]
- elif key in speedBindings.keys():
- speed = speed * speedBindings[key][0]
- turn = turn * speedBindings[key][1]
-
- print(vels(speed, turn))
- if (status == 14):
- print(msg)
- status = (status + 1) % 15
-
- elif voice_command[0] is not None:
- if voice_command[0] == "小车后退":
- print("语音控制小车前进", voice_command[0])
- x = moveBindings['i'][0]
- y = moveBindings['i'][1]
- z = moveBindings['i'][2]
- th = moveBindings['i'][3]
- elif voice_command[0] == "小车前进":
- print("语音控制小车后退", voice_command[0])
- x = moveBindings[','][0]
- y = moveBindings[','][1]
- z = moveBindings[','][2]
- th = moveBindings[','][3]
- elif voice_command[0] == "小车左转":
- print("语音控制小车左转", voice_command[0])
- x = moveBindings['j'][0]
- y = moveBindings['j'][1]
- z = moveBindings['j'][2]
- th = moveBindings['j'][3]
- elif voice_command[0] == "小车右转":
- print("语音控制小车右转", voice_command[0])
- x = moveBindings['l'][0]
- y = moveBindings['l'][1]
- z = moveBindings['l'][2]
- th = moveBindings['l'][3]
- elif voice_command[0] == "小车停":
- print("语音控制小车停", voice_command[0])
- x = moveBindings['k'][0]
- y = moveBindings['k'][1]
- z = moveBindings['k'][2]
- th = moveBindings['k'][3]
- voice_command[0] = None
- else:
- x = 0.0
- y = 0.0
- z = 0.0
- th = 0.0
- if (key == '\x03'):
- break
-
- if stamped:
- twist_msg.header.stamp = node.get_clock().now().to_msg()
-
- twist.linear.x = x * speed
- twist.linear.y = y * speed
- twist.linear.z = z * speed
- twist.angular.x = 0.0
- twist.angular.y = 0.0
- twist.angular.z = th * turn
- pub.publish(twist_msg)
-
- # Print timestamp every second
- time.sleep(1)
- print("时间戳:", time.time())
-
- except Exception as e:
- print(e)
-
- finally:
- if stamped:
- twist_msg.header.stamp = node.get_clock().now().to_msg()
-
- twist.linear.x = 0.0
- twist.linear.y = 0.0
- twist.linear.z = 0.0
- twist.angular.x = 0.0
- twist.angular.y = 0.0
- twist.angular.z = 0.0
- pub.publish(twist_msg)
- rclpy.shutdown()
- spinner.join()
-
- restoreTerminalSettings(settings)
-
-
- if __name__ == '__main__':
- main()
-
- // xufen3_ws工作空间下
- // 终端1:
- colcon build
-
- . install/setup.bash
-
- ros2 launch ros2_stm32_bridge driver.launch.py
-
-
- // 终端2:
- . install/setup.bash
-
- ros2 run teleop_twist_keyboard teleop_twist_keyboard
-
-
- // 终端3 ~/xufen3_ws/voice_ros2$ 目录下 :
-
- python3 voice.py
然后就可以通过语音控制小车
在右侧终端按1进行语音识别,此时将识别到小车前进的命令并打印,在左侧终端按回车健获取result中的命令,将输出voice_command 小车前进,此时再按键ctrl+c,将输出语音控制小车前进 小车前进并且小车开始移动。
目前的代码需要按键才能加载进来语音的命令并控制小车移动,但好在实现了功能,后续还会继续优化。
终端3中,输入数字1 然后 语音输入指令 “小车前进” 或“ 小车后退” 或 “小车左转” 或“”小车右转”
等到终端3中,打印了语音指令后,鼠标移动到终端2,按下回车键即可小车移动。
需要按键控制,感觉发出语音指令后,要等好几秒才能移动小车,还需要按键,不过还是初步实现了语音控制,后期优化,实现更实用的语音控制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。