node.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 
00004 # Import Python packages
00005 import os
00006 import sys
00007 import rospy
00008 import rospkg
00009 import datetime
00010 import platform
00011 from datetime import datetime as dt
00012 
00013 # Import ROS messages
00014 import std_msgs.msg
00015 from rospeex_msgs.msg import SignalProcessingResponse
00016 from rospeex_msgs.msg import SpeechSynthesisState
00017 from rospeex_msgs.msg import SignalProcessingStream
00018 
00019 # Import other libraries
00020 from rospeex_core import logging_util
00021 from rospeex_core.spi.signal_processing_interface import ConnectorInterface
00022 from rospeex_core import exceptions as ext
00023 
00024 logging_util.setup_logging(use_ros_logging=True)
00025 
00026 
00027 class SignalProcessingInterface(object):
00028     """ SignalProcessingInterface class """
00029 
00030     _SPI_RESPONSE_TOPIC_NAME = 'spi_res'
00031     _SS_STATE_TOPIC_NAME = 'ss_state'
00032     _SPI_STREAM_TOPIC_NAME = 'spi_stream'
00033 
00034     def __init__(self):
00035         """ init function """
00036         package = rospkg.RosPack()
00037         rospeex_dir = package.get_path('rospeex_core')
00038         self._connector = None
00039         self._ip_addr = '127.0.0.1'
00040         self._app_dir = os.path.join(rospeex_dir, 'bin')
00041         self._controller = 'NICTmmcvController'
00042         self._nict_mmcv = 'NICTmmcv'
00043         self._mmse_setting = 'NICTmmcv.mmse.ini'
00044         self._vad_setting = 'NICTmmcv.vad.ini'
00045         self._audio_dir = 'rospeex'
00046         self._recv_port = 5002
00047         self._send_port = 16001
00048         self._websocket_port = 9000
00049         self._vadoff_during_play = True
00050         self._request_id = 0
00051         self._stream_seq = 0
00052         self._log_level = 'warn'
00053         self._audio_monitor = None
00054         self._pub_spi = None
00055         self._pub_spi_stream = None
00056         self._ss_state_dict = {}
00057 
00058     def _ss_state_response(self, response):
00059         """ receive speech synthesis node state
00060         @param response: response data
00061         @type  response: str
00062         """
00063         rospy.loginfo(response)
00064 
00065         # add dict
00066         user = response.header.user
00067         if response.header.user not in self._ss_state_dict:
00068             self._ss_state_dict[user] = [0, dt.now()]
00069 
00070         # update state
00071         if response.play_state is True:
00072             self._ss_state_dict[user][0] += 1
00073         else:
00074             self._ss_state_dict[user][0] -= 1
00075         self._ss_state_dict[user][1] = dt.now()
00076 
00077         # update state
00078         state_list = [state[0] for state in self._ss_state_dict.values()]
00079         if self._vadoff_during_play:
00080             play_state = True if sum(state_list) > 0 else False
00081         else:
00082             play_state = False
00083         self._connector.set_play_sound_state(play_state)
00084 
00085     def _ui_response(self, data):
00086         """ receive user interface response
00087         @param data: voice data
00088         @type  data: str
00089         """
00090         msg = SignalProcessingResponse()
00091         msg.header.user = rospy.get_name()
00092         msg.header.request_id = str(self._request_id)
00093         msg.data = data
00094         self._pub_spi.publish(msg)
00095         self._request_id += 1
00096 
00097         now = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
00098         filename = '%s.wav' % now
00099         filepath = os.path.join(self._audio_dir, filename)
00100         with open(filepath, 'wb') as wavefile:
00101             wavefile.write(data)
00102 
00103     def _stream_response(self, packet_type, packet_data):
00104         """ receive user interface response
00105 
00106         @param data: voice data
00107         @type  data: str
00108         """
00109         msg = SignalProcessingStream()
00110         msg.header = std_msgs.msg.Header()
00111         msg.header.stamp = rospy.Time.now()
00112         msg.packet_type = packet_type
00113         msg.packet_data = packet_data
00114         self._pub_spi_stream.publish(msg)
00115 
00116     def _update_connection_parameter(self):
00117         """ update connection parameter """
00118         self._ip_addr = rospy.get_param(
00119             '~ip_addr',
00120             self._ip_addr
00121         )
00122         self._recv_port = rospy.get_param(
00123             '~recv_port',
00124             self._recv_port
00125         )
00126         self._send_port = rospy.get_param(
00127             '~send_port',
00128             self._send_port
00129         )
00130         self._log_level = rospy.get_param(
00131             '~log_level',
00132             self._log_level
00133         )
00134         self._websocket_port = rospy.get_param(
00135             '~websocket_port',
00136             self._websocket_port
00137         )
00138         self._audio_dir = rospy.get_param(
00139             '~audio_dir',
00140             self._audio_dir
00141         )
00142         self._vadoff_during_play = rospy.get_param(
00143             '~vadoff_during_play',
00144             self._vadoff_during_play
00145         )
00146         self._audio_monitor = None
00147 
00148         # show parameter list
00149         msg = 'parameter:\n'\
00150               '\tip_addr           :{}\n'\
00151               '\trecv_port         :{}\n'\
00152               '\tsend_port         :{}\n'\
00153               '\twebsocket_port    :{}\n'\
00154               '\tvadoff_during_play:{}'.format(
00155                     self._ip_addr,
00156                     self._recv_port,
00157                     self._send_port,
00158                     self._websocket_port,
00159                     self._vadoff_during_play
00160                 )
00161         rospy.loginfo(msg)
00162 
00163     def _update_application_dir(self):
00164         """ update application directory. (32bit or 64bit) """
00165         arch = platform.architecture()
00166         try:
00167             if arch[0] == '32bit':
00168                 self._app_dir = os.path.join(self._app_dir, 'x86')
00169             else:
00170                 self._app_dir = os.path.join(self._app_dir, 'x64')
00171 
00172         except IndexError:
00173             msg = 'platform.architecture() returns unexcepted value. '\
00174                   'Value: {}'.format(str(arch))
00175             rospy.info(msg)
00176             self._app_dir = os.path.join(self._app_dir, 'x64')
00177 
00178     def shutdown(self):
00179         """ shutdown speech processing interface """
00180         if self._connector:
00181             self._connector.join()
00182 
00183         if self._audio_monitor:
00184             self._audio_monitor.exit()
00185 
00186     def run(self):
00187         """ run application """
00188         rospy.init_node('rospeex_spi')
00189 
00190         # create publisher / sucscriber
00191         self._pub_spi = rospy.Publisher(
00192             self._SPI_RESPONSE_TOPIC_NAME,
00193             SignalProcessingResponse,
00194             queue_size=10
00195         )
00196         self._pub_spi_stream = rospy.Publisher(
00197             self._SPI_STREAM_TOPIC_NAME,
00198             SignalProcessingStream,
00199             queue_size=100
00200         )
00201         rospy.Subscriber(
00202             self._SS_STATE_TOPIC_NAME,
00203             SpeechSynthesisState,
00204             self._ss_state_response
00205         )
00206 
00207         # update parameters
00208         self._update_connection_parameter()
00209 
00210         # update application directory
00211         self._update_application_dir()
00212 
00213         # create path
00214         if not os.path.exists(self._audio_dir):
00215             os.makedirs(self._audio_dir)
00216 
00217         # create connection
00218         self._connector = ConnectorInterface(
00219             app_dir=self._app_dir,
00220             controller=self._controller,
00221             nict_mmcv=self._nict_mmcv,
00222             mmse_setting=self._mmse_setting,
00223             vad_setting=self._vad_setting,
00224             ip_addr=self._ip_addr,
00225             recv_port=self._recv_port,
00226             send_port=self._send_port,
00227             log_level=self._log_level
00228         )
00229 
00230         self._connector.register_callback(self._ui_response)
00231         self._connector.register_stream_callback(self._stream_response)
00232         self._connector.start()
00233 
00234         # main loop
00235         rospy.loginfo('start signal processing interface node.')
00236         rate = rospy.Rate(100)
00237         while not rospy.is_shutdown():
00238             rate.sleep()
00239 
00240 
00241 def main():
00242     """ mian function """
00243     spi_node = None
00244 
00245     try:
00246         spi_node = SignalProcessingInterface()
00247         spi_node.run()
00248 
00249     except ext.SignalProcessingInterfaceException as err:
00250         rospy.logfatal(str(err))
00251 
00252     except rospy.ROSInterruptException as err:
00253         rospy.loginfo(str(err))
00254 
00255     except Exception as err:
00256         rospy.logfatal(str(err))
00257 
00258     finally:
00259         if spi_node is not None:
00260             spi_node.shutdown()
00261     return 0
00262 
00263 
00264 if __name__ == '__main__':
00265     sys.exit(main())


rospeex_core
Author(s): Komei Sugiura
autogenerated on Thu Jun 6 2019 18:53:10