一、前言
接上一篇博客:ros机器人编程实践(15.1)- 使用科大讯飞语音控制turtlebot导航
二、使用科大讯飞语音SDK
对着上一篇博客中科大讯飞的安装教程,创建了robot_voice的基于roscpp的包创建robot_voice包教程。科大讯飞sdk的安装教程那位博主写了四篇博客介绍已经很详细,就不累述了。
2.1 测试语音识别
//启动ros服务
roscore
//启动语音识别节点
rosrun robot_voice iat_publish
//发布唤醒语音识别的话题消息,任意消息即可唤醒
rostopic pub /voiceWakeup std_msgs/String "data: 'anny string'"
效果如下: 当然还可以在iat_publish发布的消息中查看语音识别的效果:
rostopic echo /voiceWords
2.1 测试语音合成
详细教程在这:语音合成,博主写的很详细了,这里也不累述。
rosrun xfei_asr tts_subscribe_speak
rostopic pub xfwords std_msgs/String "你好,世界!"
三、代码实现
3.1 修改语音识别的源码
首先修改语音识别的源码,他需要识别一次唤醒一次,我们希望它一直监听。
sudo gedit ~/wanderbot_ws/src/robot_voice/src/iat_publish.cpp
看下源码发现他是在收到/voiceWakeup话题的任何消息后进入回调函数实现唤醒语音识别,如下图中代码: 那好办,把唤醒函数抄一份,我们不通过回调来调用,我们主动的调用它。 如下图修改:
void WakeUp(const std_msgs::String::ConstPtr& msg)
{
printf("waking up\r\n");
usleep(700*1000);
wakeupFlag=1;
}
void Wake()
{
printf("waking up\r\n");
usleep(700*1000);
wakeupFlag=1;
}
然后在每次识别完成发布了识别消息后唤醒识别系统。 如下图倒数第五行,调用了我们自己写的唤醒函数: ros里写cpp的脚本是需要编译的,所以回到工作区编译:
cd ~/wanderbot_ws
catkin_make
source ./devel/setup.bash
这里非常重要哦,之前写的都是Python的脚本是不需要这一笔操作的,和容易忘记了,忘了的话你每次修改cpp文件都会发现没有效果。 然后测试下我们改写的效果:
//启动ros服务
roscore
//启动语音识别节点
rosrun robot_voice iat_publish
3.2 创建语音识别结果的监听脚本
cd ~/wanderbot_ws/src/wanderbot/src
sudo gedit voice_contrl.py
如果看了我《ros机器人编程实践(8.9.10)-用turtlebot3仿真实现机器人在多点间来回导航》这篇博客应该知道这个脚本是在turtlebot多点导航的基础上修改的。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import rospy
import actionlib
import roslib;
import rospy
from std_msgs.msg import String#添加了接受的消息类型
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
waypoints = [ #导航的坐标点
[(1.522, 0.444, 0.0), (0.0, 0.0, -0.519, 0.85)],
[(-2.0432, -0.439, 0.0), (0.0, 0.0, -0.559, 0.82902)]
]
def goal_pose(pose): #坐标点转换成对应的消息类型
goal_pose = MoveBaseGoal()
goal_pose.target_pose.header.frame_id = 'map'
goal_pose.target_pose.pose.position.x = pose[0][0]
goal_pose.target_pose.pose.position.y = pose[0][1]
goal_pose.target_pose.pose.position.z = pose[0][2]
goal_pose.target_pose.pose.orientation.x = pose[1][0]
goal_pose.target_pose.pose.orientation.y = pose[1][1]
goal_pose.target_pose.pose.orientation.z = pose[1][2]
goal_pose.target_pose.pose.orientation.w = pose[1][3]
return goal_pose
def callback(msg):
print msg.data#这里注意需要.data而不是msg本身,data里存的才是字符串
if msg.data.find('one') > -1:
pose = waypoints[0]
elif msg.data.find('three') > -1:
pose = waypoints[1]
else:
return;
client = actionlib.SimpleActionClient('move_base', MoveBaseAction) # <3>
client.wait_for_server()
print("goal:x=%f y=%f"%(pose[0][0],pose[0][1]))
goal = goal_pose(pose)
client.send_goal(goal)
client.wait_for_result()
if __name__ == '__main__':
rospy.init_node('message_publisher')
pub=rospy.Publisher('voiceWakeup',String,queue_size = 1)
rospy.sleep(1)
pub.publish('wake up')#唤醒语音识别系统
sub = rospy.Subscriber('voiceWords', String,callback)#监听识别结果的消息传入回调函数
rospy.spin()
好了到这里就大功告成了。
四、效果测试
启动仿真环境:
roslaunch turtlebot3_gazebo turtlebot3_world.launch
启动rviz:
roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:=$HOME/map.yaml
启动语音检测脚本:
rosrun robot_voice iat_publish
启动语音控制导航脚本:
rosrun wanderbot voice_contrl.py
~自己玩玩吧 Tips:识别关键字是‘one’ 和‘three’ 为什么不用two呢。。。。因为他会识别成‘to’。。。我是醉了