栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

ROS语音控制——小乌龟按设定图形路线运动

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ROS语音控制——小乌龟按设定图形路线运动

最近几天在学习语音识别、语音合成,应用到ROS当中实现一些简单的案例,下面是使用语音来控制turtle小乌龟走设定图形路线的案例。

ROS小乌龟走设定图形路线(键盘控制+Python代码实现)_笨小古的博客-CSDN博客

在上面代码的基础上加了一个语音控制函数 :

# 接收到语音命令后发布速度指令
def get_voice(data):
    voice_text=data.data
    rospy.loginfo("语音已接收")

    if voice_text == "走圆圈。":
        name = 'circle'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走方形。":
        name = 'squ'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走漏斗形。":
        name = 'hourglass'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走60度三角形。":
        name = 'tri60'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走直角三角形。":
        name = 'tri90'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)

完整代码:

#! /usr/bin/env python2
# coding:UTF-8

import math
import rospy
import sys
from turtlesim.msg import Pose  # Pose数据类型包含坐标和角度
from geometry_msgs.msg import Twist  # Twist数据类型包含线速度和角速度
from std_msgs.msg import String



class Turtlerun:
    """ 一个乌龟走图形路线的类 """

    def __init__(self, graph):
        """ 初始化 """
        self.pub = rospy.Publisher("/turtle1/cmd_vel", Twist, queue_size=10)  # 实例化发布者
        rospy.Subscriber("/turtle1/pose", Pose, self.control, queue_size=10)  # 实例化订阅者
        self.twist = Twist()
        self.graph = graph
        self.x = None  # 乌龟目前所在x坐标
        self.y = None  # 乌龟目前所在y坐标
        self.size = 3.0  # 图形边长大小
        self.rate = rospy.Rate(100)  # 循环频率
        self.theta = None  # 乌龟初始角度
        self.goal = []  # 选择的图形目标点
        self.goals = {}  # 储存的图形目标点
        self.error = None  # 距离目标点的差值
        self.lock = 0  # 直线行走与旋转互锁
        self.side = 0  # 乌龟移动目标点的索引值
        self.aim_line = 0.035  # 乌龟转弯前走直线时距离目标距离的精度值
        self.aim_angle = 0.01  # 乌龟直走前转弯时距离目标角度的精度值
        self.i = 1
        self.turns = 0
        self.num = None  # 图形边数索引量

    def control(self, pose):
        """订阅的回调函数"""
        self.turtle_run(self.graph, pose)  # 设定要走什么形状

    def turtle_run(self, graph, pose):
        """ 控制乌龟运动 """
        self.pose_get(pose)
        if self.i == 1:
            # 目标点只设定一次
            self.set_goal(pose, graph)
            self.i += 1
        self.go_line()
        self.rorate()

    def pose_get(self, pose):
        """ 获取当前坐标和角度 """
        self.x = pose.x
        self.y = pose.y
        self.theta = pose.theta

    def set_goal(self, pose, graph):
        """ 设定目标点 """
        self.goals = {
            'squ': [[pose.x + self.size, pose.y, math.pi / 2],
                    [pose.x + self.size, pose.y + self.size, math.pi],
                    [pose.x, pose.y + self.size, - math.pi / 2],
                    [pose.x, pose.y, 0]],
            'tri60': [[pose.x + self.size, pose.y, math.pi * 2 / 3],
                      [pose.x + self.size / 2, pose.y + (self.size / 2 * math.tan(math.pi / 3)), - math.pi * 2 / 3],
                      [pose.x, pose.y, 0]],
            'tri90': [[pose.x + self.size, pose.y, math.pi / 2],
                      [pose.x + self.size, pose.y + self.size, -3 * math.pi / 4],
                      [pose.x, pose.y, 0]],
            'hourglass': [[pose.x, pose.y, math.pi / 3],
                          [pose.x + self.size / 2, pose.y + (self.size * math.sin(math.pi / 3)), math.pi],
                          [pose.x - self.size / 2, pose.y + (self.size * math.sin(math.pi / 3)), - math.pi / 3],
                          [pose.x + self.size / 2, pose.y - (self.size * math.sin(math.pi / 3)), math.pi],
                          [pose.x - self.size / 2, pose.y - (self.size * math.sin(math.pi / 3)), math.pi / 3],
                          [pose.x, pose.y, math.pi / 3]],

        }
        # 条件选择图形目标
        if graph == 'squ':
            self.goal = self.goals['squ']
        elif graph == 'tri60':
            self.goal = self.goals['tri60']
        elif graph == 'tri90':
            self.goal = self.goals['tri90']
        elif graph == 'hourglass':
            self.goal = self.goals['hourglass']
        elif graph == 'circle':
            self.circle()
        self.num = len(self.goal) - 1

    def go_line(self):
        """ 走直线 """
        if self.lock == 0:  # 和旋转互锁
            # 计算现在的误差
            self.error = math.sqrt(
                (self.x - self.goal[self.side][0]) ** 2 + (self.y - self.goal[self.side][1]) ** 2)

            if self.error > self.aim_line:  # 未到设定精度时前进
                self.twist.linear.x = 1.0
            else:
                self.twist.linear.x = 0
                self.lock = 1  # 解锁旋转
            self.pub.publish(self.twist)  # 发布乌龟速度

    def rorate(self):
        """ 转动角度到达另一边 """
        if self.lock == 1:
            self.error = abs(self.theta - self.goal[self.side][2])
            if self.error > self.aim_angle:  # 未到达转动角度精度时继续旋转
                self.twist.angular.z = 1.0
            else:
                self.twist.angular.z = 0
                self.lock = 0
                if self.side < self.num:
                    self.side = self.side + 1
                else:
                    self.side = 0  # 走完一轮目标点后重置目标点
                    self.i = 1
                    self.turns += 1
                    print(self.turns)
            self.pub.publish(self.twist)  # 发布乌龟速度

    def circle(self):
        """ 走圆圈 """
        while not rospy.is_shutdown():
            self.twist.linear.x = 2.0
            self.twist.angular.z = 1.0
            self.pub.publish(self.twist)
            rospy.loginfo("message have published x = %d angular z = %0.2f", self.twist.linear.x, self.twist.angular.z)
            # 在终端打印一份日志
            self.rate.sleep()
            # 按照设置的速率进行延时

# 接收到语音命令后发布速度指令
def get_voice(data):
    voice_text=data.data
    rospy.loginfo("语音已接收")

    if voice_text == "走圆圈。":
        name = 'circle'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走方形。":
        name = 'squ'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走漏斗形。":
        name = 'hourglass'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走60度三角形。":
        name = 'tri60'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)
    elif voice_text == "走直角三角形。":
        name = 'tri90'
        rospy.loginfo("I said:: %s",voice_text)
        Turtlerun(name)



if __name__ == '__main__':
    a = input("选择控制方式:1.命令行;2.语音控制n")


    if a == 1:
        graph_list = ['circle', 'squ', 'tri60', 'tri90', 'hourglass']
        if len(sys.argv) > 1 and sys.argv[1] in graph_list:  # 实现rosrun xx yy.py squ直接跑对应图形
            name = sys.argv[1]   
        else:
            name = input(
                'Please input graph name(circle squ tri60 tri90 hourglass): ')  # 没在命令输对图形名称时提示输入
        try:
            rospy.init_node('turtle_run', anonymous=True)  # 对节点进行初始化,命名一个叫turtle_run的节点
            name = str(name)
            Turtlerun(name)
            rospy.spin()
        except rospy.ROSInterruptException:
            pass

    else:
        rospy.init_node('voice_teleop')
        while not rospy.is_shutdown():
            rospy.loginfo("Starting voice Teleop")
            # 订阅语音识别的输出字符
            rospy.Subscriber("/voiceWords", String, get_voice)
            rospy.spin()

 这里的语音功能包使用的是科大讯飞的,需要到科大讯飞网站注册帐号(需要APPID),讯飞开放平台-以语音交互为核心的人工智能开放平台

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1033378.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号