Beispiel #1
0
 def test_prob_experiment(self):
     hat = Hat(blue=3, red=2, green=6)
     probability = experiment(hat=hat,
                              expected_balls={
                                  "blue": 2,
                                  "green": 1
                              },
                              num_balls_drawn=4,
                              num_experiments=1000)
     actual = probability
     expected = 0.272
     self.assertAlmostEqual(
         actual,
         expected,
         delta=0.01,
         msg='Expected experiemnt method to return a different probability.'
     )
     hat = Hat(yellow=5, red=1, green=3, blue=9, test=1)
     probability = experiment(hat=hat,
                              expected_balls={
                                  "yellow": 2,
                                  "blue": 3,
                                  "test": 1
                              },
                              num_balls_drawn=20,
                              num_experiments=100)
     actual = probability
     expected = 1.0
     self.assertAlmostEqual(
         actual,
         expected,
         delta=0.01,
         msg='Expected experiment method to return a different probability.'
     )
Beispiel #2
0
 def test_hat_draw(self):
     hat = Hat(red=5, blue=2)
     actual = hat.draw(2)
     expected = ['blue', 'red']
     self.assertEqual(
         actual, expected,
         'Expected hat draw to return two random items from hat contents.')
     actual = len(hat.contents)
     expected = 5
     self.assertEqual(
         actual, expected,
         'Expected hat draw to reduce number of items in contents.')
Beispiel #3
0
 def test_hat_class_contents(self):
     hat = Hat(red=3, blue=2)
     actual = hat.contents
     expected = ["red", "red", "red", "blue", "blue"]
     self.assertEqual(
         actual, expected,
         'Expected creation of hat object to add correct contents.')
    def run(self):
        """ Make random draw honoring exclusions

            Using the people in the exchange self.args.exchange,
            make a random drawing where no person draws someone
            prohibited to them in the database exclude table
            Print the results in a file with eacj "from to" pair
            on a separate line.

        """
        self.db = sqlite3.connect(self.args.database)
        people = self.get_people()

        # If no people are listed, no exchange, so show valid exchanges
        if not people:
            self.list_valid_exchanges()
            quit()

        excludes = self.set_exclusions(people)

        try:
            exchange = Hat(people, excludes).draw()
        except NoValidDraw:
            print("Could not make a draw for", file=sys.stderr)
            print("people: %s" % (people), file=sys.stderr)
            print("excludes:", file=sys.stderr)
            for person, exclude in excludes.items():
                print("    %s: %s" % (person, exclude), file=sys.stderr)
        else:
            self.output(exchange)
Beispiel #5
0
    def __init__(
        self,
        frequency=30,
        debug=False,
        verbose=0,
        calibration_file="bot.json",
    ):
        self.debug = debug
        self.verbose = verbose
        self.frequency = frequency

        self.hat = Hat(debug=debug, verbose=verbose)
        self.hat.open()
        self.camera = OpenCVCameraSensor(frequency=frequency)
        self.detector = hsv_detector(debug=debug)

        # Set the calibration
        self.calibration_file = calibration_file
        self.reset_calibration()
Beispiel #6
0
    def __init__(
        self,
        frequency=30,
        debug=False,
        verbose=0,
        derivative_fn=derivative,
        calibration_file="bot.json",
    ):
        self.debug = debug
        self.verbose = verbose
        self.frequency = frequency
        self.derivative_fn = derivative
        self.vel_x = self.derivative_fn(frequency)
        self.vel_y = self.derivative_fn(frequency)
        self.sum_x, self.sum_y = 0, 0

        self.hat = Hat(debug=debug, verbose=verbose)
        self.hat.open()
        self.camera = OpenCVCameraSensor(frequency=frequency)
        self.detector = hsv_detector(debug=debug)

        self.calibration_file = calibration_file
        self.reset_calibration()
Beispiel #7
0
class MoabEnv:
    def __init__(
        self,
        frequency=30,
        debug=False,
        verbose=0,
        derivative_fn=derivative,
        calibration_file="bot.json",
    ):
        self.debug = debug
        self.verbose = verbose
        self.frequency = frequency
        self.derivative_fn = derivative
        self.vel_x = self.derivative_fn(frequency)
        self.vel_y = self.derivative_fn(frequency)
        self.sum_x, self.sum_y = 0, 0

        self.hat = Hat(debug=debug, verbose=verbose)
        self.hat.open()
        self.camera = OpenCVCameraSensor(frequency=frequency)
        self.detector = hsv_detector(debug=debug)

        self.calibration_file = calibration_file
        self.reset_calibration()

    def __enter__(self):
        self.camera.start()
        return self

    def __exit__(self, type, value, traceback):
        self.hat.go_down()
        self.hat.disable_servos()
        self.hat.display_power_symbol("TO WAKE", PowerIcon.POWER)
        self.hat.close()
        self.camera.stop()

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return f"hue: {self.hue}, offsets: {self.servo_offsets}"

    def reset_calibration(self, calibration_file=None):
        # Use default if not defined
        calibration_file = calibration_file or self.calibration_file

        # Get calibration settings
        if os.path.isfile(calibration_file):
            with open(calibration_file, "r") as f:
                calib = json.load(f)
        else:  # Use defaults
            calib = {
                "ball_hue": 44,
                "plate_offsets": (0.0, 0.0),
                "servo_offsets": (0.0, 0.0, 0.0),
            }

        plate_offsets = calib["plate_offsets"]
        self.plate_offsets_pixels = meters_to_pixels(plate_offsets)
        self.servo_offsets = calib["servo_offsets"]
        self.hue = calib["ball_hue"]

        # Set the servo offsets (self.hue & self.plate_offsets_pixels are used in step)
        self.hat.set_servo_offsets(*self.servo_offsets)
        self.camera.x_offset_pixels = self.plate_offsets_pixels[0]
        self.camera.y_offset_pixels = self.plate_offsets_pixels[1]

    def reset(self, text=None, icon=None):
        # Optionally display the controller active text
        if icon and text:
            self.hat.display_string_icon(text, icon)
        elif text:
            self.hat.display_string(text)

        # Reset the derivative of the position
        # Use a high pass filter instead of a numerical derivative for stability.
        # A high pass filtered signal can be thought of as a derivative of a low
        # pass filtered signal: fc*s / (s + fc) = fc*s * 1 / (s + fc)
        # For more info: https://en.wikipedia.org/wiki/Differentiator
        # Or: https://www.youtube.com/user/ControlLectures/
        self.vel_x = self.derivative_fn(self.frequency)
        self.vel_y = self.derivative_fn(self.frequency)
        # Reset the integral of the position
        self.sum_x, self.sum_y = 0, 0

        # Return the state after a step with no motor actions
        return self.step((0, 0))

    def step(self, action) -> Tuple[EnvState, bool, Buttons]:
        plate_x, plate_y = action
        self.hat.set_angles(plate_x, plate_y)

        frame, elapsed_time = self.camera()
        ball_detected, cicle_feature = self.detector(frame, hue=self.hue)
        ball_center, ball_radius = cicle_feature

        x, y = ball_center

        # Update derivate calulation
        vel_x, vel_y = self.vel_x(x), self.vel_y(y)
        # Update the summation (integral calculation)
        self.sum_x += x
        self.sum_y += y

        buttons = self.hat.get_buttons()
        state = EnvState(x, y, vel_x, vel_y, self.sum_x, self.sum_y)

        return state, ball_detected, buttons
Beispiel #8
0
from hat import Hat, Icon, PowerIcon

with Hat() as hat:
    hat.display_string_icon("DOT", Icon.DOT)
    input("Confirm: • DOT")

    hat.display_string_icon("X Mark", Icon.X)
    input("Confirm: × Mark")

    hat.display_power_symbol("POWER", PowerIcon.POWER)
    input("Confirm: ⏻ POWER")

    hat.display_power_symbol("TOGGLE", PowerIcon.TOGGLE_POWER)
    input("Confirm: ⏼ TOGGLE")

    hat.display_power_symbol("ON", PowerIcon.POWER_ON)
    input("Confirm: ⏽ ON")

    hat.display_power_symbol("OFF", PowerIcon.POWER_OFF)
    input("Confirm: ⭘ OFF")

    hat.display_power_symbol("SLEEP", PowerIcon.SLEEP_MODE)
    input("Confirm: ⏾ SLEEP")

    menus = {
        0: "§ Berkeley\nCalifornia",
        1: "Albany\nKansas City\nBerkeley",
        2: "Vancouver, Canada...Albany, NY\nKansas City, MO...Berkeley, CA",
    }

    hat.display_long_string(menus[0])
Beispiel #9
0
class MoabHardware:
    def __init__(
        self,
        frequency=30,
        debug=False,
        verbose=0,
        calibration_file="bot.json",
    ):
        self.debug = debug
        self.verbose = verbose
        self.frequency = frequency

        self.hat = Hat(debug=debug, verbose=verbose)
        self.hat.open()
        self.camera = OpenCVCameraSensor(frequency=frequency)
        self.detector = hsv_detector(debug=debug)

        # Set the calibration
        self.calibration_file = calibration_file
        self.reset_calibration()

    def __enter__(self):
        self.camera.start()
        return self

    def __exit__(self, type, value, traceback):
        self.go_down()
        self.hat.disable_servos()
        self.hat.display_power_symbol("TO WAKE", PowerIcon.POWER)
        self.hat.close()
        self.camera.stop()

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return f"hue: {self.hue}, servo offsets: {self.servo_offsets}, plate offsets: {self.plate_offsets}"

    def reset_calibration(self, calibration_file=None):
        # Use default if not defined
        calibration_file = calibration_file or self.calibration_file

        # Get calibration settings
        if os.path.isfile(calibration_file):
            with open(calibration_file, "r") as f:
                calib = json.load(f)
        else:  # Use defaults
            calib = {
                "ball_hue": 44,
                "plate_offsets": (0.0, 0.0),
                "servo_offsets": (0.0, 0.0, 0.0),
            }

        self.plate_offsets = calib["plate_offsets"]
        self.servo_offsets = calib["servo_offsets"]
        self.hue = calib["ball_hue"]

    def go_up(self):
        # Set the plate to its hover position, experimentally found to be 150
        self.set_servos(150, 150, 150)
        time.sleep(
            0.200)  # Give enough time for the action before turning off servos

    def go_down(self):
        # Set the plate to its lowest position, experimentally found to be 155
        self.set_servos(155, 155, 155)
        time.sleep(
            0.200)  # Give enough time for the action before turning off servos

    def get_buttons(self):
        # Get the buttons after doing a noop (ensure the buttons are up to date)
        self.hat.noop()
        return self.hat.get_buttons()

    def enable_servos(self):
        self.hat.enable_servos()

    def disable_servos(self):
        self.hat.disable_servos()

    def set_servos(self, s1, s2, s3):
        # Note the indexing offset
        s1 += self.servo_offsets[0]
        s2 += self.servo_offsets[1]
        s3 += self.servo_offsets[2]
        self.hat.set_servos((s1, s2, s3))

    def display(
        self,
        text: Optional[str] = None,
        icon: Optional[str] = None,
        scrolling: bool = False,
    ):
        # Optionally display the controller active text
        if icon and text:
            if scrolling:
                raise ValueError(
                    "Cannot display scrolling screen with an icon")
            self.hat.display_string_icon(text, icon)
        elif text:
            if scrolling:
                self.hat.display_long_string(text)
            else:
                self.hat.display_string(text)

    def set_angles(self, pitch, roll):
        s1, s2, s3 = plate_angles_to_servo_positions(pitch, roll)
        self.set_servos(s1, s2, s3)

    def step(self, pitch, roll) -> Buttons:
        self.set_angles(pitch, roll)
        frame, elapsed_time = self.camera()
        buttons = self.hat.get_buttons()
        ball_detected, (ball_center, ball_radius) = self.detector(frame,
                                                                  hue=self.hue)
        return ball_center, ball_detected, buttons
Beispiel #10
0
from game import Game
from player import Player
from repositories.game import GameRepository

import callbacks.register_flow

from telegram.ext import Updater, CommandHandler, MessageHandler, Filters

from utils.read_token import read_token

import logging

TOKEN = read_token()

game_repo = GameRepository()
hat = Hat()
game = game_repo.create(hat)

logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO)

logger = logging.getLogger(__name__)


def main():
    updater = Updater(TOKEN, use_context=True)
    dispatcher = updater.dispatcher

    dispatcher.add_handler(
        CommandHandler("start", callbacks.register_flow.start))