voice_command.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # copyright 2014 UNL Nimbus Lab 
00003 #
00004 #  Licensed under the Apache License, Version 2.0 (the "License");
00005 #     you may not use this file except in compliance with the License.
00006 #    You may obtain a copy of the License at
00007 #  
00008 #        http://www.apache.org/licenses/LICENSE-2.0
00009 #  
00010 #    Unless required by applicable law or agreed to in writing, software
00011 #  distributed under the License is distributed on an "AS IS" BASIS,
00012 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 #   See the License for the specific language governing permissions and
00014 #   limitations under the License.
00015 import rospy
00016 from ros_glass_tools.srv import * 
00017 from std_msgs.msg import Empty
00018 
00019 class VoiceCommandControl:
00020     '''Node to translate a voice/text command into a ROS message command
00021       This node takes in a list of robots prefixes, a list of global commands and topics, and a list of robot
00022       commands and topics. 
00023       
00024         When a global command is received in a request it publishes a blank message on that topic.
00025 
00026         When a robot command is received which means robot #, or all. It will publish a command on that topic
00027         with the robot prefex added to the namespace. 
00028         and example launch file to set this up is shown below.
00029 
00030           <node name="voice_commands" type="voice_command.py" pkg="ros_glass_tools">
00031             <rosparam param="global_commands">
00032               [ [stop, stop],[go, go] ]
00033            
00034             </rosparam>
00035             <rosparam param="robots">
00036               [a, b]
00037             </rosparam>
00038             <rosparam param="robot_commands">
00039               [
00040                 [forward, forward],
00041                 [backward, backward]
00042               ]
00043             </rosparam>
00044            </node>
00045         '''
00046 
00047 
00048 
00049     def __init__(self):
00050       #init nodes and services
00051         rospy.init_node("voice_command_trans")
00052         self.serv = rospy.Service("glass_voice_command", Command, self.command)
00053         
00054         #read lists
00055         input_global_commands =  rospy.get_param('~global_commands', None)
00056         input_robots =  rospy.get_param('~robots', None)
00057         input_robot_commands=  rospy.get_param('~robot_commands', None)
00058 
00059         #create commands
00060         self.global_commands =  create_command_dict(input_global_commands)
00061         self.robot_commands =  create_robot_commands(input_robot_commands, input_robots)
00062 
00063     
00064         
00065 
00066     def command(self, request):
00067         '''
00068           Handle a service request at the moment handles requests of the following syntax for one word commands
00069           execute `command` -> Publish to the global command topic if defined
00070           all `command` -> Publsih the command on all robots topics if defined 
00071           robot # `command` -> Publsih the command on the # robot topics if robot exists and command defined
00072           Returns the warning message or success string
00073         '''
00074         robot_number = 'All' 
00075         command_arr = request.command.split(' ')
00076         result = 'Fail'
00077         #are they commanding a single robot
00078         if command_arr[0] == 'robot':
00079             try:
00080                 #see if it parsed the speech as an int
00081                 robot_number = int(command_arr[1])
00082             except:
00083                 #otherwise use this to get the correct value
00084                 number = command_arr[1]
00085                 #to and too and four cause problems and must be replaced
00086                 if number == 'to' or number == 'too':
00087                   number = 'two'
00088                 if number == 'for':
00089                   number = 'four'
00090                 robot_number = text2int(number)
00091             cmd = command_arr[2]
00092             #send the commands
00093             result = send_robot_command(robot_number, cmd, self.robot_commands)
00094 
00095         #are they command all of the robots
00096         elif command_arr[0] == 'all':
00097             cmd = command_arr[1]
00098             result = send_robot_command(robot_number, cmd, self.robot_commands)
00099 
00100         #or is it a global command
00101         elif command_arr[0] == 'execute':
00102             cmd = command_arr[1]
00103             result = send_command(cmd, self.global_commands)
00104 
00105         #or are they talking gibberish
00106         else:
00107             result = "INVALID COMMAND MUST BEGIN WITH All, Robot #, or execute"
00108 
00109         rospy.logerr(result)
00110         return CommandResponse(result)
00111 
00112 def send_command(cmd, cmd_dict):
00113     '''publish an Empty message on the cmd if defined in the dictonary of command topics or 
00114       just return that we don't have a defined command
00115     '''
00116     if cmd not in cmd_dict:
00117         return "Command %s Not Defined"%cmd
00118     else:
00119         msg = Empty()
00120         cmd_dict[cmd].publish(msg)
00121         return "Sent Command: " + cmd  
00122 
00123 def send_robot_command(robot_number, cmd, robot_list):
00124     '''publish the command on the specific robot
00125         If all is selected it will publish it on every robot on the list
00126         otherwise it is based on which robot number is defined
00127     '''
00128     cmd = cmd.lower()
00129     if robot_number == 'All':
00130         results = []
00131          #send the command on all of them
00132         for rob in robot_list:
00133             res = send_command(cmd, rob)
00134             results.append(res)
00135         return  '\n'.join(results)
00136             
00137     else:
00138         #only send it on one
00139         if robot_number > len(robot_list):
00140             return "Robot Number invalid"
00141         else:
00142             return send_command(cmd, robot_list[robot_number-1])
00143 
00144 
00145     
00146 
00147 def create_command_dict(command_arr, prefix = ''):
00148     '''create a dictonary that maps command word to a publisher that will get 
00149         an empty message when the command is received 
00150     '''
00151     command_dict = {}
00152     for pair in command_arr:
00153         topic_name = prefix + pair[1]
00154         publisher = rospy.Publisher(topic_name, Empty)
00155         command_dict[pair[0]] = publisher   
00156     return command_dict
00157 
00158 def create_robot_commands(commands, robots):
00159     '''with the list of commands and the list of robots make the robot array so
00160       we can publish to specific robots
00161      '''
00162     robot_list = []
00163     for prefix in robots:
00164        #create the dictonary with the robot prefix appended to the namespace
00165         robot_list.append(create_command_dict(commands,  prefix + '/'))
00166     return robot_list
00167 
00168         
00169 def text2int(textnum):
00170         '''simple text number represnetation to integer value'''
00171         nums = [
00172         "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
00173         "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
00174         "sixteen", "seventeen", "eighteen", "nineteen"
00175         ]
00176         val = nums.index(textnum.lower())
00177         return val
00178 
00179 
00180 
00181 
00182 if __name__ == '__main__':
00183     vcc = VoiceCommandControl()
00184     rospy.spin()


ros_glass_tools
Author(s):
autogenerated on Thu Aug 27 2015 14:47:21