Commit 08e41376 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Added support for recording of non-player agents.

parent 37af3268
...@@ -35,7 +35,7 @@ list(APPEND LINK_LIBS ...@@ -35,7 +35,7 @@ list(APPEND LINK_LIBS
) )
add_executable(sample_coach ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/sample_coach.cpp ${SOURCES}) add_executable(sample_coach ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/sample_coach.cpp ${SOURCES})
add_executable(sample_player ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCES}) add_executable(sample_player ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCES} ${SOURCE_DIR}/agent.cpp)
add_executable(sample_trainer ${SOURCE_DIR}/main_trainer.cpp ${SOURCE_DIR}/sample_trainer.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_executable(agent ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/agent.cpp ${SOURCES})
add_library(hfo-lib SHARED ${SOURCE_DIR}/HFO.hpp ${SOURCE_DIR}/HFO.cpp) add_library(hfo-lib SHARED ${SOURCE_DIR}/HFO.hpp ${SOURCE_DIR}/HFO.cpp)
......
...@@ -659,6 +659,16 @@ class Trainer(object): ...@@ -659,6 +659,16 @@ class Trainer(object):
agent = self.launch_agent(agent_num, play_offense=False, port=port) agent = self.launch_agent(agent_num, play_offense=False, port=port)
self._agentPopen.append(agent) self._agentPopen.append(agent)
necProcesses.append([agent, 'defense_agent_' + str(agent_num)]) necProcesses.append([agent, 'defense_agent_' + str(agent_num)])
# Broadcast the HFO configuration
offense_nums = ' '.join([str(self.convertToExtPlayer(self._offenseTeamName, i))
for i in xrange(1, self._numOffense + 1)])
defense_nums = ' '.join([str(self.convertToExtPlayer(self._defenseTeamName, i))
for i in xrange(self._numDefense)])
self.send('(say HFO_SETUP offense_name %s defense_name %s num_offense %d'\
' num_defense %d offense_nums %s defense_nums %s)'
%(self._offenseTeamName, self._defenseTeamName,
self._numOffense, self._numDefense,
offense_nums, defense_nums))
self.startGame() self.startGame()
while self.checkLive(necProcesses): while self.checkLive(necProcesses):
prevFrame = self._frame prevFrame = self._frame
......
...@@ -6,8 +6,55 @@ ...@@ -6,8 +6,55 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <assert.h>
#include <netdb.h> #include <netdb.h>
#include <iostream> #include <iostream>
#include <sstream>
bool HFOEnvironment::ParseHFOConfig(const std::string& message,
HFO_Config& config) {
config.num_offense = -1;
config.num_defense = -1;
std::istringstream iss(message);
std::string header = "HFO_SETUP";
std::string key, val;
iss >> key;
if (header.compare(key) != 0) {
std::cerr << "Got unexpected message header: " << header;
return false;
}
while (iss >> key) {
if (key.compare("offense_name") == 0) {
iss >> config.offense_team_name;
} else if (key.compare("defense_name") == 0) {
iss >> config.defense_team_name;
} else if (key.compare("num_offense") == 0) {
iss >> val;
config.num_offense = strtol(val.c_str(), NULL, 0);
} else if (key.compare("num_defense") == 0) {
iss >> val;
config.num_defense = strtol(val.c_str(), NULL, 0);
} else if (key.compare("offense_nums") == 0) {
assert(config.num_offense >= 0);
for (int i=0; i<config.num_offense; ++i) {
iss >> val;
config.offense_nums.push_back(strtol(val.c_str(), NULL, 0));
}
} else if (key.compare("defense_nums") == 0) {
assert(config.num_defense >= 0);
for (int i=0; i<config.num_defense; ++i) {
iss >> val;
config.defense_nums.push_back(strtol(val.c_str(), NULL, 0));
}
} else {
std::cerr << "Unrecognized key: " << key << std::endl;
return false;
}
}
assert(config.offense_nums.size() == config.num_offense);
assert(config.defense_nums.size() == config.num_defense);
return true;
};
void error(const char *msg) { void error(const char *msg) {
perror(msg); perror(msg);
......
#ifndef __HFO_HPP__ #ifndef __HFO_HPP__
#define __HFO_HPP__ #define __HFO_HPP__
#include <string>
#include <vector> #include <vector>
// For descriptions of the different feature sets see // For descriptions of the different feature sets see
...@@ -41,11 +42,27 @@ struct Action { ...@@ -41,11 +42,27 @@ struct Action {
float arg2; float arg2;
}; };
// Configuration of the HFO domain including the team names and player
// numbers for each team. This can be populated by ParseHFOConfig().
struct HFO_Config {
std::string offense_team_name;
std::string defense_team_name;
int num_offense; // Number of offensive players
int num_defense; // Number of defensive players
std::vector<int> offense_nums; // Offensive player numbers
std::vector<int> defense_nums; // Defensive player numbers
};
class HFOEnvironment { class HFOEnvironment {
public: public:
HFOEnvironment(); HFOEnvironment();
~HFOEnvironment(); ~HFOEnvironment();
// Parse a message sent from Trainer to construct an HFO config.
// Returns a bool indicating if the struct was correctly parsed.
static bool ParseHFOConfig(const std::string& message, HFO_Config& config);
// Connect to the server that controls the agent on the specified port. // Connect to the server that controls the agent on the specified port.
void connectToAgentServer(int server_port=6000, void connectToAgentServer(int server_port=6000,
feature_set_t feature_set=HIGH_LEVEL_FEATURE_SET); feature_set_t feature_set=HIGH_LEVEL_FEATURE_SET);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#endif #endif
#include "agent.h" #include "agent.h"
#include "HFO.cpp"
#include "strategy.h" #include "strategy.h"
#include "field_analyzer.h" #include "field_analyzer.h"
...@@ -112,13 +113,6 @@ using namespace rcsc; ...@@ -112,13 +113,6 @@ using namespace rcsc;
float min_feat_val = 1e8; float min_feat_val = 1e8;
float max_feat_val = -1e8; float max_feat_val = -1e8;
// Socket Error
void error(const char *msg)
{
perror(msg);
exit(1);
}
// Minimium and feature values // Minimium and feature values
#define FEAT_MIN -1. #define FEAT_MIN -1.
#define FEAT_MAX 1. #define FEAT_MAX 1.
...@@ -296,7 +290,11 @@ void Agent::clientHandshake() { ...@@ -296,7 +290,11 @@ void Agent::clientHandshake() {
error("[Agent Server] ERROR recv from socket"); error("[Agent Server] ERROR recv from socket");
} }
// Create the corresponding FeatureExtractor // Create the corresponding FeatureExtractor
feature_extractor = getFeatureExtractor(feature_set); if (feature_extractor != NULL) {
delete feature_extractor;
}
feature_extractor = getFeatureExtractor(feature_set, num_teammates,
num_opponents, playing_offense);
// Send the number of features // Send the number of features
int numFeatures = feature_extractor->getNumFeatures(); int numFeatures = feature_extractor->getNumFeatures();
assert(numFeatures > 0); assert(numFeatures > 0);
...@@ -314,11 +312,10 @@ void Agent::clientHandshake() { ...@@ -314,11 +312,10 @@ void Agent::clientHandshake() {
std::cout << "[Agent Server] Handshake complete" << std::endl; std::cout << "[Agent Server] Handshake complete" << std::endl;
} }
FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx) { FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
if (feature_extractor != NULL) { int num_teammates,
delete feature_extractor; int num_opponents,
} bool playing_offense) {
switch (feature_set_indx) { switch (feature_set_indx) {
case LOW_LEVEL_FEATURE_SET: case LOW_LEVEL_FEATURE_SET:
return new LowLevelFeatureExtractor(num_teammates, num_opponents, return new LowLevelFeatureExtractor(num_teammates, num_opponents,
...@@ -335,11 +332,12 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx) { ...@@ -335,11 +332,12 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx) {
} }
} }
hfo_status_t Agent::getGameStatus() { hfo_status_t Agent::getGameStatus(const rcsc::AudioSensor& audio_sensor,
long& lastTrainerMessageTime) {
hfo_status_t game_status = IN_GAME; hfo_status_t game_status = IN_GAME;
if (audioSensor().trainerMessageTime().cycle() > lastTrainerMessageTime) { if (audio_sensor.trainerMessageTime().cycle() > lastTrainerMessageTime) {
lastTrainerMessageTime = audioSensor().trainerMessageTime().cycle(); const std::string& message = audio_sensor.trainerMessage();
const std::string& message = audioSensor().trainerMessage(); bool recognized_message = true;
if (message.compare("GOAL") == 0) { if (message.compare("GOAL") == 0) {
game_status = GOAL; game_status = GOAL;
} else if (message.compare("CAPTURED_BY_DEFENSE") == 0) { } else if (message.compare("CAPTURED_BY_DEFENSE") == 0) {
...@@ -349,8 +347,10 @@ hfo_status_t Agent::getGameStatus() { ...@@ -349,8 +347,10 @@ hfo_status_t Agent::getGameStatus() {
} else if (message.compare("OUT_OF_TIME") == 0) { } else if (message.compare("OUT_OF_TIME") == 0) {
game_status = OUT_OF_TIME; game_status = OUT_OF_TIME;
} else { } else {
std::cout << "[Agent Server] Unrecognized Trainer Message: " << message recognized_message = false;
<< std::endl; }
if (recognized_message) {
lastTrainerMessageTime = audio_sensor.trainerMessageTime().cycle();
} }
} }
return game_status; return game_status;
...@@ -367,7 +367,7 @@ void Agent::actionImpl() { ...@@ -367,7 +367,7 @@ void Agent::actionImpl() {
} }
// Update and send the game status // Update and send the game status
hfo_status_t game_status = getGameStatus(); hfo_status_t game_status = getGameStatus(audioSensor(), lastTrainerMessageTime);
if (send(newsockfd, &game_status, sizeof(int), 0) < 0) { if (send(newsockfd, &game_status, sizeof(int), 0) < 0) {
error("[Agent Server] ERROR sending from socket"); error("[Agent Server] ERROR sending from socket");
} }
......
...@@ -42,6 +42,16 @@ public: ...@@ -42,6 +42,16 @@ public:
virtual ~Agent(); virtual ~Agent();
virtual FieldEvaluator::ConstPtr getFieldEvaluator() const; virtual FieldEvaluator::ConstPtr getFieldEvaluator() const;
// Get the current game status
static hfo_status_t getGameStatus(const rcsc::AudioSensor& audio_sensor,
long& lastTrainerMessageTime);
// Returns the feature extractor corresponding to the feature_set_t
static FeatureExtractor* getFeatureExtractor(feature_set_t feature_set,
int num_teammates,
int num_opponents,
bool playing_offense);
protected: protected:
// You can override this method. But you must call // You can override this method. But you must call
// PlayerAgent::initImpl() in this method. // PlayerAgent::initImpl() in this method.
...@@ -60,18 +70,12 @@ protected: ...@@ -60,18 +70,12 @@ protected:
virtual FieldEvaluator::ConstPtr createFieldEvaluator() const; virtual FieldEvaluator::ConstPtr createFieldEvaluator() const;
virtual ActionGenerator::ConstPtr createActionGenerator() const; virtual ActionGenerator::ConstPtr createActionGenerator() const;
// Get the current game status
hfo_status_t getGameStatus();
// Start the server and listen for a connection. // Start the server and listen for a connection.
void startServer(int server_port=6008); void startServer(int server_port=6008);
// Transmit information to the client and ensure it can recieve. // Transmit information to the client and ensure it can recieve.
void clientHandshake(); void clientHandshake();
// Returns the feature extractor corresponding to the feature_set_t
FeatureExtractor* getFeatureExtractor(feature_set_t feature_set);
protected: protected:
FeatureExtractor* feature_extractor; FeatureExtractor* feature_extractor;
long lastTrainerMessageTime; // Last time the trainer sent a message long lastTrainerMessageTime; // Last time the trainer sent a message
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#endif #endif
#include "sample_player.h" #include "sample_player.h"
#include "agent.h"
#include "strategy.h" #include "strategy.h"
#include "field_analyzer.h" #include "field_analyzer.h"
...@@ -52,6 +53,8 @@ ...@@ -52,6 +53,8 @@
#include "view_tactical.h" #include "view_tactical.h"
#include "intention_receive.h" #include "intention_receive.h"
#include "lowlevel_feature_extractor.h"
#include "highlevel_feature_extractor.h"
#include <rcsc/action/basic_actions.h> #include <rcsc/action/basic_actions.h>
#include <rcsc/action/bhv_emergency.h> #include <rcsc/action/bhv_emergency.h>
...@@ -95,7 +98,12 @@ SamplePlayer::SamplePlayer() ...@@ -95,7 +98,12 @@ SamplePlayer::SamplePlayer()
: PlayerAgent(), : PlayerAgent(),
M_communication(), M_communication(),
M_field_evaluator( createFieldEvaluator() ), M_field_evaluator( createFieldEvaluator() ),
M_action_generator( createActionGenerator() ) M_action_generator( createActionGenerator() ),
feature_extractor(NULL),
lastTrainerMessageTime(-1),
num_teammates(-1),
num_opponents(-1),
playing_offense(false)
{ {
boost::shared_ptr< AudioMemory > audio_memory( new AudioMemory ); boost::shared_ptr< AudioMemory > audio_memory( new AudioMemory );
...@@ -157,7 +165,9 @@ SamplePlayer::SamplePlayer() ...@@ -157,7 +165,9 @@ SamplePlayer::SamplePlayer()
*/ */
SamplePlayer::~SamplePlayer() SamplePlayer::~SamplePlayer()
{ {
if (feature_extractor != NULL) {
delete feature_extractor;
}
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
...@@ -215,6 +225,34 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser ) ...@@ -215,6 +225,34 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser )
return true; return true;
} }
/*! Listen from a message from the trainer that reveals the
configuration of the HFO domain. Use this to populate our HFO_Config
struct.
*/
bool SamplePlayer::getHFOConfig() {
const AudioSensor& audio_sensor = audioSensor();
if (audio_sensor.trainerMessageTime().cycle() > lastTrainerMessageTime) {
const std::string& message = audio_sensor.trainerMessage();
if (HFOEnvironment::ParseHFOConfig(message, hfo_config)) {
lastTrainerMessageTime = audio_sensor.trainerMessageTime().cycle();
if (config().teamName().compare(hfo_config.offense_team_name) == 0) {
playing_offense = true;
} else if (config().teamName().compare(hfo_config.defense_team_name) == 0) {
playing_offense = false;
}
if (playing_offense) {
num_teammates = std::max(0, hfo_config.num_offense - 1);
num_opponents = hfo_config.num_defense;
} else {
num_teammates = std::max(0, hfo_config.num_defense - 1);
num_opponents = hfo_config.num_offense;
}
return true;
}
}
return false;
}
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/*! /*!
main decision main decision
...@@ -223,6 +261,24 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser ) ...@@ -223,6 +261,24 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser )
void void
SamplePlayer::actionImpl() SamplePlayer::actionImpl()
{ {
#ifdef ELOG
if (config().record()) {
if (feature_extractor == NULL) {
if (getHFOConfig()) {
feature_extractor = Agent::getFeatureExtractor(
LOW_LEVEL_FEATURE_SET, num_teammates, num_opponents, playing_offense);
}
} else {
hfo_status_t game_status = Agent::getGameStatus(
audioSensor(), lastTrainerMessageTime);
elog.addText(Logger::WORLD, "GameStatus %d", game_status);
elog.flush();
feature_extractor->ExtractFeatures(this->world());
feature_extractor->LogFeatures();
}
}
#endif
// //
// update strategy and analyzer // update strategy and analyzer
// //
......
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
#ifndef SAMPLE_PLAYER_H #ifndef SAMPLE_PLAYER_H
#define SAMPLE_PLAYER_H #define SAMPLE_PLAYER_H
#include "HFO.hpp"
#include "action_generator.h" #include "action_generator.h"
#include "field_evaluator.h" #include "field_evaluator.h"
#include "communication.h" #include "communication.h"
#include "feature_extractor.h"
#include <rcsc/player/player_agent.h> #include <rcsc/player/player_agent.h>
#include <vector> #include <vector>
...@@ -95,6 +97,16 @@ private: ...@@ -95,6 +97,16 @@ private:
public: public:
virtual virtual
FieldEvaluator::ConstPtr getFieldEvaluator() const; FieldEvaluator::ConstPtr getFieldEvaluator() const;
protected:
// Listens for a HFO Config message
bool getHFOConfig();
HFO_Config hfo_config;
FeatureExtractor* feature_extractor;
long lastTrainerMessageTime;
int num_teammates, num_opponents;
bool playing_offense;
}; };
#endif #endif
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