• Nenhum resultado encontrado

3. TRABALHOS RELACIONADOS

4.3 TESTES PRELIMINARES

Para realizar um teste mais complexo optou-se por utilizar um projeto de teste disponibilizado pela própria arquitetura JASON chamado Cleaning Robots, ou robôs de limpeza. Este projeto se faz interessante para o teste pois possui dois agentes com tarefas

bem definidas, uma interface gráfica simples tornando fácil a verificação do correto funcionamento do motor BDI. Este projeto consiste em dois agentes R1 e R2, situados em um cenário de mundo extremamente simples: um tabuleiro semelhante ao do xadrez.

Figura 8​ - INTERFACE GRÁFICA DO AMBIENTE DO PROJETO CLEANING ROBOTS

O objetivo dos agentes é fazer a “limpeza” do cenário, sendo gerado em algumas posições do tabuleiro um objeto “lixo”. Cada um dos agentes possuem papéis diferentes, sendo eles:

● R1: Deve caminhar de quadrado em quadrado do tabuleiro, buscando encontrar o lixo. Uma vez encontrado um lixo, o agente deve recolhê-lo e leva-lo até o agente R2. Após entregar o lixo, o agente R1 deve voltar para a posição em que estava antes de encontrá-lo e continuar buscando outros lixos;

● R2: Fica parado esperando o R1 entregar o lixo. Quando recebe o lixo, é responsável apenas por queimá-lo. (Observe que a ação “queimar” consiste em apenas “deletar” o objeto lixo do cenário);

Para ser possível realizar a execução do projeto ​Cleaning Robots com as modificações feitas na arquitetura foi necessário criar as classes de definições para os agentes, chamadas de ​r1.java e ​r2.java ​. Objetivando realizar um teste inicial, foi criado um atuador e um sensor simples, com implementações de métodos vazias, ou seja que não realizam nada. Executando o projeto foi possível constatar que ele inicia sem erros e como esperado o agente R1 não se mexe - já que o atuador não realiza papel algum. Na sequência foi realizada a implementação do sensor: já que o projeto ainda possui uma

classe responsável por implementar o ambiente (e por consequência possui métodos responsáveis por realizar a implementação de como é feita a captura das percepções do agente) foi optado por buscar a instância do ambiente (representado pela classe MarsEnv.java​), e realizar a chamada do mesmo no sensor. Sendo assim o método perceive() ​ficou responsável apenas por realizar a chamada do método ​getPercepts(String) do ambiente. A implementação do atuador foi feita da mesma maneira, no método ​act() buscando a instância do ambiente e chamando o método ​executeAction(Stirng,Structure).

Observa-se que neste teste a responsabilidade de implementar a captura das percepções do agente e a implementação das ações não está realmente no atuador e no sensor, já que estes ficaram responsáveis apenas por repassar a responsabilidade para o ambiente. Ou seja, o sensor e atuador apenas fazem uma “ponte” entre a arquitetura do agente e o ambiente fornecido na implementação original do cenário. O modo como foi realizada a implementação do atuador e sensor neste teste não representa a forma como este trabalho propõe-se a realizar a implementação dos mesmos. Optou-se por realizá-la desta forma com a intenção de garantir que o motor BDI continua funcionando mesmo com a utilização destes componentes.

Realizada a implementação foi executado o teste e a execução ocorreu sem problemas: ambos os agentes executaram suas funções. Visando fazer uma comparação em termos de desempenho o Cleaning Robots também foi executado na versão do JASON sem as modificações deste trabalho e nenhuma diferença significativa foi constatada no tempo de execução.

Constatada esta necessidade optou-se por realizar mais um teste em um cenário mais próximo do cenário do projeto Awareness - onde será realizado o estudo de caso deste trabalho. O ambiente do projeto Awareness é realizado utilizando a tecnologia Unity que é um framework para desenvolvimento de cenários virtuais, mais especificamente para jogos. É multi-plataforma e permite a criação de cenários 2D ou 3D e conta com uma IDE própria chamada Unity Editor para o desenvolvimento de cenários em Unity. De maneira resumida o desenvolvimento de cenários é baseado em componentes: uma pessoa é um componente, uma parede é um componente e até a câmera do próprio jogador é um componente, cada um com suas propriedades específicas. Diferentes comportamentos podem ser adicionados aos componentes através de scripts.

O cenário do Awareness é de grande complexidade, mas objetivando realizar uma simulação inicial foi utilizado um projeto mais simples no Unity desenvolvido pelo bolsista do

projeto Awareness, acadêmico Paulo Lefol, mas que em paralelo possui os requisitos necessários para realizar este teste. Consiste em um cenário 3D onde o corpo do agente se encontra em um terreno plano, e a sua volta existem “fotos” de alguns personagens de filme. Cada um desses quadros possui como propriedade um nome.

Neste cenário o objetivo do agente consiste em encontrar uma foto em seu cenário. Como os objetos estão distribuídos em volta do agente, basta que ele rotacione sua visão para os lados até que encontre uma foto. Buscando simplificar a implementação, ficou estabelecido então que o agente tem como objetivo rotacionar a sua visão para a direita até que encontre uma foto.

Antes de dar início ao desenvolvimento do projeto JASON, que implementaria o agente deste cenários, um problema foi identificado: Uma vez que o Unity é um processo separado do JASON, como realizar a comunicação entre eles? Existe um agravante neste comunicação, que é o fato de o Unity ser desenvolvido em uma linguagem diferente (C#) 8

do JASON (Java).

Com o objetivo de elencar possíveis tecnologias e ferramentas a serem utilizadas como ponte entre os dois processos foi dado inicio á um estudo e dentre as possíveis tecnologias e a que demonstrou melhor adesão às necessidades específicas deste trabalho foi a utilização de ​Socket​. O socket consiste basicamente em uma comunicação onde uma entidade atua como cliente e outra como servidor. Uma vez estabelecida uma conexão cliente-servidor ambos estão livres para trocar mensagens em uma espécie de conversa. Dentre as vantagens do socket pode-se destacar:

● Tecnologia altamente conhecida, com grande suporte em fóruns on-line; ● Suporte das principais linguagens de programação;

● Diversas APIs em diferentes linguagens para facilitar sua utilização;

● Permite que o servidor e o cliente estejam na mesma máquina, ou em máquinas diferentes;

Neste teste uma comunicação simples em socket foi implementada: o ambiente que roda em Unity irá atuar como o servidor socket e o JASON irá atuar como cliente. A comunicação é reduzida e não existe troca de dados complexos entre os participantes, apenas de números representando o tipo de requisição, e uma String representando a

8https://docs.microsoft.com/pt-br/dotnet/csharp/getting-started/introduction-to-the-csharp-language-an d-the-net-framework

possível resposta. Sendo assim, o servidor socket foi projetado para atuar da seguinte maneira:

1. Aguarda uma conexão do cliente.

2. Verificar o tipo de mensagem na conexão, podendo a mensagem ser de dois tipos: a. Requisição de visão: no caso de uma requisição de visão o ambiente deve

responder com o quê está o agente está vendo. Essa requisição é feita pelo sensor, para que ele possa gerar as percepções do agente a partir do que o agente “vê” no ambiente.

b. Requisição de ação: no caso de uma requisição de ação, o ambiente deve receber o comando de ação e executá-la em seu framework. A única ação implementada foi a “rotação” do agente, ou seja, fazer com que a visão do agente rotacione levemente para o lado.

3. Encerra a conexão.

Neste ponto foi identificado que seria necessário a implementação em unity de 3 pontos:

● Servidor socket;

● Script para identificar o que está a frente de um “objeto” (o agente é representado como um “objeto” dentro do ambiente Unity);

● Script para rotacionar a visão do agente;

O Unity tem um bom suporte a inserção de novos comportamentos a seus objetos e fluxos já existentes. Para o servidor socket foi adicionado um script que roda uma ​thread​em paralelo e é responsável por manter o servidor ativo. Para a identificação da visão do agente foi utilizado um script que é ativado sempre que um novo objeto entra no campo de visão do mesmo, então o script tem apenas de armazenar o nome do objeto como atributo, e então quando necessário o servidor socket requisita ao script este atributo. Para rotacionar o agente foi apenas necessário buscar a referência do objeto que representa o agente, e utilizar um método do próprio Unity responsável por modificar o objeto fisicamente.

Neste ponto todos os aspectos do servidor e da conexão estão implementados, sendo assim o próximo passo é a implementação do sensor, atuador e da definição .​asl do agente. O sensor foi definido em uma classe chamada ​UnitySensor e a imeplementação do seu método ​perceive() ​consiste em:

1. Iniciar a conexão ​socket

2. Enviar uma requisição de visão ao servidor

3. Verificar se existe um objeto a frente do agente (resposta não pode ser vazia) 4. Caso exista um objeto, cria um objeto do tipo ​Literal que representa a crença de que

existe um objeto a frente do agente e retorna-a como resultado do método. Esta crença é representada pela expressão ​foundSomething(r1).

Já o atuador foi chamado de ​UnityActuator ​e a implementação do seu método act(ActionExec) ​é bastante simples e consiste em:

1. Verifica se ação a ser executada é do tipo ​turnRight​ (rotacionar a visão do agente). 2. Caso afirmativo, inicia a conexão socket e envia a requisição de ação. Caso

contrário não faz nada.

Congruente com a baixa complexidade do objetivo do agente, a definição do agente consiste em:

● Definição do objetivo inicial: o agente é iniciado com o objetivo ​check.

● A definição do plano a ser executada sempre que o agente possuir o objetivo check é: verificar se existe a crença ​foundSomething(r1)​: caso afirmativo não faz nada, caso negativo executa ação ​turnRight(r1) e adiciona ​check á lista de objetivos novamente.

Feitas as implementações, foi dado início à execução do projeto que ocorreu sem apresentar erros, tanto do lado do cliente (JASON) como do lado do servidor (Unity). Porém um problema foi constatado: o agente executou a ação ​turnRight ​apenas uma vez, mesmo sem ter encontrado um objeto a frente do agente. Ou seja, o agente executou a ação uma vez e ficou congelado após a execução da mesma. Deu-se início então a uma extensiva busca do motivo da falha, que indica um problema no fluxo de operação do motor BDI. Objetivando facilitar a busca foi necessário passar a utilizar a classe ​RunCentralisedMas como ponto de partida para execução do projeto JASON, pois através dela é possível executar o framework diretamente do código, sem ser necessário a geração de um ​.jar ​e possibilitando assim que o código seja depurado através da ferramenta Eclipse, facilitando o processo de reprodução e estudo da falha. Após uma série de reproduções da falha foi identificado que o motor BDI atua de forma síncrona sobre as ações: ele dá início a execução de um ação, e não começa uma nova ação até que seja dado um sinal ao agente de que a execução terminou, informando o resultado. A responsabilidade de dar este “sinal” ao agente era do ambiente, e já que o mesmo foi completamente desacoplado da estrutura

do agente, ninguém enviava este sinal e o agente ficava aguardando-o por tempo indeterminado. E é exatamente por este motivo que este erro foi detectado apenas aqui, e não no primeiro teste preliminar: como no primeiro teste os atuadores e sensores funcionavam apenas como uma “ponte” entre o ambiente e o agente, o ambiente ainda desempenhava o papel de dar o sinal para o agente de que a ação terminou.

Sendo assim a solução para o problema foi implementada no método act(ActionExec) ​da arquitetura do agente e consiste simplesmente em realizar a chamada do método ​actionExecuted(ActionExec) ​- que é o método que era chamado pelo ambiente de forma a dar o “sinal” que a ação tinha sido executada. Após esta correção uma nova execução do teste foi realizada e o agente executou seu papel perfeitamente: do ponto de vista do ambiente o agente foi rotacionando sua visão para o lado até que encontrasse um objeto, e então terminou sua execução. Com este teste foi possível concluir que o motor BDI continua funcionando corretamente mesmo com as modificações no fluxo.

Documentos relacionados