1
0
mirror of https://github.com/undera/pylgbst.git synced 2020-11-18 19:37:26 -08:00

Struggle with math

This commit is contained in:
Andrey Pohilko 2017-12-19 13:11:35 +03:00
parent a6cb301688
commit b600cc93c3
4 changed files with 156 additions and 40 deletions

View File

@ -1,14 +1,12 @@
import logging import logging
import sys import sys
import time import time
import traceback
from pylgbst import MoveHub, BLEConnection from pylgbst import MoveHub
from pylgbst.comms import DebugServerConnection
from pylgbst.peripherals import EncodedMotor from pylgbst.peripherals import EncodedMotor
BASE_SPEED = 0.5 BASE_SPEED = 0.5
CARET_WIDTH = -940 CARET_WIDTH = 940
class Plotter(MoveHub): class Plotter(MoveHub):
@ -20,26 +18,30 @@ class Plotter(MoveHub):
self.__last_rotation_value = sys.maxsize self.__last_rotation_value = sys.maxsize
def initialize(self): def initialize(self):
self.motor_A.subscribe(self._on_rotate, mode=EncodedMotor.SENSOR_SPEED) self._reset_caret()
self.motor_A.constant(0.4)
count = 0
max_tries = 50
while self.__last_rotation_value > 5 and count < max_tries:
logging.info("Last rot: %s", self.__last_rotation_value)
time.sleep(5.0 / max_tries)
count += 1
logging.info("Tries: %s, last: %s", count, self.__last_rotation_value)
self.motor_A.unsubscribe(self._on_rotate)
self.motor_A.stop()
if count >= max_tries:
raise RuntimeError("Failed to center caret")
self.motor_A.angled(CARET_WIDTH, BASE_SPEED)
self.xpos = 0 self.xpos = 0
self.ypos = 0 self.ypos = 0
self.is_tool_down = False self.is_tool_down = False
def _reset_caret(self):
self.motor_A.timed(0.5, -0.3)
self.motor_A.subscribe(self._on_rotate, mode=EncodedMotor.SENSOR_SPEED)
self.motor_A.constant(0.3)
count = 0
max_tries = 50
while abs(self.__last_rotation_value) > 5 and count < max_tries:
logging.debug("Last rot: %s", self.__last_rotation_value)
time.sleep(10.0 / max_tries)
count += 1
logging.debug("Centering tries: %s, last value: %s", count, self.__last_rotation_value)
self.motor_A.unsubscribe(self._on_rotate)
self.motor_A.stop()
if count >= max_tries:
raise RuntimeError("Failed to center caret")
self.motor_A.angled(-CARET_WIDTH, BASE_SPEED)
def _on_rotate(self, value): def _on_rotate(self, value):
logging.info("Rotation: %s", value) logging.debug("Rotation: %s", value)
self.__last_rotation_value = value self.__last_rotation_value = value
def _tool_down(self): def _tool_down(self):
@ -50,6 +52,12 @@ class Plotter(MoveHub):
self.motor_external.angled(-270, BASE_SPEED) self.motor_external.angled(-270, BASE_SPEED)
self.is_tool_down = False self.is_tool_down = False
def finalize(self):
if self.is_tool_down:
self._tool_up()
self.move(-self.xpos, -self.ypos)
def move(self, movx, movy): def move(self, movx, movy):
if self.is_tool_down: if self.is_tool_down:
self._tool_up() self._tool_up()
@ -61,29 +69,58 @@ class Plotter(MoveHub):
self._transfer_to(movx, movy) self._transfer_to(movx, movy)
def _transfer_to(self, movx, movy): def _transfer_to(self, movx, movy):
angle = max(abs(movy), abs(movx)) if self.xpos + movx < -CARET_WIDTH:
speed_a = BASE_SPEED logging.warning("Invalid xpos: %s", self.xpos)
speed_b = BASE_SPEED * 0.5 movx += self.xpos - CARET_WIDTH
self.motor_AB.angled(angle, speed_a, speed_b)
def finalize(self): if self.xpos + movx > CARET_WIDTH:
if self.is_tool_down: logging.warning("Invalid xpos: %s", self.xpos)
self._tool_up() movx -= self.xpos - CARET_WIDTH
self.xpos -= self.xpos - CARET_WIDTH
if not movy and not movx:
logging.warning("No movement, ignored")
return
self.xpos += movx
self.ypos += movy
angle, speed_a, speed_b = calc_motor(movx, movy)
if not speed_b:
self.motor_A.angled(angle, speed_a * BASE_SPEED)
elif not speed_a:
self.motor_B.angled(angle, speed_b * BASE_SPEED)
else:
self.motor_AB.angled(angle, speed_a * BASE_SPEED, speed_b * BASE_SPEED)
# time.sleep(0.5)
if __name__ == '__main__': def calc_motor(movx, movy):
logging.basicConfig(level=logging.INFO) amovy = abs(movy)
amovx = abs(movx)
angle = max(amovx, amovy)
try: speed_a = (movx / float(amovx)) if amovx else 0.0
conn = DebugServerConnection() speed_b = (movy / float(amovy)) if amovy else 0.0
except BaseException: if amovx > amovy:
logging.warning("Failed to use debug server: %s", traceback.format_exc()) speed_b = (movy / float(amovx)) if movx else 0
conn = BLEConnection().connect() else:
speed_a = (movx / float(amovy)) if movy else 0
plotter = Plotter(conn) if speed_a:
plotter.initialize() speed_b *= 2.75
plotter.line(100, 100) else:
plotter.line(100, -100) angle *= 1.5
plotter.line(-100, -100)
plotter.line(-100, 100) norm = max(abs(speed_a), abs(speed_b))
plotter.finalize() speed_a /= norm
speed_b /= norm
angle *= speed_a
logging.info("Motor: %s with %s/%s", angle, speed_a, speed_b)
assert -1 <= speed_a <= 1
assert -1 <= speed_b <= 1
return angle, speed_a, speed_b

64
examples/plotter/try.py Normal file
View File

@ -0,0 +1,64 @@
import logging
import traceback
from examples.plotter import Plotter, CARET_WIDTH
from pylgbst.comms import DebugServerConnection, BLEConnection
def cross():
plotter.line(CARET_WIDTH, CARET_WIDTH)
plotter.move(-CARET_WIDTH, 0)
plotter.line(CARET_WIDTH, -CARET_WIDTH)
def moves():
plotter.move(CARET_WIDTH, CARET_WIDTH)
plotter.move(-CARET_WIDTH, -CARET_WIDTH)
plotter.move(CARET_WIDTH, 0)
plotter.move(-CARET_WIDTH, 0)
plotter.move(0, CARET_WIDTH)
plotter.move(0, -CARET_WIDTH)
def square():
plotter.line(CARET_WIDTH, 0)
plotter.line(0, CARET_WIDTH)
plotter.line(-CARET_WIDTH, 0)
plotter.line(0, -CARET_WIDTH)
def triangle():
plotter.line(CARET_WIDTH, 0)
plotter.line(0, CARET_WIDTH)
plotter.line(-CARET_WIDTH, -CARET_WIDTH)
def romb():
plotter.move(-CARET_WIDTH * 2, 0)
plotter.line(CARET_WIDTH, CARET_WIDTH)
plotter.line(CARET_WIDTH, -CARET_WIDTH)
plotter.line(-CARET_WIDTH, -CARET_WIDTH)
plotter.line(-CARET_WIDTH, CARET_WIDTH)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
try:
conn = DebugServerConnection()
except BaseException:
logging.warning("Failed to use debug server: %s", traceback.format_exc())
conn = BLEConnection().connect()
plotter = Plotter(conn)
#plotter.initialize()
# plotter._tool_up() # and plotter._tool_up()
triangle()
# moves()
# square()
# cross()
# romb()
plotter.finalize()

View File

@ -81,6 +81,8 @@ class MoveHub(object):
raise RuntimeError("Failed to obtain all builtin devices") raise RuntimeError("Failed to obtain all builtin devices")
def _notify(self, handle, data): def _notify(self, handle, data):
# 1b0e000500823701
orig = data orig = data
if handle != MOVE_HUB_HARDWARE_HANDLE: if handle != MOVE_HUB_HARDWARE_HANDLE:

View File

@ -1,6 +1,7 @@
import unittest import unittest
from binascii import unhexlify from binascii import unhexlify
from examples.plotter import calc_motor
from pylgbst import * from pylgbst import *
from pylgbst.comms import Connection from pylgbst.comms import Connection
from pylgbst.movehub import MoveHub from pylgbst.movehub import MoveHub
@ -191,3 +192,15 @@ class GeneralTest(unittest.TestCase):
hub.notify_mock.append((HANDLE, notify)) hub.notify_mock.append((HANDLE, notify))
Thread(target=inject).start() Thread(target=inject).start()
class TestPlotter(unittest.TestCase):
def test_calc(self):
self.assertEqual((100, 0, 0.24), calc_motor(100, 100))
self.assertEqual((100, 0, 0.24), calc_motor(-100, -100))
self.assertEqual((100, 0, 0.24), calc_motor(0, 100))
self.assertEqual((100, 0.75, 0), calc_motor(100, 0))
self.assertEqual((100, -0.75, 0), calc_motor(-100, 0))
self.assertEqual((100, 0, -0.24), calc_motor(0, -100))
self.assertEqual((100, 0.75, 0.12), calc_motor(100, 50))
self.assertEqual((100, 0.375, 0.24), calc_motor(50, 100))