Commit 24dc458f authored by Matthew Hausknecht's avatar Matthew Hausknecht

Merge pull request #14 from mhauskn/launch_refactor

Launch refactor
parents db95ebef 18a6d4d1
...@@ -4,6 +4,7 @@ __pycache__/ ...@@ -4,6 +4,7 @@ __pycache__/
# C extensions # C extensions
*.so *.so
*.a
# Distribution / packaging # Distribution / packaging
.Python .Python
...@@ -31,6 +32,7 @@ var/ ...@@ -31,6 +32,7 @@ var/
# Installer logs # Installer logs
pip-log.txt pip-log.txt
pip-delete-this-directory.txt pip-delete-this-directory.txt
install_manifest.txt
# Unit test / coverage reports # Unit test / coverage reports
htmlcov/ htmlcov/
...@@ -64,7 +66,16 @@ bin/agent ...@@ -64,7 +66,16 @@ bin/agent
bin/sample_coach bin/sample_coach
bin/sample_player bin/sample_player
bin/sample_trainer bin/sample_trainer
bin/rcssserver
bin/soccerwindow2
example/hfo_example_agent example/hfo_example_agent
example/high_level_random_agent
example/low_level_random_agent
# Dependency directories
librcsc-prefix/
rcssserver-prefix/
soccerwindow2-prefix/
# Logs # Logs
log/ log/
......
...@@ -62,7 +62,7 @@ class Communicator(object): ...@@ -62,7 +62,7 @@ class Communicator(object):
raise TimeoutError raise TimeoutError
else: else:
retryCount -= 1 retryCount -= 1
print 'error receiving message, trying again' print '[Trainer] waiting for message, retry =', retryCount
time.sleep(0.3) time.sleep(0.3)
#raise ValueError('Error while receiving message') #raise ValueError('Error while receiving message')
(msg,sep,rest) = msg.partition('\0') (msg,sep,rest) = msg.partition('\0')
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
# encoding: utf-8 # encoding: utf-8
import subprocess, os, time, numpy, sys import subprocess, os, time, numpy, sys
from signal import SIGKILL
# Global list of all/essential running processes # Global list of all/essential running processes
processes, necProcesses = [], [] processes, necProcesses = [], []
...@@ -11,41 +10,27 @@ SERVER_BIN = 'rcssserver' ...@@ -11,41 +10,27 @@ SERVER_BIN = 'rcssserver'
# Command to run the monitor. Edit as needed. # Command to run the monitor. Edit as needed.
MONITOR_BIN = 'soccerwindow2' MONITOR_BIN = 'soccerwindow2'
def getAgentDirCmd(binary_dir, teamname, server_port=6000, coach_port=6002, def launch(cmd, name = 'Unknown', necessary = True, supressOutput = True):
logDir='log', record=False):
""" Returns the team name, command, and directory to run a team. """
cmd = 'start.sh -t %s -p %i -P %i --log-dir %s'%(teamname, server_port,
coach_port, logDir)
if record:
cmd += ' --record'
cmd = os.path.join(binary_dir, cmd)
return teamname, cmd
def launch(cmd, necessary=True, supressOutput=True, name='Unknown'):
"""Launch a process. """Launch a process.
Appends to list of processes and (optionally) necProcesses if Appends to list of processes and (optionally) necProcesses if
necessary flag is True. necessary flag is True.
Returns: The launched process. Returns: The launched process.
""" """
kwargs = {} kwargs = {}
if supressOutput: if supressOutput:
kwargs = {'stdout':open('/dev/null','w'),'stderr':open('/dev/null','w')} kwargs = {'stdout': open('/dev/null', 'w'),
p = subprocess.Popen(cmd.split(' '),shell=False,**kwargs) 'stderr': open('/dev/null', 'w')}
p = subprocess.Popen(cmd.split(' '), shell = False, **kwargs)
processes.append(p) processes.append(p)
if necessary: if necessary:
necProcesses.append([p,name]) necProcesses.append([p,name])
return p return p
def main(args, team1='left', team2='right', rng=numpy.random.RandomState()): def main(args, team1='left', team2='right'):
"""Sets up the teams, launches the server and monitor, starts the """Sets up the teams, launches the server and monitor, starts the trainer.
trainer.
""" """
if args.seed:
print '[start.py] Seeding RNG with seed: ', args.seed
rng.seed(args.seed)
if not os.path.exists(args.logDir): if not os.path.exists(args.logDir):
os.makedirs(args.logDir) os.makedirs(args.logDir)
num_agents = args.offenseAgents + args.defenseAgents num_agents = args.offenseAgents + args.defenseAgents
...@@ -57,21 +42,23 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()): ...@@ -57,21 +42,23 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
serverOptions = ' server::port=%i server::coach_port=%i ' \ serverOptions = ' server::port=%i server::coach_port=%i ' \
'server::olcoach_port=%i server::coach=1 ' \ 'server::olcoach_port=%i server::coach=1 ' \
'server::game_logging=%i server::text_logging=%i ' \ 'server::game_logging=%i server::text_logging=%i ' \
'server::hfo_logging=%i server::hfo_log_dir=%s ' \
'server::game_log_dir=%s server::text_log_dir=%s '\ 'server::game_log_dir=%s server::text_log_dir=%s '\
'server::synch_mode=%i ' \ 'server::synch_mode=%i server::hfo=1 ' \
'server::fullstate_l=%i server::fullstate_r=%i' \ 'server::fullstate_l=%i server::fullstate_r=%i ' \
'server::coach_w_referee=1 server::hfo_max_trial_time=%i ' \
'server::hfo_max_trials=%i server::hfo_max_frames=%i ' \
'server::hfo_offense_on_ball=%i server::random_seed=%i' \
%(server_port, coach_port, olcoach_port, %(server_port, coach_port, olcoach_port,
args.logging, args.logging, args.logging, args.logging, args.logging,
args.logDir, args.logDir, args.logDir, args.logDir, args.logDir,
args.sync, args.sync, args.fullstate, args.fullstate,
args.fullstate, args.fullstate) args.maxFramesPerTrial, args.numTrials, args.numFrames,
team1, team1Cmd = getAgentDirCmd(binary_dir, team1, server_port, coach_port, args.offenseOnBall, args.seed)
args.logDir, args.record) # server::record_messages=on -- useful for debug
team2, team2Cmd = getAgentDirCmd(binary_dir, team2, server_port, coach_port,
args.logDir, args.record)
try: try:
# Launch the Server # Launch the Server
server = launch(serverCommand + serverOptions, name='server') server = launch(serverCommand + serverOptions, name='server', supressOutput=True)
time.sleep(0.2) time.sleep(0.2)
assert server.poll() is None,\ assert server.poll() is None,\
'[start.py] Failed to launch Server with command: \"%s\"' \ '[start.py] Failed to launch Server with command: \"%s\"' \
...@@ -82,30 +69,25 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()): ...@@ -82,30 +69,25 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
launch(monitorCommand + monitorOptions, name='monitor') launch(monitorCommand + monitorOptions, name='monitor')
# Launch the Trainer # Launch the Trainer
from Trainer import Trainer from Trainer import Trainer
trainer = Trainer(args=args, rng=rng, server_port=server_port, trainer = Trainer(args=args, server_port=server_port, coach_port=coach_port)
coach_port=coach_port)
trainer.initComm() trainer.initComm()
# Start Team1 # Add Team1
launch(team1Cmd,False) trainer.addTeam(team1)
trainer.waitOnTeam(True) # wait to make sure of team order # Add Team2
# Start Team2 trainer.addTeam(team2)
launch(team2Cmd,False) # Run
trainer.waitOnTeam(False)
# Make sure all players are connected
trainer.checkIfAllPlayersConnected()
trainer.setTeams()
# Run HFO
trainer.run(necProcesses) trainer.run(necProcesses)
except KeyboardInterrupt: except KeyboardInterrupt:
print '[start.py] Exiting for CTRL-C' print '[start.py] Exiting for CTRL-C'
finally: finally:
print '[start.py] Cleaning up server and other processes' print '[start.py] Cleaning up server and other processes'
for p in processes: for p in reversed(processes):
try: try:
p.send_signal(SIGKILL) p.terminate()
time.sleep(0.1)
p.kill()
except: except:
pass pass
time.sleep(0.1)
def parseArgs(): def parseArgs():
import argparse import argparse
...@@ -138,17 +120,33 @@ def parseArgs(): ...@@ -138,17 +120,33 @@ def parseArgs():
help='Directory to store logs.') help='Directory to store logs.')
p.add_argument('--record', dest='record', action='store_true', p.add_argument('--record', dest='record', action='store_true',
help='Record logs of states and actions.') help='Record logs of states and actions.')
p.add_argument('--agent-on-ball', dest='agent_on_ball', action='store_true', p.add_argument('--offense-on-ball', dest='offenseOnBall', action='store_true',
help='Agent starts with the ball.') help='Offense starts with the ball.')
p.add_argument('--fullstate', dest='fullstate', action='store_true', p.add_argument('--fullstate', dest='fullstate', action='store_true',
help='Server provides full-state information to agents.') help='Server provides full-state information to agents.')
p.add_argument('--seed', dest='seed', type=int, p.add_argument('--seed', dest='seed', type=int, default=-1,
help='Seed the trainer\'s RNG. Default: time.') help='Seed the server\'s RNG. Default: time.')
args = p.parse_args() args = p.parse_args()
assert args.offenseAgents + args.offenseNPCs in xrange(0, 11), \ if args.offenseAgents not in xrange(0, 11):
'Invalid number of offensive players: (choose from [0,10])' p.error('argument --offense-agents: invalid choice: '\
assert args.defenseAgents + args.defenseNPCs in xrange(0, 12), \ + str(args.offenseAgents) + ' (choose from [0-10])')
'Invalid number of defensive players: (choose from [0,11])' if args.offenseNPCs not in xrange(0, 11):
p.error('argument --offense-npcs: invalid choice: '\
+ str(args.offenseNPCs) + ' (choose from [0-10])')
if args.defenseAgents not in xrange(0, 12):
p.error('argument --defense-agents: invalid choice: '\
+ str(args.defenseAgents) + ' (choose from [0-11])')
if args.defenseNPCs not in xrange(0, 12):
p.error('argument --offense-npcs: invalid choice: '\
+ str(args.defenseNPCs) + ' (choose from [0-11])')
if args.offenseAgents + args.offenseNPCs not in xrange(1, 11):
p.error('Offense players (offense-agents + offense-npcs): '\
'invalid choice: ' + str(args.offenseAgents + args.offenseNPCs) +\
' (choose from [1,10])')
if args.defenseAgents + args.defenseNPCs not in xrange(0, 12):
p.error('Defense players (defense-agents + defense-npcs): '\
'invalid choice: ' + str(args.defenseAgents + args.defenseNPCs) +\
' (choose from [0,11])')
return args return args
if __name__ == '__main__': if __name__ == '__main__':
......
This diff is collapsed.
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#include <rcsc/player/say_message_builder.h> #include <rcsc/player/say_message_builder.h>
#include <rcsc/player/audio_sensor.h> #include <rcsc/player/audio_sensor.h>
#include <rcsc/player/freeform_parser.h> #include <rcsc/player/freeform_parser.h>
#include <rcsc/player/free_message.h>
#include <rcsc/common/basic_client.h> #include <rcsc/common/basic_client.h>
#include <rcsc/common/logger.h> #include <rcsc/common/logger.h>
...@@ -108,6 +109,7 @@ ...@@ -108,6 +109,7 @@
#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 <poll.h>
using namespace rcsc; using namespace rcsc;
using namespace hfo; using namespace hfo;
...@@ -119,7 +121,7 @@ Agent::Agent() ...@@ -119,7 +121,7 @@ Agent::Agent()
M_action_generator(createActionGenerator()), M_action_generator(createActionGenerator()),
lastTrainerMessageTime(-1), lastTrainerMessageTime(-1),
server_port(6008), server_port(6008),
server_running(false), client_connected(false),
num_teammates(-1), num_teammates(-1),
num_opponents(-1), num_opponents(-1),
playing_offense(false) playing_offense(false)
...@@ -230,12 +232,14 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) { ...@@ -230,12 +232,14 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) {
assert(num_teammates >= 0); assert(num_teammates >= 0);
assert(num_opponents >= 0); assert(num_opponents >= 0);
startServer(server_port);
return true; return true;
} }
void Agent::startServer(int server_port) { void Agent::startServer(int server_port) {
std::cout << "[Agent Server] Starting Server on Port " << server_port << std::endl; std::cout << "[Agent Server] Starting Server on Port " << server_port << std::endl;
struct sockaddr_in serv_addr, cli_addr; struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { if (sockfd < 0) {
perror("[Agent Server] ERROR opening socket"); perror("[Agent Server] ERROR opening socket");
...@@ -250,16 +254,32 @@ void Agent::startServer(int server_port) { ...@@ -250,16 +254,32 @@ void Agent::startServer(int server_port) {
exit(1); exit(1);
} }
listen(sockfd, 5); listen(sockfd, 5);
socklen_t clilen = sizeof(cli_addr); }
std::cout << "[Agent Server] Waiting for client to connect... " << std::endl;
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); void Agent::listenForConnection() {
if (newsockfd < 0) { int rv;
perror("[Agent Server] ERROR on accept"); struct pollfd ufd;
close(sockfd); ufd.fd = sockfd;
exit(1); ufd.events = POLLIN;
rv = poll(&ufd, 1, 1000);
if (rv == -1) {
perror("poll"); // error occurred in poll()
} else if (rv == 0) {
std::cout << "[Agent Server] Waiting for client to connect... " << std::endl;
} else {
if (ufd.revents & POLLIN) {
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("[Agent Server] ERROR on accept");
close(sockfd);
exit(1);
}
std::cout << "[Agent Server] Connected" << std::endl;
clientHandshake();
}
} }
std::cout << "[Agent Server] Connected" << std::endl;
server_running = true;
} }
void Agent::clientHandshake() { void Agent::clientHandshake() {
...@@ -316,6 +336,9 @@ void Agent::clientHandshake() { ...@@ -316,6 +336,9 @@ void Agent::clientHandshake() {
exit(1); exit(1);
} }
std::cout << "[Agent Server] Handshake complete" << std::endl; std::cout << "[Agent Server] Handshake complete" << std::endl;
client_connected = true;
rcsc::FreeMessage<5> *free_msg = new FreeMessage<5>("ready");
addSayMessage(free_msg);
} }
FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx, FeatureExtractor* Agent::getFeatureExtractor(feature_set_t feature_set_indx,
...@@ -367,9 +390,13 @@ status_t Agent::getGameStatus(const rcsc::AudioSensor& audio_sensor, ...@@ -367,9 +390,13 @@ status_t Agent::getGameStatus(const rcsc::AudioSensor& audio_sensor,
virtual method in super class virtual method in super class
*/ */
void Agent::actionImpl() { void Agent::actionImpl() {
if (!server_running) { // For now let's not worry about turning the neck or setting the vision.
startServer(server_port); this->setViewAction(new View_Tactical());
clientHandshake(); this->setNeckAction(new Neck_TurnToBallOrScan());
if (!client_connected) {
listenForConnection();
return;
} }
// Update and send the game status // Update and send the game status
...@@ -451,10 +478,6 @@ void Agent::actionImpl() { ...@@ -451,10 +478,6 @@ void Agent::actionImpl() {
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
// For now let's not worry about turning the neck or setting the vision.
this->setViewAction(new View_Tactical());
this->setNeckAction(new Neck_TurnToBallOrScan());
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
......
...@@ -72,7 +72,7 @@ protected: ...@@ -72,7 +72,7 @@ protected:
// 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);
void listenForConnection();
// Transmit information to the client and ensure it can recieve. // Transmit information to the client and ensure it can recieve.
void clientHandshake(); void clientHandshake();
...@@ -80,7 +80,7 @@ protected: ...@@ -80,7 +80,7 @@ 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
int server_port; // Port to start the server on int server_port; // Port to start the server on
bool server_running; // Is the server running? bool client_connected; // Has the client connected and handshake?
int sockfd, newsockfd; // Server sockets int sockfd, newsockfd; // Server sockets
int num_teammates, num_opponents; int num_teammates, num_opponents;
bool playing_offense; bool playing_offense;
......
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