Ejemplo n.º 1
0
    def __init__(self, interface: RevvyControl, sound_paths, sw_version):
        self._interface = interface

        self._start_time = time.time()

        # read versions
        hw = interface.get_hardware_version()
        fw = interface.get_firmware_version()
        sw = sw_version

        print('Hardware: {}\nFirmware: {}\nFramework: {}'.format(hw, fw, sw))

        self._version = RobotVersion(hw, fw, sw)

        setup = {
            Version('1.0'): setup_sound_v1,
            Version('1.1'): setup_sound_v1,
            Version('2.0'): setup_sound_v2,
        }
        play = {
            Version('1.0'): play_sound_v1,
            Version('1.1'): play_sound_v1,
            Version('2.0'): play_sound_v2,
        }

        self._ring_led = RingLed(interface)
        self._sound = Sound(setup[hw], play[hw], sound_paths or {})

        self._status = RobotStatusIndicator(interface)
        self._status_updater = McuStatusUpdater(interface)
        self._battery = BatteryStatus(0, 0, 0)

        self._imu = IMU()

        def _motor_config_changed(motor: PortInstance, config_name):
            callback = None if config_name == 'NotConfigured' else motor.update_status
            self._status_updater.set_slot(mcu_updater_slots["motors"][motor.id], callback)

        def _sensor_config_changed(sensor: PortInstance, config_name):
            callback = None if config_name == 'NotConfigured' else sensor.update_status
            self._status_updater.set_slot(mcu_updater_slots["sensors"][sensor.id], callback)

        self._motor_ports = create_motor_port_handler(interface, Motors)
        for port in self._motor_ports:
            port.on_config_changed(_motor_config_changed)

        self._sensor_ports = create_sensor_port_handler(interface, Sensors)
        for port in self._sensor_ports:
            port.on_config_changed(_sensor_config_changed)

        self._drivetrain = DifferentialDrivetrain(interface, self._motor_ports.port_count)
Ejemplo n.º 2
0
    def __enter__(self):
        self._comm_interface = self._bus_factory()

        self._robot_control = self._comm_interface.create_application_control()
        self._bootloader_control = self._comm_interface.create_bootloader_control(
        )

        self._stopwatch = Stopwatch()

        # read versions
        while True:
            try:
                self._hw_version = self._robot_control.get_hardware_version()
                self._fw_version = self._robot_control.get_firmware_version()
                break
            except OSError:
                try:
                    self._hw_version = self._bootloader_control.get_hardware_version(
                    )
                    self._fw_version = Version('0.0.0')
                    break
                except OSError:
                    self._log('Failed to read robot version')

        from revvy.firmware_updater import update_firmware
        update_firmware(os.path.join('data', 'firmware'), self)

        # read version again in case it was updated
        self._fw_version = self._robot_control.get_firmware_version()

        self._log(f'Hardware: {self._hw_version}')
        self._log(f'Firmware: {self._fw_version}')

        setup = {
            Version('1.0'): SoundControlV1,
            Version('1.1'): SoundControlV1,
            Version('2.0'): SoundControlV2,
        }

        self._ring_led = RingLed(self._robot_control)
        self._sound = Sound(setup[self._hw_version](),
                            self._assets.category_loader('sounds'))

        self._status = RobotStatusIndicator(self._robot_control)
        self._status_updater = McuStatusUpdater(self._robot_control)
        self._battery = BatteryStatus(0, 0, 0)

        self._imu = IMU()

        def _set_updater(slot_name, port, config_name):
            if config_name is None:
                self._status_updater.disable_slot(slot_name)
            else:
                self._status_updater.enable_slot(slot_name, port.update_status)

        self._motor_ports = create_motor_port_handler(self._robot_control)
        for port in self._motor_ports:
            port.on_config_changed.add(
                partial(_set_updater, f'motor_{port.id}'))

        self._sensor_ports = create_sensor_port_handler(self._robot_control)
        for port in self._sensor_ports:
            port.on_config_changed.add(
                partial(_set_updater, f'sensor_{port.id}'))

        self._drivetrain = DifferentialDrivetrain(self._robot_control,
                                                  self._imu)

        self.update_status = self._status_updater.read
        self.ping = self._robot_control.ping

        return self
Ejemplo n.º 3
0
class Robot(RobotInterface):
    @staticmethod
    def _default_bus_factory() -> RevvyTransportBase:
        from revvy.hardware_dependent.rrrc_transport_i2c import RevvyTransportI2C

        return RevvyTransportI2C(1)

    def __init__(self, bus_factory=None):
        if bus_factory is None:
            bus_factory = self._default_bus_factory
        self._bus_factory = bus_factory

        self._assets = Assets()
        self._assets.add_source(os.path.join('data', 'assets'))

        self._log = get_logger('Robot')

    def __enter__(self):
        self._comm_interface = self._bus_factory()

        self._robot_control = self._comm_interface.create_application_control()
        self._bootloader_control = self._comm_interface.create_bootloader_control(
        )

        self._stopwatch = Stopwatch()

        # read versions
        while True:
            try:
                self._hw_version = self._robot_control.get_hardware_version()
                self._fw_version = self._robot_control.get_firmware_version()
                break
            except OSError:
                try:
                    self._hw_version = self._bootloader_control.get_hardware_version(
                    )
                    self._fw_version = Version('0.0.0')
                    break
                except OSError:
                    self._log('Failed to read robot version')

        from revvy.firmware_updater import update_firmware
        update_firmware(os.path.join('data', 'firmware'), self)

        # read version again in case it was updated
        self._fw_version = self._robot_control.get_firmware_version()

        self._log(f'Hardware: {self._hw_version}')
        self._log(f'Firmware: {self._fw_version}')

        setup = {
            Version('1.0'): SoundControlV1,
            Version('1.1'): SoundControlV1,
            Version('2.0'): SoundControlV2,
        }

        self._ring_led = RingLed(self._robot_control)
        self._sound = Sound(setup[self._hw_version](),
                            self._assets.category_loader('sounds'))

        self._status = RobotStatusIndicator(self._robot_control)
        self._status_updater = McuStatusUpdater(self._robot_control)
        self._battery = BatteryStatus(0, 0, 0)

        self._imu = IMU()

        def _set_updater(slot_name, port, config_name):
            if config_name is None:
                self._status_updater.disable_slot(slot_name)
            else:
                self._status_updater.enable_slot(slot_name, port.update_status)

        self._motor_ports = create_motor_port_handler(self._robot_control)
        for port in self._motor_ports:
            port.on_config_changed.add(
                partial(_set_updater, f'motor_{port.id}'))

        self._sensor_ports = create_sensor_port_handler(self._robot_control)
        for port in self._sensor_ports:
            port.on_config_changed.add(
                partial(_set_updater, f'sensor_{port.id}'))

        self._drivetrain = DifferentialDrivetrain(self._robot_control,
                                                  self._imu)

        self.update_status = self._status_updater.read
        self.ping = self._robot_control.ping

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._comm_interface.close()

    @property
    def assets(self):
        return self._assets

    @property
    def robot_control(self):
        return self._robot_control

    @property
    def bootloader_control(self):
        return self._bootloader_control

    @property
    def hw_version(self) -> Version:
        return self._hw_version

    @property
    def fw_version(self) -> Version:
        return self._fw_version

    @property
    def battery(self):
        return self._battery

    @property
    def imu(self):
        return self._imu

    @property
    def status(self):
        return self._status

    @property
    def motors(self):
        return self._motor_ports

    @property
    def sensors(self):
        return self._sensor_ports

    @property
    def drivetrain(self):
        return self._drivetrain

    @property
    def led(self):
        return self._ring_led

    @property
    def sound(self):
        return self._sound

    def play_tune(self, name):
        self._sound.play_tune(name)

    def time(self):
        return self._stopwatch.elapsed

    def reset(self):
        self._log('reset()')
        self._ring_led.start_animation(RingLed.BreathingGreen)
        self._status_updater.reset()

        def _process_battery_slot(data):
            assert len(data) == 4
            main_status, main_percentage, _, motor_percentage = data

            self._battery = BatteryStatus(chargerStatus=main_status,
                                          main=main_percentage,
                                          motor=motor_percentage)

        self._status_updater.enable_slot("battery", _process_battery_slot)
        self._status_updater.enable_slot("axl", self._imu.update_axl_data)
        self._status_updater.enable_slot("gyro", self._imu.update_gyro_data)
        self._status_updater.enable_slot("yaw", self._imu.update_yaw_angles)
        # TODO: do something useful with the reset signal
        self._status_updater.enable_slot(
            "reset", lambda _: self._log('MCU reset detected'))

        self._drivetrain.reset()
        self._motor_ports.reset()
        self._sensor_ports.reset()
        self._sound.reset_volume()

        self._status.robot_status = RobotStatus.NotConfigured
        self._status.update()

    def stop(self):
        self._sound.wait()
Ejemplo n.º 4
0
class Robot:
    def __init__(self, interface: RevvyControl, sound_paths, sw_version):
        self._interface = interface

        self._start_time = time.time()

        # read versions
        hw = interface.get_hardware_version()
        fw = interface.get_firmware_version()
        sw = sw_version

        print('Hardware: {}\nFirmware: {}\nFramework: {}'.format(hw, fw, sw))

        self._version = RobotVersion(hw, fw, sw)

        setup = {
            Version('1.0'): setup_sound_v1,
            Version('1.1'): setup_sound_v1,
            Version('2.0'): setup_sound_v2,
        }
        play = {
            Version('1.0'): play_sound_v1,
            Version('1.1'): play_sound_v1,
            Version('2.0'): play_sound_v2,
        }

        self._ring_led = RingLed(interface)
        self._sound = Sound(setup[hw], play[hw], sound_paths or {})

        self._status = RobotStatusIndicator(interface)
        self._status_updater = McuStatusUpdater(interface)
        self._battery = BatteryStatus(0, 0, 0)

        self._imu = IMU()

        def _motor_config_changed(motor: PortInstance, config_name):
            callback = None if config_name == 'NotConfigured' else motor.update_status
            self._status_updater.set_slot(mcu_updater_slots["motors"][motor.id], callback)

        def _sensor_config_changed(sensor: PortInstance, config_name):
            callback = None if config_name == 'NotConfigured' else sensor.update_status
            self._status_updater.set_slot(mcu_updater_slots["sensors"][sensor.id], callback)

        self._motor_ports = create_motor_port_handler(interface, Motors)
        for port in self._motor_ports:
            port.on_config_changed(_motor_config_changed)

        self._sensor_ports = create_sensor_port_handler(interface, Sensors)
        for port in self._sensor_ports:
            port.on_config_changed(_sensor_config_changed)

        self._drivetrain = DifferentialDrivetrain(interface, self._motor_ports.port_count)

    @property
    def start_time(self):
        return self._start_time

    @property
    def version(self):
        return self._version

    @property
    def battery(self):
        return self._battery

    @property
    def imu(self):
        return self._imu

    @property
    def status(self):
        return self._status

    @property
    def motors(self):
        return self._motor_ports

    @property
    def sensors(self):
        return self._sensor_ports

    @property
    def drivetrain(self):
        return self._drivetrain

    @property
    def led_ring(self):
        return self._ring_led

    @property
    def sound(self):
        return self._sound

    def update_status(self):
        self._status_updater.read()

    def reset(self):
        self._ring_led.set_scenario(RingLed.BreathingGreen)
        self._status_updater.reset()

        def _process_battery_slot(data):
            assert len(data) == 4
            main_status = data[0]
            main_percentage = data[1]
            # motor_status = data[2]
            motor_percentage = data[3]

            self._battery = BatteryStatus(chargerStatus=main_status, main=main_percentage, motor=motor_percentage)

        self._status_updater.set_slot(mcu_updater_slots["battery"], _process_battery_slot)
        self._status_updater.set_slot(mcu_updater_slots["axl"], self._imu.update_axl_data)
        self._status_updater.set_slot(mcu_updater_slots["gyro"], self._imu.update_gyro_data)
        self._status_updater.set_slot(mcu_updater_slots["yaw"], self._imu.update_yaw_angles)

        self._drivetrain.reset()
        self._motor_ports.reset()
        self._sensor_ports.reset()

        self._status.robot_status = RobotStatus.NotConfigured
        self._status.update()