예제 #1
0
def simulate(batch_file, preset_filename, bot_paths, seed, override_settings,
             *queues_sizes):
    result_queue = queues_sizes[0][0]
    result_queue._internal_size = queues_sizes[0][1]
    StateHandler.instance.shared_info = {
        "result_queue": result_queue,
    }
    send_queues = [q for q, _ in queues_sizes[1::2]]
    for i, (_, size) in enumerate(queues_sizes[1::2]):
        send_queues[i]._internal_size = size
    recv_queues = [q for q, _ in queues_sizes[2::2]]
    for i, (_, size) in enumerate(queues_sizes[2::2]):
        recv_queues[i]._internal_size = size

    Randomiser.createGlobalRandomiserWithSeed(seed)

    preset_file = find_abs(preset_filename, allowed_areas=preset_locations())
    with open(preset_file, "r") as f:
        config = yaml.safe_load(f)
    config["settings"] = config.get("settings", {})
    recursive_merge(config["settings"], override_settings)

    config["robots"] = config.get("robots", []) + bot_paths

    initialiseFromConfig(config, send_queues, recv_queues)
예제 #2
0
    def captureBotImage(self, directory, filename):
        self.resetVisualElements()
        from os.path import join
        from ev3sim.simulation.loader import ScriptLoader
        from ev3sim.robot import initialise_bot, RobotInteractor
        from ev3sim.simulation.randomisation import Randomiser

        Randomiser.createGlobalRandomiserWithSeed(0)
        ScriptLoader.instance.reset()
        ScriptLoader.instance.startUp()
        elems = {}
        initialise_bot(elems, find_abs(filename, [directory]), "", 0)
        ScriptLoader.instance.loadElements(elems.get("elements", []))
        for interactor in ScriptLoader.instance.active_scripts:
            if isinstance(interactor, RobotInteractor):
                interactor.connectDevices()
                interactor.initialiseDevices()
        for interactor in ScriptLoader.instance.active_scripts:
            interactor.startUp()
            interactor.tick(0)
            interactor.afterPhysics()
        screen = pygame.Surface((480, 480), pygame.SRCALPHA)
        custom_map = {
            "SCREEN_WIDTH": 480,
            "SCREEN_HEIGHT": 480,
            "MAP_WIDTH": 25,
            "MAP_HEIGHT": 25,
        }
        for elem in self.objects.values():
            elem.customMap = custom_map
            elem.calculatePoints()
        self.applyToScreen(screen, bg=pygame.Color(self.instance.background_colour))
        colorkey = pygame.Color(self.instance.background_colour)
        for x in range(480):
            for y in range(480):
                val = screen.get_at((x, y))
                val.a = 0 if (val.r == colorkey.r and val.g == colorkey.g and val.b == colorkey.b) else 255
                screen.set_at((x, y), val)
        self.resetVisualElements()
        ScriptLoader.instance.reset()
        config_path = join(find_abs(filename, [directory]), "config.bot")
        with open(config_path, "r") as f:
            config = yaml.safe_load(f)
        pygame.image.save(screen, join(find_abs(filename, [directory]), config.get("preview_path", "preview.png")))
예제 #3
0
def single_run(preset_filename,
               robots,
               bind_addr,
               seed,
               batch_file=None,
               override_settings={}):
    if batch_file:
        ScreenObjectManager.BATCH_FILE = batch_file
    ScreenObjectManager.PRESET_FILE = preset_filename
    import ev3sim

    try:
        latest_version = get_version_pypi("ev3sim")
        ScreenObjectManager.NEW_VERSION = latest_version != ev3sim.__version__
        if ScreenObjectManager.NEW_VERSION:
            update_message = f"""\

==========================================================================================
There is a new version of ev3sim available ({latest_version}).
Keeping an up to date version of ev3sim ensures you have the latest bugfixes and features.
Please update ev3sim by running the following command:
    python -m pip install -U ev3sim
==========================================================================================

"""
            print(update_message)
    except:
        ScreenObjectManager.NEW_VERSION = False

    Randomiser.createGlobalRandomiserWithSeed(seed)

    preset_file = find_abs(preset_filename,
                           allowed_areas=[
                               "local", "local/presets/", "package",
                               "package/presets/"
                           ])
    with open(preset_file, "r") as f:
        config = yaml.safe_load(f)

    config["robots"] = config.get("robots", []) + robots

    shared_data = {
        "tick": 0,  # Current tick.
        "write_stack":
        deque(),  # All write actions are processed through this.
        "data_queue": {},  # Simulation data for each bot.
        "active_count":
        {},  # Keeps track of which code connection each bot has.
        "bot_locks":
        {},  # Threading Locks and Conditions for each bot to wait for connection actions.
        "bot_communications_data":
        {},  # Buffers and information for all bot communications.
        "tick_updates":
        {},  # Simply a dictionary where the simulation tick will push static data, so the other methods are aware of when the simulation has exited.
        "events": {},  # Any events that should be sent to robots.
    }

    result_bucket = Queue(maxsize=1)

    from threading import Thread
    from ev3sim.simulation.communication import start_server_with_shared_data

    def run(shared_data, result):
        try:
            runFromConfig(config, shared_data)
        except Exception as e:
            result.put(("Simulation", e))
            return
        result.put(True)

    # Handle any other settings modified by the preset.
    settings = config.get("settings", {})
    settings.update(override_settings)
    for keyword, value in settings.items():
        run = mock.patch(keyword, value)(run)

    comm_thread = Thread(target=start_server_with_shared_data,
                         args=(shared_data, result_bucket, bind_addr),
                         daemon=True)
    sim_thread = Thread(target=run,
                        args=(shared_data, result_bucket),
                        daemon=True)

    comm_thread.start()
    sim_thread.start()

    try:
        with result_bucket.not_empty:
            while not result_bucket._qsize():
                result_bucket.not_empty.wait(0.1)
        r = result_bucket.get()
        # Chuck it back on the queue so that other threads know we are quitting.
        result_bucket.put(r)
        if r is not True:
            print(
                f"An error occurred in the {r[0]} thread. Raising an error now..."
            )
            time.sleep(1)
            raise r[1]
    except KeyboardInterrupt:
        pass