wt_node: battery capacity
[ros_wild_thumper.git] / scripts / pocketsphinx.rb
1 #!/usr/bin/ruby -w
2
3 require 'gst'
4 require 'pry'
5 require 'logger'
6 require 'ros'
7 require 'std_msgs/String'
8
9 class Speak
10         def initialize(node)
11                 @logger = Logger.new(STDOUT)
12                 @publisher = node.advertise('asr_result', Std_msgs::String)
13                 @pipeline = Gst.parse_launch('alsasrc device="plughw:1,0" ! audio/x-raw,format=S16LE,channels=1,rate=16000 ! cutter leaky=true name=cutter'\
14                                              ' ! tee name=jsgf ! queue leaky=downstream ! valve name=valve_jsgf drop=true ! pocketsphinx name=asr_jsgf ! fakesink async=false jsgf.'\
15                                              ' ! pocketsphinx name=asr_kws ! fakesink async=false'\
16                                             )
17                 # Ignore everything below the configured volume
18                 cutter = @pipeline.get_by_name('cutter')
19                 cutter.set_property('threshold-dB', -20)
20                 cutter.set_property('pre-length', 100000000) # pocketsphinx needs about 0.1s before start
21                 cutter.set_property('run-length', 1300000000)
22
23                 asr_jsgf = @pipeline.get_by_name('asr_jsgf')
24                 asr_jsgf.set_property('hmm', 'pocketsphinx/adapt/cmusphinx-en-us-5.2')
25                 asr_jsgf.set_property('mllr', 'pocketsphinx/adapt/mllr_matrix')
26                 asr_jsgf.set_property('jsgf', 'data/robot.jsgf')
27
28                 asr_kws = @pipeline.get_by_name('asr_kws')
29                 asr_kws.set_property('hmm', 'pocketsphinx/adapt/cmusphinx-en-us-5.2')
30                 asr_kws.set_property('mllr', 'pocketsphinx/adapt/mllr_matrix')
31                 asr_kws.set_property('kws', 'data/keywords.kws')
32
33                 bus = @pipeline.bus()
34                 bus.add_watch do |bus, message|
35                         case message.type
36                         when Gst::MessageType::EOS
37                                 loop.quit
38                         when Gst::MessageType::ERROR
39                                 p message.parse_error
40                                 binding.pry # open console
41                                 loop.quit
42                         when Gst::MessageType::ELEMENT
43                                 if message.src.name == "asr_kws" and message.structure.get_value(:final).value
44                                         keyword_detect(message.structure.get_value(:hypothesis).value, message.structure.get_value(:confidence).value)
45                                 elsif message.src.name == "asr_jsgf"
46                                         if message.structure.get_value(:final).value
47                                                 final_result(message.structure.get_value(:hypothesis).value, message.structure.get_value(:confidence).value)
48                                         end
49                                 elsif message.src.name == "cutter"
50                                         if message.structure.get_value(:above).value
51                                                 @logger.debug "Start recording.."
52                                         else
53                                                 @logger.debug "Stop recording"
54                                         end
55                                 end
56                         end
57                         true
58                 end
59
60                 @pipeline.play
61         end
62
63         # Enables/Disables the jsgf pipeline
64         def enable_jsgf(bEnable)
65                 valve = @pipeline.get_by_name('valve_jsgf')
66                 valve.set_property("drop", !bEnable)
67         end
68
69         # Result of jsgf pipeline
70         def final_result(hyp, confidence)
71                 @logger.info "final: " + hyp + " " + confidence.to_s
72                 enable_jsgf(false)
73
74                 # Publish pocketsphinx result as ros message
75                 msg = Std_msgs::String.new
76                 msg.data = hyp
77                 @publisher.publish(msg)
78         end
79
80         def keyword_detect(hyp, confidence)
81                 @logger.debug "Got keyword: " + hyp
82                 enable_jsgf(true)
83         end
84
85         def stop
86                 @pipeline.stop
87         end
88 end
89
90 if __FILE__ == $0
91         node = ROS::Node.new('wild_thumper/pocketsphinx')
92         app = Speak.new(node)
93         loop = GLib::MainLoop.new(nil, false)
94         begin
95                 Thread.new {
96                         loop.run
97                 }
98                 node.spin
99         rescue Interrupt
100         ensure
101                 app.stop
102                 node.shutdown
103                 loop.quit
104         end
105 end