Commit d5665ab8 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Fixes to directly connected agents.

parent 358653d5
......@@ -17,6 +17,8 @@
using namespace hfo;
#define MAX_STEPS 100
HFOEnvironment::HFOEnvironment() {
client = new rcsc::BasicClient();
agent = new Agent();
......@@ -33,7 +35,8 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
int server_port,
std::string server_addr,
std::string team_name,
bool play_goalie) {
bool play_goalie,
std::string record_dir) {
agent->setFeatureSet(feature_set);
rcsc::PlayerConfig& config = agent->mutable_config();
config.setConfigDir(config_dir);
......@@ -42,6 +45,10 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
config.setHost(server_addr);
config.setTeamName(team_name);
config.setGoalie(play_goalie);
if (!record_dir.empty()) {
config.setLogDir(record_dir);
config.setRecord(true);
}
if (!agent->init(client, 0, NULL)) {
std::cerr << "Init failed" << std::endl;
exit(1);
......@@ -52,8 +59,13 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set,
exit(1);
}
assert(client->isServerAlive() == true);
// Do nothing until the agent begins getting state features
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() {
}
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;
long start_cycle = agent->cycle();
while ((agent->cycle() <= start_cycle)
|| (agent->getLastDecisionTime() < agent->cycle())
|| (end_of_trial && agent->getGameStatus() != IN_GAME)) {
bool still_eot = false;
int steps = 0;
do {
client->runStep(agent);
if (steps++ > MAX_STEPS) {
break;
}
if (!client->isServerAlive()) {
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();
}
......@@ -33,7 +33,8 @@ class HFOEnvironment {
int server_port=6000,
std::string server_addr="localhost",
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.
const std::vector<float>& getState();
......
......@@ -99,9 +99,8 @@ Agent::Agent()
feature_extractor(NULL),
lastTrainerMessageTime(-1),
lastTeammateMessageTime(-1),
lastDecisionTime(-1),
game_status(IN_GAME),
action(NOOP)
requested_action(NOOP)
{
boost::shared_ptr< AudioMemory > audio_memory( new AudioMemory );
......@@ -178,7 +177,7 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) {
const std::list<std::string>& args = cmd_parser.args();
if (std::find(args.begin(), args.end(), "--record") != args.end()) {
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"
<< " and recompile with -DELOG. See CMakeLists.txt"
<< std::endl;
......@@ -218,71 +217,36 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
playing_offense);
break;
default:
std::cerr << "[Feature Extractor] ERROR Unrecognized Feature set index: "
std::cerr << "ERROR: Unrecognized Feature set index: "
<< feature_set_indx << std::endl;
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
virtual method in super class
*/
void Agent::actionImpl() {
lastDecisionTime = world().time().cycle();
// For now let's not worry about turning the neck or setting the vision.
this->setViewAction(new View_Tactical());
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();
if (requested_action < 0) {
std::cerr << "ERROR: No action. Did you forget to call act()?" << std::endl;
exit(1);
}
// 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();
if (hfo::NumParams(requested_action) > params.size()) {
std::cerr << "ERROR: Not enough params for requested action! Action "
<< ActionToString(requested_action) << " requires "
<< hfo::NumParams(requested_action)
<< " parameters, given " << params.size() << std::endl;
exit(1);
}
#ifdef ELOG
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) {
switch(requested_action) {
case DASH:
this->doDash(params[0], params[1]);
break;
......@@ -337,13 +301,19 @@ void Agent::actionImpl() {
case NOOP:
break;
case QUIT:
std::cout << "[Agent Server] Got quit from agent." << std::endl;
std::cout << "Got quit from agent." << std::endl;
exit(0);
default:
std::cerr << "[Agent Server] ERROR Unsupported Action: "
<< action << std::endl;
std::cerr << "ERROR: Unsupported Action: "
<< requested_action << std::endl;
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() {
void
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()
void
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
// can conflict with our comm messages.
// if ( M_communication )
......
......@@ -27,6 +27,9 @@ protected:
// PlayerAgent::initImpl() in this method.
virtual bool initImpl(rcsc::CmdLineParser& cmd_parser);
// We override PlayerAgent's Action function
virtual void action();
// main decision
virtual void actionImpl();
......@@ -45,12 +48,11 @@ protected:
FeatureExtractor* feature_extractor; // Extracts the features
long lastTrainerMessageTime; // Last time the trainer 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::Player player_on_ball; // Player in posession of the ball
std::vector<float> state; // Vector of current state features
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
public:
......@@ -58,12 +60,10 @@ protected:
inline hfo::status_t getGameStatus() { return game_status; }
inline const hfo::Player& getPlayerOnBall() { return player_on_ball; }
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 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; }
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