SOAR: Controlando o WorldServer3D
DemoSOAR
O DemoSOAR é um programa que implementa uma mente artificial para um agente controlar o robô do ambiente WorldServer3D. Essa mente artificial opera segundo as regras escritas num programa SOAR. O programa SOAR que será usado para controlar a criatura artificial está escrito no arquivo soar-rules.soar. Antes de detalhar o funcionamento desse programa, será necessário entender algumas características necessárias para realizar a comunicação entre a mente do agente (programa SOAR) e o ambiente de simulação do WorldServer3D. Dois pontos importantes são: o gerenciamento do código JNI para diferentes versões do sistema operacional, e, o interfaceamento entre o WorldServer3D e o SOAR.
Gerenciamento do Código JNI
A classe SimulationSOAR.java, disponível no código fonte do DemoSOAR, possui o método main() responsável por rodar a mente da criatura artificial. No entanto, antes de criar o agente SOAR, é preciso carregar os arquivos responsáveis por gerar a lógica de funcionamento da arquitetura SOAR; ou seja, é preciso carregar a biblioteca do SOAR. Apesar do SOAR ter sido escrito usando a linguagem Java, a arquitetura do SOAR está disponibilizada em diferentes versões de acordo com o sistema operacional usado pelo usuário programador. Isso gera um problema de ser necessário criar um aplicativo (programa com a mente do agente) que possa rodar em qualquer sistema operacional usado pelo usuário cliente.
Esse é o problema do gerenciamento do código JNI que deve ser solucionado. O DemoSOAR, escrito em Java, resolve esse problema por meio do uso da classe NativeUtils.java. A figura a seguir ilustra esse procedimento:
A figura acima exibe a tela do NetBeans com parte do método main() da classe SimulationSOAR. A parte esquerda da figura exibe os diferentes pacotes com os arquivos das bibliotecas SOAR disponibilizados para cada versão de sistema operacional. Basicamente, a classe SimulationSOAR realiza uma verificação do sistema operacional usado pelo usuário e carrega os arquivos adequados para cada versão do sistema operacional. Isso é realizado por meio do uso de métodos disponibilizados pela classe NativeUtils.java. As linhas de código abaixo ilustram as etapas finais desse procedimento:
NativeUtils.loadFileFromJar("/soar-rules.soar");
String soarRulesPath = "soar-rules.soar";
String soarDebuggerPath = "";
Integer soarDebuggerPort = 12121;
Um método da classe NativeUtils carrega o arquivo, soar-rules.soar, que contém as regras para controlar o agente SOAR responsável pela mente da criatura artificial. Também há instruções para permitir o uso do aplicativo SOARDebugger para visualizar a operação do agente SOAR.
Interfaceamento entre WorldServer3D e SOAR
A próxima etapa do método main() da classe SimulationSOAR é criar um novo objeto da classe SimulationTask.java e chamar seu método runSimulation() que executará todas as tarefas responsáveis por gerar a simulação do programa DemoSOAR. É nessa classe, SimulationTask, que são criados o agente (Creature) e o mundo do agente (World). Outros dois objetos importantes também são criados nessa classe: SoarBridge (discutido a seguir) e WS3DProxy. O WS3DProxy é uma biblioteca responsável por efetuar a conexão do programa DemoSOAR com o ambiente do WorldServer3D. Essa biblioteca também envia e recebe comandos entre o agente (SOAR) e o seu mundo (ambiente do WorldServer3D).
Analisando a classe SimulationTask, observa-se que a mesma se utiliza de métodos disponibilizados pela biblioteca WS3DProxy. Uma classe muito utilizada dessa biblioteca é a classe CommandUtility.java. Essa classe possui os métodos responsáveis por gerar as mensagens (comandos) enviadas para o WorldServer3D, gerando a troca de informações entre o agente SOAR e o ambiente de simulação do WorldServer3D. Alguns métodos da biblioteca WS3DProxy, usados pela classe SimulationTask, são responsáveis por mover (MOVE) o agente, pegar uma jóia (GET) ou pegar comida (EAT). As jóias e "comidas" que surgem no ambiente de simulação também são geradas por métodos da biblioteca WS3DProxy.
A classe SoarBridge.java também é usada pela classe SimulationTask. Essa classe é responsável por enviar as informações sensoriais do ambiente do WorldServer3D para o agente SOAR. Da mesma forma, essa classe envia os comandos gerados pelo agente SOAR para o ambiente do agente. Um método importante da classe SoarBridge é o método setupStackHolder(). Esse método cria alguns dos WME's usados pelo programa SOAR, além de preenchê-los com as informações fornecidas pelos métodos da classe SimulationRobot.java que comunica-se com o agente (Creature) criado. Outro método da classe SoarBridge, o método getReceivedCommands(), é responsável pelo tratamento e geração dos comandos que serão enviados para o agente criado.
Programa DemoSOAR
A lógica de funcionamento do programa de simulação de uma mente artificial gerenciada pelo SOAR está contida no arquivo soar-rules.soar. Esse arquivo contém as regras que vão gerar o comportamento da criatura artificial. O operador wander faz o agente (robô do ambiente WorldServer3D) girar, movendo seus sensores (câmera) pelo ambiente à procura de objetos no campo visual do robô. Ao detectar algum objeto (jóia ou comida) no campo visual do agente, serão propostos operadores (seeEntityWithoutMemoryCount e seeEntityWithMemoryCount) para memorizar os objetos (JEWEL ou FOOD) captados pela câmera do robô. Os objetos memorizados são armazenados no WME ^MEMORY na forma de novas entidades (^ENTITY) criadas nesse elemento. A partir das entidades armazenadas na memória do agente, serão propostos operadores para mover o robô até os objetos detectados pela câmera e memorizados.
O operador moveFood move o robô na direção de um objeto FOOD (comida) e o operador moveJewel move o robô até uma jóia (JEWEL) detectada pela câmera do robô e memorizada pelo agente SOAR. Quando o robô se aproxima de algum objeto, JEWEL ou FOOD, são propostos operadores para coletar tais objetos. O operador eatFood coleta comida, enquanto o operador getJewel coleta as jóias próximas ao robô. Caso haja dois operadores propostos, um que coleta comida e outro para coletar uma jóia, o operador getJewel terá preferência sobre o operador eatFood proposto.
O comportamento da criatura artificial, robô do ambiente WorldServer3D, consiste basicamente em coletar jóias e/ou comida espalhada pelo ambiente da criatura, conforme ilustrado na figura abaixo. Uma melhoria desse comportamento será proposta para fazer o robô coletar apenas alguns tipos específicos (cores) de jóias e apenas uma certa quantidade delas. Essas informações serão disponibilizadas pelo "leaflet" do robô do ambiente WorldServer3D.