voice_teleop_advanced.py
Go to the documentation of this file.
00001 #!/usr/bin/env
00002 
00003 """
00004 voice_nav.py - Version 1.1 2013-12-20
00005 
00006 Allows controlling a mobile base using simple speech commands.
00007 
00008 Based on the voice_cmd_vel.py script by Michael Ferguson in
00009 the pocketsphinx ROS package.
00010 
00011 See http://www.ros.org/wiki/pocketsphinx
00012 """
00013 import rospy
00014 from geometry_msgs.msg import Twist
00015 from std_msgs.msg import String
00016 from math import copysign
00017 
00018 class VoiceNav:
00019      def __init__(self):
00020         #initialize the ROS node
00021         rospy.init_node('voice_teleop')
00022         rospy.on_shutdown(self.cleanup)
00023     
00024         # Set a number of parameters affecting the robot's speed
00025         self.max_speed = rospy.get_param("~max_speed", 0.4)
00026         self.max_angular_speed = rospy.get_param("~max_angular_speed", 1.5)
00027         self.speed = rospy.get_param("~start_speed", 0.1)
00028         self.angular_speed = rospy.get_param("~start_angular_speed", 0.5)
00029         self.linear_increment = rospy.get_param("~linear_increment", 0.05)
00030         self.angular_increment = rospy.get_param("~angular_increment", 0.4)
00031     
00032         # We don't have to run the script very fast
00033         self.rate = rospy.get_param("~rate", 5)
00034         r = rospy.Rate(self.rate)
00035     
00036         # A flag to determine whether or not voice control is paused
00037         self.paused = False
00038     
00039         # Initialize the Twist message we will publish.
00040         self.cmd_vel = Twist()
00041     
00042         # Publish the Twist message to the cmd_vel topic
00043         self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=5)
00044     
00045         # Subscribe to the /recognizer/output topic to receive voice commands.
00046         rospy.Subscriber('/recognizer/output', String, self.speech_callback)
00047     
00048         # A mapping from keywords or phrases to commands
00049         #These are different kinds of commands you can give to the robot and you can delete/add any command you want.
00050         self.keywords_to_command = {'stop': ['stop', 'halt', 'abort', 'kill', 'panic', 'off', 'freeze', 'shut down', 'turn off', 'help', 'help me'],
00051                                     'slower': ['slow down', 'slower'],
00052                                     'faster': ['speed up', 'faster'],
00053                                     'forward': ['forward', 'ahead', 'straight'],
00054                                     'backward': ['back', 'backward', 'back up'],
00055                                     'rotate left': ['rotate left'],
00056                                     'rotate right': ['rotate right'],
00057                                     'turn left': ['turn left'],
00058                                     'turn right': ['turn right'],
00059                                     'quarter': ['quarter speed'],
00060                                     'half': ['half speed'],
00061                                     'full': ['full speed'],
00062                                     'pause': ['pause speech'],
00063                                     'continue': ['continue speech']}
00064     
00065         rospy.loginfo("Ready to receive voice commands")
00066     
00067         # We have to keep publishing the cmd_vel message if we want the robot to keep moving.
00068         while not rospy.is_shutdown():
00069             self.cmd_vel_pub.publish(self.cmd_vel)
00070             r.sleep()
00071 
00072 def get_command(self, data):
00073     # Attempt to match the recognized word or phrase to the
00074     # keywords_to_command dictionary and return the appropriate
00075     # command
00076     for (command, keywords) in self.keywords_to_command.iteritems():
00077         for word in keywords:
00078             if data.find(word) > -1:
00079                 return command
00080 
00081 def speech_callback(self, msg):
00082     # Get the motion command from the recognized phrase
00083     command = self.get_command(msg.data)
00084 
00085     # Log the command to the screen
00086     rospy.loginfo("Command: " + str(command))
00087 
00088     # If the user has asked to pause/continue voice control,
00089     # set the flag accordingly
00090     if command == 'pause':
00091         self.paused = True
00092     elif command == 'continue':
00093         self.paused = False
00094 
00095     # If voice control is paused, simply return without
00096     # performing any action
00097     if self.paused:
00098         return
00099 
00100     # The list of if-then statements should be fairly
00101     # self-explanatory
00102     if command == 'forward':
00103         self.cmd_vel.linear.x = self.speed
00104         self.cmd_vel.angular.z = 0
00105 
00106     elif command == 'rotate left':
00107         self.cmd_vel.linear.x = 0
00108         self.cmd_vel.angular.z = self.angular_speed
00109 
00110     elif command == 'rotate right':
00111         self.cmd_vel.linear.x = 0
00112         self.cmd_vel.angular.z = -self.angular_speed
00113 
00114     elif command == 'turn left':
00115         if self.cmd_vel.linear.x != 0:
00116             self.cmd_vel.angular.z += self.angular_increment
00117         else:
00118             self.cmd_vel.angular.z = self.angular_speed
00119 
00120     elif command == 'turn right':
00121         if self.cmd_vel.linear.x != 0:
00122             self.cmd_vel.angular.z -= self.angular_increment
00123         else:
00124             self.cmd_vel.angular.z = -self.angular_speed
00125 
00126     elif command == 'backward':
00127         self.cmd_vel.linear.x = -self.speed
00128         self.cmd_vel.angular.z = 0
00129 
00130     elif command == 'stop':
00131         # Stop the robot!  Publish a Twist message consisting of all zeros.
00132         self.cmd_vel = Twist()
00133 
00134     elif command == 'faster':
00135         self.speed += self.linear_increment
00136         self.angular_speed += self.angular_increment
00137         if self.cmd_vel.linear.x != 0:
00138             self.cmd_vel.linear.x += copysign(self.linear_increment, self.cmd_vel.linear.x)
00139         if self.cmd_vel.angular.z != 0:
00140             self.cmd_vel.angular.z += copysign(self.angular_increment, self.cmd_vel.angular.z)
00141 
00142     elif command == 'slower':
00143         self.speed -= self.linear_increment
00144         self.angular_speed -= self.angular_increment
00145         if self.cmd_vel.linear.x != 0:
00146             self.cmd_vel.linear.x -= copysign(self.linear_increment, self.cmd_vel.linear.x)
00147         if self.cmd_vel.angular.z != 0:
00148             self.cmd_vel.angular.z -= copysign(self.angular_increment, self.cmd_vel.angular.z)
00149 
00150     elif command in ['quarter', 'half', 'full']:
00151         if command == 'quarter':
00152             self.speed = copysign(self.max_speed / 4, self.speed)
00153 
00154         elif command == 'half':
00155             self.speed = copysign(self.max_speed / 2, self.speed)
00156 
00157         elif command == 'full':
00158             self.speed = copysign(self.max_speed, self.speed)
00159 
00160         if self.cmd_vel.linear.x != 0:
00161             self.cmd_vel.linear.x = copysign(self.speed, self.cmd_vel.linear.x)
00162 
00163         if self.cmd_vel.angular.z != 0:
00164             self.cmd_vel.angular.z = copysign(self.angular_speed, self.cmd_vel.angular.z)
00165 
00166     else:
00167         return
00168 
00169     self.cmd_vel.linear.x = min(self.max_speed, max(-self.max_speed, self.cmd_vel.linear.x))
00170     self.cmd_vel.angular.z = min(self.max_angular_speed, max(-self.max_angular_speed, self.cmd_vel.angular.z))
00171 
00172 def cleanup(self):
00173     # When shutting down be sure to stop the robot!
00174     twist = Twist()
00175     self.cmd_vel_pub.publish(twist)
00176     rospy.sleep(1)
00177 
00178 if __name__=="__main__":
00179   try:
00180       VoiceNav()
00181       rospy.spin()
00182   except rospy.ROSInterruptException:
00183       rospy.loginfo("Voice navigation terminated.")


gapter
Author(s):
autogenerated on Thu Jun 6 2019 22:05:13