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
)
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(agent ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/agent.cpp ${SOURCES})
add_library(hfo-lib SHARED ${SOURCE_DIR}/HFO.hpp ${SOURCE_DIR}/HFO.cpp)
......
......@@ -659,6 +659,16 @@ class Trainer(object):
agent = self.launch_agent(agent_num, play_offense=False, port=port)
self._agentPopen.append(agent)
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()
while self.checkLive(necProcesses):
prevFrame = self._frame
......
......@@ -6,8 +6,55 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include <netdb.h>
#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) {
perror(msg);
......
#ifndef __HFO_HPP__
#define __HFO_HPP__
#include <string>
#include <vector>
// For descriptions of the different feature sets see
......@@ -41,11 +42,27 @@ struct Action {
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 {
public:
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.
void connectToAgentServer(int server_port=6000,
feature_set_t feature_set=HIGH_LEVEL_FEATURE_SET);
......
......@@ -29,6 +29,7 @@
#endif
#include "agent.h"
#include "HFO.cpp"
#include "strategy.h"
#include "field_analyzer.h"
......@@ -112,13 +113,6 @@ using namespace rcsc;
float min_feat_val = 1e8;
float max_feat_val = -1e8;
// Socket Error
void error(const char *msg)
{
perror(msg);
exit(1);
}
// Minimium and feature values
#define FEAT_MIN -1.
#define FEAT_MAX 1.
......@@ -296,7 +290,11 @@ void Agent::clientHandshake() {
error("[Agent Server] ERROR recv from socket");
}
// 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
int numFeatures = feature_extractor->getNumFeatures();
assert(numFeatures > 0);
......@@ -314,11 +312,10 @@ void Agent::clientHandshake() {
std::cout << "[Agent Server] Handshake complete" << std::endl;
}
FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx) {
if (feature_extractor != NULL) {
delete feature_extractor;
}
FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
int num_teammates,
int num_opponents,
bool playing_offense) {
switch (feature_set_indx) {
case LOW_LEVEL_FEATURE_SET:
return new LowLevelFeatureExtractor(num_teammates, num_opponents,
......@@ -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;
if (audioSensor().trainerMessageTime().cycle() > lastTrainerMessageTime) {
lastTrainerMessageTime = audioSensor().trainerMessageTime().cycle();
const std::string& message = audioSensor().trainerMessage();
if (audio_sensor.trainerMessageTime().cycle() > lastTrainerMessageTime) {
const std::string& message = audio_sensor.trainerMessage();
bool recognized_message = true;
if (message.compare("GOAL") == 0) {
game_status = GOAL;
} else if (message.compare("CAPTURED_BY_DEFENSE") == 0) {
......@@ -349,8 +347,10 @@ hfo_status_t Agent::getGameStatus() {
} else if (message.compare("OUT_OF_TIME") == 0) {
game_status = OUT_OF_TIME;
} else {
std::cout << "[Agent Server] Unrecognized Trainer Message: " << message
<< std::endl;
recognized_message = false;
}
if (recognized_message) {
lastTrainerMessageTime = audio_sensor.trainerMessageTime().cycle();
}
}
return game_status;
......@@ -367,7 +367,7 @@ void Agent::actionImpl() {
}
// 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) {
error("[Agent Server] ERROR sending from socket");
}
......
......@@ -42,6 +42,16 @@ public:
virtual ~Agent();
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:
// You can override this method. But you must call
// PlayerAgent::initImpl() in this method.
......@@ -60,18 +70,12 @@ protected:
virtual FieldEvaluator::ConstPtr createFieldEvaluator() const;
virtual ActionGenerator::ConstPtr createActionGenerator() const;
// Get the current game status
hfo_status_t getGameStatus();
// Start the server and listen for a connection.
void startServer(int server_port=6008);
// Transmit information to the client and ensure it can recieve.
void clientHandshake();
// Returns the feature extractor corresponding to the feature_set_t
FeatureExtractor* getFeatureExtractor(feature_set_t feature_set);
protected:
FeatureExtractor* feature_extractor;
long lastTrainerMessageTime; // Last time the trainer sent a message
......
......@@ -29,6 +29,7 @@
#endif
#include "sample_player.h"
#include "agent.h"
#include "strategy.h"
#include "field_analyzer.h"
......@@ -52,6 +53,8 @@
#include "view_tactical.h"
#include "intention_receive.h"
#include "lowlevel_feature_extractor.h"
#include "highlevel_feature_extractor.h"
#include <rcsc/action/basic_actions.h>
#include <rcsc/action/bhv_emergency.h>
......@@ -95,7 +98,12 @@ SamplePlayer::SamplePlayer()
: PlayerAgent(),
M_communication(),
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 );
......@@ -157,7 +165,9 @@ SamplePlayer::SamplePlayer()
*/
SamplePlayer::~SamplePlayer()
{
if (feature_extractor != NULL) {
delete feature_extractor;
}
}
/*-------------------------------------------------------------------*/
......@@ -215,6 +225,34 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser )
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
......@@ -223,6 +261,24 @@ SamplePlayer::initImpl( CmdLineParser & cmd_parser )
void
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
//
......
......@@ -27,9 +27,11 @@
#ifndef SAMPLE_PLAYER_H
#define SAMPLE_PLAYER_H
#include "HFO.hpp"
#include "action_generator.h"
#include "field_evaluator.h"
#include "communication.h"
#include "feature_extractor.h"
#include <rcsc/player/player_agent.h>
#include <vector>
......@@ -95,6 +97,16 @@ private:
public:
virtual
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
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