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