A primeira parte desta aula foi dedicada ao estudo da solução "ClarionDemo", fornecida como exemplo de integração Clarion com o ambiente WorldServer3D.
Essa solução exemplo cria uma criatura que fica simplesmente vagando pelo tabuleiro, sobre o qual foram criados barreiras em todas as laterais.
Inicialmente a solução não funcionou corretamente: a criatura chegava até um obstáculo e parava. Feita a investigação ainda durante a aula determinou-se que o problema era o LOCALE do laboratório - onde todas as instalações estão em português: isso trazia a resposta dos comandos do WorldServer3D com a "vírgula" como separador de casas decimais, enquanto o esperado era o "ponto".
O uso do comando:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
no delegate de envio do comando para o WorldServer3D (mais detalhes adiante) resolveu o problema.
Estudo da solução
A solução é composta por 3 projetos, com as seguintes características:
- ClarionDEMO: é a solução principal, onde está a primeira classe executada; através dos outros projetos instancia a comunicação com o WorldServer3D e também o agente Clarion
- WorldServerLibrary: contém a classes de interface com o WorldServer3D, para comunicação e envio dos comandos e com classes para representar o modelo de dados.
- WorldServerAgent: contém a thread do agente Clarion, responsável pelo loop de execução da simulação, interagindo tanto com o Clarion quanto com o WorldServer3D - com este através das classes do projeto WorldServerLibrary.
Estudo do agente Clarion - regras
Para a simples simulação construída, o agente Clarion cria 2 "ExternalActionChunks", representando as 2 operações que executa:
- ROTATE_CLOCKWISE: utilizada para desviar quando encontra um obstáculo à frente;
- GO_AHEAD: utilizada para andar para frente em linha reta, quando não existe obstáculo à frente;
Para externalizar essas 2 ações o agente utiliza 2 "FixedRules" - ruleGoAhead, ruleAvoidCollisionWall - cuja ativação é controlada por duas funções de customização "SupportCalculator":
private double FixedRuleDelegateToAvoidColissionWall(ActivationCollection currentInput, Rule target)
{
// See partial match threshold to verify what
// are the rules available for action selection
return ((currentInput.Contains(InputWallAhead, CurrentAgent.Parameters.MAX_ACTIVATION))) ? 1.0 : 0.0;
}
private double FixedRuleDelegateToGoAhead(ActivationCollection currentInput, Rule target)
{
// Here we will make the logic to go ahead
return ((currentInput.Contains(InputWallAhead, CurrentAgent.Parameters.MIN_ACTIVATION))) ? 1.0 : 0.0;
}
Como é possível verificar, a lógica das funções depende da ativação do par dimensão/valor "InputWallAhead", ativado sempre que houver um obstáculo a uma distância mínima - distância essa que permita a criatura rotacionar sobre seu eixo sem ficar travada no obstáculo.
O agente comanda a criatura para andar à frente sempre que não houver um obstáculo à frente, ativando ao máximo a regra "ruleGoAhead" e mantendo a mínima ativação para a regra "ruleAvoidCollisionWall"; quando houver um obstáculo à frente, as ativações são ao contrário e o agente comanda a criatura para rotacionar no sentido horário.
Estudo do agente Clarion - interface com WorldServer3D
Para interfacear com o WorldServer3D - buscando o status atual da criatura através do comando "getcreaturestate", ou enviando os comandos definidos - o agente utiliza 2 delegates C#, associados à funções da classe "MainClass":
public delegate IList<Thing> InputVisualSensorialInformationEventHandler();
esse delegate é associado à seguinte função da classe "MainClass":
agent_OnNewVisualSensorialInformation()
public delegate void OutputActionChunkEventHandler(ClarionAgentActionType externalAction);
esse delegate é associado à segunte função da classe "MainClass":
agent_OnNewExternalActionSelected()
Estudo do agente Clarion - loop de execução
O loop de execução do agente está numa thread separada, cujo funcionamento é realizado pela função "RunThread()" com os seguintes passos:
- A cada ciclo o agente vai buscar o estado no WorldServer3D, chamando "OnNewVisualSensorialInformation()".
- Sobre a lista de coisas visualizadas pela criatura, é criada a "SensoryInformation" de entrada para o ciclo cognitivo, através do método "MakePerceptionFromSensorialInput()"; é nesse método que é definida a ativação do elemento "InputWallAhead".
- Passa o "SensoryInformation" para o agente analizar, através da chamada:
CurrentAgent.Perceive(si)
- Busca então a ação externa definida pelo agente:
CurrentAgent.GetChosenExternalAction(si)
- Repassa a ação definida para ser traduzida em um comando do WorldServer3D, usando "OnNewExternalActionSelected()".
- Recomeça o ciclo.
Rápida análise do que precisará ser desenvolvido
Considerando-se que novamente o objetivo é fazer com o que o agente consiga controlar a criatura para que ela complete seus "leaflets", as seguintes implementações podem ser rapidamente identificadas, tendo essa simulação descrita como base:
- Criar comando para gerar um leaflet para criatura;
- Criar comando para entregar um leaflet;
- Dentro do agente, parser e armazenamento da informação de leaflet recebida em "getcreaturestate";
- Criação de jóias/alimentos pelo tabuleiro;
- Regras para:
- Levar a criatura até os elementos - jóias/alimentos;
- Coletar jóias;
- Comer alimentos;
- Ir até o "delivery-spot";
- Entregar leaflet completo;
- Controle, no agente, para contabilizar todas as JÓIAS e ALIMENTOS visualizados, bem como de todas as JÓIAS coletadas, de forma a possibilitar a verificação de leaflets completados.