Inicio     |     Sobre     |     GitHub     |     Games     |     Contato                        

sexta-feira, 29 de março de 2019

Resumo Semanal de Pesquisa: Project Malmo e Possibilidades de Experimentos



 A leitura completa do artigo/tutorial <http://microsoft.github.io/malmo/blog/BuildBattle/Introduction/> auxilia na experiencia e familiarização do código e da estrutura de funcionamento do Project Malmo. Já essa página <http://modelai.gettysburg.edu/2019/minecraft/> disponibiliza um pacote de projetos que utilizam o Project Malmo para aplicações de planejamento de caminhos, planejamento clássico, ampliação iterativa, satisfação de restrições, programação linear e programação inteira. A leitura do mesmo dá uma boa visão de como é possível aplicar o Malmo em diferentes tipos de projetos e experimentos.


Instalação no Linux:


    Conforme já foi dito antes a instalação do Project Malmo no Windows é bem simples, basta seguir as instruções presentes nessa página <https://github.com/Microsoft/malmo> e tudo fucnionará normalmente. Porém tive alguns problemas ao tentar instalar da mesma forma no Linux (Kubuntu), precisei passar por uma etapa de passos tentando resolver os problemas que tive. Com isso resolvi deixar aqui algumas dicas que podem ajudar a corrigir problemas que possam vir a aparecer no Linux:

1- Download: Primeiramente o download deve ser feito nessa pagina <https://github.com/Microsoft/malmo/releases> de acordo com seu sistema operacional;

2- Escolha uma pasta e extraia o arquivo (dica facilite o nome da pasta), no meu caso deixei nomeada como "Malmo";

3- Em seguida instale seguindo o tutorial <https://github.com/Microsoft/malmo/blob/master/doc/install_linux.md>. O seguinte comando é dado para fazer o download e instalação: 

sudo apt-get install libboost-all-dev libpython3.5 openjdk-8-jdk ffmpeg python-tk python-imaging-tk

4- É preciso verificar a versão do java em uso pelo sistema, visto que o Malmo só funciona com a versão 8 do java. O java 8 é instalado na etapa anterior (3) mas para verificar se o mesmo esta no sistema é possível usar o comando:

sudo update-alternatives --config java

Ele mostra no sistema a seguinte informação:

carolhcs@pc-desktop:~/Documents/Carolhcs/ProjMestrado/Malmo/Schemas$ sudo update-alternatives --confi
g java 
There are 2 choices for the alternative java (providing /usr/bin/java). 

 Selection    Path                                            Priority   Status 
------------------------------------------------------------ 
* 0            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1101      auto mode 
 1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1101      manual mode 
 2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode 

Press <enter> to keep the current choice[*], or type selection number: 2

   A seguinte linha (2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode) indica que o java 8 está instalado, porém não esta em uso, para usá-lo informe o número que está na frente e de Enter. Uma alternativa é usando o comando: 

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/bin/java

Use esse comando para verificar se foi mudado:

echo $JAVA_HOME

5- Não esquecer de conferir a definição do local dos esquemas (Schemas). Na pasta em que o Malmo foi extraído há uma pasta chamada "Schemas". É preciso definir o local dessa pasta cada vez que o malmo e atualizado de acordo com o item 3 desse tutorial <https://github.com/Microsoft/malmo/blob/master/doc/install_linux.md>. Para isso é necessário usar o comando: 

export MALMO_XSD_PATH=~/Documents/Carolhcs/ProjMestrado/Malmo/Schemas

6- Com isso se não houver nenhum erro, a instalação estará completa, agora para fazer um teste básico usando o terminal, entre na pasta Malmo/Minecraft, e execute o arquivo launchClient.sh, no caso usei o seguinte comando:

cd Minecraft
./launchClient.sh

Isso abrirá o jogo no menu do minecraft;

7- Para executar um agente básico de exemplo basta seguir as instruções no tutorial <https://github.com/Microsoft/malmo>. Na pasta Java_Examples (para exemplos em java) e executar o exemplo, no terminal deve ficar assim:

cd Java_Examples
java -cp MalmoJavaJar.jar:JavaExamples_run_mission.jar -Djava.library.path=. JavaExamples_run_mission

8- Durante um teste ocorreu um erro referente a falta do JAVA_HOME e do MALMO_XSD_PATH no environment. Para a correção desses adicionei o caminho via terminal e abri o arquivo environment (/etc/) e adicionei ambos os caminhos:

JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java"
MALMO_XSD_PATH="~/Documents/Carolhcs/ProjMestrado/Malmo/Schemas"

9- No fim da noite ao tentar rodar o Project Malmo, seguindo os mesmos passos anteriores, aconteceu um erro dizendo que o java home estava direcionado erroneamente, após varias tentativas o erro persistiu. O sistema foi atualizado pouco antes do erro, por isso pode ser interessante reinstalar o java 8.

cd /home/carolhcs/Documents/Carolhcs/ProjMestrado/Malmo/Minecraft/
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
./launchClient.sh

     É isso, caso os problemas insistam vale a pena dar uma olhada no wiki e nas páginas de solução de problemas do Project Malmo no Github.

Experimento em java:


     Dando continuidade ao projeto, como o MECA (arquitetura cognitiva que estarei usando nesse trabalho) utiliza a linguagem de programação Java e todos os experimentos feitos até o momento eram em Python, é interessante tentar desenvolver uma aplicação java que possa ser usada no Malmo. Tentei usar a aplicação de exemplo que acompanha o Project Malmo, tive alguns problemas mas consegui roda-lá. Para fixar todo o funcionamento da API e dos experimentos eu tentei refazer os experimentos anteriores feitos em Python, porém agora em Java e usando o NetBeans, a IDE que uso. É possível conferir os códigos e resultados no GitHub <https://github.com/carolhcs/code-malmo-testes>.


     A ideia de construir os experimentos em Java se mostrou ainda mais interessante conforme seu desenvolvimento. Foi possível observar como características das linguagens de programação faziam diferença durante a execução. O primeiro código é simples e conforme o tutorial demonstra apenas como criar um agente e controla-lo no ambiente:

import com.microsoft.msr.malmo.*; import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author carol
*/
public class ExpMalmoMeca1b {
static
{
System.loadLibrary("MalmoJava"); // attempts to load MalmoJava.dll (on Windows) or libMalmoJava.so (on Linux)
}
/**
* @param argv the command line arguments
*/
////public static void main(String argv[])
////public static void main(String[] args) {
public static void main(String argv[]){
// TODO code application logic here
AgentHost agent_host = new AgentHost(); //Criar agente
try {
StringVector args = new StringVector();
//args.add("JavaExamples_run_mission");
args.add("ExpMalmoMeca1b");
for( String arg : argv )
args.add( arg );
agent_host.parse( args );
}
catch( Exception e ) {
System.err.println( "ERROR: " + e.getMessage() );
System.err.println( agent_host.getUsage() );
System.exit(1);
}
if( agent_host.receivedArgument("help") ) {
System.out.println( agent_host.getUsage() );
System.exit(0);
}
MissionSpec my_mission = new MissionSpec();
MissionRecordSpec my_mission_record = new MissionRecordSpec();
my_mission.setSummary("Primeiro Experimento de Missão");
//my_mission.timeLimitInSeconds(60);
//Definindo Missão
//Attempt to start a mission:
try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}
//Loop until mission starts:
WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(10);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
System.out.println( "Mission running" );
//Commands
agent_host.sendCommand("move 1");
agent_host.sendCommand("turn -0.5");
agent_host.sendCommand("jump 1");
agent_host.sendCommand("pitch 1");
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca1.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("attack 1");
//Commands End
//Loop until mission ends:
do {
try {
Thread.sleep((long) 0.1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca1b.class.getName()).log(Level.SEVERE, null, ex);
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission ended" );
//Mission has ended.
//END
}
}
<https://github.com/carolhcs/code-malmo-testes/blob/master/ExpMalmoMeca1b.java>

     Já o segundo código demonstra o uso do XML para construir uma missão e modificar o ambiente, essa também foi uma etapa mais tranquila de reproduzir:

import com.microsoft.msr.malmo.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author carol
*/
public class ExpMalmoMeca2 {
static
{
System.loadLibrary("MalmoJava"); // attempts to load MalmoJava.dll (on Windows) or libMalmoJava.so (on Linux)
}
/**
* @param argv the command line arguments
*/
////public static void main(String argv[])
////public static void main(String[] args) {
public static void main(String argv[]){
// TODO code application logic here
//XML da missão
String missionXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalon=\"no\" ?>"
+"<Mission xmlns=\"http://ProjectMalmo.microsoft.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<About><Summary>Hello World in Java!</Summary></About>"
+"<ServerSection>"
+"<ServerInitialConditions>"
+"<Time><StartTime>12000</StartTime><AllowPassageOfTime>false</AllowPassageOfTime></Time>"
+"<Weather>rain</Weather>"
+"</ServerInitialConditions>"
+"<ServerHandlers>"
+"<FlatWorldGenerator generatorString=\"3;7,44*49,73,35:1,159:4,95:13,35:13,159:11,95:10,159:14,159:6,35:6,95:6;12;\"/>"
+"<DrawingDecorator><DrawBlock x=\"-27\" y=\"70\" z=\"0\" type=\"air\"/></DrawingDecorator>"
+"<ServerQuitFromTimeUp timeLimitMs=\"30000\"/>"
+"<ServerQuitWhenAnyAgentFinishes/>"
+"</ServerHandlers>"
+"</ServerSection>"
+"<AgentSection mode=\"Survival\">"
+"<Name>MalmoTutorialBot</Name>"
+"<AgentStart>"
+"<Placement x=\"0\" y=\"56\" z=\"0\" yaw=\"90\"/>"
+"<Inventory><InventoryItem slot=\"0\" type=\"diamond_pickaxe\"/></Inventory>"
+"</AgentStart>"
+"<AgentHandlers>"
+"<ObservationFromFullStats/>"
+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>"
+"</AgentHandlers>"
+"</AgentSection>"
+"</Mission>";
AgentHost agent_host = new AgentHost(); //Criar agente
try {
StringVector args = new StringVector();
//args.add("JavaExamples_run_mission");
args.add("ExpMalmoMeca2");
for( String arg : argv )
args.add( arg );
agent_host.parse( args );
}
catch( Exception e ) {
System.err.println( "ERROR: " + e.getMessage() );
System.err.println( agent_host.getUsage() );
System.exit(1);
}
if( agent_host.receivedArgument("help") ) {
System.out.println( agent_host.getUsage() );
System.exit(0);
}
MissionSpec my_mission;
try {
my_mission = new MissionSpec(missionXML, true);
MissionRecordSpec my_mission_record = new MissionRecordSpec();
my_mission.setSummary("Primeiro Experimento de Missão");
try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}
} catch (Exception ex) {
Logger.getLogger(ExpMalmoMeca2.class.getName()).log(Level.SEVERE, null, ex);
}
//MissionRecordSpec my_mission_record = new MissionRecordSpec();
//my_mission.timeLimitInSeconds(60);
//Definindo Missão
//Attempt to start a mission:
/*try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}*/
//Loop until mission starts:
WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(10);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
System.out.println( "Mission running" );
//Commands
agent_host.sendCommand("move 1");
agent_host.sendCommand("turn -0.5");
agent_host.sendCommand("jump 1");
agent_host.sendCommand("pitch 1");
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca2.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("attack 1");
//Commands End
//Loop until mission ends:
do {
try {
Thread.sleep((long) 0.1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca2.class.getName()).log(Level.SEVERE, null, ex);
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission ended" );
//Mission has ended.
//END
}
}

<https://github.com/carolhcs/code-malmo-testes/blob/master/ExpMalmoMeca2.java>

O terceiro código teve novas regras relacionadas a missão adicionadas no XML:

import com.microsoft.msr.malmo.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author carol
*/
public class ExpMalmoMeca3 {
static
{
System.loadLibrary("MalmoJava"); // attempts to load MalmoJava.dll (on Windows) or libMalmoJava.so (on Linux)
}
/**
* @param argv the command line arguments
*/
////public static void main(String argv[])
////public static void main(String[] args) {
//Essas funções deveriam ser usadas no meio do XML porém tivel alguns problemas, tentarei usa-las novamente mais a diante
public String GenCuboid(int x1, int y1, int z1, int x2, int y2, int z2, String blocktype){
return "<DrawCuboid x1=" + Integer.toString(x1) + " y1=" + Integer.toString(y1) + " +z1=" + Integer.toString(z1) + " x2=" + Integer.toString(x2) + " +y2=" + Integer.toString(y2) + " +z2=" + Integer.toString(z2) + " +type=" + blocktype + "/>";
}
public String Menger(int xorg, int yorg, int zorg, int size, String blocktype, String holetype ){
String genstring = "";
//draw solid chunk
genstring = GenCuboid(xorg,yorg,zorg,xorg+size-1,yorg+size-1,zorg+size-1,blocktype) + "\n";
//now remove holes
int unit = size;
while (unit >= 3){
int w=unit/3;
for (int i=0; i<size;i=i+unit){
for(int j=0;j<size;j=j+unit){
int x=xorg+i;
int y=yorg+j;
genstring += GenCuboid(x+w,y+w,zorg,(x+2*w)-1,(y+2*w)-1,zorg+size-1,holetype) + "\n";
y=yorg+i;
int z=zorg+j;
genstring += GenCuboid(xorg,y+w,z+w,xorg+size-1, (y+2*w)-1,(z+2*w)-1,holetype) + "\n";
genstring += GenCuboid(x+w,yorg,z+w,(x+2*w)-1,yorg+size-1,(z+2*w)-1,holetype) + "\n";
}
}
unit = w;
}
return genstring;
}
public static void main(String argv[]){
// TODO code application logic here
//XML da missão
String missionXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalon=\"no\" ?>"
+"<Mission xmlns=\"http://ProjectMalmo.microsoft.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<About><Summary>Hello World in Java!</Summary></About>"
+"<ServerSection>"
+"<ServerInitialConditions>"
+"<Time><StartTime>12000</StartTime><AllowPassageOfTime>false</AllowPassageOfTime></Time>"
+"<Weather>clear</Weather>"
+"</ServerInitialConditions>"
+"<ServerHandlers>"
+"<FlatWorldGenerator generatorString=\"3;7,44*49,73,35:1,159:4,95:13,35:13,159:11,95:10,159:14,159:6,35:6,95:6;12;\"/>"
+"<DrawingDecorator><DrawSphere x=\"-27\" y=\"70\" z=\"0\" radius=\"30\" type=\"air\"/>"
+"</DrawingDecorator>"
+"<ServerQuitFromTimeUp timeLimitMs=\"30000\"/>"
+"<ServerQuitWhenAnyAgentFinishes/>"
+"</ServerHandlers>"
+"</ServerSection>"
+"<AgentSection mode=\"Survival\">"
+"<Name>MalmoTutorialBot</Name>"
+"<AgentStart>"
+"<Placement x=\"0\" y=\"56\" z=\"0\" yaw=\"90\"/>"
+"<Inventory><InventoryItem slot=\"0\" type=\"diamond_pickaxe\"/></Inventory>"
+"</AgentStart>"
+"<AgentHandlers>"
+"<ObservationFromFullStats/>"
+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>"
+"</AgentHandlers>"
+"</AgentSection>"
+"</Mission>";
AgentHost agent_host = new AgentHost(); //Criar agente
try {
StringVector args = new StringVector();
//args.add("JavaExamples_run_mission");
args.add("ExpMalmoMeca3");
for( String arg : argv )
args.add( arg );
agent_host.parse( args );
}
catch( Exception e ) {
System.err.println( "ERROR: " + e.getMessage() );
System.err.println( agent_host.getUsage() );
System.exit(1);
}
if( agent_host.receivedArgument("help") ) {
System.out.println( agent_host.getUsage() );
System.exit(0);
}
MissionSpec my_mission;
try {
my_mission = new MissionSpec(missionXML, true);
MissionRecordSpec my_mission_record = new MissionRecordSpec();
my_mission.setSummary("Primeiro Experimento de Missão");
try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}
} catch (Exception ex) {
Logger.getLogger(ExpMalmoMeca3.class.getName()).log(Level.SEVERE, null, ex);
}
//MissionRecordSpec my_mission_record = new MissionRecordSpec();
//my_mission.timeLimitInSeconds(60);
//Definindo Missão
//Attempt to start a mission:
/*try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}*/
//Loop until mission starts:
WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(10);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
System.out.println( "Mission running" );
//Commands
agent_host.sendCommand("move 1");
//agent_host.sendCommand("turn -0.5");
agent_host.sendCommand("jump 1");
//agent_host.sendCommand("pitch 1");
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca3.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("attack 1");
//Commands End
//Loop until mission ends:
do {
try {
Thread.sleep((long) 0.1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca3.class.getName()).log(Level.SEVERE, null, ex);
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission ended" );
//Mission has ended.
//END
}
}

<https://github.com/carolhcs/code-malmo-testes/blob/master/ExpMalmoMeca3.java>

     As mudanças entre os códigos 2, 3 e 4 são poucas e podem ser vistas diretamente no github. Vamos direto ao quinto código, onde estou trabalhando no momento. Aqui há uma adição muito importante ao código, que é a possibilidade do agente ver os blocos a sua volta através de objetos JSON. E é aqui que as coisas começaram a ficar um pouco mais complicadas, primeiramente por conta de passar para Java a parte do código em Python que recebe o Array JSON, mas depois de um tempo isso foi feito.

import com.microsoft.msr.malmo.*;
import java.util.logging.Level;
import java.util.logging.Logger;
//import org.json.simple.JSONObject;
import org.json.*;
/**
*
* @author carol
*/
public class ExpMalmoMeca5 {
static
{
System.loadLibrary("MalmoJava"); // attempts to load MalmoJava.dll (on Windows) or libMalmoJava.so (on Linux)
}
/**
* @param argv the command line arguments
*/
public static void main(String argv[]){
// TODO code application logic here
//XML da missão
//+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>" ou +"<DiscreteMovementCommands/>"
String missionXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalon=\"no\" ?>"
+"<Mission xmlns=\"http://ProjectMalmo.microsoft.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<About><Summary>Hello World in Java!</Summary></About>"
+"<ServerSection>"
+"<ServerInitialConditions>"
+"<Time><StartTime>1000</StartTime><AllowPassageOfTime>false</AllowPassageOfTime></Time>"
+"<Weather>clear</Weather>"
+"</ServerInitialConditions>"
+"<ServerHandlers>"
+"<FlatWorldGenerator generatorString=\"3;7,44*49,73,35:1,159:4,95:13,35:13,159:11,95:10,159:14,159:6,35:6,95:6;12;\"/>"
+"<DrawingDecorator>"
+"<DrawSphere x=\"-27\" y=\"69\" z=\"0\" radius=\"30\" type=\"air\"/>"
+"<DrawCuboid x1=\"-25\" y1=\"39\" z1=\"-2\" x2=\"-29\" y2=\"39\" z2=\"2\" type=\"lava\"/>"
+"<DrawCuboid x1=\"-26\" y1=\"39\" z1=\"-1\" x2=\"-28\" y2=\"39\" z2=\"1\" type=\"obsidian\"/>"
+"<DrawBlock x=\"-27\" y=\"39\" z=\"0\" type=\"diamond_block\"/>"
+"</DrawingDecorator>"
+"<ServerQuitFromTimeUp timeLimitMs=\"30000\"/>"
+"<ServerQuitWhenAnyAgentFinishes/>"
+"</ServerHandlers>"
+"</ServerSection>"
+"<AgentSection mode=\"Survival\">"
+"<Name>MalmoTutorialBot</Name>"
+"<AgentStart>"
+"<Placement x=\"0.5\" y=\"56.0\" z=\"0.5\" yaw=\"90\"/>"
+"<Inventory><InventoryItem slot=\"8\" type=\"diamond_pickaxe\"/></Inventory>"
+"</AgentStart>"
+"<AgentHandlers>"
+"<ObservationFromFullStats/>"
+"<ObservationFromGrid>"
+"<Grid name=\"floor3x3\">"
+"<min x=\"-1\" y=\"-1\" z=\"-1\"/>"
+"<max x=\"1\" y=\"-1\" z=\"1\"/>"
+"</Grid>"
+"</ObservationFromGrid>"
+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>"
+"<InventoryCommands/>"
+"<AgentQuitFromTouchingBlockType>"
+"<Block type=\"diamond_block\" />"
+"</AgentQuitFromTouchingBlockType>"
+"</AgentHandlers>"
+"</AgentSection>"
+"</Mission>";
AgentHost agent_host = new AgentHost(); //Criar agente
try {
StringVector args = new StringVector();
//args.add("JavaExamples_run_mission");
args.add("ExpMalmoMeca5");
for( String arg : argv )
args.add( arg );
agent_host.parse( args );
}
catch( Exception e ) {
System.err.println( "ERROR: " + e.getMessage() );
System.err.println( agent_host.getUsage() );
System.exit(1);
}
if( agent_host.receivedArgument("help") ) {
System.out.println( agent_host.getUsage() );
System.exit(0);
}
MissionSpec my_mission;
try {
my_mission = new MissionSpec(missionXML, true);
MissionRecordSpec my_mission_record = new MissionRecordSpec();
my_mission.setSummary("Primeiro Experimento de Missão");
try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}
} catch (Exception ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
//Loop until mission starts:
WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(10);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
System.out.println( "Mission running" );
//Commands
agent_host.sendCommand("hotbar.9 1");//Press the hotbar key
agent_host.sendCommand("hotbar.9 0");//Release hotbar key - agent should now be holding diamond_pickaxe
agent_host.sendCommand("pitch 0.2");//Start looking downward slowly
try {
Thread.sleep(1);//Wait a second until we are looking in roughly the right direction
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("pitch 0");//Stop tilting the camera
agent_host.sendCommand("move 1");//And start running...
agent_host.sendCommand("attack 1");//Whilst flailing our pickaxe!
//Commands End
boolean pular = false;
//Loop until mission ends:
do {
try {
Thread.sleep((long) 0.1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
/*
System.out.print( "video,observations,rewards received: " );
System.out.print( world_state.getNumberOfVideoFramesSinceLastState() + "," );
System.out.print( world_state.getNumberOfObservationsSinceLastState() + "," );
System.out.println( world_state.getNumberOfRewardsSinceLastState() );
for( int i = 0; i < world_state.getRewards().size(); i++ ) {
TimestampedReward reward = world_state.getRewards().get(i);
System.out.println( "Summed reward: " + reward.getValue() );
}
*/
//Parcialmente funcionando
if (world_state.getNumberOfObservationsSinceLastState() > 0){
TimestampedStringVector observations = world_state.getObservations();
if (observations.isEmpty())System.out.println("Observation Vazio!!");
String obs_text = observations.get((int) (observations.size() - 1)).getText();
JSONObject observation = new JSONObject(obs_text);
JSONArray blocks = observation.getJSONArray("floor3x3");
String grid[] = {"","","","","","","","",""};
//Ver o que há em todas as posições do array
for (int i = 0; i < 9; ++i) {
String block = blocks.getString(i);
grid[i] = block;
System.out.println("Posição: "+ i + "=" +block+ "\n");
//if (grid [i] == "lava") grid[3]="lava";
}
//grid[3]="lava";
if (!pular && (grid[4] != "lava")){
//agent_host.sendCommand("move 1");
agent_host.sendCommand("jump 0");
pular = false;
}
if (grid[3]=="lava"){
//agent_host.sendCommand("move 0");
agent_host.sendCommand("jump 1");
pular = true;
}
//------
/*TimestampedString msg = world_state.getObservations().get(0);
String msg2 = msg.getText();
JSONObject observations = new JSONObject();
JSONArray floor = new JSONArray();
floor = (JSONArray) observations.get("floor3x3");
System.out.println(floor);*/
//-----
//JSONObject jobj = new JSONObject();
//String grid = jobj.getJSONObject("floor3x3").getString("floor3x3");
//JSONArray json = new JSONArray();
//json.getJSONArray(0);
//String obj = (String) json.get("floor3x3");
//System.out.print(json);
//System.out.print( world_state.getNumberOfObservationsSinceLastState());
//String msg = world_state.getObservations().toString();
//JSONObject json = new JSONObject();
//String observation = json.getString(msg);
//String grid[] = null;
//for( int i = 0; i < world_state.getObservations().size(); i++ ) {
//System.out.print(world_state.getObservations().get(i));
//}
}
/*
if world_state.number_of_observations_since_last_state > 0:
msg = world_state.observations[-1].text
observations = json.loads(msg)
grid = observations.get(u'floor3x3', 0)
if jumping and grid[4]!=u'lava':
agent_host.sendCommand("jump 0")
jumping = False
if grid[3]==u'lava':
agent_host.sendCommand("jump 1")
jumping = True
*/
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission ended" );
//Mission has ended.
//END
}
}

<https://github.com/carolhcs/code-malmo-testes/blob/master/ExpMalmoMeca5.java>

     Esse código propõem um pequeno desafio onde o agente deve ver os blocos a sua volta e caso haja um bloco de lava a sua frente o comando pular deve ser chamado. Depois de um tempo o código ficou pronto mas ai surgiu um problema do qual um colega de laboratório também se deparou, sincronia. Ao que parece, há um problema de sincronia no código em java, acompanhando a entrada dos valores do grid de visualização do agente é possível perceber que o bloco lava passa pela posição 0, 3 e 6 (na frende do agente) e logo em seguida passa pela posição 1, 4 e 7 (abaixo do agente). Porém isso acontece muito, muito antes do agente na simulação de fato chegar próximo a lava, com isso quando isso de fato acontece o mesmo cai na lava e as informações do grid mostram que há apenas obsidianas a seu redor.

     Com isso podemos entender que a percepção do ambiente está totalmente dessincronizado com a ação no ambiente, no momento estou tentando entender melhor como isso funciona. Foi dada a ideia de usar um Timer para desacelerar o processo de percepção, é uma ideia que tentarei usar mas pode afetar o desempenho do programa. O código até o momento é o deixado acima, os próximos passos nessa parte envolvem buscar opções de contornar esse problema, terminar a escrita dos códigos de exemplo (tutoriais) com objetivo de evitar futuras "surpresas ruins" e ajudar quaisquer pessoas que queiram usar o Project Malmo com a linguagem Java. Também já é importante começar a utilizar o MECA para controlar de forma simples o agente e assim começar o desenvolvimento da arquitetura. E começar a colocar em prática o desenvolvimento do/dos experimentos que serão usados, uma vez que já se tem domínio suficiente da criação de experimentos no Malmo.

Planejamento dos experimentos a serem realizados nesse projeto:


    Como o foco desse trabalho é estar demonstrando a possibilidade do uso da arquitetura cognitiva MECA (Multipurpose Enhanced Cognitive Architecture) em jogos digitais (com foco em ambientes complexos), a ideia é que os experimentos usados nesse projeto consigam demonstrar de maneira clara que a arquitetura com o uso dos processos duais e da memória episódica dão conta de controlar o agente. O experimento deverá possuir mais de um objetivo (e.g. se alimentar, buscar diamante, sobreviver) e uma quantia considerável de possíveis ações para que o agente não fique limitado as mesmas decisões e comportamentos.

Podemos ver mais um exemplo interessante no seguinte trabalho, onde o autor desenvolve um experimento multi-agentes.


Imagem tirada do trabalho citado acima.

Outras ideias de experimentos podem ser encontradas no marlo:

Labirinto, onde o agente deve aprender a sair do labirinto chegando até determinado bloco antes que acabe o tempo.


Andar sobre uma plataforma, é um experimento onde o agente deve aprender a andar sobre uma plataforma e pegar o item diamante sem cair na lava.


Pegue o animal, nesse experimento o agente deve aprender a chegar até a posição de um determinado animal dentro de um cercado, lembrando que os animais podem ser mexer e assim mudar sua posição.


Encontre o objetivo é um experimento mais simples onde o agente deve aprender a chegar até um objeto presente dentro de um ambiente pequeno, não há obstáculos e esse objetivo não é capaz de se mover como os animais no experimento anterior.


Encontre o objetivo. Você já olhou no sótão? é uma versão um pouco mais complexa da anterior onde o objetivo esta acima do agente, logo a opções de movimentação são um pouco maiores.


   Existem mais duas versões do experimento acima, uma onde o agente deve aprender a usar uma escada para subir no próximo andar e outra onde o agente deve aprender a abrir portas.
   Missão simples, 10 segundo com recompensa por alcançar um local.


Missão de sobrevivência em minecraft.


Dieta saudável é um experimento onde há vários tipos de alimentos espalhados pelo chão, e o agente deve aprender a buscar apenas os certos e evitar os errados.


Já na missão abaixo, o agente deve se mover em torno de uma área para encontrar uma meta ou sair dela.


E por fim há as missões batalha de construção onde o agente deve aprender a construir uma estrutura, e caçadores do tesouro onde o agente deve sobreviver e buscar determinado item.

Mais sobre esses experimentos podem ser vistos nessa página, e no github do projeto. O próprio malmo vem com exemplos de desafios e ambientes muito bons e.g.:

Perseguir um monstro:

Explorar ambientes:



E coletar objetos:


Além de possuir também vários dos desafios já mostrados anteriormente no marlo. Um dos experimentos que achei mais interessante e talvez um dos mais complexos é o chamado mob_fun, onde o agente deve coletar maças espalhadas em posições aleatórias em um espaço pequeno, porém com o tempo surgem mais monstros que perseguem o agente, logo ele deve saber escolher qual maçã pegar e desviar dos grupos de monstros que o perseguem:



Com isso, algumas ideias do que podemos fazer são:

1- A maioria dos experimentos vistos possuem um único objetivo, pode ser interessante também testar a arquitetura nesse tipo de ambiente, porém acredita-se que isso não seria capaz de demonstrar o uso da arquitetura e principalmente da teoria dos processos duais. Um ambiente mais incerto e dinâmico onde o agente tenha de lidar com diferentes situações e tomar mais tipos de decisão, pode ser mais interessante. Por isso foi decidido montar um experimento com mais de 1 objetivo.

2- Sabendo o tipo de experimento que buscamos, foi decidido tentar reproduzir alguns experimentos já existentes porém em um único ambiente.
PS: Dois sistemas que podem ser usados para facilitar a construção do ambiente são Superflat Generator e o Minecraft Superflat Preset Generator.

3- Sobrevivência + caça ao tesouro + buscar alimentos, são três exemplos de objetivos principais que podem existir dentro do ambiente. Essa é a resposta para uma das varias questões importantes na hora de desenvolver o ambiente. A outras questões podem ser listadas como:

1 - Como será o terreno?
(Terrenos planos diminuem a necessidade de comandos como pular ou destruir um bloco)
Plano ou Irregular?
Pequeno ou grande?
Limpo ou cheio de objetos e obstáculos (e.g. lava, arvores)?

2 - As ações serão diretas ou desenvolvidas/pronta?
(Na hora de escolher uma ação o agente terá que se decidir por ações simples e diretas como "move 1", "attack 1", "pitch 1" ou ações mais desenvolvidas como pro exemplo "Quebrar bloco" que chama um grupo de comandos "pitch 0.2" > "pitch 0" > "attack 1">"pitch - 0.2" > "pitch 0"?)

3 - Quais ações estarão disponíveis ao agente?
Relembrando que a tabela de ações disponíveis é:


4 - Como será o feedback que o agente receberá a cada interação com o ambiente?
Será dado pontos por determinada ação?
Será dado pontos por adquirir determinado item ou chegar a determinada posição?
Será dado pontos de satisfação?
Os pontos de satisfação são decrescentes ou estáticos?

5 - Os experimentos, missões/simulações serão por turnos ou diretas?

6 - Como a missão é finalizada?
(e.g. com o tempo, quando o agente morre, quando há um erro, quando o agente atinge determinada pontuação negativa ou positiva)

7 - Quanto tempo a missão irá durar?
(e.g. segundos, minutos, horas, missão sem condição de parada baseada em tempo)

8 - Quais dados serão salvos?
(e.g. tempo, blocos e objetos a volta, ação tomada, pontuações)

9 - Como serão salvos os dados?
(e.g. vídeo, dados em texto)



Essas questões deixadas são referentes apenas ao ambiente em si, com a análise em andamento do MECA serão desenvolvidas novas questões como:

Quando o Sistema 1 será usado?
Quando o Sistema 2 será usado?
Como serão classificadas as situações que ativam o Sistema 2?
Como é definida uma ação automática executada pelo sistema 1?
Qual a linha de visão/percepção do agente?

Com base no estudo feito até o momento, já é possível iniciar o desenvolvimento do ambiente e os testes usando a arquitetura cognitiva MECA. Para completar essas tarefas deverá ser feito o planejamento de como os codelets do MECA serão implementados e como será a comunicação entre a arquitetura e o experimento. Com esses planejamentos bem definidos e com a resolução dos problemas que surgiram ao usar o java com o malmo, poderá se iniciar o desenvolvimento completo do projeto. A expectativa é que essas questões possam ser respondidas e resolvidas até a próxima semana.

Próxima semana:

  • Resolver o problema de sincronia usando Time;
  • Terminar os experimentos simples em Java;
  • Usar o meca para controlar de forma simples um agente;
  • Iniciar construção do experimento;


Referências e Links:

Documentação API <http://microsoft.github.io/malmo/0.14.0/Documentation/annotated.html>
Documentação XML <http://microsoft.github.io/malmo/0.14.0/Schemas/Mission.html>
Código Malmo <https://github.com/Microsoft/malmo>
Código Marlo <https://github.com/crowdAI/marLo>
Outro Experimento <https://github.com/kuri8ive/Deep-Reinforcement-Learning-Hands-on-by-Minecraft-with-ChainerRL/blob/master/README.md>
Página CST <http://cst.fee.unicamp.br/>
Código CST <https://github.com/CST-Group/cst>
Código Meca <https://github.com/CST-Group/meca>


<https://chunkbase.com/apps/superflat-generator#3;7,2*3,2;1;village>
<http://www.minecraft101.net/superflat/>
<https://riunet.upv.es/bitstream/handle/10251/111663/Mart%C3%ADnez%20-%20Creaci%C3%B3n%20de%20tareas%20competitivas%20multi-agente%20en%20Minecraft.pdf?sequence=1&isAllowed=y>
<http://www.conquestone.com.br/blog/guia-pratico-para-dominar-machine-learning/>


Nenhum comentário:

Postar um comentário