1
0
mirror of https://github.com/undera/pylgbst.git synced 2020-11-18 19:37:26 -08:00
Andrey Pokhilko 32eecac1a6
Make v1.0, based on official docs (#27)
* It's HUB ID

* Rename file

* Working with official doc

* Some progress

* AttachedIO msg

* device action impl

* some better device alert impl

* restructuring

* Some port commands handled

* Some command feedback waiting

* Some more request-reply things

* Some more request-reply things

* Reworked msg classes

* Getting back to UTs

* Getting back to UTs

* Facing sync lock problems

* Facing sync lock problems

* Testing it

* Covering more with tests

* handle actions

* Hub class is almost covered

* done coverage for Hub

* done coverage for MoveHub

* Button is tested

* remove debug server from examples

* Current and voltage tested

* color sensor basic test

* cover tilt sensor

* motor sensor tested

* constant motor

* motor is tested

* hold_speed impl for motor

* motor commands recorded

* some cleanup

* some cleanup

* some cleanup

* debug

* debug

* FIX a bug

* acc/dec profiles figured out

* UT motor ops

* UT motor ops

* Get rid of weird piggyback

* fix UT

* Fix encoding?

* fix test mb

* More robust

* Checked demo works

* cosmetics

* cosmetics

* Maybe better test

* fetching and decoding some device caps

* describing devs

* describing devs works

* Applying modes we've learned

* Simple and extensible dev attach

* Reworking peripherals based on modes

* Applying modes we've learned

* implemented getting sensor data

* fixed port subscribe

* Added led out cmds on vision sensor

* Worked on color-distance sensor

* Introduce some locking for consistency

* Improved it all

* Travis flags

* improve

* improve

* improve docs
2019-05-30 17:02:50 +03:00

175 lines
6.1 KiB
Python

# coding=utf-8
import hashlib
import os
import re
import subprocess
import time
from pylgbst import *
from pylgbst.hub import MoveHub
try:
import gtts
def say(text):
print("%s" % text)
if isinstance(text, str):
text = text.decode("utf-8")
md5 = hashlib.md5(text.encode('utf-8')).hexdigest()
fname = "/tmp/%s.mp3" % md5
if not os.path.exists(fname):
myre = re.compile('[[A-Za-z]', re.UNICODE)
lang = 'en' if myre.match(text) else 'ru'
logging.getLogger('requests').setLevel(logging.getLogger('').getEffectiveLevel())
tts = gtts.gTTS(text=text, lang=lang, slow=False)
tts.save(fname)
with open(os.devnull, 'w') as fnull:
subprocess.call("mplayer %s" % fname, shell=True, stderr=fnull, stdout=fnull)
except BaseException:
def say(text):
print("%s" % text)
forward = FORWARD = right = RIGHT = 1
backward = BACKWARD = left = LEFT = -1
straight = STRAIGHT = 0
SPEECH_LANG_MAP = {
'en': {
'ready': "Vernie the Robot is ready.",
"commands help": "Available commands are: "
"forward, backward, turn left, turn right, "
"head left, head right, head straight, shot and say",
"finished": "Thank you! Robot is now turning off",
"text is empty": "Please, enter not empty text to say!"
},
"ru": {
"ready": "Робот Веернии готов к работе",
"type commands": "печатайте команды",
"ok": "хорошо",
"commands help": "Доступные команды это: вперёд, назад, влево, вправо, "
"голову влево, голову вправо, голову прямо, выстрел, скажи",
"finished": "Робот завершает работу. Спасибо!",
"commands from file": "Исполняю команды из файла",
"fire": "Выстрел!",
"text is empty": "Пожалуйста, наберите не пустой текст!"
}
}
VERNIE_TO_MOTOR_DEGREES = 2.6
VERNIE_SINGLE_MOVE = 430
class Vernie(MoveHub):
def __init__(self, language='en'):
super(Vernie, self).__init__()
self.language = language
while True:
required_devices = (self.vision_sensor, self.motor_external)
if None not in required_devices:
break
log.debug("Waiting for required devices to appear: %s", required_devices)
time.sleep(1)
self._head_position = 0
self.motor_external.subscribe(self._external_motor_data)
self._reset_head()
self.say("ready")
time.sleep(1)
def say(self, phrase):
if phrase in SPEECH_LANG_MAP[self.language]:
phrase = SPEECH_LANG_MAP[self.language][phrase]
say(phrase)
def _external_motor_data(self, data):
log.debug("External motor position: %s", data)
self._head_position = data
def _reset_head(self):
self.motor_external.timed(1, -0.2)
self.head(RIGHT, angle=45)
def head(self, direction=RIGHT, angle=25, speed=0.1):
if direction == STRAIGHT:
angle = -self._head_position
direction = 1
self.motor_external.angled(direction * angle, speed)
def turn(self, direction, degrees=90, speed=0.3):
self.head(STRAIGHT, speed=0.5)
self.head(direction, 35, 1)
self.motor_AB.angled(int(VERNIE_TO_MOTOR_DEGREES * degrees), speed * direction, -speed * direction)
self.head(STRAIGHT, speed=0.5)
def move(self, direction, distance=1, speed=0.2):
self.head(STRAIGHT, speed=0.5)
self.motor_AB.angled(distance * VERNIE_SINGLE_MOVE, speed * direction, speed * direction)
def shot(self):
self.motor_external.timed(0.5)
self.head(STRAIGHT)
self.head(STRAIGHT)
def interpret_command(self, cmd, confirm):
cmd = cmd.strip().lower().split(' ')
if cmd[0] in ("head", "голова", "голову"):
if cmd[-1] in ("right", "вправо", "направо"):
confirm(cmd)
self.head(RIGHT)
elif cmd[-1] in ("left", "влево", "налево"):
confirm(cmd)
self.head(LEFT)
else:
confirm(cmd)
self.head(STRAIGHT)
elif cmd[0] in ("say", "скажи", "сказать"):
if not cmd[1:]:
self.say("text is empty")
return
say(' '.join(cmd[1:]))
elif cmd[0] in ("fire", "shot", "огонь", "выстрел"):
say("fire")
self.shot()
elif cmd[0] in ("end", "finish", "конец", "стоп"):
self.say("finished")
raise KeyboardInterrupt()
elif cmd[0] in ("forward", "вперёд", "вперед"):
try:
dist = int(cmd[-1])
except BaseException:
dist = 1
confirm(cmd)
self.move(FORWARD, distance=dist)
elif cmd[0] in ("backward", "назад"):
try:
dist = int(cmd[-1])
except BaseException:
dist = 1
confirm(cmd)
self.move(BACKWARD, distance=dist)
elif cmd[0] in ("turn", "поворот", 'повернуть'):
if cmd[-1] in ("right", "вправо", "направо"):
confirm(cmd)
self.turn(RIGHT)
elif cmd[-1] in ("left", "влево", "налево"):
confirm(cmd)
self.turn(LEFT)
else:
confirm(cmd)
self.turn(RIGHT, degrees=180)
elif cmd[0] in ("right", "вправо", "направо"):
confirm(cmd)
self.turn(RIGHT)
elif cmd[0] in ("left", "влево", "налево"):
confirm(cmd)
self.turn(LEFT)
elif cmd[0]:
self.say("Unknown command")
self.say("commands help")