def on_menu_down(self, sender: IDevice):
        sender.stop()

        # Hover the plate and deactivate the servos
        pymoab.hoverPlate()
        pymoab.sync()
        sleep(0.5)
        pymoab.disableServoPower()
        pymoab.sync()
        sleep(0.5)
    def _calibration_failure(self, sender: Device):
        log.warn("Failed to calibrate.")
        self._print_results()

        pymoab.setIcon(pymoab.Icon.BLANK)
        pymoab.setText(pymoab.Text.ERROR)
        pymoab.sync()
        sleep(2)

        sender.stop()
    def _calibration_success(self, sender: Device):
        log.info("Calibration Success.")
        self._print_results()
        self._write_calibration(sender)

        pymoab.setIcon(pymoab.Icon.CHECK)
        pymoab.setText(pymoab.Text.CAL_COMPLETE)
        pymoab.sync()
        sleep(2)

        sender.stop()
Beispiel #4
0
    def update(self):

        # get input IO and dispatch it to listeners
        event = self.events.get_next_event()
        if event is not None:
            self.events.dispatch_event(self, event)

        # check if we should still run after processing events
        if self.runloop.running:
            # get sensor data
            elapsedSec: float = 0
            img: Optional[np.ndarray] = None

            if self.sensor:
                counter.start("sensor", WindowedAverageCounter)
                elapsedSec, img = self.sensor.getNextInput(self)
                counter.stop()

            # fetch previous plate angles if we have an actuator
            lastPlateAngles = Vector2(0, 0)
            if self.actuator:
                lastPlateAngles = self.actuator.getLastSetPlateAngles()

            # pass sensor output to various detectors
            detectorResults: Dict[str, Any] = {}
            if self.detectors and img is not None:
                for detectorName in self.detectors:
                    detector = self.detectors[detectorName]

                    counter.start(detectorName, WindowedAverageCounter)
                    feature = detector.detect(self, img, lastPlateAngles)
                    detectorResults[detectorName] = detector.post_detect(
                        feature)
                    counter.stop()

            # run the controller
            output = self.controller.getControlOutput(self, elapsedSec,
                                                      detectorResults,
                                                      lastPlateAngles)

            # actuate
            if self.actuator:
                self.actuator.setPlateAngles(self, output)

            # and execute debuging decorators
            if self.config.debug:
                if self.debug_decorator is not None:
                    self.debug_decorator.decorate({SENSOR_IMG_ARG: img})

        # sync our desired state with servos and display
        pymoab.sync()
Beispiel #5
0
def signal_handler(sig, frame) -> int:
    log.info(f"Signal {sig} received, shutting down...")

    # Lower the plate and deactivate the servos
    # lowerPlate is 155º; testing a lower position of 160º
    pymoab.setServoPositions(155, 155, 155)
    pymoab.sync()
    time.sleep(0.2)

    pymoab.disableServoPower()
    pymoab.sync()
    time.sleep(0.1)

    # Clear the screen
    pymoab.setIcon(pymoab.Icon.BLANK)
    pymoab.setText(pymoab.Text.BLANK)
    pymoab.sync()
    time.sleep(0.1)

    sys.exit(0)
Beispiel #6
0
def main():
    args = parse_args()

    # load configs
    config = load_config(args.config)

    # Load calibration.json file which contains the ball hue (22 default)
    calibration = load_calibration(args.calibration)

    # Now that log is configured, we can say we're starting up
    log.info("Moab starting.")

    # onetime init of pymoab library
    # side effect of setting OLED to Initalizing... which is ok
    pymoab.init()
    pymoab.sync()
    time.sleep(0.1)

    # put plate in "ready" mode, then cut power until needed
    pymoab.setServoPositions(150, 150, 150)
    pymoab.sync()
    time.sleep(0.1)
    pymoab.disableServoPower()
    pymoab.sync()
    time.sleep(0.1)

    # optional perf timing
    global perf_timer
    if args.perf_interval_sec > 0:
        perf_timer = ThreadedTimer()
        perf_timer.start(args.perf_interval_sec, printPerformanceCounters)

    try:
        devices = config["devices"]
    except Exception as e:
        log.exception(f"Error reading devices from {args.config}\n{e}")
        sys.exit(-1)

    device_stack = deque()
    device_stack.append(args.device)

    previous_menu: int = 0

    # Register the signal handler
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    while True:

        curr_device = device_stack.pop() if len(device_stack) > 0 else None
        if curr_device is None:
            break

        try:
            config = from_dict(IDevice.Config, devices.get(curr_device))
            config.menu_idx = previous_menu
            device = Device.createFromConfig(config, calibration)

            log.info("{} §".format(curr_device.upper()))
            device.run()
            previous_menu = device.previous_menu

            # Did our current device ask us to activate another one?
            next_device = device.get_next_device()
            if next_device is not None:
                # Save this device so we can go back to it
                device_stack.append(curr_device)

                # Will be the one popped off next iteration
                device_stack.append(next_device)
        except Exception as e:
            log.exception(f"Error instantiating {args.device}\n{e}")
            curr_device = None
            continue

        # Reload configs
        config = load_config(args.config)
        calibration = load_calibration(args.calibration)