Commit d5665ab8 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Fixes to directly connected agents.

parent 358653d5
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
using namespace hfo; using namespace hfo;
#define MAX_STEPS 100
HFOEnvironment::HFOEnvironment() { HFOEnvironment::HFOEnvironment() {
client = new rcsc::BasicClient(); client = new rcsc::BasicClient();
agent = new Agent(); agent = new Agent();
...@@ -33,7 +35,8 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set, ...@@ -33,7 +35,8 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
int server_port, int server_port,
std::string server_addr, std::string server_addr,
std::string team_name, std::string team_name,
bool play_goalie) { bool play_goalie,
std::string record_dir) {
agent->setFeatureSet(feature_set); agent->setFeatureSet(feature_set);
rcsc::PlayerConfig& config = agent->mutable_config(); rcsc::PlayerConfig& config = agent->mutable_config();
config.setConfigDir(config_dir); config.setConfigDir(config_dir);
...@@ -42,6 +45,10 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set, ...@@ -42,6 +45,10 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
config.setHost(server_addr); config.setHost(server_addr);
config.setTeamName(team_name); config.setTeamName(team_name);
config.setGoalie(play_goalie); config.setGoalie(play_goalie);
if (!record_dir.empty()) {
config.setLogDir(record_dir);
config.setRecord(true);
}
if (!agent->init(client, 0, NULL)) { if (!agent->init(client, 0, NULL)) {
std::cerr << "Init failed" << std::endl; std::cerr << "Init failed" << std::endl;
exit(1); exit(1);
...@@ -52,8 +59,13 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set, ...@@ -52,8 +59,13 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
exit(1); exit(1);
} }
assert(client->isServerAlive() == true); assert(client->isServerAlive() == true);
// Do nothing until the agent begins getting state features
while (agent->getState().empty()) { while (agent->getState().empty()) {
step(); act(NOOP);
agent->executeAction();
do {
client->runStep(agent);
} while (agent->lastPreActionTime() < agent->currentTime());
} }
} }
...@@ -95,15 +107,36 @@ Player HFOEnvironment::playerOnBall() { ...@@ -95,15 +107,36 @@ Player HFOEnvironment::playerOnBall() {
} }
status_t HFOEnvironment::step() { status_t HFOEnvironment::step() {
// Agent sends action to server
agent->executeAction();
// Wait until server replies with new game state
long start_cycle = agent->currentTime().cycle();
bool cycle_advanced = false;
bool end_of_trial = agent->getGameStatus() != IN_GAME; bool end_of_trial = agent->getGameStatus() != IN_GAME;
long start_cycle = agent->cycle(); bool still_eot = false;
while ((agent->cycle() <= start_cycle) int steps = 0;
|| (agent->getLastDecisionTime() < agent->cycle()) do {
|| (end_of_trial && agent->getGameStatus() != IN_GAME)) {
client->runStep(agent); client->runStep(agent);
if (steps++ > MAX_STEPS) {
break;
}
if (!client->isServerAlive()) { if (!client->isServerAlive()) {
return SERVER_DOWN; return SERVER_DOWN;
} }
cycle_advanced = agent->currentTime().cycle() > start_cycle;
} while (!cycle_advanced || agent->lastPreActionTime() < agent->currentTime());
// If the trial is over, wait until the next episode starts
if (end_of_trial) {
while (agent->getGameStatus() != IN_GAME) {
act(NOOP);
agent->executeAction();
do {
client->runStep(agent);
if (!client->isServerAlive()) {
return SERVER_DOWN;
}
} while (agent->lastPreActionTime() < agent->currentTime());
}
} }
return agent->getGameStatus(); return agent->getGameStatus();
} }
...@@ -33,7 +33,8 @@ class HFOEnvironment { ...@@ -33,7 +33,8 @@ class HFOEnvironment {
int server_port=6000, int server_port=6000,
std::string server_addr="localhost", std::string server_addr="localhost",
std::string team_name="base_left", std::string team_name="base_left",
bool play_goalie=false); bool play_goalie=false,
std::string record_dir="");
// Get the current state of the domain. Returns a reference to feature_vec. // Get the current state of the domain. Returns a reference to feature_vec.
const std::vector<float>& getState(); const std::vector<float>& getState();
......
...@@ -99,9 +99,8 @@ Agent::Agent() ...@@ -99,9 +99,8 @@ Agent::Agent()
feature_extractor(NULL), feature_extractor(NULL),
lastTrainerMessageTime(-1), lastTrainerMessageTime(-1),
lastTeammateMessageTime(-1), lastTeammateMessageTime(-1),
lastDecisionTime(-1),
game_status(IN_GAME), game_status(IN_GAME),
action(NOOP) requested_action(NOOP)
{ {
boost::shared_ptr< AudioMemory > audio_memory( new AudioMemory ); boost::shared_ptr< AudioMemory > audio_memory( new AudioMemory );
...@@ -178,7 +177,7 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) { ...@@ -178,7 +177,7 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) {
const std::list<std::string>& args = cmd_parser.args(); const std::list<std::string>& args = cmd_parser.args();
if (std::find(args.begin(), args.end(), "--record") != args.end()) { if (std::find(args.begin(), args.end(), "--record") != args.end()) {
std::cerr std::cerr
<< "[Agent Client] ERROR: Action recording requested but no supported." << "ERROR: Action recording requested but no supported."
<< " To enable action recording, install https://github.com/mhauskn/librcsc" << " To enable action recording, install https://github.com/mhauskn/librcsc"
<< " and recompile with -DELOG. See CMakeLists.txt" << " and recompile with -DELOG. See CMakeLists.txt"
<< std::endl; << std::endl;
...@@ -218,71 +217,36 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx, ...@@ -218,71 +217,36 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
playing_offense); playing_offense);
break; break;
default: default:
std::cerr << "[Feature Extractor] ERROR Unrecognized Feature set index: " std::cerr << "ERROR: Unrecognized Feature set index: "
<< feature_set_indx << std::endl; << feature_set_indx << std::endl;
exit(1); exit(1);
} }
} }
// Instead of calling PlayerAgent::action() we instead call preAction
// which does everything up to actionImpl(). actionImpl() is then
// called in hfo::step(), PlayerAgent::executeAction().
void Agent::action() {
preAction();
}
/*! /*!
main decision main decision
virtual method in super class virtual method in super class
*/ */
void Agent::actionImpl() { void Agent::actionImpl() {
lastDecisionTime = world().time().cycle(); if (requested_action < 0) {
// For now let's not worry about turning the neck or setting the vision. std::cerr << "ERROR: No action. Did you forget to call act()?" << std::endl;
this->setViewAction(new View_Tactical()); exit(1);
this->setNeckAction(new Neck_TurnToBallOrScan());
// Process new trainer messages
if (audioSensor().trainerMessageTime().cycle() > lastTrainerMessageTime) {
const std::string& message = audioSensor().trainerMessage();
if (feature_extractor == NULL) {
hfo::Config hfo_config;
if (hfo::ParseConfig(message, hfo_config)) {
bool playing_offense = world().ourSide() == rcsc::LEFT;
int num_teammates = playing_offense ?
hfo_config.num_offense - 1 : hfo_config.num_defense - 1;
int num_opponents = playing_offense ?
hfo_config.num_defense : hfo_config.num_offense;
feature_extractor = getFeatureExtractor(
feature_set, num_teammates, num_opponents, playing_offense);
}
}
hfo::ParseGameStatus(message, game_status);
hfo::ParsePlayerOnBall(message, player_on_ball);
lastTrainerMessageTime = audioSensor().trainerMessageTime().cycle();
} }
// Process new teammate message if (hfo::NumParams(requested_action) > params.size()) {
hear_msg.clear(); std::cerr << "ERROR: Not enough params for requested action! Action "
if (audioSensor().teammateMessageTime().cycle() > lastTeammateMessageTime) { << ActionToString(requested_action) << " requires "
const std::list<HearMessage> teammateMessages = audioSensor().teammateMessages(); << hfo::NumParams(requested_action)
for (std::list<HearMessage>::const_iterator msgIter = teammateMessages.begin(); << " parameters, given " << params.size() << std::endl;
msgIter != teammateMessages.end(); msgIter++) { exit(1);
if ((*msgIter).unum_ != world().self().unum()) {
hear_msg = (*msgIter).str_;
break; // For now we just take one.
}
}
lastTeammateMessageTime = audioSensor().teammateMessageTime().cycle();
} }
#ifdef ELOG switch(requested_action) {
if (config().record() && feature_extractor != NULL) {
elog.addText(Logger::WORLD, "GameStatus %d", game_status);
elog.flush();
feature_extractor->LogFeatures();
}
#endif
// Update state features
if (feature_extractor != NULL) {
state = feature_extractor->ExtractFeatures(this->world());
}
if (!say_msg.empty()) {
addSayMessage(new CustomMessage(say_msg));
say_msg.clear();
}
// Execute the action
assert(hfo::NumParams(action) <= params.size());
switch(action) {
case DASH: case DASH:
this->doDash(params[0], params[1]); this->doDash(params[0], params[1]);
break; break;
...@@ -337,13 +301,19 @@ void Agent::actionImpl() { ...@@ -337,13 +301,19 @@ void Agent::actionImpl() {
case NOOP: case NOOP:
break; break;
case QUIT: case QUIT:
std::cout << "[Agent Server] Got quit from agent." << std::endl; std::cout << "Got quit from agent." << std::endl;
exit(0); exit(0);
default: default:
std::cerr << "[Agent Server] ERROR Unsupported Action: " std::cerr << "ERROR: Unsupported Action: "
<< action << std::endl; << requested_action << std::endl;
exit(1); exit(1);
} }
// Clear the action
requested_action = (hfo::action_t) -1;
params.clear();
// For now let's not worry about turning the neck or setting the vision.
this->setViewAction(new View_Tactical());
this->setNeckAction(new Neck_TurnToBallOrScan());
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
...@@ -353,7 +323,53 @@ void Agent::actionImpl() { ...@@ -353,7 +323,53 @@ void Agent::actionImpl() {
void void
Agent::handleActionStart() Agent::handleActionStart()
{ {
// Process new trainer messages
if (audioSensor().trainerMessageTime().cycle() > lastTrainerMessageTime) {
const std::string& message = audioSensor().trainerMessage();
if (feature_extractor == NULL) {
hfo::Config hfo_config;
if (hfo::ParseConfig(message, hfo_config)) {
bool playing_offense = world().ourSide() == rcsc::LEFT;
int num_teammates = playing_offense ?
hfo_config.num_offense - 1 : hfo_config.num_defense - 1;
int num_opponents = playing_offense ?
hfo_config.num_defense : hfo_config.num_offense;
feature_extractor = getFeatureExtractor(
feature_set, num_teammates, num_opponents, playing_offense);
}
}
hfo::ParseGameStatus(message, game_status);
hfo::ParsePlayerOnBall(message, player_on_ball);
lastTrainerMessageTime = audioSensor().trainerMessageTime().cycle();
}
// Process new teammate message
hear_msg.clear();
if (audioSensor().teammateMessageTime().cycle() > lastTeammateMessageTime) {
const std::list<HearMessage> teammateMessages = audioSensor().teammateMessages();
for (std::list<HearMessage>::const_iterator msgIter = teammateMessages.begin();
msgIter != teammateMessages.end(); msgIter++) {
if ((*msgIter).unum_ != world().self().unum()) {
hear_msg = (*msgIter).str_;
break; // For now we just take one.
}
}
lastTeammateMessageTime = audioSensor().teammateMessageTime().cycle();
}
// Update state features
if (feature_extractor != NULL) {
state = feature_extractor->ExtractFeatures(this->world());
}
// Optionally write to logfile
#ifdef ELOG
if (config().record() && feature_extractor != NULL) {
elog.addText(Logger::WORLD, "GameStatus %d", game_status);
elog.flush();
feature_extractor->LogFeatures();
}
#endif
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
...@@ -531,6 +547,11 @@ Agent::handlePlayerType() ...@@ -531,6 +547,11 @@ Agent::handlePlayerType()
void void
Agent::communicationImpl() Agent::communicationImpl()
{ {
// Say the outgoing message
if (!say_msg.empty()) {
addSayMessage(new CustomMessage(say_msg));
say_msg.clear();
}
// Disabled since it adds default communication messages which // Disabled since it adds default communication messages which
// can conflict with our comm messages. // can conflict with our comm messages.
// if ( M_communication ) // if ( M_communication )
......
...@@ -27,6 +27,9 @@ protected: ...@@ -27,6 +27,9 @@ protected:
// PlayerAgent::initImpl() in this method. // PlayerAgent::initImpl() in this method.
virtual bool initImpl(rcsc::CmdLineParser& cmd_parser); virtual bool initImpl(rcsc::CmdLineParser& cmd_parser);
// We override PlayerAgent's Action function
virtual void action();
// main decision // main decision
virtual void actionImpl(); virtual void actionImpl();
...@@ -45,12 +48,11 @@ protected: ...@@ -45,12 +48,11 @@ protected:
FeatureExtractor* feature_extractor; // Extracts the features FeatureExtractor* feature_extractor; // Extracts the features
long lastTrainerMessageTime; // Last time the trainer sent a message long lastTrainerMessageTime; // Last time the trainer sent a message
long lastTeammateMessageTime; // Last time a teammate sent a message long lastTeammateMessageTime; // Last time a teammate sent a message
long lastDecisionTime; // Last time we made a decision
hfo::status_t game_status; // Current status of the game hfo::status_t game_status; // Current status of the game
hfo::Player player_on_ball; // Player in posession of the ball hfo::Player player_on_ball; // Player in posession of the ball
std::vector<float> state; // Vector of current state features std::vector<float> state; // Vector of current state features
std::string say_msg, hear_msg; // Messages to/from teammates std::string say_msg, hear_msg; // Messages to/from teammates
hfo::action_t action; // Currently requested action hfo::action_t requested_action; // Currently requested action
std::vector<float> params; // Parameters of current action std::vector<float> params; // Parameters of current action
public: public:
...@@ -58,12 +60,10 @@ protected: ...@@ -58,12 +60,10 @@ protected:
inline hfo::status_t getGameStatus() { return game_status; } inline hfo::status_t getGameStatus() { return game_status; }
inline const hfo::Player& getPlayerOnBall() { return player_on_ball; } inline const hfo::Player& getPlayerOnBall() { return player_on_ball; }
inline const std::string& getHearMsg() { return hear_msg; } inline const std::string& getHearMsg() { return hear_msg; }
inline long cycle() { return world().time().cycle(); }
inline long getLastDecisionTime() { return lastDecisionTime; }
inline void setFeatureSet(hfo::feature_set_t fset) { feature_set = fset; } inline void setFeatureSet(hfo::feature_set_t fset) { feature_set = fset; }
inline std::vector<float>* mutable_params() { return &params; } inline std::vector<float>* mutable_params() { return &params; }
inline void setAction(hfo::action_t a) { action = a; } inline void setAction(hfo::action_t a) { requested_action = a; }
inline void setSayMsg(const std::string& message) { say_msg = message; } inline void setSayMsg(const std::string& message) { say_msg = message; }
private: private:
......
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