Commit 44277b38 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Further progress on the cpp and python interfaces.

parent fdef3ceb
cmake_minimum_required(VERSION 2.8.3)
find_package(Threads REQUIRED)
# find_package(XMLRPC REQUIRED c++)
project(hfo)
# Change these to reflect the location of your librcsc-4.1.0 install
......@@ -11,10 +10,10 @@ set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${SOURCE_DIR}
${SOURCE_DIR}/chain_action
${LIBRCSC_INCLUDE}
# ${XMLRPC_INCLUDE_DIRS}
)
link_directories(
......@@ -22,7 +21,7 @@ link_directories(
)
file(GLOB SOURCES ${SOURCE_DIR}/*.cpp ${SOURCE_DIR}/chain_action/*.cpp)
list(REMOVE_ITEM SOURCES ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/main_trainer.cpp ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/sample_coach.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCE_DIR}/sample_trainer.cpp ${SOURCE_DIR}/agent.cpp)
list(REMOVE_ITEM SOURCES ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/main_trainer.cpp ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/sample_coach.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCE_DIR}/sample_trainer.cpp ${SOURCE_DIR}/agent.cpp ${SOURCE_DIR}/HFO.cpp)
list(APPEND LINK_LIBS
rcsc_agent
......@@ -40,8 +39,18 @@ add_executable(sample_coach ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/sample_co
add_executable(sample_player ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCES})
add_executable(sample_trainer ${SOURCE_DIR}/main_trainer.cpp ${SOURCE_DIR}/sample_trainer.cpp ${SOURCES})
add_executable(agent ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/agent.cpp ${SOURCES})
add_library(hfo-lib SHARED ${CMAKE_CURRENT_SOURCE_DIR}/include/HFO.hpp ${SOURCE_DIR}/HFO.cpp)
set_target_properties(hfo-lib PROPERTIES OUTPUT_NAME hfo)
set_target_properties(hfo-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
target_link_libraries(sample_coach ${LINK_LIBS})
target_link_libraries(sample_player ${LINK_LIBS})
target_link_libraries(sample_trainer ${LINK_LIBS})
target_link_libraries(agent ${LINK_LIBS})
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
add_executable(hfo_example_agent ${CMAKE_CURRENT_SOURCE_DIR}/example/hfo_example_agent.cpp)
set_target_properties(hfo_example_agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/example)
target_link_libraries(hfo_example_agent hfo)
add_dependencies(hfo_example_agent hfo-lib)
import socket, struct, thread, time
class Actions:
''' An enum of the possible HFO actions
Dash(power, relative_direction)
Turn(direction)
Tackle(direction)
Kick(power, direction)
'''
DASH, TURN, TACKLE, KICK = range(4)
class HFOEnvironment(object):
'''The HFOEnvironment is designed to be the main point of contact
''' The HFOEnvironment is designed to be the main point of contact
between a learning agent and the Half-Field-Offense domain.
'''
......@@ -23,12 +35,11 @@ class HFOEnvironment(object):
continue
else:
break
print '[Agent Client] Connected', server_port
print '[Agent Client] Connected'
self.handshakeAgentServer()
def handshakeAgentServer(self):
'''Handshake with the agent's server. Returns the number of state
features in the domain. '''
'''Handshake with the agent's server. '''
# Recieve float 123.2345
data = self.socket.recv(struct.calcsize("f"))
f = struct.unpack("f", data)[0]
......@@ -53,9 +64,9 @@ class HFOEnvironment(object):
features = struct.unpack('f'*self.numFeatures, data)
return features
def act(self, action_number):
def act(self, action):
''' Send an action and recieve the resulting reward from the environment.'''
self.socket.send(struct.pack("i", action_number))
self.socket.send(struct.pack("iff", *action))
# TODO: Get the rewards from the domain
return 0
......
#include <iostream>
#include <vector>
#include <HFO.hpp>
using namespace std;
// First Start the server by calling start.py in bin
int main() {
// Create the HFO environment
HFOEnvironment hfo;
// Connect the agent's server which should be listening if
// ./bin/start.py was called.
hfo.connectToAgentServer();
// Continue until finished
while (true) {
// Grab the vector of state features for the current state
const std::vector<float>& feature_vec = hfo.getState();
// Create a dash action
Action a = {DASH, 100., 0.};
// Perform the dash and recieve the reward
float reward = hfo.act(a);
}
};
......@@ -3,10 +3,13 @@
import imp
# First Start the server by calling start.py in bin
if __name__ == '__main__':
# First Start the server by calling start.py in bin
# Load the HFO library
hfo_module = imp.load_source('HFO', '../HFO.py')
# Get the possible actions
actions = hfo_module.Actions
# Create the HFO Environment
hfo = hfo_module.HFOEnvironment()
hfo.connectToAgentServer()
......@@ -15,6 +18,6 @@ if __name__ == '__main__':
# Grab the state features from the environment
features = hfo.getState()
# Take an action and get the reward
reward = hfo.act(0)
reward = hfo.act((actions.KICK, 100, 12.3))
# Cleanup when finished
hfo.cleanup()
#ifndef __HFO_HPP__
#define __HFO_HPP__
#include <vector>
#include "agent.h"
class HFOEnvironment {
public:
HFOEnvironment();
~HFOEnvironment();
// Connect to the server that controls the agent on the specified port.
void connectToAgentServer(int server_port=6008);
// Get the current state of the domain. Returns a reference to feature_vec.
const std::vector<float>& getState();
// The actions available to the agent
// enum action_t
// {
// DASH, // Dash(power, relative_direction)
// TURN, // Turn(direction)
// TACKLE, // Tackle(direction)
// KICK // Kick(power, direction)
// };
// Take an action and recieve the resulting reward.
float act(Action action);
protected:
int numFeatures; // The number of features in this domain
int sockfd; // Socket file desriptor for connection to agent server
std::vector<float> feature_vec; // Holds the features
// Handshake with the agent server to ensure data is being correctly
// passed. Also sets the number of features to expect.
virtual void handshakeAgentServer();
};
#endif
#include "HFO.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <iostream>
void error(const char *msg) {
perror(msg);
exit(0);
}
HFOEnvironment::HFOEnvironment() {}
HFOEnvironment::~HFOEnvironment() {
close(sockfd);
}
void HFOEnvironment::connectToAgentServer(int server_port) {
std::cout << "[Agent Client] Connecting to Agent Server on port "
<< server_port << std::endl;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
struct hostent *server = gethostbyname("localhost");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(server_port);
int status = -1;
while (status < 0) {
status = connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
sleep(1);
}
std::cout << "[Agent Client] Connected" << std::endl;
handshakeAgentServer();
}
void HFOEnvironment::handshakeAgentServer() {
// Recieve float 123.2345
float f;
if (recv(sockfd, &f, sizeof(float), 0) < 0) {
error("[Agent Client] ERROR recv from socket");
}
// Check that error is within bounds
if (abs(f - 123.2345) > 1e-4) {
error("[Agent Client] Handshake failed. Improper float recieved.");
}
// Send float 5432.321
f = 5432.321;
if (send(sockfd, &f, sizeof(float), 0) < 0) {
error("[Agent Client] ERROR sending from socket");
}
// Recieve the number of features
if (recv(sockfd, &numFeatures, sizeof(int), 0) < 0) {
error("[Agent Client] ERROR recv from socket");
}
if (send(sockfd, &numFeatures, sizeof(int), 0) < 0) {
error("[Agent Client] ERROR sending from socket");
}
std::cout << "[Agent Client] Handshake complete" << std::endl;
}
const std::vector<float>& HFOEnvironment::getState() {
if (feature_vec.size() != numFeatures) {
feature_vec.resize(numFeatures);
}
if (recv(sockfd, &(feature_vec.front()), numFeatures*sizeof(float), 0) < 0) {
error("[Agent Client] ERROR recieving state features from socket");
}
return feature_vec;
}
float HFOEnvironment::act(Action action) {
if (send(sockfd, &action, sizeof(Action), 0) < 0) {
error("[Agent Client] ERROR sending from socket");
}
return 0.;
}
......@@ -446,34 +446,29 @@ void Agent::actionImpl() {
}
// Get the action
action_t action;
if (recv(newsockfd, &action, sizeof(int), 0) < 0) {
Action action;
if (recv(newsockfd, &action, sizeof(Action), 0) < 0) {
error("[Agent Server] ERROR recv from socket");
}
switch(action) {
switch(action.action) {
case DASH:
this->doDash(100., 0);
this->doDash(action.arg1, action.arg2);
break;
case TURN:
this->doTurn(10);
this->doTurn(action.arg1);
break;
case TACKLE:
this->doTackle(0, false);
this->doTackle(action.arg1, false);
break;
case KICK:
this->doKick(100., 0);
this->doKick(action.arg1, action.arg2);
break;
default:
error("[Agent Server] Unsupported Action!");
std::cerr << "[Agent Server] ERROR Unsupported Action: "
<< action.action << std::endl;
exit(1);
}
// char buffer[256];
// bzero(buffer,256);
// if (read(newsockfd,buffer,255) < 0) {
// error("[Agent Server] ERROR reading from socket");
// }
// printf("Here is the message: %s\n",buffer);
// TODO: How to get rewards?
// For now let's not worry about turning the neck or setting the vision.
......
......@@ -34,14 +34,27 @@
#include <rcsc/player/player_agent.h>
#include <vector>
// The actions available to the agent
enum action_t
{
DASH, // Dash(power, relative_direction)
TURN, // Turn(direction)
TACKLE, // Tackle(direction)
KICK // Kick(power, direction)
};
struct Action {
action_t action;
float arg1;
float arg2;
};
class Agent : public rcsc::PlayerAgent {
public:
Agent();
virtual ~Agent();
virtual FieldEvaluator::ConstPtr getFieldEvaluator() const;
enum action_t { DASH, TURN, TACKLE, KICK };
protected:
// You can override this method. But you must call
// PlayerAgent::initImpl() in this method.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment