You are here

Aula 7 - SOAR: Controlando o WorldServer3D - Atividade 1

Atividade 1

O código do WorldServer3D modificado e o DemoSOAR foram executados pelo Webstart na máquina local:

A clicar no link é feita a escolha de como o webstart será executado, a figura 1 apresente esse processo.



















Figura 1

Para executar os programas é necessário confirmar a definição de segurança conforme figura 2.



Figura2



A figura 3 o print do WorldServer3D e do DEMOsoar já conectados

Figura 3



Depois que os arquivos-fonte dos dois programas e da biblioteca WS3DProxy (lib de apoio para conectar o SOAR ao WorldServer3D) foram baixados para a máquina local o código foi compilado e executado no Netbeans.



A figura 4 demonstra o Netbeans com o código fonte dos programas apresentados acima:

WorldServer3D

DemoSOAR

WS3DProxy

Figura 4



A figura 5 ilustra a explicação a seguir.



Figura 5

A seguir foi feita leitura da classe SimulationSOAR e o método main, a primeira tarefa do programa é descobrir a pasta atual na classe NativeUtils e depois são utilizados os seguintes métodos:

System.getProperties().getProperty("os.name")
System.getProperties().getProperty("os.arch")

O primeiro método é usado para descobrir o sistema operacional que está em uso. Já o segundo comando obtém o tipo de arquitetura do computador.

Nesse teste obtivemos os seguintes valores:

OS:Linux e Arquitetura: amd64


Esses valores são armazenadas em duas variáveis: String osName e String osArch. As duas variáveis serão usadas para se obter as bibliotecas que correspondem ao sistema operacional e a respctiva arquitetura de hardware, e assim é utilizada a estrutura condicional para determinar que arquivos irão ser carregados.


No meu caso, o meu sistema operacional utilizado foi o Linux com arquitetura amd64, por conta disso serão carregados os arquivos: /linux64/libSoar.so e /linux64/libJava_sml_ClientInterface.so



Somente a partir desse ponto será carregado o arquivo /soar-rules.soar que contem as regras do Soar. Em seguida é definida a variável String soarRulesPath = "soar-rules.soar" e depois a porta para o Debugger do soar: Integer soarDebuggerPort = 12121; A figura 6 ilustra esse pedaço do código-fonte.



Figura 6

Após carregar os arquivos e inicializar algumas variáveis o programa entra no loop principal:

            //Start enviroment data
            SimulationTask simulationTask = new SimulationTask();
            simulationTask.initializeEnviroment(Boolean.FALSE);
            simulationTask.initializeCreatureAndSOAR(soarRulesPath,true,soarDebuggerPath,soarDebuggerPort);

            // Run Simulation until some criteria was reached
            Thread.sleep(3000);

            while(true)
            {
                simulationTask.runSimulation();
                Thread.sleep(100);
            }

O método runSimulation() da classe simulationTask é executado indefinidamente enquanto o programa está sendo executado.

Toda vez que é executado o método runSimulation() serão realizadas as seguintes tarefas:

  1. Atualizar o estado da criatura;

  2. Obter os objetos “vistos” pela criatura;

  3. As informações: posição, pitch e outras, da criatura e os objetos que ela capta pelos sensores são traduzidos na linguagem do SOAR criando Working Memory Elements (WME)

  4. Assim será enviada essa estrutura de informação gerada para o SOAR. No SOAR serão executadas as regras do arquivo soar-rules.soar e a patir daí será obtida uma resposta, em forma de comando de saída que será enviada novamente ao programa cliente.

  5. O programa cliente recebe a saída do SOAR e processa a informação executando os comandos de resposta do SOAR na criatura, este processo de executar os comandos muda o estado atual da criatura e o processa começa de novo.

Em suma, a criatura obtêm informação da sua localização e dos objetos que ela consegue ver, organiza as informações em uma estrutura de dados que o SOAR consegue entender e são enviados para seu processamento.

No SOAR as regras do arquivo soar-rules.soar são executadas, sempre será escolhido um operador e a regra de aplicação desse operador, os comandos serão criados no elemento output-link do estado. Após a seleção dos comandos a serem enviados ao cliente, o programa cliente recebe os comandos de saída, provenientes do SOAR, e executa as ações modificando o estado da criatura.


Método usado para preparar a informação a ser enviada ao SOAR:

prepareAndSetupCreatureToSimulation()


Nesse passo é criado o sensor visual e o sensor de constituível.

Após obter do objeto simulationCreature os sensores disponíveis.

Após isso será chamado o método setupStackHolder() da classe soarBridge que é o incubido de criar a estrutura de dados para o SOAR a partir da informação da criatura e os arredores.

No método setupStackHolder() é verificado se o tipo de entidade é uma criatura e se for gera a seguinte estrutura de Working Memory Elements, a figura 7 ilustra esses elementos.




Figura 7

Podemos concluir que existem tantos valores “ENTITY” quantos elementos que possam ser vistos pela criatura.


Uma lista dos sensores disponíveis pode ser obtida a partir de seguinte função:

creatureParameter.getSensorsEnabled()


A posição da criatura pode ser obtida a partir das duas funções a seguir:

creatureParameter.getPosition().getX()
creatureParameter.getPosition().getY()


Para se obter o valor do combustível e os elementos que podem ser vistos pela criatura no mundo virtual é usada a função:

creatureParameter.getSensorHandler(<param>).getSensorReadings();

O parâmetro: <param> pode ser SensorType.VISUAL ou SensorType.FUEL, no primeiro caso será obtida uma lista com os objetos vistos pela criatura, e no segundo caso o valor atual do combustível.

Existem três tipos de elementos no mundo virtual: jewel (jóias) , food (comida) e brick (tijolos).

A execução da simulação é feita através do método runSimulation() da classe soarBridge.

Após a execução das regras no SOAR é completada, o método processResponseCommands() obtêm e processa a informação enviada desde SOAR.

A resposta do SOAR está constituída por uma lista de comandos a serem executados no robô. Existem três tipos de comandos: move (mover), get (obter) e eat (comer). Os comandos são processados pelas funções:

  • processMoveCommand()
  • processGetCommand()
  • processEatCommand()

cada comando leva os argumentos necessários para processar a instrução, tais como: direção de movimento, velocidade, etc.

Programa de regras de SOAR


No programa de regras do SOAR o primeiro operador a ser proposto é chamado de WANDER

Este operador permite à criatura se movimentar ao redor com uma velocidade VelR igual a 2


Proposição:

# This operator will make the agent to walk ahead at the enviroment
# Propose*wander:
sp {propose*wander
   (state <s> ^attribute state
              ^impasse no-change
              ^superstate <ss>)
   (<ss> ^io.input-link <il>)
   (<ss> ^superstate nil)
   (<il> ^CREATURE <creature>)
   (<creature> ^SENSOR.VISUAL <visual>)
-->
   (<ss> ^operator <o> +)
   (<o> ^name wander)}

Aplicação:

# Apply*wander:
# If the wander operator is selected, then generate an output command to it
sp {apply*wander
   (state <s> ^operator <o>
              ^io <io>)
   (<io> ^output-link <ol>)
   (<o> ^name wander)
-->
   (<ol> ^MOVE <command>)
   (<command> ^Vel 0)
   (<command> ^VelR 2)
   (<command> ^VelL 0)}



Regra que elimina o comando caso ele esteja concluído

# If the wander operator is selected,
# and there is a completed move command on the output link,
# then remove that command.
sp {apply*wander*remove*move
   (state <s> ^operator.name wander
              ^io.output-link <out>)
   (<out> ^MOVE <move>)
   (<move> ^status complete)
-->
   (<out> ^MOVE <move> -)}



O operador seeEntityWithMemoryCount possibilita guardar na memória as entidades que a criatura pode ver no mundo virtual, este operador é proposto se o agente já possui alguma entidade na memória.

O operador seeEntityWithoutMemoryCount realiza o mesmo trabalho do operador seeEntityWithMemoryCount mas é aplicado quando ainda não existe nenhuma entidade no agente.

Depois são declarados os operadores de movimento em direção na comida (moveFood), o operador de comer a comida (eatFood), o operador de ir em direção as joias (moveJewel), o operador de pegar as joias (getJewel) e o operador de evitar os tijolos (avoidBrick).


Após isso são criadas as regras de controle e de preferência e as regras que resolverão os conflitos.








Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer