Commit 0104ff75 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Merge pull request #18 from sanmit/master

Updated referee model to broadcast last player to touch the ball
parents 2687b320 63c3fb68
...@@ -215,18 +215,23 @@ class Trainer(object): ...@@ -215,18 +215,23 @@ class Trainer(object):
assert body[0] == 'referee', 'Expected referee message.' assert body[0] == 'referee', 'Expected referee message.'
_,ts,event = body _,ts,event = body
self._frame = int(ts) self._frame = int(ts)
if event == 'GOAL': endOfTrial = False
if 'GOAL' in event:
self._numGoals += 1 self._numGoals += 1
self._numGoalFrames += self._frame - self._lastTrialStart self._numGoalFrames += self._frame - self._lastTrialStart
endOfTrial = True
elif event == 'OUT_OF_BOUNDS': elif event == 'OUT_OF_BOUNDS':
self._numBallsOOB += 1 self._numBallsOOB += 1
elif event == 'CAPTURED_BY_DEFENSE': endOfTrial = True
elif 'CAPTURED_BY_DEFENSE' in event:
self._numBallsCaptured += 1 self._numBallsCaptured += 1
endOfTrial = True
elif event == 'OUT_OF_TIME': elif event == 'OUT_OF_TIME':
self._numOutOfTime += 1 self._numOutOfTime += 1
endOfTrial = True
elif event == 'HFO_FINISHED': elif event == 'HFO_FINISHED':
self._done = True self._done = True
if event in {'GOAL','OUT_OF_BOUNDS','CAPTURED_BY_DEFENSE','OUT_OF_TIME'}: if endOfTrial:
self._numTrials += 1 self._numTrials += 1
print 'EndOfTrial: %d / %d %d %s'%\ print 'EndOfTrial: %d / %d %d %s'%\
(self._numGoals, self._numTrials, self._frame, event) (self._numGoals, self._numTrials, self._frame, event)
......
...@@ -39,18 +39,18 @@ if __name__ == '__main__': ...@@ -39,18 +39,18 @@ if __name__ == '__main__':
hfo_env.say('Message') hfo_env.say('Message')
status = hfo_env.step() status = hfo_env.step()
print 'Episode', episode, 'ended with', print 'Episode', episode, 'ended with',
# Check what the outcome of the episode was # Check what the outcome of the episode was
if status == HFO_Status.GOAL: if status == HFO_Status.GOAL:
print 'goal' print 'goal', hfo.playerOnBall().unum
elif status == HFO_Status.CAPTURED_BY_DEFENSE: elif status == HFO_Status.CAPTURED_BY_DEFENSE:
print 'captured by defense' print 'captured by defense', hfo.playerOnBall().unum
elif status == HFO_Status.OUT_OF_BOUNDS: elif status == HFO_Status.OUT_OF_BOUNDS:
print 'out of bounds' print 'out of bounds'
elif status == HFO_Status.OUT_OF_TIME: elif status == HFO_Status.OUT_OF_TIME:
print 'out of time' print 'out of time'
else: else:
print 'Unknown status', status print 'Unknown status', status
exit() exit()
# Cleanup when finished # Cleanup when finished
hfo_env.cleanup() hfo_env.cleanup()
...@@ -19,21 +19,21 @@ if __name__ == '__main__': ...@@ -19,21 +19,21 @@ if __name__ == '__main__':
# Connect to the agent server on port 6000 with the specified # Connect to the agent server on port 6000 with the specified
# feature set. See feature sets in hfo.py/hfo.hpp. # feature set. See feature sets in hfo.py/hfo.hpp.
hfo.connectToAgentServer(port, HFO_Features.HIGH_LEVEL_FEATURE_SET) hfo.connectToAgentServer(port, HFO_Features.HIGH_LEVEL_FEATURE_SET)
# Play 5 episodes # Play 100 episodes
for episode in xrange(5): for episode in xrange(100):
status = HFO_Status.IN_GAME status = HFO_Status.IN_GAME
while status == HFO_Status.IN_GAME: while status == HFO_Status.IN_GAME:
# Grab the state features from the environment # Grab the state features from the environment
features = hfo.getState() features = hfo.getState()
# Take an action and get the current game status # Take an action and get the current game status
hfo.act(HFO_Actions.DASH, 20.0, 0) hfo.act(HFO_Actions.DASH, 20.0, 0)
hfo.step() status = hfo.step()
print 'Episode', episode, 'ended with', print 'Episode', episode, 'ended with',
# Check what the outcome of the episode was # Check what the outcome of the episode was
if status == HFO_Status.GOAL: if status == HFO_Status.GOAL:
print 'goal' print 'goal', hfo.playerOnBall().unum
elif status == HFO_Status.CAPTURED_BY_DEFENSE: elif status == HFO_Status.CAPTURED_BY_DEFENSE:
print 'captured by defense' print 'captured by defense', hfo.playerOnBall().unum
elif status == HFO_Status.OUT_OF_BOUNDS: elif status == HFO_Status.OUT_OF_BOUNDS:
print 'out of bounds' print 'out of bounds'
elif status == HFO_Status.OUT_OF_TIME: elif status == HFO_Status.OUT_OF_TIME:
......
...@@ -36,6 +36,26 @@ int main(int argc, char** argv) { ...@@ -36,6 +36,26 @@ int main(int argc, char** argv) {
// Advance the environment and get the game status // Advance the environment and get the game status
status = hfo.step(); status = hfo.step();
} }
// Check what the outcome of the episode was
cout << "Episode " << episode << " ended with status: ";
switch (status) {
case GOAL:
cout << "goal " << hfo.playerOnBall().unum << endl;
break;
case CAPTURED_BY_DEFENSE:
cout << "captured by defense " << hfo.playerOnBall().unum << endl;
break;
case OUT_OF_BOUNDS:
cout << "out of bounds" << endl;
break;
case OUT_OF_TIME:
cout << "out of time" << endl;
break;
default:
cout << "Unknown status " << status << endl;
exit(1);
}
} }
hfo.act(QUIT); hfo.act(QUIT);
}; };
...@@ -46,6 +46,25 @@ int main(int argc, char** argv) { ...@@ -46,6 +46,25 @@ int main(int argc, char** argv) {
// Advance the environment and get the game status // Advance the environment and get the game status
status = hfo.step(); status = hfo.step();
} }
// Check what the outcome of the episode was
cout << "Episode " << episode << " ended with status: ";
switch (status) {
case GOAL:
cout << "goal " << hfo.playerOnBall().unum << endl;
break;
case CAPTURED_BY_DEFENSE:
cout << "captured by defense " << hfo.playerOnBall().unum << endl;
break;
case OUT_OF_BOUNDS:
cout << "out of bounds" << endl;
break;
case OUT_OF_TIME:
cout << "out of time" << endl;
break;
default:
cout << "Unknown status " << status << endl;
exit(1);
}
} }
hfo.act(QUIT); hfo.act(QUIT);
}; };
import socket, struct, thread, time import socket, struct, thread, time, collections
class HFO_Features: class HFO_Features:
''' An enum of the possible HFO feature sets. For descriptions see ''' An enum of the possible HFO feature sets. For descriptions see
...@@ -30,10 +30,17 @@ class HFO_Actions: ...@@ -30,10 +30,17 @@ class HFO_Actions:
DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \ DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \
MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT = range(15) MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT = range(15)
HFO_Player = collections.namedtuple("HFO_Player", "side unum")
class HFO_Status: class HFO_Status:
''' Current status of the HFO game. ''' ''' Current status of the HFO game. '''
IN_GAME, GOAL, CAPTURED_BY_DEFENSE, OUT_OF_BOUNDS, OUT_OF_TIME = range(5) IN_GAME, GOAL, CAPTURED_BY_DEFENSE, OUT_OF_BOUNDS, OUT_OF_TIME = range(5)
class HFO_SideID:
''' Team side for a player or object'''
RIGHT, NEUTRAL, LEFT = range(-1, 2)
class HFOEnvironment(object): 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
...@@ -47,6 +54,7 @@ class HFOEnvironment(object): ...@@ -47,6 +54,7 @@ class HFOEnvironment(object):
self.requested_action = None # Action to execute and parameters self.requested_action = None # Action to execute and parameters
self.say_msg = '' # Outgoing message to say self.say_msg = '' # Outgoing message to say
self.hear_msg = '' # Incoming heard message self.hear_msg = '' # Incoming heard message
self.player_on_ball = None # Current player holding the ball
def NumParams(self, action_type): def NumParams(self, action_type):
''' Returns the number of required parameters for each action type. ''' ''' Returns the number of required parameters for each action type. '''
...@@ -117,8 +125,9 @@ class HFOEnvironment(object): ...@@ -117,8 +125,9 @@ class HFOEnvironment(object):
# Send what we recieved # Send what we recieved
self.socket.send(struct.pack("i", self.numFeatures)) self.socket.send(struct.pack("i", self.numFeatures))
# Get the current game status # Get the current game status
data = self.socket.recv(struct.calcsize("i")) data = self.socket.recv(struct.calcsize("iii"))
status = struct.unpack("i", data)[0] status, side, unum = struct.unpack("iii", data)
self.player_on_ball = HFO_Player(side,unum)
assert status == HFO_Status.IN_GAME, "Status check failed" assert status == HFO_Status.IN_GAME, "Status check failed"
print '[Agent Client] Handshake complete' print '[Agent Client] Handshake complete'
...@@ -144,6 +153,10 @@ class HFOEnvironment(object): ...@@ -144,6 +153,10 @@ class HFOEnvironment(object):
''' Receive incoming communications from other players. ''' ''' Receive incoming communications from other players. '''
return self.hear_msg return self.hear_msg
def playerOnBall(self):
''' Get the current player holding the ball'''
return self.player_on_ball
def step(self): def step(self):
''' Indicates the agent is done and the environment should ''' Indicates the agent is done and the environment should
progress. Returns the game status after the step''' progress. Returns the game status after the step'''
...@@ -157,8 +170,9 @@ class HFOEnvironment(object): ...@@ -157,8 +170,9 @@ class HFOEnvironment(object):
self.say_msg = '' self.say_msg = ''
# Get the current game status # Get the current game status
data = self.socket.recv(struct.calcsize("i")) data = self.socket.recv(struct.calcsize("iii"))
status = struct.unpack("i", data)[0] status, side, unum = struct.unpack("iii", data)
self.player_on_ball = HFO_Player(side,unum)
# Get the next state features # Get the next state features
state_data = self.socket.recv(struct.calcsize('f')*self.numFeatures) state_data = self.socket.recv(struct.calcsize('f')*self.numFeatures)
......
...@@ -248,17 +248,19 @@ void HFOEnvironment::handshakeAgentServer(feature_set_t feature_set) { ...@@ -248,17 +248,19 @@ void HFOEnvironment::handshakeAgentServer(feature_set_t feature_set) {
exit(1); exit(1);
} }
// Recieve the game status // Recieve the game status
status_t status; int game_status[3];
if (recv(sockfd, &status, sizeof(status_t), 0) < 0) { if (recv(sockfd, &(game_status[0]), 3 * sizeof(int), 0) < 0) {
perror("[Agent Client] ERROR recv from socket"); perror("[Agent Client] ERROR receiving game status from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
if (status != IN_GAME) { if (game_status[0] != IN_GAME) {
std::cout << "[Agent Client] Handshake failed: status check." << std::endl; std::cout << "[Agent Client] Handshake failed: status check." << std::endl;
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
player_on_ball.side = (SideID)game_status[1];
player_on_ball.unum = game_status[2];
std::cout << "[Agent Client] Handshake complete" << std::endl; std::cout << "[Agent Client] Handshake complete" << std::endl;
} }
...@@ -289,6 +291,10 @@ std::string HFOEnvironment::hear() { ...@@ -289,6 +291,10 @@ std::string HFOEnvironment::hear() {
return hear_msg; return hear_msg;
} }
Player HFOEnvironment::playerOnBall(){
return player_on_ball;
}
status_t HFOEnvironment::step() { status_t HFOEnvironment::step() {
status_t game_status; status_t game_status;
...@@ -328,14 +334,19 @@ status_t HFOEnvironment::step() { ...@@ -328,14 +334,19 @@ status_t HFOEnvironment::step() {
say_msg.clear(); say_msg.clear();
// Get the game status // Get the game status
if (recv(sockfd, &game_status, sizeof(status_t), 0) < 0) { int full_status[3];
perror("[Agent Client] ERROR recieving from socket"); if (recv(sockfd, &(full_status[0]), 3 * sizeof(int), 0) < 0) {
perror("[Agent Client] ERROR receiving game status from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
game_status = (status_t)full_status[0];
player_on_ball.side = (SideID)full_status[1];
player_on_ball.unum = full_status[2];
// Get the next game state // Get the next game state
if (recv(sockfd, &(feature_vec.front()), numFeatures * sizeof(float), 0) < 0) { if (recv(sockfd, &(feature_vec.front()), numFeatures * sizeof(float), 0) < 0) {
perror("[Agent Client] ERROR recieving state features from socket"); perror("[Agent Client] ERROR receiving state features from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
...@@ -345,7 +356,7 @@ status_t HFOEnvironment::step() { ...@@ -345,7 +356,7 @@ status_t HFOEnvironment::step() {
// Message length // Message length
uint32_t msgLength; uint32_t msgLength;
if (recv(sockfd, &msgLength, sizeof(uint32_t), 0) < 0){ if (recv(sockfd, &msgLength, sizeof(uint32_t), 0) < 0){
perror("[Agent Client] ERROR recieving hear message length from socket"); perror("[Agent Client] ERROR receiving hear message length from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
...@@ -354,7 +365,7 @@ status_t HFOEnvironment::step() { ...@@ -354,7 +365,7 @@ status_t HFOEnvironment::step() {
std::vector<char> hearMsgBuffer; std::vector<char> hearMsgBuffer;
hearMsgBuffer.resize(msgLength); hearMsgBuffer.resize(msgLength);
if (recv(sockfd, &hearMsgBuffer[0], msgLength, 0) < 0){ if (recv(sockfd, &hearMsgBuffer[0], msgLength, 0) < 0){
perror("[Agent Client] ERROR recieving hear message from socket"); perror("[Agent Client] ERROR receiving hear message from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
......
...@@ -52,6 +52,12 @@ enum status_t ...@@ -52,6 +52,12 @@ enum status_t
OUT_OF_TIME // Trial has ended due to time limit OUT_OF_TIME // Trial has ended due to time limit
}; };
enum SideID {
RIGHT = -1,
NEUTRAL = 0,
LEFT = 1
};
// Configuration of the HFO domain including the team names and player // Configuration of the HFO domain including the team names and player
// numbers for each team. This struct is populated by ParseConfig(). // numbers for each team. This struct is populated by ParseConfig().
struct Config { struct Config {
...@@ -63,6 +69,11 @@ struct Config { ...@@ -63,6 +69,11 @@ struct Config {
std::vector<int> defense_nums; // Defensive player numbers std::vector<int> defense_nums; // Defensive player numbers
}; };
struct Player {
SideID side;
int unum;
};
class HFOEnvironment { class HFOEnvironment {
public: public:
HFOEnvironment(); HFOEnvironment();
...@@ -92,6 +103,9 @@ class HFOEnvironment { ...@@ -92,6 +103,9 @@ class HFOEnvironment {
virtual void say(const std::string& message); virtual void say(const std::string& message);
virtual std::string hear(); virtual std::string hear();
// Get the current player holding the ball
virtual Player playerOnBall();
// Indicates the agent is done and the environment should // Indicates the agent is done and the environment should
// progress. Returns the game status after the step // progress. Returns the game status after the step
virtual status_t step(); virtual status_t step();
...@@ -103,6 +117,7 @@ class HFOEnvironment { ...@@ -103,6 +117,7 @@ class HFOEnvironment {
action_t requested_action; // Action requested action_t requested_action; // Action requested
std::vector<float> action_params; // Action parameters std::vector<float> action_params; // Action parameters
std::string say_msg, hear_msg; // Messages to hear/say std::string say_msg, hear_msg; // Messages to hear/say
Player player_on_ball;
// Handshake with the agent server to ensure data is being correctly // Handshake with the agent server to ensure data is being correctly
// passed. Also sets the number of features to expect. // passed. Also sets the number of features to expect.
......
...@@ -364,28 +364,52 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx, ...@@ -364,28 +364,52 @@ FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
} }
} }
status_t Agent::getGameStatus(const rcsc::AudioSensor& audio_sensor, std::vector<int> Agent::getGameStatus(const rcsc::AudioSensor& audio_sensor,
long& lastTrainerMessageTime) { long& lastTrainerMessageTime) {
std::vector<int> status;
status_t game_status = IN_GAME; status_t game_status = IN_GAME;
int playerIndex = -1; // Keeps track of which defender stopped the shot
int playerTeam = hfo::LEFT;
if (audio_sensor.trainerMessageTime().cycle() > lastTrainerMessageTime) { if (audio_sensor.trainerMessageTime().cycle() > lastTrainerMessageTime) {
const std::string& message = audio_sensor.trainerMessage(); const std::string& message = audio_sensor.trainerMessage();
bool recognized_message = true; bool recognized_message = true;
if (message.compare("GOAL") == 0) { if (message.find("GOAL") != std::string::npos){
playerIndex = atoi((message.substr(message.find("-")+1)).c_str());
playerTeam = hfo::LEFT;
game_status = GOAL; game_status = GOAL;
} else if (message.compare("CAPTURED_BY_DEFENSE") == 0) { } else if (message.find("CAPTURED_BY_DEFENSE") != std::string::npos) {
playerIndex = atoi((message.substr(message.find("-")+1)).c_str());
playerTeam = hfo::RIGHT;
game_status = CAPTURED_BY_DEFENSE; game_status = CAPTURED_BY_DEFENSE;
} else if (message.compare("OUT_OF_BOUNDS") == 0) { } else if (message.compare("OUT_OF_BOUNDS") == 0) {
game_status = OUT_OF_BOUNDS; game_status = OUT_OF_BOUNDS;
} 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 if (message.find("IN_GAME") != std::string::npos){
switch (message.at(message.find("-")+1)){
case 'L':
playerTeam = hfo::LEFT;
break;
case 'R':
playerTeam = hfo::RIGHT;
break;
case 'U':
playerTeam = hfo::NEUTRAL;
break;
}
playerIndex = atoi((message.substr(message.find("-")+2)).c_str());
}
else {
recognized_message = false; recognized_message = false;
} }
if (recognized_message) { if (recognized_message) {
lastTrainerMessageTime = audio_sensor.trainerMessageTime().cycle(); lastTrainerMessageTime = audio_sensor.trainerMessageTime().cycle();
} }
} }
return game_status; status.push_back(game_status);
status.push_back(playerTeam);
status.push_back(playerIndex);
return status;
} }
/*! /*!
...@@ -403,20 +427,20 @@ void Agent::actionImpl() { ...@@ -403,20 +427,20 @@ void Agent::actionImpl() {
} }
// Update and send the game status // Update and send the game status
status_t game_status = getGameStatus(audioSensor(), lastTrainerMessageTime); std::vector<int> game_status = getGameStatus(audioSensor(), lastTrainerMessageTime);
if (send(newsockfd, &game_status, sizeof(int), 0) < 0) { if (send(newsockfd, &(game_status.front()), game_status.size() * sizeof(int), 0) < 0){
perror("[Agent Server] ERROR sending from socket"); perror("[Agent Server] ERROR sending game state from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
// Update and send the state features // Update and send the state features
const std::vector<float>& features = const std::vector<float>& features =
feature_extractor->ExtractFeatures(this->world()); feature_extractor->ExtractFeatures(this->world());
#ifdef ELOG #ifdef ELOG
if (config().record()) { if (config().record()) {
elog.addText(Logger::WORLD, "GameStatus %d", game_status); elog.addText(Logger::WORLD, "GameStatus %d", game_status[0]);
elog.flush(); elog.flush();
feature_extractor->LogFeatures(); feature_extractor->LogFeatures();
} }
......
...@@ -42,8 +42,8 @@ public: ...@@ -42,8 +42,8 @@ public:
virtual ~Agent(); virtual ~Agent();
virtual FieldEvaluator::ConstPtr getFieldEvaluator() const; virtual FieldEvaluator::ConstPtr getFieldEvaluator() const;
// Get the current game status // Get the current game status, and the side and uniform number of the player holding the ball
static hfo::status_t getGameStatus(const rcsc::AudioSensor& audio_sensor, static std::vector<int> getGameStatus(const rcsc::AudioSensor& audio_sensor,
long& lastTrainerMessageTime); long& lastTrainerMessageTime);
// Returns the feature extractor corresponding to the feature_set_t // Returns the feature extractor corresponding to the feature_set_t
......
...@@ -269,9 +269,9 @@ SamplePlayer::actionImpl() ...@@ -269,9 +269,9 @@ SamplePlayer::actionImpl()
hfo::LOW_LEVEL_FEATURE_SET, num_teammates, num_opponents, playing_offense); hfo::LOW_LEVEL_FEATURE_SET, num_teammates, num_opponents, playing_offense);
} }
} else { } else {
hfo::status_t game_status = Agent::getGameStatus( std::vector<int> game_status = Agent::getGameStatus(
audioSensor(), lastTrainerMessageTime); audioSensor(), lastTrainerMessageTime);
elog.addText(Logger::WORLD, "GameStatus %d", game_status); elog.addText(Logger::WORLD, "GameStatus %d", game_status[0]);
elog.flush(); elog.flush();
feature_extractor->ExtractFeatures(this->world()); feature_extractor->ExtractFeatures(this->world());
feature_extractor->LogFeatures(); feature_extractor->LogFeatures();
......
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