Skip to content

conceitos o que e um coach

Eduardo Makita edited this page Jul 21, 2023 · 2 revisions

Um coach é um módulo especial no NeonFC. O coach é tratado no sistema como uma entidade.

Um coach é instanciado no objeto match (ver def start). Durante a sua inicialização, ele verifica pela chave match.coach_name para instanciar a classe certa. Para isso, é necessario adicionar a relação chave/valor na variável AVAILABLE_COACHES, dentro de entities/coach/__init__.py.

O coach é executado durante toda iteração do loop principal, no update do match. Ele é encarregado por escolher qual comportamento (estratégia) cada um dos robôs da equipe vai seguir. Existem 3 maneiras que normalmente usamos para fazer isso: estático, cada estratégia é passada sempre para o mesmo robô; dinâmico, o coach escolhe qual estratégia cada robô seguirá, baseado na função das suas posições; ou ainda o coach playbook, do qual mais informações podem ser encontradas aqui.

Uma instância de Coach precisa ter apenas dois métodos:

  • __init__ (construtor): No método construtor, deverá ser passada a referência da match. Aqui, você poderá instanciar as estratégias contidas no seu coach, assim como objetos auxiliares para a tomada de decisão.

  • decide: Esse método deverá atribuir para cada robô uma nova estratégia. É importante que após a execução desse método cada robô tenha uma estratégia válida, caso contrário o NeonFC irá quebrar.

Exemplo 1: Atribuidor simples

Nesse exmplo, usamos as estratégias da LARC 2020 de forma que, sempre os robôs de id 0, 1 e 2 recebem as estratégias Goalkeeper, Attacker e Midfielder consecutivamente.

import algorithms
import strategy
import math
from commons.math import angular_speed, speed, rotate_via_numpy, unit_vector

class Coach(object):
    def __init__(self, match):
        self.match = match
        self.constraints = [
            strategy.larc2020.GoalKeeper(self.match),
            strategy.larc2020.Attacker(self.match),
            strategy.larc2020.MidFielder(self.match)
        ]
    
    def decide (self):
        robots = [r.robot_id for r in self.match.robots]
        for robot_id in robots:
            self.match.robots[robot_id].strategy = self.constraints[robot_id]

Nesse caso, nada é necessário além de uma simples iteração, sabemos através da criação da lista match.robots que ela sempre será ordenada. Então a atribuição funcionará sempre.

Exemplo 2: larc2020.py

Esse exemplo é o coach utilizado pela equipe Project Neon na LARC 2020.

import algorithms
import strategy
import math
from commons.math import angular_speed, speed, rotate_via_numpy, unit_vector

class Coach(object):
    def __init__(self, match):
        self.match = match
        self.constraints = [
            #estratégia - função eleitora - prioridade
            (strategy.larc2020.GoalKeeper(self.match), self.elect_goalkeeper, 0),
            (strategy.larc2020.Attacker(self.match), self.elect_attacker, 0),
            (strategy.larc2020.MidFielder(self.match), self.elect_midfielder, 0)
        ]
    
    def decide (self):
        robots = [r.robot_id for r in self.match.robots]
        for strategy, fit_fuction, priority in self.constraints:
            elected = -1
            best_fit = -99999
            for robot_id in robots:
                robot_fit = fit_fuction(self.match.robots[robot_id])
                if (robot_fit > best_fit):
                    best_fit = robot_fit
                    elected = robot_id
            if self.match.robots[elected].strategy is None:
                self.match.robots[elected].strategy = strategy
            elif self.match.robots[elected].strategy.name != strategy.name:
                self.match.robots[elected].strategy = strategy
                self.match.robots[elected].start()
            robots.remove(elected)
    
    def elect_attacker(self, robot):
        dist_to_ball = math.sqrt(
            (robot.x - self.match.ball.x)**2 + (robot.y - self.match.ball.y)**2
        )
        return 1000 - dist_to_ball

    def elect_goalkeeper(self, robot):
        dist_to_goal = math.sqrt(
            (robot.x - 0)**2 + (robot.y - 0.65)**2
        )
        return 1000 - dist_to_goal

    def elect_midfielder(self, robot):
        return 1

Assim que estiver familiarizado com a funçao do objeto coach você pode experimentar a criação através do Playbook.