def test_get_rover_commands(self): controller = Controller(ControllerTestCase.path) rover_commands = controller.get_rover_commands() expected_commands = [['1', '2', 'N'], ['LMLMLMLMM'], ['3', '3', 'E'], ['MMRMMRMRRM']] for i, j in enumerate(rover_commands): self.assertEqual(rover_commands[i], expected_commands[i], msg='{0}'.format(ControllerTestCase.error_list['10']))
async def start(websocket, path): ctrl = Controller() setup = Setup() p_rate = CONF.GUI['web_socket_pulse_rate'] w_rate = CONF.GUI['web_socket_wait_rate'] SCRfield = setup.field() SCRenv = setup.env(SCRfield=SCRfield, roll='WS') GUIraw = copy(CONF.GUI['GUIraw']) SCRenv['log'].output(lv='INFO', log='new conection.') try: while True: time.sleep(p_rate) send_json, GUIraw = ctrl.websocket_chaser(SCRfield=SCRfield, GUIenv=SCRenv, GUIraw=GUIraw) if (len(send_json.keys()) == 0): time.sleep(w_rate) await websocket.send('check') else: await websocket.send(json.dumps(send_json)) except websockets.exceptions.ConnectionClosedError: SCRenv['log'].output(lv='INFO', log='close conection.') GUIraw = {}
def main(): profile_path = os.path.join(os.environ['HOME'], '.pmaya') app = QtGui.QApplication(sys.argv) controller = Controller(app) controller.loadProfile(profile_path) app.exec_() controller.saveProfile(profile_path)
def run() -> None: rospy.init_node("follow_wall") Controller.run( model=init_model, update=update, subscriptions=subscriptions, ) rospy.spin()
def run() -> None: rospy.init_node("drive_square") Controller.run( model=init_model, update=update, subscriptions=subscriptions, ) rospy.spin()
def main(): ''' 需要安装'crawlergo','dirsearch','oneforall','xray_linux_amd64'到tools目录 定义是自动下载,但是由于github问题可能经常会出错;出错的话手动下载解压最好; 具体链接在download_tools.py里有 ''' if not os.path.exists(os.path.join(TOOLS_DIR, 'install.lock')): print('tools not exists; downloading ...') time.sleep(3) from lib.download_tools import download download() arguments = ArgumentParser() controller = Controller(arguments) controller.assign_task()
def main(): controller = Controller() kwargs = {"num_workers": 1, "pin_memory": True} if FLAGS.CUDA else {} train_loader = DataLoader( datasets.Omniglot( "data", train=True, download=True, transform=transforms.Compose([ transforms.ToTensor(), # transforms.Normalize(mean, std) should add for better performance, + other transforms ])), batch_sizer=FLAGS.BATCH_SIZE, shuffle=True, **kwargs) test_loader = DataLoader( datasets.Omniglot( "data", train=False, transform=transforms.Compose([ transforms.ToTensor(), # transforms.Normalize(mean, std) should add for better performance, + other transforms ])), batch_sizer=FLAGS.BATCH_SIZE, shuffle=True, **kwargs) if FLAGS.TRAIN: train(controller, train_loader) else: test(controller, test_loader)
def __init__(self): self.script_path = os.path.dirname(os.path.realpath(__file__)) self.arguments = ArgumentParser(self.script_path) if self.arguments.quiet: self.output = PrintOutput(self.arguments.color) else: self.output = CLIOutput(self.arguments.color) self.controller = Controller(self.script_path, self.arguments, self.output)
def main(): try: _loader = ConfigLoader(Level.INFO) filename = 'config.yaml' _config = _loader.configure(filename) _queue = MessageQueue(Level.INFO) _ifs = IntegratedFrontSensor(_config, _queue, Level.INFO) _motors = Motors(_config, None, None, Level.INFO) # configure Controller and Arbitrator _controller = Controller(_config, _ifs, _motors, _callback_shutdown, Level.INFO) _arbitrator = Arbitrator(_config, _queue, _controller, Level.WARN) print(Fore.RED + 'roam...' + Style.RESET_ALL) _ifs.enable() _arbitrator.start() # _controller.enable() _roam = RoamBehaviour(_motors, Level.INFO) _roam.roam() while _roam.is_roaming(): print(Fore.BLACK + Style.DIM + '(roaming)' + Style.RESET_ALL) time.sleep(1.0) print(Fore.YELLOW + 'complete: closing...' + Style.RESET_ALL) _motors.close() print(Fore.YELLOW + 'closed.' + Style.RESET_ALL) sys.exit(0) except KeyboardInterrupt: print('test complete') sys.exit(0) except Exception as e: print(Fore.RED + Style.BRIGHT + 'error in PID controller: {}'.format(e)) traceback.print_exc(file=sys.stdout) sys.exit(1)
#!/usr/bin/env python3.8 from lib.views.Frames import topView from lib.controller import Controller import wx if __name__ == "__main__": app = wx.App(False) controller = Controller(app) app.MainLoop()
def main(): """ Prepara las ventanas, define modelos, controlador y vista y corre el programa :return: void """ # Se obtiene el checksum del juego checksum = [path_checksum('lib', VERBOSE), md5file('main.py', VERBOSE).upper(), path_checksum('bin', VERBOSE)] # Se cargan las configuraciones control_config = configLoader(DIR_CONFIG + "control.ini", verbose=VERBOSE) game_config = configLoader(DIR_CONFIG + "game.ini", verbose=VERBOSE) map_config = configLoader(DIR_CONFIG + "map.ini", verbose=VERBOSE) score_config = configLoader(DIR_CONFIG + "scoreboard.ini", verbose=VERBOSE) user_config = configLoader(DIR_CONFIG + "user.ini", verbose=VERBOSE) view_config = configLoader(DIR_CONFIG + "view.ini", verbose=VERBOSE) window_config = configLoader(DIR_CONFIG + "window.ini", verbose=VERBOSE) world_config = configLoader(DIR_CONFIG + "world.ini", verbose=VERBOSE) # Se carga el idioma lang = langs.langLoader(game_config.getValue("LANG")) # @UndefinedVariable # Se carga la información de la pantalla del cliente display_info = pygame.display.Info() # @UndefinedVariable # Se comprueba que el nombre de jugador no sea Player, si no es valido se pide uno nuevo if not username.validate( user_config.getValue("NAME")): # @UndefinedVariable new_name = username.request(lang.get(111), lang.get(112)) # @UndefinedVariable if new_name is not username.NO_VALID_NAME: # @UndefinedVariable user_config.setParameter("NAME", new_name) user_config.export() else: utils.destroyProcess() # @UndefinedVariable # Creación de ventana window = Window(window_config, lang.get(10), pygame.image.load(getIcons("icon")), display_info) # @UndefinedVariable clock = pygame.time.Clock() # reloj @UndefinedVariable fps = int(game_config.getValue("FPS")) # fps a dibujar # Se crea el mundo world = World(world_config, map_config, window, checksum, score_config, user_config, lang, game_config, verbose=VERBOSE) # TEST: world.loadMap(1) # Se crean los menús de inicio y pause menus = Createuimenu(lang, window, world, game_config, user_config, view_config, window_config, world_config, map_config) # Se crea la vista vista = View(window, clock, world, lang, view_config, menus) menus.addView(vista) # Se crea el controlador control = Controller(world, clock, lang, control_config, window, menus, verbose=VERBOSE) menus.addController(control) vista.add_controller(control) # Se lanza el mainloop while True: clock.tick(fps) vista.draw(control.event_loop())
from lib.controller import Controller, PlayerDeath import json import random game = Controller() game.start_game() # beginning scene begin_file = open('txt/begin.txt', 'r') begin_dialogue = list(begin_file) print(begin_dialogue[0]) envs = open('lib/environment.json') data = json.loads(envs.read()) episodes = data['episodes'] def view(episode): print(episode['desc']) actions = list(episode['actions'].keys()) possible_choices = range(len(actions)) action_map = dict(zip(possible_choices, actions)) for i in possible_choices: key = action_map[i] print("{0}: {1}".format(i, key)) return action_map def play_episode(episode, choice, action_map): action = action_map[choice] scenario = episode['actions'][action] result = scenario[1] if result == 'walk':
class ROS(AbstractTask): ''' Extends AbstractTask as a Finite State Machine (FSM) basis of a Robot Operating System (ROS) or behaviour-based system (BBS), including spawning the various tasks and an Arbitrator as separate threads, inter-communicating over a common message queue. This establishes a message queue, an Arbitrator and a Controller, as well as an optional RESTful flask-based web service. The message queue receives Event-containing messages, which are passed on to the Arbitrator, whose job it is to determine the highest priority action to execute for that task cycle. Example usage: try: _ros = ROS() _ros.start() except Exception: _ros.close() There is also a rosd linux daemon, which can be used to start, enable and disable ros (actually via its Arbitrator). ''' # .......................................................................... def __init__(self): ''' This initialises the ROS and calls the YAML configurer. ''' self._queue = MessageQueue(Level.INFO) self._mutex = threading.Lock() super().__init__("ros", self._queue, None, None, self._mutex) self._log.info('initialising...') self._active = False self._closing = False self._disable_leds = False # self._switch = None self._motors = None self._arbitrator = None self._controller = None self._gamepad = None self._features = [] # self._flask_wrapper = None # read YAML configuration _loader = ConfigLoader(Level.INFO) filename = 'config.yaml' self._config = _loader.configure(filename) self._gamepad_enabled = self._config['ros'].get('gamepad').get( 'enabled') self._log.info('initialised.') self._configure() # .......................................................................... def _configure(self): ''' Configures ROS based on both KR01 standard hardware as well as optional features, the latter based on devices showing up (by address) on the I²C bus. Optional devices are only enabled at startup time via registration of their feature availability. ''' scanner = I2CScanner(Level.WARN) self._addresses = scanner.getAddresses() hexAddresses = scanner.getHexAddresses() self._addrDict = dict( list(map(lambda x, y: (x, y), self._addresses, hexAddresses))) for i in range(len(self._addresses)): self._log.debug( Fore.BLACK + Style.DIM + 'found device at address: {}'.format(hexAddresses[i]) + Style.RESET_ALL) self._log.info('configure default features...') # standard devices ........................................... self._log.info('configuring integrated front sensors...') self._ifs = IntegratedFrontSensor(self._config, self._queue, Level.INFO) self._log.info('configure ht0740 switch...') self._switch = Switch(Level.INFO) # since we're using the HT0740 Switch, turn it on to enable sensors that rely upon its power # self._switch.enable() self._switch.on() self._log.info('configuring button...') self._button = Button(self._config, self.get_message_queue(), self._mutex) self._log.info('configure battery check...') _battery_check = BatteryCheck(self._config, self.get_message_queue(), Level.INFO) self.add_feature(_battery_check) self._log.info('configure CPU temperature check...') _temperature_check = Temperature(self._config, self._queue, Level.INFO) self.add_feature(_temperature_check) ultraborg_available = (0x36 in self._addresses) if ultraborg_available: self._log.debug(Fore.CYAN + Style.BRIGHT + '-- UltraBorg available at 0x36.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no UltraBorg available at 0x36.' + Style.RESET_ALL) self._set_feature_available('ultraborg', ultraborg_available) thunderborg_available = (0x15 in self._addresses) if thunderborg_available: # then configure motors self._log.debug(Fore.CYAN + Style.BRIGHT + '-- ThunderBorg available at 0x15' + Style.RESET_ALL) _motor_configurer = MotorConfigurer(self, self._config, Level.INFO) self._motors = _motor_configurer.configure() else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no ThunderBorg available at 0x15.' + Style.RESET_ALL) self._set_feature_available('thunderborg', thunderborg_available) # optional devices ........................................... # the 5x5 RGB Matrix is at 0x74 for port, 0x77 for starboard rgbmatrix5x5_stbd_available = (0x74 in self._addresses) if rgbmatrix5x5_stbd_available: self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x74.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x74.' + Style.RESET_ALL) self._set_feature_available('rgbmatrix5x5_stbd', rgbmatrix5x5_stbd_available) rgbmatrix5x5_port_available = (0x77 in self._addresses) if rgbmatrix5x5_port_available: self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x77.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x77.' + Style.RESET_ALL) self._set_feature_available('rgbmatrix5x5_port', rgbmatrix5x5_port_available) if rgbmatrix5x5_stbd_available or rgbmatrix5x5_port_available: self._log.info('configure rgbmatrix...') self._rgbmatrix = RgbMatrix(Level.INFO) self.add_feature(self._rgbmatrix) # FIXME this is added twice # ............................................ # the 11x7 LED matrix is at 0x75 for starboard, 0x77 for port. The latter # conflicts with the RGB LED matrix, so both cannot be used simultaneously. matrix11x7_stbd_available = (0x75 in self._addresses) if matrix11x7_stbd_available: self._log.debug(Fore.CYAN + Style.BRIGHT + '-- 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) self._set_feature_available('matrix11x7_stbd', matrix11x7_stbd_available) # device availability ........................................ bno055_available = (0x28 in self._addresses) if bno055_available: self._log.info('configuring BNO055 9DoF sensor...') self._bno055 = BNO055(self._config, self.get_message_queue(), Level.INFO) else: self._log.debug(Fore.RED + Style.BRIGHT + 'no BNO055 orientation sensor available at 0x28.' + Style.RESET_ALL) self._set_feature_available('bno055', bno055_available) # NOTE: the default address for the ICM20948 is 0x68, but this conflicts with the PiJuice icm20948_available = (0x69 in self._addresses) if icm20948_available: self._log.debug(Fore.CYAN + Style.BRIGHT + 'ICM20948 available at 0x69.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + 'no ICM20948 available at 0x69.' + Style.RESET_ALL) self._set_feature_available('icm20948', icm20948_available) lsm303d_available = (0x1D in self._addresses) if lsm303d_available: self._log.debug(Fore.CYAN + Style.BRIGHT + 'LSM303D available at 0x1D.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + 'no LSM303D available at 0x1D.' + Style.RESET_ALL) self._set_feature_available('lsm303d', lsm303d_available) vl53l1x_available = (0x29 in self._addresses) if vl53l1x_available: self._log.debug(Fore.CYAN + Style.BRIGHT + 'VL53L1X available at 0x29.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + 'no VL53L1X available at 0x29.' + Style.RESET_ALL) self._set_feature_available('vl53l1x', vl53l1x_available) as7262_available = (0x49 in self._addresses) if as7262_available: self._log.debug(Fore.CYAN + Style.BRIGHT + '-- AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + '-- no AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) self._set_feature_available('as7262', as7262_available) pijuice_available = (0x68 in self._addresses) if pijuice_available: self._log.debug(Fore.CYAN + Style.BRIGHT + 'PiJuice hat available at 0x68.' + Style.RESET_ALL) else: self._log.debug(Fore.RED + Style.BRIGHT + 'no PiJuice hat available at 0x68.' + Style.RESET_ALL) self._set_feature_available('pijuice', pijuice_available) self._log.info('configured.') # .......................................................................... def summation(): ''' Displays unaccounted I2C addresses. This is currently non-functional, as we don't remove a device from the list when its address is found. ''' self._log.info(Fore.YELLOW + '-- unaccounted for self._addresses:') for i in range(len(self._addresses)): hexAddr = self._addrDict.get(self._addresses[i]) self._log.info(Fore.YELLOW + Style.BRIGHT + '-- address: {}'.format(hexAddr) + Style.RESET_ALL) # .......................................................................... def _set_feature_available(self, name, value): ''' Sets a feature's availability to the boolean value. ''' self._log.debug(Fore.BLUE + Style.BRIGHT + '-- set feature available. name: \'{}\' value: \'{}\'.' .format(name, value)) self.set_property('features', name, value) # .......................................................................... def get_message_queue(self): return self._queue # .......................................................................... def get_controller(self): return self._controller # .......................................................................... def get_configuration(self): return self._config # .......................................................................... def get_property(self, section, property_name): ''' Return the value of the named property of the application configuration, provided its section and property name. ''' return self._config[section].get(property_name) # .......................................................................... def set_property(self, section, property_name, property_value): ''' Set the value of the named property of the application configuration, provided its section, property name and value. ''' self._log.debug( Fore.GREEN + 'set config on section \'{}\' for property key: \'{}\' to value: {}.' .format(section, property_name, property_value)) if section == 'ros': self._config[section].update(property_name=property_value) else: _ros = self._config['ros'] _ros[section].update(property_name=property_value) # .......................................................................... def _set_pi_leds(self, enable): ''' Enables or disables the Raspberry Pi's board LEDs. ''' sudo_name = self.get_property('pi', 'sudo_name') led_0_path = self._config['pi'].get('led_0_path') led_1_path = self._config['pi'].get('led_1_path') if enable: self._log.info('re-enabling LEDs...') os.system('echo 1 | {} tee {}'.format(sudo_name, led_0_path)) os.system('echo 1 | {} tee {}'.format(sudo_name, led_1_path)) else: self._log.debug('disabling LEDs...') os.system('echo 0 | {} tee {}'.format(sudo_name, led_0_path)) os.system('echo 0 | {} tee {}'.format(sudo_name, led_1_path)) # .......................................................................... def _connect_gamepad(self): if not self._gamepad_enabled: self._log.info('gamepad disabled.') return if self._gamepad is None: self._log.info('creating gamepad...') try: self._gamepad = Gamepad(self._config, self._queue, Level.INFO) except GamepadConnectException as e: self._log.error('unable to connect to gamepad: {}'.format(e)) self._gamepad = None self._gamepad_enabled = False self._log.info('gamepad unavailable.') return if self._gamepad is not None: self._log.info('enabling gamepad...') self._gamepad.enable() _count = 0 while not self._gamepad.has_connection(): _count += 1 if _count == 1: self._log.info('connecting to gamepad...') else: self._log.info( 'gamepad not connected; re-trying... [{:d}]'.format( _count)) self._gamepad.connect() time.sleep(0.5) if self._gamepad.has_connection() or _count > 5: break # .......................................................................... def has_connected_gamepad(self): return self._gamepad is not None and self._gamepad.has_connection() # .......................................................................... def get_arbitrator(self): return self._arbitrator # .......................................................................... def add_feature(self, feature): ''' Add the feature to the list of features. Features must have an enable() method. ''' self._features.append(feature) self._log.info('added feature {}.'.format(feature.name())) # .......................................................................... def _callback_shutdown(self): _enable_self_shutdown = self._config['ros'].get('enable_self_shutdown') if _enable_self_shutdown: self._log.critical('callback: shutting down os...') self.close() sys.exit(0) else: self._log.critical('self-shutdown disabled.') # .......................................................................... def run(self): ''' This first disables the Pi's status LEDs, establishes the message queue arbitrator, the controller, enables the set of features, then starts the main OS loop. ''' super(AbstractTask, self).run() loop_count = 0 # display banner! _banner = '\n' \ 'ros\n' \ 'ros █▒▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ \n' \ + 'ros █▒▒▒▒▒▒ █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros\n' self._log.info(_banner) self._disable_leds = self._config['pi'].get('disable_leds') if self._disable_leds: # disable Pi LEDs since they may be distracting self._set_pi_leds(False) self._log.info('enabling features...') for feature in self._features: self._log.info('enabling feature {}...'.format(feature.name())) feature.enable() # __enable_player = self._config['ros'].get('enable_player') # if __enable_player: # self._log.info('configuring sound player...') # self._player = Player(Level.INFO) # else: # self._player = None # i2c_slave_address = config['ros'].get('i2c_master').get('device_id') # i2c hex address of I2C slave device vl53l1x_available = True # self.get_property('features', 'vl53l1x') ultraborg_available = True # self.get_property('features', 'ultraborg') if vl53l1x_available and ultraborg_available: self._log.critical('starting scanner tool...') self._lidar = Lidar(self._config, Level.INFO) self._lidar.enable() else: self._log.critical( 'lidar scanner tool does not have necessary dependencies.') # wait to stabilise features? # configure the Controller and Arbitrator self._log.info('configuring controller...') self._controller = Controller(self._config, self._ifs, self._motors, self._callback_shutdown, Level.INFO) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(self._config, self._queue, self._controller, Level.WARN) _flask_enabled = self._config['flask'].get('enabled') if _flask_enabled: self._log.info('starting flask web server...') self.configure_web_server() else: self._log.info( 'not starting flask web server (suppressed from command line).' ) # bluetooth gamepad controller if self._gamepad_enabled: self._connect_gamepad() self._log.warning('Press Ctrl-C to exit.') _wait_for_button_press = self._config['ros'].get( 'wait_for_button_press') self._controller.set_standby(_wait_for_button_press) # begin main loop .............................. self._log.info('starting button thread...') self._button.start() # self._log.info('enabling bno055 sensor...') # self._bno055.enable() # self._bumpers.enable() self._indicator = Indicator(Level.INFO) # add indicator as message consumer self._queue.add_consumer(self._indicator) self._log.info(Fore.MAGENTA + 'enabling integrated front sensor...') self._ifs.enable() # self._log.info('starting info thread...') # self._info.start() # self._log.info('starting blinky thread...') # self._rgbmatrix.enable(DisplayType.RANDOM) # enable arbitrator tasks (normal functioning of robot) main_loop_delay_ms = self._config['ros'].get('main_loop_delay_ms') self._log.info( 'begin main os loop with {:d}ms delay.'.format(main_loop_delay_ms)) _loop_delay_sec = main_loop_delay_ms / 1000 _main_loop_count = 0 self._arbitrator.start() self._active = True while self._active: # The sensors and the flask service sends messages to the message queue, # which forwards those messages on to the arbitrator, which chooses the # highest priority message to send on to the controller. So the timing # of this loop is inconsequential; it exists solely as a keep-alive. _main_loop_count += 1 self._log.debug(Fore.BLACK + Style.DIM + '[{:d}] main loop...'.format(_main_loop_count)) time.sleep(_loop_delay_sec) # end application loop ......................... if not self._closing: self._log.warning('closing following loop...') self.close() # end main ................................... # .......................................................................... def configure_web_server(self): ''' Start flask web server. ''' try: self._mutex.acquire() self._log.info('starting web service...') self._flask_wrapper = FlaskWrapperService(self._queue, self._controller) self._flask_wrapper.start() except KeyboardInterrupt: self._log.error('caught Ctrl-C interrupt.') finally: self._mutex.release() time.sleep(1) self._log.info(Fore.BLUE + 'web service started.' + Style.RESET_ALL) # .......................................................................... def emergency_stop(self): ''' Stop immediately, something has hit the top feelers. ''' self._motors.stop() self._log.info(Fore.RED + Style.BRIGHT + 'emergency stop: contact on upper feelers.') # .......................................................................... def send_message(self, message): ''' Send the Message into the MessageQueue. ''' self._queue.add(message) # .......................................................................... def enable(self): super(AbstractTask, self).enable() # .......................................................................... def disable(self): super(AbstractTask, self).disable() # .......................................................................... def close(self): ''' This sets the ROS back to normal following a session. ''' if self._closing: # this also gets called by the arbitrator so we ignore that self._log.info('already closing.') return else: self._active = False self._closing = True self._log.info(Style.BRIGHT + 'closing...') if self._gamepad: self._gamepad.close() if self._motors: self._motors.close() if self._ifs: self._ifs.close() # close features for feature in self._features: self._log.info('closing feature {}...'.format(feature.name())) feature.close() self._log.info('finished closing features.') if self._arbitrator: self._arbitrator.disable() self._arbitrator.close() # self._arbitrator.join(timeout=1.0) if self._controller: self._controller.disable() # if self._flask_wrapper is not None: # self._flask_wrapper.close() super().close() # self._info.close() # self._rgbmatrix.close() # if self._switch: # self._switch.close() # super(AbstractTask, self).close() if self._disable_leds: # restore LEDs self._set_pi_leds(True) # GPIO.cleanup() # self._log.info('joining main thread...') # self.join(timeout=0.5) self._log.info('os closed.') sys.stderr = DevNull() sys.exit(0)
def api_rest(env): g_c = Controller() json = g_c.get_json(path=env['PATH_INFO']) headers = [('Content-Type', 'text/json; charset=utf-8')] return '200 OK', headers, [bytes(json, encoding='utf-8')]
def test_controller_file_input(self,mock___init__): Controller.__init__("path") mock___init__.assert_called_with("path")
def api_index(env): g_c = Controller() html = g_c.get_index() headers = [('Content-Type', 'text/html; charset=utf-8')] return '200 OK', headers, html
class ROS(AbstractTask): ''' Extends AbstractTask as a Finite State Machine (FSM) basis of a Robot Operating System (ROS) or behaviour-based system (BBS), including spawning the various tasks and an Arbitrator as separate threads, inter-communicating over a common message queue. This establishes a RESTful flask service, a message queue, an Arbitrator and a Controller. The message queue receives Event-containing messages, which are passed on to the Arbitrator, whose job it is to determine the highest priority action to execute for that task cycle. Example usage: try: _ros = ROS() _ros.start() except Exception: _ros.close() ''' # .......................................................................... def __init__(self): ''' This initialises the ROS and calls the YAML configurer. ''' self._queue = MessageQueue(Level.INFO) self._mutex = threading.Lock() super().__init__("os", self._queue, None, None, self._mutex) self._log.info('initialising...') self._active = False self._closing = False self._disable_leds = False self._switch = None self._motors = None self._arbitrator = None self._controller = None # read YAML configuration _loader = ConfigLoader(Level.INFO) filename = 'config.yaml' self._config = _loader.configure(filename) # import available features self._features = [] _configurer = Configurer(self, Level.INFO) _configurer.scan() self._log.info('initialised.') # def configure(self): # ''' # Read and return configuration from the YAML file. # ''' # filename = 'config.yaml' # self._log.info('reading from yaml configuration file {}...'.format(filename)) # _config = yaml.safe_load(open(filename, 'r')) # for key, value in _config.items(): # self._log.debug('config key: {}; value: {}'.format(key, str(value))) # self._log.info('configuration read.') # return _config # .......................................................................... def get_message_queue(self): return self._queue # .......................................................................... def get_controller(self): return self._controller # .......................................................................... def get_configuration(self): return self._config # .......................................................................... def get_property(self, section, property_name): ''' Return the value of the named property of the application configuration, provided its section and property name. ''' return self._config[section].get(property_name) # .......................................................................... def set_property(self, section, property_name, property_value): ''' Set the value of the named property of the application configuration, provided its section, property name and value. ''' self._log.info( Fore.GREEN + 'set config on section \'{}\' for property key: \'{}\' to value: {}.' .format(section, property_name, property_value)) if section == 'ros': self._config[section].update(property_name=property_value) else: _ros = self._config['ros'] _ros[section].update(property_name=property_value) # .......................................................................... def _set_pi_leds(self, enable): ''' Enables or disables the Raspberry Pi's board LEDs. ''' sudo_name = self.get_property('pi', 'sudo_name') led_0_path = self._config['pi'].get('led_0_path') led_1_path = self._config['pi'].get('led_1_path') if enable: self._log.info('re-enabling LEDs...') os.system('echo 1 | {} tee {}'.format(sudo_name, led_0_path)) os.system('echo 1 | {} tee {}'.format(sudo_name, led_1_path)) else: self._log.debug('disabling LEDs...') os.system('echo 0 | {} tee {}'.format(sudo_name, led_0_path)) os.system('echo 0 | {} tee {}'.format(sudo_name, led_1_path)) # .......................................................................... def add_feature(self, feature): ''' Add the feature to the list of features. Features must have an enable() method. ''' self._features.append(feature) self._log.info('added feature {}.'.format(feature.name())) # .......................................................................... def _callback_shutdown(self): __enable_self_shutdown = self._config['ros'].get( 'enable_self_shutdown') if _enable_self_shutdown: self._log.critical('callback: shutting down os...') if self._arbitrator: self._arbitrator.disable() self.close() else: self._log.critical('self-shutdown disabled.') # .......................................................................... def run(self): ''' This first disables the Pi's status LEDs, establishes the message queue arbitrator, the controller, enables the set of features, then starts the main OS loop. ''' super(AbstractTask, self).run() loop_count = 0 self._disable_leds = self._config['pi'].get('disable_leds') if self._disable_leds: # disable Pi LEDs since they may be distracting self._set_pi_leds(False) self._log.info('enabling features...') for feature in self._features: self._log.info('enabling feature {}...'.format(feature.name())) feature.enable() __enable_player = self._config['ros'].get('enable_player') if __enable_player: self._log.info('configuring sound player...') self._player = Player(Level.INFO) else: self._player = None vl53l1x_available = True # self.get_property('features', 'vl53l1x') self._log.critical('vl53l1x_available? {}'.format(vl53l1x_available)) ultraborg_available = True # self.get_property('features', 'ultraborg') self._log.critical( 'ultraborg available? {}'.format(ultraborg_available)) if vl53l1x_available and ultraborg_available: self._log.critical('starting scanner tool...') self._lidar = Lidar(self._config, self._player, Level.INFO) self._lidar.enable() else: self._log.critical( 'scanner tool does not have necessary dependencies.') # wait to stabilise features? # configure the Controller and Arbitrator self._log.info('configuring controller...') self._controller = Controller(Level.INFO, self._config, self._switch, self._infrareds, self._motors, self._rgbmatrix, self._lidar, self._callback_shutdown) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(_level, self._queue, self._controller, self._mutex) flask_enabled = self._config['flask'].get('enabled') if flask_enabled: self._log.info('starting flask web server...') self.configure_web_server() else: self._log.info( 'not starting flask web server (suppressed from command line).' ) self._log.warning('Press Ctrl-C to exit.') wait_for_button_press = self._config['ros'].get( 'wait_for_button_press') self._controller.set_standby(wait_for_button_press) # begin main loop .............................. # self._log.info('starting battery check thread...') # self._battery_check.enable() self._log.info('starting button thread...') self._button.start() # self._log.info('enabling bno055 sensor...') # self._bno055.enable() self._log.info('enabling bumpers...') self._bumpers.enable() # self._log.info('starting info thread...') # self._info.start() # self._log.info('starting blinky thread...') # self._rgbmatrix.enable(DisplayType.RANDOM) # enable arbitrator tasks (normal functioning of robot) main_loop_delay_ms = self._config['ros'].get('main_loop_delay_ms') self._log.info( 'begin main os loop with {:d}ms delay.'.format(main_loop_delay_ms)) _loop_delay_sec = main_loop_delay_ms / 1000 self._arbitrator.start() while self._arbitrator.is_alive(): # The sensors and the flask service sends messages to the message queue, # which forwards those messages on to the arbitrator, which chooses the # highest priority message to send on to the controller. So the timing # of this loop is inconsequential; it exists solely as a keep-alive. time.sleep(_loop_delay_sec) # end application loop ......................... if not self._closing: self._log.warning('closing following loop...') self.close() # end main ................................... # .......................................................................... def configure_web_server(self): ''' Start flask web server. ''' try: self._mutex.acquire() self._log.info('starting web service...') self._flask_wrapper = FlaskWrapperService(self._queue, self._controller) self._flask_wrapper.start() except KeyboardInterrupt: self._log.error('caught Ctrl-C interrupt.') finally: self._mutex.release() time.sleep(1) self._log.info(Fore.BLUE + 'web service started.' + Style.RESET_ALL) # .......................................................................... def emergency_stop(self): ''' Stop immediately, something has hit the top feelers. ''' self._motors.stop() self._log.info(Fore.RED + Style.BRIGHT + 'emergency stop: contact on upper feelers.') # .......................................................................... def send_message(self, message): ''' Send the Message into the MessageQueue. ''' self._queue.add(message) # .......................................................................... def enable(self): super(AbstractTask, self).enable() # .......................................................................... def disable(self): super(AbstractTask, self).disable() # .......................................................................... def close(self): ''' This sets the ROS back to normal following a session. ''' if self._closing: # this also gets called by the arbitrator so we ignore that self._log.info('already closing.') return else: self._active = False self._closing = True self._log.info(Style.BRIGHT + 'closing...') self._flask_wrapper.close() if self._arbitrator: self._arbitrator.disable() super().close() # self._arbitrator.join(timeout=1.0) # close features for feature in self._features: self._log.info('closing feature {}...'.format(feature.name())) feature.close() self._log.info('finished closing features.') if self._motors: self._motors.close() # self._info.close() # self._rgbmatrix.close() if self._switch: self._switch.close() # super(AbstractTask, self).close() if self._arbitrator: self._arbitrator.close() if self._disable_leds: # restore LEDs self._set_pi_leds(True) # GPIO.cleanup() # self._log.info('joining main thread...') # self.join(timeout=0.5) self._log.info('os closed.') sys.stderr = DevNull() sys.exit(0)
def run(self): ''' This first disables the Pi's status LEDs, establishes the message queue arbitrator, the controller, enables the set of features, then starts the main OS loop. ''' super(AbstractTask, self).run() loop_count = 0 self._disable_leds = self._config['pi'].get('disable_leds') if self._disable_leds: # disable Pi LEDs since they may be distracting self._set_pi_leds(False) self._log.info('enabling features...') for feature in self._features: self._log.info('enabling feature {}...'.format(feature.name())) feature.enable() __enable_player = self._config['ros'].get('enable_player') if __enable_player: self._log.info('configuring sound player...') self._player = Player(Level.INFO) else: self._player = None vl53l1x_available = True # self.get_property('features', 'vl53l1x') self._log.critical('vl53l1x_available? {}'.format(vl53l1x_available)) ultraborg_available = True # self.get_property('features', 'ultraborg') self._log.critical( 'ultraborg available? {}'.format(ultraborg_available)) if vl53l1x_available and ultraborg_available: self._log.critical('starting scanner tool...') self._lidar = Lidar(self._config, self._player, Level.INFO) self._lidar.enable() else: self._log.critical( 'scanner tool does not have necessary dependencies.') # wait to stabilise features? # configure the Controller and Arbitrator self._log.info('configuring controller...') self._controller = Controller(Level.INFO, self._config, self._switch, self._infrareds, self._motors, self._rgbmatrix, self._lidar, self._callback_shutdown) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(_level, self._queue, self._controller, self._mutex) flask_enabled = self._config['flask'].get('enabled') if flask_enabled: self._log.info('starting flask web server...') self.configure_web_server() else: self._log.info( 'not starting flask web server (suppressed from command line).' ) self._log.warning('Press Ctrl-C to exit.') wait_for_button_press = self._config['ros'].get( 'wait_for_button_press') self._controller.set_standby(wait_for_button_press) # begin main loop .............................. # self._log.info('starting battery check thread...') # self._battery_check.enable() self._log.info('starting button thread...') self._button.start() # self._log.info('enabling bno055 sensor...') # self._bno055.enable() self._log.info('enabling bumpers...') self._bumpers.enable() # self._log.info('starting info thread...') # self._info.start() # self._log.info('starting blinky thread...') # self._rgbmatrix.enable(DisplayType.RANDOM) # enable arbitrator tasks (normal functioning of robot) main_loop_delay_ms = self._config['ros'].get('main_loop_delay_ms') self._log.info( 'begin main os loop with {:d}ms delay.'.format(main_loop_delay_ms)) _loop_delay_sec = main_loop_delay_ms / 1000 self._arbitrator.start() while self._arbitrator.is_alive(): # The sensors and the flask service sends messages to the message queue, # which forwards those messages on to the arbitrator, which chooses the # highest priority message to send on to the controller. So the timing # of this loop is inconsequential; it exists solely as a keep-alive. time.sleep(_loop_delay_sec) # end application loop ......................... if not self._closing: self._log.warning('closing following loop...') self.close()
def __init__(self, input_file_path): controller = Controller(input_file_path) self.plateau = RectangularPlateau(controller.get_plateau_bounds()) self.rover_commands = controller.get_rover_commands() self.rovers = []
#!/usr/bin/python try: import sys from lib.controller import Controller from lib.core.common import * from lib.core.version import * except ImportError,e: import sys sys.stdout.write("%s\n" %e) print exit_message sys.exit(1) ## ### Main ... ## if __name__ == "__main__": try: controller = Controller() controller.run() except Exception, err_mess: print err_mess print exit_message sys.exit(2)
def test_get_plateau_bounds(self): controller = Controller(ControllerTestCase.path) self.assertEqual(ControllerTestCase.plateau_bounds, controller.get_plateau_bounds(), msg= '{0}'.format(ControllerTestCase.error_list['9']))
def configure(self, arguments): ''' Provided with a set of configuration arguments, configures ROS based on both KD01/KR01 standard hardware as well as optional features, the latter based on devices showing up (by address) on the I²C bus. Optional devices are only enabled at startup time via registration of their feature availability. ''' self._log.heading('configuration', 'configuring ros...', '[1/2]' if arguments.start else '[1/1]') self._log.info('application log level: {}'.format( self._log.level.name)) # configuration from command line arguments self._using_mocks = False self._permit_mocks = arguments.mock self._enable_camera = arguments.camera # TODO # read YAML configuration _loader = ConfigLoader(self._log.level) _config_file = arguments.config_file if arguments.config_file is not None else 'config.yaml' self._config = _loader.configure(_config_file) # scan I2C bus self._log.info('scanning I²C address bus...') scanner = I2CScanner(self._log.level) self._addresses = scanner.get_int_addresses() _hex_addresses = scanner.get_hex_addresses() self._addrDict = dict( list(map(lambda x, y: (x, y), self._addresses, _hex_addresses))) # for i in range(len(self._addresses)): for _address in self._addresses: _device_name = self.get_device_for_address(_address) self._log.info('found device at I²C address 0x{:02X}: {}'.format( _address, _device_name) + Style.RESET_ALL) # TODO look up address and make assumption about what the device is # establish basic subsumption components self._log.info('configure application messaging...') self._message_factory = MessageFactory(self._log.level) self._message_bus = MessageBus(self._log.level) self._log.info('configuring system clock...') self._clock = Clock(self._config, self._message_bus, self._message_factory, Level.WARN) self.add_feature(self._clock) # standard devices ........................................... self._log.info('configure default features...') self._log.info('configure CPU temperature check...') _temperature_check = Temperature(self._config, self._clock, self._log.level) if _temperature_check.get_cpu_temperature() > 0: self.add_feature(_temperature_check) else: self._log.warning('no support for CPU temperature.') motors_enabled = not arguments.no_motors and (0x15 in self._addresses) if motors_enabled: # then configure motors self._log.debug(Fore.CYAN + Style.BRIGHT + '-- ThunderBorg available at 0x15' + Style.RESET_ALL) _motor_configurer = MotorConfigurer(self._config, self._clock, self._log.level) self._motors = _motor_configurer.get_motors() self.add_feature(self._motors) self._set_feature_available('motors', motors_enabled) elif self._permit_mocks: self._using_mocks = True self._log.debug(Fore.RED + Style.BRIGHT + '-- no ThunderBorg available, using mocks.' + Style.RESET_ALL) from mock.motor_configurer import MockMotorConfigurer _motor_configurer = MockMotorConfigurer(self._config, self._clock, self._log.level) self._motors = _motor_configurer.get_motors() self.add_feature(self._motors) self._set_feature_available('motors', motors_enabled) ifs_available = (0x0E in self._addresses) if ifs_available: self._log.info('configuring integrated front sensor...') self._ifs = IntegratedFrontSensor(self._config, self._clock, self._log.level) self.add_feature(self._ifs) elif self._permit_mocks: self._using_mocks = True self._log.info( 'integrated front sensor not available; loading mock sensor.') from mock.ifs import MockIntegratedFrontSensor self._ifs = MockIntegratedFrontSensor(self._message_bus, exit_on_complete=False, level=self._log.level) self._message_bus.set_ifs(self._ifs) self.add_feature(self._ifs) else: self._ifs = None self._log.warning('no integrated front sensor available.') # ultraborg_available = ( 0x36 in self._addresses ) # if ultraborg_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- UltraBorg available at 0x36.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no UltraBorg available at 0x36.' + Style.RESET_ALL) # self._set_feature_available('ultraborg', ultraborg_available) # # optional devices ........................................... self._log.info('configure optional features...') self._gamepad_enabled = arguments.gamepad and self._config['ros'].get( 'gamepad').get('enabled') # # the 5x5 RGB Matrix is at 0x74 for port, 0x77 for starboard # rgbmatrix5x5_stbd_available = ( 0x74 in self._addresses ) # if rgbmatrix5x5_stbd_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x74.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x74.' + Style.RESET_ALL) # self._set_feature_available('rgbmatrix5x5_stbd', rgbmatrix5x5_stbd_available) # rgbmatrix5x5_port_available = ( 0x77 in self._addresses ) # if rgbmatrix5x5_port_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x77.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x77.' + Style.RESET_ALL) # self._set_feature_available('rgbmatrix5x5_port', rgbmatrix5x5_port_available) # if rgbmatrix5x5_stbd_available or rgbmatrix5x5_port_available: # self._log.info('configure rgbmatrix...') # self._rgbmatrix = RgbMatrix(Level.INFO) # self.add_feature(self._rgbmatrix) # FIXME this is added twice # # ............................................ # # the 11x7 LED matrix is at 0x75 for starboard, 0x77 for port. The latter # # conflicts with the RGB LED matrix, so both cannot be used simultaneously. # matrix11x7_stbd_available = ( 0x75 in self._addresses ) # if matrix11x7_stbd_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) # self._set_feature_available('matrix11x7_stbd', matrix11x7_stbd_available) # # device availability ........................................ # bno055_available = ( 0x28 in self._addresses ) # if bno055_available: # self._log.info('configuring BNO055 9DoF sensor...') # self._bno055 = BNO055(self._config, self.get_message_queue(), Level.INFO) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no BNO055 orientation sensor available at 0x28.' + Style.RESET_ALL) # self._set_feature_available('bno055', bno055_available) # # NOTE: the default address for the ICM20948 is 0x68, but this conflicts with the PiJuice # icm20948_available = ( 0x69 in self._addresses ) # if icm20948_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'ICM20948 available at 0x69.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no ICM20948 available at 0x69.' + Style.RESET_ALL) # self._set_feature_available('icm20948', icm20948_available) # lsm303d_available = ( 0x1D in self._addresses ) # if lsm303d_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'LSM303D available at 0x1D.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no LSM303D available at 0x1D.' + Style.RESET_ALL) # self._set_feature_available('lsm303d', lsm303d_available) # # vl53l1x_available = ( 0x29 in self._addresses ) # if vl53l1x_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'VL53L1X available at 0x29.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no VL53L1X available at 0x29.' + Style.RESET_ALL) # self._set_feature_available('vl53l1x', vl53l1x_available) # as7262_available = ( 0x49 in self._addresses ) # if as7262_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) # self._set_feature_available('as7262', as7262_available) # pijuice_available = ( 0x68 in self._addresses ) # if pijuice_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'PiJuice hat available at 0x68.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no PiJuice hat available at 0x68.' + Style.RESET_ALL) # self._set_feature_available('pijuice', pijuice_available) self._log.info(Fore.YELLOW + 'configure subsumption support...') # configure the MessageQueue, Controller and Arbitrator self._log.info('configuring message queue...') self._queue = MessageQueue(self._message_bus, self._log.level) self._message_bus.add_handler(Message, self._queue.handle) self._log.info('configuring controller...') self._controller = Controller(self._config, self._ifs, self._motors, self._callback_shutdown, self._log.level) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(self._config, self._queue, self._controller, self._log.level) self._log.info('configured.')
def test_controller_init(self): controller = Controller(ControllerTestCase.path) self.assertEqual(ControllerTestCase.plateaubounds, (controller.x_plateau_lower, controller.y_plateau_lower, controller.x_plateau_upper, controller.y_plateau_upper))
class ROS(AbstractTask): ''' Extends AbstractTask as a Finite State Machine (FSM) basis of a Robot Operating System (ROS) or behaviour-based system (BBS), including spawning the various tasks and an Arbitrator as separate threads, inter-communicating over a common message queue. This establishes the basic subsumption foundation of a MessageBus, a MessageFactory, a system Clock, an Arbitrator and a Controller. The MessageBus receives Event-containing messages from sensors and other message sources, which are passed on to the Arbitrator, whose job it is to determine the highest priority action to execute for that task cycle, by passing it on to the Controller. There is also a rosd linux daemon, which can be used to start, enable and disable ros. :param mutex: the optional logging mutex, passed on from rosd ''' # .......................................................................... def __init__(self, mutex=None, level=Level.INFO): ''' This initialises the ROS and calls the YAML configurer. ''' self._mutex = mutex if mutex is not None else threading.Lock() super().__init__("ros", None, self._mutex) self._log.info('setting process as high priority...') # set ROS as high priority proc = psutil.Process(os.getpid()) proc.nice(10) self._config = None self._active = False self._closing = False self._disable_leds = False self._arbitrator = None self._controller = None self._gamepad = None self._motors = None self._ifs = None self._features = [] self._log.info('initialised.') # .......................................................................... def configure(self, arguments): ''' Provided with a set of configuration arguments, configures ROS based on both KD01/KR01 standard hardware as well as optional features, the latter based on devices showing up (by address) on the I²C bus. Optional devices are only enabled at startup time via registration of their feature availability. ''' self._log.heading('configuration', 'configuring ros...', '[1/2]' if arguments.start else '[1/1]') self._log.info('application log level: {}'.format( self._log.level.name)) # configuration from command line arguments self._using_mocks = False self._permit_mocks = arguments.mock self._enable_camera = arguments.camera # TODO # read YAML configuration _loader = ConfigLoader(self._log.level) _config_file = arguments.config_file if arguments.config_file is not None else 'config.yaml' self._config = _loader.configure(_config_file) # scan I2C bus self._log.info('scanning I²C address bus...') scanner = I2CScanner(self._log.level) self._addresses = scanner.get_int_addresses() _hex_addresses = scanner.get_hex_addresses() self._addrDict = dict( list(map(lambda x, y: (x, y), self._addresses, _hex_addresses))) # for i in range(len(self._addresses)): for _address in self._addresses: _device_name = self.get_device_for_address(_address) self._log.info('found device at I²C address 0x{:02X}: {}'.format( _address, _device_name) + Style.RESET_ALL) # TODO look up address and make assumption about what the device is # establish basic subsumption components self._log.info('configure application messaging...') self._message_factory = MessageFactory(self._log.level) self._message_bus = MessageBus(self._log.level) self._log.info('configuring system clock...') self._clock = Clock(self._config, self._message_bus, self._message_factory, Level.WARN) self.add_feature(self._clock) # standard devices ........................................... self._log.info('configure default features...') self._log.info('configure CPU temperature check...') _temperature_check = Temperature(self._config, self._clock, self._log.level) if _temperature_check.get_cpu_temperature() > 0: self.add_feature(_temperature_check) else: self._log.warning('no support for CPU temperature.') motors_enabled = not arguments.no_motors and (0x15 in self._addresses) if motors_enabled: # then configure motors self._log.debug(Fore.CYAN + Style.BRIGHT + '-- ThunderBorg available at 0x15' + Style.RESET_ALL) _motor_configurer = MotorConfigurer(self._config, self._clock, self._log.level) self._motors = _motor_configurer.get_motors() self.add_feature(self._motors) self._set_feature_available('motors', motors_enabled) elif self._permit_mocks: self._using_mocks = True self._log.debug(Fore.RED + Style.BRIGHT + '-- no ThunderBorg available, using mocks.' + Style.RESET_ALL) from mock.motor_configurer import MockMotorConfigurer _motor_configurer = MockMotorConfigurer(self._config, self._clock, self._log.level) self._motors = _motor_configurer.get_motors() self.add_feature(self._motors) self._set_feature_available('motors', motors_enabled) ifs_available = (0x0E in self._addresses) if ifs_available: self._log.info('configuring integrated front sensor...') self._ifs = IntegratedFrontSensor(self._config, self._clock, self._log.level) self.add_feature(self._ifs) elif self._permit_mocks: self._using_mocks = True self._log.info( 'integrated front sensor not available; loading mock sensor.') from mock.ifs import MockIntegratedFrontSensor self._ifs = MockIntegratedFrontSensor(self._message_bus, exit_on_complete=False, level=self._log.level) self._message_bus.set_ifs(self._ifs) self.add_feature(self._ifs) else: self._ifs = None self._log.warning('no integrated front sensor available.') # ultraborg_available = ( 0x36 in self._addresses ) # if ultraborg_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- UltraBorg available at 0x36.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no UltraBorg available at 0x36.' + Style.RESET_ALL) # self._set_feature_available('ultraborg', ultraborg_available) # # optional devices ........................................... self._log.info('configure optional features...') self._gamepad_enabled = arguments.gamepad and self._config['ros'].get( 'gamepad').get('enabled') # # the 5x5 RGB Matrix is at 0x74 for port, 0x77 for starboard # rgbmatrix5x5_stbd_available = ( 0x74 in self._addresses ) # if rgbmatrix5x5_stbd_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x74.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x74.' + Style.RESET_ALL) # self._set_feature_available('rgbmatrix5x5_stbd', rgbmatrix5x5_stbd_available) # rgbmatrix5x5_port_available = ( 0x77 in self._addresses ) # if rgbmatrix5x5_port_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- RGB Matrix available at 0x77.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no RGB Matrix available at 0x77.' + Style.RESET_ALL) # self._set_feature_available('rgbmatrix5x5_port', rgbmatrix5x5_port_available) # if rgbmatrix5x5_stbd_available or rgbmatrix5x5_port_available: # self._log.info('configure rgbmatrix...') # self._rgbmatrix = RgbMatrix(Level.INFO) # self.add_feature(self._rgbmatrix) # FIXME this is added twice # # ............................................ # # the 11x7 LED matrix is at 0x75 for starboard, 0x77 for port. The latter # # conflicts with the RGB LED matrix, so both cannot be used simultaneously. # matrix11x7_stbd_available = ( 0x75 in self._addresses ) # if matrix11x7_stbd_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no 11x7 Matrix LEDs available at 0x75.' + Style.RESET_ALL) # self._set_feature_available('matrix11x7_stbd', matrix11x7_stbd_available) # # device availability ........................................ # bno055_available = ( 0x28 in self._addresses ) # if bno055_available: # self._log.info('configuring BNO055 9DoF sensor...') # self._bno055 = BNO055(self._config, self.get_message_queue(), Level.INFO) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no BNO055 orientation sensor available at 0x28.' + Style.RESET_ALL) # self._set_feature_available('bno055', bno055_available) # # NOTE: the default address for the ICM20948 is 0x68, but this conflicts with the PiJuice # icm20948_available = ( 0x69 in self._addresses ) # if icm20948_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'ICM20948 available at 0x69.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no ICM20948 available at 0x69.' + Style.RESET_ALL) # self._set_feature_available('icm20948', icm20948_available) # lsm303d_available = ( 0x1D in self._addresses ) # if lsm303d_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'LSM303D available at 0x1D.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no LSM303D available at 0x1D.' + Style.RESET_ALL) # self._set_feature_available('lsm303d', lsm303d_available) # # vl53l1x_available = ( 0x29 in self._addresses ) # if vl53l1x_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'VL53L1X available at 0x29.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no VL53L1X available at 0x29.' + Style.RESET_ALL) # self._set_feature_available('vl53l1x', vl53l1x_available) # as7262_available = ( 0x49 in self._addresses ) # if as7262_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + '-- AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + '-- no AS7262 Spectrometer available at 0x49.' + Style.RESET_ALL) # self._set_feature_available('as7262', as7262_available) # pijuice_available = ( 0x68 in self._addresses ) # if pijuice_available: # self._log.debug(Fore.CYAN + Style.BRIGHT + 'PiJuice hat available at 0x68.' + Style.RESET_ALL) # else: # self._log.debug(Fore.RED + Style.BRIGHT + 'no PiJuice hat available at 0x68.' + Style.RESET_ALL) # self._set_feature_available('pijuice', pijuice_available) self._log.info(Fore.YELLOW + 'configure subsumption support...') # configure the MessageQueue, Controller and Arbitrator self._log.info('configuring message queue...') self._queue = MessageQueue(self._message_bus, self._log.level) self._message_bus.add_handler(Message, self._queue.handle) self._log.info('configuring controller...') self._controller = Controller(self._config, self._ifs, self._motors, self._callback_shutdown, self._log.level) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(self._config, self._queue, self._controller, self._log.level) self._log.info('configured.') # .......................................................................... def _set_feature_available(self, name, value): ''' Sets a feature's availability to the boolean value. ''' self._log.debug(Fore.BLUE + Style.BRIGHT + '-- set feature available. name: \'{}\' value: \'{}\'.' .format(name, value)) self.set_property('features', name, value) # .......................................................................... def get_device_for_address(self, address): if address == 0x0E: return 'RGB Potentiometer' elif address == 0x0F: return 'RGB Encoder' # default, moved to 0x16 elif address == 0x15: return 'ThunderBorg' elif address == 0x16: return 'RGB Encoder' elif address == 0x18: return 'IO Expander' elif address == 0x48: return 'ADS1015' elif address == 0x4A: return 'Unknown' elif address == 0x74: return '5x5 RGB Matrix' elif address == 0x77: return '5x5 RGB Matrix (or 11x7 LED Matrix)' else: return 'Unknown' # .......................................................................... @property def controller(self): return self._controller # .......................................................................... @property def configuration(self): return self._config # .......................................................................... def get_property(self, section, property_name): ''' Return the value of the named property of the application configuration, provided its section and property name. ''' return self._config[section].get(property_name) # .......................................................................... def set_property(self, section, property_name, property_value): ''' Set the value of the named property of the application configuration, provided its section, property name and value. ''' self._log.debug(Fore.GREEN + 'set config on section \'{}\' for property key: \'{}\' to value: {}.'.format(\ section, property_name, property_value)) if section == 'ros': self._config[section].update(property_name=property_value) else: _ros = self._config['ros'] _ros[section].update(property_name=property_value) # .......................................................................... def _set_pi_leds(self, enable): ''' Enables or disables the Raspberry Pi's board LEDs. ''' sudo_name = self.get_property('pi', 'sudo_name') # led_0_path: '/sys/class/leds/led0/brightness' _led_0_path = self._config['pi'].get('led_0_path') _led_0 = Path(_led_0_path) # led_1_path: '/sys/class/leds/led1/brightness' _led_1_path = self._config['pi'].get('led_1_path') _led_1 = Path(_led_1_path) if _led_0.is_file() and _led_0.is_file(): if enable: self._log.info('re-enabling LEDs...') os.system('echo 1 | {} tee {}'.format(sudo_name, _led_0_path)) os.system('echo 1 | {} tee {}'.format(sudo_name, _led_1_path)) else: self._log.debug('disabling LEDs...') os.system('echo 0 | {} tee {}'.format(sudo_name, _led_0_path)) os.system('echo 0 | {} tee {}'.format(sudo_name, _led_1_path)) else: self._log.warning( 'could not change state of LEDs: does not appear to be a Raspberry Pi.' ) # .......................................................................... def _connect_gamepad(self): if not self._gamepad_enabled: self._log.info('gamepad disabled.') return if self._gamepad is None: self._log.info('creating gamepad...') try: self._gamepad = Gamepad(self._config, self._queue, Level.INFO) except GamepadConnectException as e: self._log.error('unable to connect to gamepad: {}'.format(e)) self._gamepad = None self._gamepad_enabled = False self._log.info('gamepad unavailable.') return if self._gamepad is not None: self._log.info('enabling gamepad...') self._gamepad.enable() _count = 0 while not self._gamepad.has_connection(): _count += 1 if _count == 1: self._log.info('connecting to gamepad...') else: self._log.info( 'gamepad not connected; re-trying... [{:d}]'.format( _count)) self._gamepad.connect() time.sleep(0.5) if self._gamepad.has_connection() or _count > 5: break # .......................................................................... def has_connected_gamepad(self): return self._gamepad is not None and self._gamepad.has_connection() # .......................................................................... def get_arbitrator(self): return self._arbitrator # .......................................................................... def add_feature(self, feature): ''' Add the feature to the list of features. Features must have an enable() method. ''' self._features.append(feature) self._log.info('added feature {}.'.format(feature.name())) # .......................................................................... def _callback_shutdown(self): _enable_self_shutdown = self._config['ros'].get('enable_self_shutdown') if _enable_self_shutdown: self._log.critical('callback: shutting down os...') self.close() sys.exit(0) else: self._log.critical('self-shutdown disabled.') # .......................................................................... def _print_banner(self): ''' Display banner on console. ''' self._log.info('…') self._log.info('… █▒▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ ') self._log.info('… █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ ') self._log.info('… █▒▒▒▒▒▒ █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒ ') self._log.info('… █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ ') self._log.info('… █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ ') self._log.info('…') # .......................................................................... def run(self): ''' This first disables the Pi's status LEDs, establishes the message queue arbitrator, the controller, enables the set of features, then starts the main OS loop. ''' super(AbstractTask, self).run() loop_count = 0 self._print_banner() self._disable_leds = self._config['pi'].get('disable_leds') if self._disable_leds: # disable Pi LEDs since they may be distracting self._set_pi_leds(False) _main_loop_freq_hz = self._config['ros'].get('main_loop_freq_hz') self._main_loop_rate = Rate(_main_loop_freq_hz) # __enable_player = self._config['ros'].get('enable_player') # if __enable_player: # self._log.info('configuring sound player...') # self._player = Player(Level.INFO) # else: # self._player = None # i2c_slave_address = config['ros'].get('i2c_master').get('device_id') # i2c hex address of I2C slave device # vl53l1x_available = True # self.get_property('features', 'vl53l1x') # ultraborg_available = True # self.get_property('features', 'ultraborg') # if vl53l1x_available and ultraborg_available: # self._log.critical('starting scanner tool...') # self._lidar = Lidar(self._config, Level.INFO) # self._lidar.enable() # else: # self._log.critical('lidar scanner tool does not have necessary dependencies.') # wait to stabilise features? # _flask_enabled = self._config['flask'].get('enabled') # if _flask_enabled: # self._log.info('starting flask web server...') # self.configure_web_server() # else: # self._log.info('not starting flask web server (suppressed from command line).') # bluetooth gamepad controller # if self._gamepad_enabled: # self._connect_gamepad() # _wait_for_button_press = self._config['ros'].get('wait_for_button_press') # self._controller.set_standby(_wait_for_button_press) # begin main loop .............................. # self._log.info('enabling bno055 sensor...') # self._bno055.enable() # self._bumpers.enable() # self._indicator = Indicator(Level.INFO) # add indicator as message listener # self._queue.add_listener(self._indicator) # self._log.info(Fore.MAGENTA + 'enabling integrated front sensor...') # self._ifs.enable() # self._log.info('starting info thread...') # self._info.start() # self._log.info('starting blinky thread...') # self._rgbmatrix.enable(DisplayType.RANDOM) self._log.info('enabling features...') for feature in self._features: self._log.info('enabling feature {}...'.format(feature.name())) feature.enable() self._log.notice('Press Ctrl-C to exit.') self._log.info('begin main os loop.\r') # enable arbitrator tasks (normal functioning of robot) # self._arbitrator.start() _main_loop_counter = itertools.count() self._active = True while self._active: # the timing of this loop is inconsequential; it exists solely as a keep-alive. self._log.debug('[{:d}] main loop...'.format( next(_main_loop_counter))) self._main_loop_rate.wait() if not self._closing: self._log.warning('closing following loop...') self.close() # end main ................................... # .......................................................................... def emergency_stop(self): ''' Stop immediately, something has hit the top feelers. ''' self._motors.stop() self._log.info(Fore.RED + Style.BRIGHT + 'emergency stop: contact on upper feelers.') # .......................................................................... def send_message(self, message): ''' Send the Message into the MessageQueue. ''' # self._queue.add(message) raise Exception('unsupported') # .......................................................................... def enable(self): super(AbstractTask, self).enable() # .......................................................................... def disable(self): super(AbstractTask, self).disable() # .......................................................................... def close(self): ''' This sets the ROS back to normal following a session. ''' if self._closing: # this also gets called by the arbitrator so we ignore that self._log.info('already closing.') return else: self._active = False self._closing = True self._log.info(Style.BRIGHT + 'closing...') if self._gamepad: self._gamepad.close() if self._motors: self._motors.close() if self._ifs: self._ifs.close() # close features for feature in self._features: self._log.info('closing feature {}...'.format(feature.name())) feature.close() self._log.info('finished closing features.') if self._arbitrator: self._arbitrator.disable() self._arbitrator.close() # self._arbitrator.join(timeout=1.0) if self._controller: self._controller.disable() super().close() if self._disable_leds: # restore LEDs self._set_pi_leds(True) # GPIO.cleanup() # self._log.info('joining main thread...') # self.join(timeout=0.5) self._log.info('os closed.') sys.stderr = DevNull() sys.exit(0)
def main(): """ Prepara las ventanas, define modelos, controlador y vista y corre el programa. :return: void """ # Se obtiene el checksum del juego checksum = [ path_checksum('lib', VERBOSE), '8e1fd1c03d2bfe89d7dbdab8b0c4c69a'.upper(), path_checksum('bin', VERBOSE) ] # Se cargan las configuraciones control_config = Configloader(DIR_CONFIG + 'control.ini', verbose=VERBOSE) game_config = Configloader(DIR_CONFIG + 'game.ini', verbose=VERBOSE) map_config = Configloader(DIR_CONFIG + 'map.ini', verbose=VERBOSE) score_config = Configloader(DIR_CONFIG + 'scoreboard.ini', verbose=VERBOSE) user_config = Configloader(DIR_CONFIG + 'user.ini', verbose=VERBOSE) view_config = Configloader(DIR_CONFIG + 'view.ini', verbose=VERBOSE) window_config = Configloader(DIR_CONFIG + 'window.ini', verbose=VERBOSE) world_config = Configloader(DIR_CONFIG + 'world.ini', verbose=VERBOSE) # Se carga el idioma lang = langs.Langloader(game_config.getValue('LANG')) # Se carga la información de la pantalla del cliente display_info = pygame.display.Info() # Se comprueba que el nombre de jugador no sea Player, si no es valido se pide uno nuevo if not username.validate(user_config.getValue('NAME')): new_name = username.request(lang.get(111), lang.get(112)) if new_name is not username.NO_VALID_NAME: user_config.setParameter('NAME', new_name) user_config.export() else: utils.destroy_process() # Creación de ventana window = Window(window_config, lang.get(10), pygame.image.load(getIcons('icon')), display_info) clock = pygame.time.Clock() # Reloj fps = int(game_config.getValue('FPS')) # FPS a dibujar # Se crea el mundo world = World(world_config, map_config, window, checksum, score_config, user_config, lang, game_config, verbose=VERBOSE) # world.load_map(1) # Se crean los menús de inicio y pause menus = Createuimenu(lang, window, world, game_config, user_config, view_config, window_config, world_config, map_config) # Se crea la vista vista = View(window, clock, world, lang, view_config, menus) menus.addView(vista) # Se crea el controlador control = Controller(world, clock, lang, control_config, window, menus, verbose=VERBOSE) menus.addController(control) vista.add_controller(control) # Se lanza el mainloop while True: clock.tick(fps) vista.draw(control.event_loop())
def main(): app = Controller() app.run_app()
def main(): app = Flask(__name__) controller = Controller(config.controller['leds'], config.controller['neopixel_gpio_pin'], config.controller['neopixel_frequency'], config.controller['neopixel_dma'], config.controller['neopixel_invert'], config.controller['neopixel_brightness'], config.controller['neopixel_channel'], config.controller['neopixel_strip']) db = TinyDB('data/database.json') query = Query() app.config['SECRET_KEY'] = os.urandom(24) CSRFProtect(app) main.color = Color(0, 0, 0) main.brightness = 255 main.state = False main.effects = [] @app.before_first_request def init(): if db.search(query.color != ''): result = db.get(query.color != '')['color'].split(',') main.color = Color(int(result[0]), int(result[1]), int(result[2])) if db.search(query.brightness != ''): result = db.get(query.brightness != '') main.brightness = result['brightness'] if db.search(query.state != ''): result = db.get(query.state != '') main.state = bool(result['state']) if main.state: controller.color(main.color) controller.brightness(main.brightness) main.effects = controller.effects() @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': data = request.form main.color = Color(int(data['red']), int(data['green']), int(data['blue'])) main.brightness = int(data['brightness']) controller.brightness(main.brightness) if data['submit'] == 'apply': main.state = True controller.clear() controller.color(main.color) controller.brightness(main.brightness) elif data['submit'] == 'effect': main.state = True controller.clear() controller.brightness(main.brightness) if data['effect'] in main.effects: controller.start_effect( data['effect'], Color(int(data['red']), int(data['green']), int(data['blue']))) elif data['submit'] == 'off': main.state = False controller.clear() if main.state: db.update({'color': main.color.__str__()}, query.color != '') db.update({'brightness': main.brightness}, query.brightness != '') db.update({'state': main.state}, query.state != '') return redirect(url_for('index')) return render_template('index.html', effects=main.effects, color=main.color, brightness=main.brightness) @app.route('/api/v1.0/state/<string:state>', methods=['GET']) def state(state): if not state: abort(400) main.state = True if state == 'true' else False db.update({'state': main.state}, query.state != '') controller.clear() if main.state: controller.color(main.color) controller.brightness(main.brightness) return jsonify({'state': main.state}), 201 @app.route('/api/v1.0/color/<int:red>/<int:green>/<int:blue>', methods=['GET']) def color(red, green, blue): if not red or not green or not blue: abort(400) main.state = True main.color = Color(int(red), int(green), int(blue)) controller.color(main.color) db.update({'color': main.color.__str__()}, query.color != '') return jsonify({'color': main.color.__str__()}), 201 @app.route('/api/v1.0/brightness/<int:brightness>', methods=['GET']) def brightness(brightness): if not brightness: abort(400) main.state = True main.brightness = int(brightness) controller.brightness(main.brightness) db.update({'brightness': main.brightness}, query.brightness != '') return jsonify({'brightness': main.brightness}), 201 app.run(host='0.0.0.0', port=5000) db.close() atexit.register(controller.__exit__)
def run(self): ''' This first disables the Pi's status LEDs, establishes the message queue arbitrator, the controller, enables the set of features, then starts the main OS loop. ''' super(AbstractTask, self).run() loop_count = 0 # display banner! _banner = '\n' \ 'ros\n' \ 'ros █▒▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ \n' \ + 'ros █▒▒▒▒▒▒ █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒ █▒▒ █▒▒ \n' \ + 'ros █▒▒ █▒▒ █▒▒▒▒▒▒ █▒▒▒▒▒▒ █▒▒ \n' \ + 'ros\n' self._log.info(_banner) self._disable_leds = self._config['pi'].get('disable_leds') if self._disable_leds: # disable Pi LEDs since they may be distracting self._set_pi_leds(False) self._log.info('enabling features...') for feature in self._features: self._log.info('enabling feature {}...'.format(feature.name())) feature.enable() # __enable_player = self._config['ros'].get('enable_player') # if __enable_player: # self._log.info('configuring sound player...') # self._player = Player(Level.INFO) # else: # self._player = None # i2c_slave_address = config['ros'].get('i2c_master').get('device_id') # i2c hex address of I2C slave device vl53l1x_available = True # self.get_property('features', 'vl53l1x') ultraborg_available = True # self.get_property('features', 'ultraborg') if vl53l1x_available and ultraborg_available: self._log.critical('starting scanner tool...') self._lidar = Lidar(self._config, Level.INFO) self._lidar.enable() else: self._log.critical( 'lidar scanner tool does not have necessary dependencies.') # wait to stabilise features? # configure the Controller and Arbitrator self._log.info('configuring controller...') self._controller = Controller(self._config, self._ifs, self._motors, self._callback_shutdown, Level.INFO) self._log.info('configuring arbitrator...') self._arbitrator = Arbitrator(self._config, self._queue, self._controller, Level.WARN) _flask_enabled = self._config['flask'].get('enabled') if _flask_enabled: self._log.info('starting flask web server...') self.configure_web_server() else: self._log.info( 'not starting flask web server (suppressed from command line).' ) # bluetooth gamepad controller if self._gamepad_enabled: self._connect_gamepad() self._log.warning('Press Ctrl-C to exit.') _wait_for_button_press = self._config['ros'].get( 'wait_for_button_press') self._controller.set_standby(_wait_for_button_press) # begin main loop .............................. self._log.info('starting button thread...') self._button.start() # self._log.info('enabling bno055 sensor...') # self._bno055.enable() # self._bumpers.enable() self._indicator = Indicator(Level.INFO) # add indicator as message consumer self._queue.add_consumer(self._indicator) self._log.info(Fore.MAGENTA + 'enabling integrated front sensor...') self._ifs.enable() # self._log.info('starting info thread...') # self._info.start() # self._log.info('starting blinky thread...') # self._rgbmatrix.enable(DisplayType.RANDOM) # enable arbitrator tasks (normal functioning of robot) main_loop_delay_ms = self._config['ros'].get('main_loop_delay_ms') self._log.info( 'begin main os loop with {:d}ms delay.'.format(main_loop_delay_ms)) _loop_delay_sec = main_loop_delay_ms / 1000 _main_loop_count = 0 self._arbitrator.start() self._active = True while self._active: # The sensors and the flask service sends messages to the message queue, # which forwards those messages on to the arbitrator, which chooses the # highest priority message to send on to the controller. So the timing # of this loop is inconsequential; it exists solely as a keep-alive. _main_loop_count += 1 self._log.debug(Fore.BLACK + Style.DIM + '[{:d}] main loop...'.format(_main_loop_count)) time.sleep(_loop_delay_sec) # end application loop ......................... if not self._closing: self._log.warning('closing following loop...') self.close()