Skip to content

Commit

Permalink
feat(BCI): 增加 Muse 脑控唤醒功能。
Browse files Browse the repository at this point in the history
  • Loading branch information
wzpan committed Nov 23, 2019
1 parent 966632f commit 98795e4
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
47 changes: 47 additions & 0 deletions robot/BCI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import multiprocessing
from pythonosc import dispatcher as dsp
from pythonosc import osc_server
from robot import config, logging
from datetime import datetime, timedelta

logger = logging.getLogger(__name__)

class MuseBCI(object):

def __init__(self, event):
self._wakeup_event = event
self.last_blink = datetime.now() - timedelta(days=1.5)
self.last_jaw = datetime.now() - timedelta(days=1.5)

def start(self):
osc_process = multiprocessing.Process(target=self._start_osc)
osc_process.start()

def blink_handler(self, unused_addr, args, blink):
if blink:
logger.debug("blink detected")
self.last_blink = datetime.now()
if (self.last_blink - self.last_jaw) < timedelta(seconds=1):
self._wakeup_event.set()

def jaw_clench_handler(self, unused_addr, args, jaw):
if jaw:
logger.debug("Jaw_Clench detected")
self.last_jaw = datetime.now()
if (self.last_jaw - self.last_blink) < timedelta(seconds=1):
self._wakeup_event.set()

def _start_osc(self):
dispatcher = dsp.Dispatcher()
dispatcher.map("/muse/elements/blink", self.blink_handler, "EEG")
dispatcher.map("/muse/elements/jaw_clench", self.jaw_clench_handler, "EEG")

try:
server = osc_server.ThreadingOSCUDPServer(
(config.get('/muse/ip', '127.0.0.1'), int(config.get('/muse/port', '5001'))), dispatcher)
logger.info("Muse serving on {}".format(server.server_address))
server.serve_forever()
except Exception as e:
logger.error(e)


9 changes: 9 additions & 0 deletions static/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ server:
# 强烈建议修改!!!
validate: 'f4bde2a342c7c75aa276f78b26cfbd8a'

# Muse 脑机
# 推荐搭配 Muse Monitor 使用
# 并开启 OSC stream
# 同时眨眼和咬牙齿可以实现唤醒
muse:
enable: true
ip: '0.0.0.0' # 请修改为本机的 ip 地址
port: 5001 # 请修改为 OSC 的端口号

# snowboy 离线唤醒
# https://snowboy.kitt.ai/dashboard
# 建议到 https://snowboy.kitt.ai/hotword/32768
Expand Down
22 changes: 18 additions & 4 deletions wukong.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8-*-
from snowboy import snowboydecoder
from robot import config, utils, constants, logging, statistic, Player
from robot import config, utils, constants, logging, statistic, Player, BCI
from robot.Updater import Updater
from robot.ConfigMonitor import ConfigMonitor
from robot.Conversation import Conversation
Expand All @@ -9,12 +9,14 @@
from watchdog.observers import Observer
import sys
import os
import fire
import base64
import signal
import hashlib
import fire
import urllib3
import base64
import requests
import multiprocessing
import _thread as thread
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

logger = logging.getLogger(__name__)
Expand All @@ -27,7 +29,8 @@ class Wukong(object):
def init(self):
global conversation
self.detector = None
self._interrupted = False
self._interrupted = False
self._wakeup = multiprocessing.Event()
print('''
********************************************************
* wukong-robot - 中文语音对话机器人 *
Expand All @@ -47,6 +50,17 @@ def init(self):
self._observer.schedule(event_handler, constants.CONFIG_PATH, False)
self._observer.schedule(event_handler, constants.DATA_PATH, False)
self._observer.start()
self.bci = BCI.MuseBCI(self._wakeup)
self.bci.start()
thread.start_new_thread(self._loop_event, ())

def _loop_event(self):
while True:
self._wakeup.wait()
self._conversation.interrupt()
query = self._conversation.activeListen()
self._conversation.doResponse(query)
self._wakeup.clear()

def _signal_handler(self, signal, frame):
self._interrupted = True
Expand Down

0 comments on commit 98795e4

Please sign in to comment.