def __init__(self, active_ports): ''' Instantiates the Revvy motor controller and configures the list of motor ports for the Revolution Robotics DC Motor. :active_ports: a list of ports on the revvy bot that actually have motors plugged into them, ex: ['M1','M4']. ''' # Remove duplicates active_ports = set(active_ports) # instantiate MCU controller and motor handler self.hw_controller = RevvyControl( RevvyTransport(RevvyTransportI2CDevice(0x2D, SMBus(1)))) self.motor_handler = create_motor_port_handler(self.hw_controller) self.ports = {} # configure active ports for Revvy DC motpr for p in active_ports: if p in MOTOR_PORTS: port = self.motor_handler._ports[int(p.lstrip('M'))] port.configure(Motors.RevvyMotor) self.ports[p] = DcMotorController(port, Motors.RevvyMotor['config']) else: raise ValueError(f'Invalid motor port {p}')
def __init__(self): self._comm_interface = RevvyTransportI2C(1) self._robot_control = self._comm_interface.create_application_control() self._ring_led = RingLed(self._robot_control) self._sound = SoundControlV2() #self._status = RobotStatusIndicator(self._robot_control) self._status_updater = McuStatusUpdater(self._robot_control) self._status_updater.reset() self._battery = BatteryStatus(0, 0, 0) self._imu = IMU() self._motor_ports = create_motor_port_handler(self._robot_control) self._sensor_ports = create_sensor_port_handler(self._robot_control) self.disabled = False # Need to enable battery and IMU self._status_updater.enable_slot("battery", self._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) #set led color to purple on init self.set_led_color(0x6600cc)
def test_constructor_reads_port_amount_and_types(self): mock_control = Mock() mock_control.get_motor_port_amount = Mock(return_value=6) mock_control.get_motor_port_types = Mock(return_value={"NotConfigured": 0, "DcMotor": 1}) ports = create_motor_port_handler(mock_control) self.assertEqual(1, mock_control.get_motor_port_amount.call_count) self.assertEqual(1, mock_control.get_motor_port_types.call_count) self.assertEqual(6, ports.port_count)
def test_configure_raises_error_if_driver_is_not_supported_in_mcu(self): mock_control = Mock() mock_control.get_motor_port_amount = Mock(return_value=6) mock_control.get_motor_port_types = Mock(return_value={"NotConfigured": 0}) mock_control.set_motor_port_type = Mock() ports = create_motor_port_handler(mock_control) self.assertIs(PortInstance, type(ports[1])) self.assertEqual(0, mock_control.set_motor_port_type.call_count) self.assertRaises(KeyError, lambda: ports[1].configure({"driver": TestDriver, "config": {}})) self.assertEqual(0, mock_control.set_motor_port_type.call_count)
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)
def test_motor_ports_are_indexed_from_one(self): mock_control = Mock() mock_control.get_motor_port_amount = Mock(return_value=6) mock_control.get_motor_port_types = Mock(return_value={"NotConfigured": 0}) ports = create_motor_port_handler(mock_control) self.assertRaises(KeyError, lambda: ports[0]) self.assertIs(PortInstance, type(ports[1])) self.assertIs(PortInstance, type(ports[2])) self.assertIs(PortInstance, type(ports[3])) self.assertIs(PortInstance, type(ports[4])) self.assertIs(PortInstance, type(ports[5])) self.assertIs(PortInstance, type(ports[6])) self.assertRaises(KeyError, lambda: ports[7])
def test_unconfiguring_not_configured_port_does_nothing(self): configs = { "NotConfigured": { 'driver': 'NotConfigured', 'config': {} }, "Test": { 'driver': "NonExistentDriver" } } mock_control = Mock() mock_control.get_motor_port_amount = Mock(return_value=6) mock_control.get_motor_port_types = Mock( return_value={"NotConfigured": 0}) mock_control.set_motor_port_type = Mock() ports = create_motor_port_handler(mock_control, configs) self.assertIs(PortInstance, type(ports[1])) self.assertEqual(0, mock_control.set_motor_port_type.call_count) ports[1].configure("NotConfigured") self.assertEqual(0, mock_control.set_motor_port_type.call_count)
def test_configure_raises_error_if_driver_is_not_supported_in_mcu(self): configs = { "NotConfigured": { 'driver': 'NotConfigured', 'config': {} }, "Test": { 'driver': "NonExistentDriver" } } mock_control = Mock() mock_control.get_motor_port_amount = Mock(return_value=6) mock_control.get_motor_port_types = Mock( return_value={"NotConfigured": 0}) mock_control.set_motor_port_type = Mock() ports = create_motor_port_handler(mock_control, configs) self.assertIs(PortInstance, type(ports[1])) self.assertEqual(0, mock_control.set_motor_port_type.call_count) self.assertRaises(KeyError, lambda: ports[1].configure("Test")) self.assertEqual(0, mock_control.set_motor_port_type.call_count)
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