Commit 97e92d12 authored by Matthew Hausknecht's avatar Matthew Hausknecht

Merge pull request #19 from sanmit/teams

Opponent binary support
parents 0104ff75 04941856
......@@ -62,10 +62,10 @@ cmake_install.cmake
CMakeFiles/
# Executeables
bin/agent
bin/sample_coach
bin/sample_player
bin/sample_trainer
bin/teams/base/agent
bin/teams/base/sample_coach
bin/teams/base/sample_player
bin/teams/base/sample_trainer
bin/rcssserver
bin/soccerwindow2
example/hfo_example_agent
......@@ -74,6 +74,7 @@ example/low_level_random_agent
example/mid_level_move_agent
example/mid_level_kick_agent
example/mid_level_dribble_agent
example/communication_agent
# Dependency directories
librcsc-prefix/
......
......@@ -41,7 +41,7 @@ if(BUILD_SOCCERWINDOW)
INSTALL_COMMAND "")
ExternalProject_Get_Property(soccerwindow2 BINARY_DIR)
set(SOCCERWINDOW2_BINARY_DIR ${BINARY_DIR}/bin)
install(DIRECTORY ${SOCCERWINDOW2_BINARY_DIR} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${SOCCERWINDOW2_BINARY_DIR} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} USE_SOURCE_PERMISSIONS)
endif()
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
......@@ -79,9 +79,15 @@ list(APPEND LINK_LIBS rcsc_agent rcsc_geom rcsc_param rcsc_ann
add_library(player_chain_action STATIC ${PLAYER_SOURCES} ${CHAIN_ACTION_SOURCES})
add_executable(sample_coach ${SOURCE_DIR}/main_coach.cpp ${SOURCE_DIR}/sample_coach.cpp)
add_executable(sample_player ${SOURCE_DIR}/HFO.cpp ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCE_DIR}/agent.cpp)
add_executable(sample_player ${SOURCE_DIR}/HFO.cpp ${SOURCE_DIR}/main_player.cpp ${SOURCE_DIR}/sample_player.cpp ${SOURCE_DIR}/agent.cpp)
add_executable(sample_trainer ${SOURCE_DIR}/main_trainer.cpp ${SOURCE_DIR}/sample_trainer.cpp)
add_executable(agent ${SOURCE_DIR}/HFO.cpp ${SOURCE_DIR}/main_agent.cpp ${SOURCE_DIR}/agent.cpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams/base)
set_target_properties(sample_coach PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams/base)
set_target_properties(sample_player PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams/base)
set_target_properties(sample_trainer PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams/base)
set_target_properties(agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams/base)
add_library(hfo-lib SHARED ${SOURCE_DIR}/HFO.hpp ${SOURCE_DIR}/HFO.cpp)
set_target_properties(hfo-lib PROPERTIES OUTPUT_NAME hfo)
set_target_properties(hfo-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
......@@ -126,8 +132,6 @@ add_executable(communication_agent ${CMAKE_CURRENT_SOURCE_DIR}/example/communica
set_target_properties(communication_agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example)
target_link_libraries(communication_agent hfo-lib)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${RCSSSERVER_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/bin DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${RCSSSERVER_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/bin DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/teams DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin USE_SOURCE_PERMISSIONS)
......@@ -28,12 +28,14 @@ def launch(cmd, name = 'Unknown', necessary = True, supressOutput = True):
necProcesses.append([p,name])
return p
def main(args, team1='left', team2='right'):
def main(args):
"""Sets up the teams, launches the server and monitor, starts the trainer.
"""
if args.logging and not os.path.exists(args.logDir):
os.makedirs(args.logDir)
num_agents = args.offenseAgents + args.defenseAgents
team1 = args.offenseTeam
team2 = args.defenseTeam
binary_dir = os.path.dirname(os.path.realpath(__file__))
server_port = args.port + num_agents
coach_port = args.port + num_agents + 1
......@@ -118,6 +120,10 @@ def parseArgs():
help='Number of offensive uncontrolled players. Default: 0.')
p.add_argument('--defense-npcs', dest='defenseNPCs', type=int, default=0,
help='Number of defensive uncontrolled players. Default: 0.')
p.add_argument('--offense-team', dest='offenseTeam', type=str, default='base',
help='Team name to pull offensive NPCs from. Options: {base, helios} Default: base.')
p.add_argument('--defense-team', dest='defenseTeam', type=str, default='base',
help='Team name to pull defensive NPCs from. Options: {base, helios} Default: base')
p.add_argument('--no-sync', dest='sync', action='store_false', default=True,
help='Run server in non-sync mode.')
p.add_argument('--port', dest='port', type=int, default=6000,
......
#!/usr/bin/env python
# encoding: utf-8
import sys, numpy, time, os, subprocess
import sys, numpy, time, os, subprocess, teams
from Communicator import ClientCommunicator, TimeoutError
class DoneError(Exception):
......@@ -51,36 +51,6 @@ class Trainer(object):
self._connectedPlayers = []
self.initMsgHandlers()
def launch_npc(self, player_num, play_offense, wait_until_join=True):
"""Launches a player using sample_player binary
Returns a Popen process object
"""
print 'Launch npc %s-%d'%(self._offenseTeamName if play_offense
else self._defenseTeamName, player_num)
if play_offense:
team_name = self._offenseTeamName
else:
team_name = self._defenseTeamName
binary_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(binary_dir, '../config/formations-dt')
player_conf = os.path.join(binary_dir, '../config/player.conf')
player_cmd = os.path.join(binary_dir, 'sample_player')
player_cmd += ' -t %s -p %i --config_dir %s ' \
' --log_dir %s --player-config %s' \
%(team_name, self._serverPort, config_dir,
self._logDir, player_conf)
if self._record:
player_cmd += ' --record'
if player_num == 1:
player_cmd += ' -g'
kwargs = {'stdout':open('/dev/null', 'w'),
'stderr':open('/dev/null', 'w')}
p = subprocess.Popen(player_cmd.split(' '), shell = False, **kwargs)
if wait_until_join:
self.waitOnPlayer(player_num, play_offense)
return p
def launch_agent(self, agent_num, agent_ext_num, play_offense, port, wait_until_join=True):
"""Launches a learning agent using the agent binary
......@@ -105,9 +75,9 @@ class Trainer(object):
self._agentNumInt.append(internal_player_num)
numTeammates = self._numDefense - 1
numOpponents = self._numOffense
binary_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(binary_dir, '../config/formations-dt')
player_conf = os.path.join(binary_dir, '../config/player.conf')
binary_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'teams', 'base')
config_dir = os.path.join(binary_dir, 'config/formations-dt')
player_conf = os.path.join(binary_dir, '/config/player.conf')
agent_cmd = os.path.join(binary_dir, 'agent')
agent_cmd += ' -t %s -p %i --numTeammates %i --numOpponents %i' \
' --playingOffense %i --serverPort %i --log_dir %s' \
......@@ -127,45 +97,46 @@ class Trainer(object):
self.waitOnPlayer(agent_ext_num, play_offense)
return p
def getDefensiveRoster(self, team_name):
"""Returns a list of player numbers on a given team that are thought
to prefer defense. This map is not set in stone as the players on
some teams can adapt and change their roles.
"""
if team_name == 'Borregos':
return [9,10,8,11,7,4,6,2,3,5]
elif team_name == 'WrightEagle':
return [5,2,8,9,10,6,3,11,4,7]
else:
return [2,3,4,5,6,7,8,11,9,10]
def getOffensiveRoster(self, team_name):
"""Returns a list of player numbers on a given team that are thought
to prefer offense. This map is not set in stone as the players on
some teams can adapt and change their roles.
"""
if team_name == 'Borregos':
return [2,4,6,5,3,7,9,10,8,11]
elif team_name == 'WrightEagle':
return [11,4,7,3,6,10,8,9,2,5]
else:
return [11,7,8,9,10,6,3,2,4,5]
def addTeam(self, team_name):
""" Adds a team to the team list"""
self._teams.append(team_name)
# Check whether team name valid, and map to a format acceptable to third party binary
nameMap = {'base':'base', 'helios':'HELIOS'}
if team_name not in nameMap.keys():
print 'Invalid team name: ', team_name
sys.exit(1)
# Create side specific team
if len(self._teams) == 0:
self._teams.append(nameMap[team_name] + '_left')
elif len(self._teams) == 1:
self._teams.append(nameMap[team_name] + '_right')
else:
print 'Too many teams added!'
sys.exit(1)
def createTeam(self, name):
teamDir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'teams')
if 'HELIOS' in name:
print 'Creating team HELIOS'
return teams.Helios(name, os.path.join(teamDir, 'helios', 'helios-13Eindhoven'), os.path.join(teamDir, 'helios', 'local', 'lib'), 'helios_player', host='localhost', port=self._serverPort)
elif 'base' in name:
print 'Creating team Agent2d (base)'
return teams.Agent2d(name, os.path.join(teamDir, 'base'), None, 'sample_player', self._logDir, self._record, host='localhost', port=self._serverPort)
else:
print 'Invalid team found'
sys.exit(1)
def setTeams(self):
def getTeams(self):
""" Sets the offensive and defensive teams and player rosters. """
self._offenseTeamInd = 0
self._offenseTeamName = self._teams[self._offenseTeamInd]
self._defenseTeamName = self._teams[1-self._offenseTeamInd]
offensive_roster = self.getOffensiveRoster(self._offenseTeamName)
defensive_roster = self.getDefensiveRoster(self._defenseTeamName)
self._offenseOrder = [1] + offensive_roster # 1 for goalie
self._defenseOrder = [1] + defensive_roster # 1 for goalie
# set up offense
offenseTeam = self.createTeam(self._offenseTeamName)
self._offenseOrder = [1] + offenseTeam._offense_order # 1 for goalie
# set up defense
defenseTeam = self.createTeam(self._defenseTeamName)
self._defenseOrder = [1] + defenseTeam._defense_order # 1 for goalie
return (offenseTeam, defenseTeam)
def teamToInd(self, team_name):
""" Returns the index of a given team. """
......@@ -429,7 +400,7 @@ class Trainer(object):
def run(self, necProcesses):
""" Run the trainer """
try:
self.setTeams()
(offenseTeam, defenseTeam) = self.getTeams()
offense_unums = self._offenseOrder[1: self._numOffense + 1]
sorted_offense_agent_unums = sorted(self._offenseOrder[1:self._offenseAgents+1])
defense_unums = self._defenseOrder[: self._numDefense]
......@@ -446,7 +417,8 @@ class Trainer(object):
necProcesses.append([agent, 'offense_agent_' + str(agent_num)])
agent_num += 1
else:
player = self.launch_npc(player_num, play_offense=True)
player = offenseTeam.launch_npc(player_num)
self.waitOnPlayer(player_num, True)
if player_num in offense_unums:
self._npcPopen.append(player)
necProcesses.append([player, 'offense_npc_' + str(player_num)])
......@@ -464,7 +436,8 @@ class Trainer(object):
necProcesses.append([agent, 'defense_agent_' + str(agent_num)])
agent_num += 1
else:
player = self.launch_npc(player_num, play_offense=False)
player = defenseTeam.launch_npc(player_num)
self.waitOnPlayer(player_num, False)
if player_num in defense_unums:
self._npcPopen.append(player)
necProcesses.append([player, 'defense_npc_' + str(player_num)])
......
......@@ -8,8 +8,8 @@ echo " Copyright 2007-2012. Hidehisa Akiyama and Hiroki Shimora"
echo " All rights reserved."
echo "******************************************************************"
BINARY_DIR=`dirname $0`
CONFIG_DIR=$BINARY_DIR/../config
BINARY_DIR=`dirname $0`/teams/base
CONFIG_DIR=$BINARY_DIR/config
player="${BINARY_DIR}/sample_player"
coach="${BINARY_DIR}/sample_coach"
......
#!/bin/bash
BINARY_DIR=`dirname $0` #"$( cd "$( dirname "$0" )" && pwd )"
CONFIG_DIR=$BINARY_DIR/../config
BINARY_DIR=`dirname $0`/teams/base #"$( cd "$( dirname "$0" )" && pwd )"
CONFIG_DIR=$BINARY_DIR/config
player="${BINARY_DIR}/agent"
coach="${BINARY_DIR}/sample_coach"
......
#!/usr/bin/env python
# encoding: utf-8
import os, subprocess
class Team(object):
""" Abstract class. Handles launching players from 3rd party binaries.
"""
def __init__(self, name, binaryPath, libDir, options, offenseOrder, defenseOrder):
"""
Creates a team
name: name of the team
binaryPath: absolute path of the executable
libDir: library dependencies directory
options: team-specific parameters for executable in string format
offenseOrder: order to prioritize offensive unums (do not include 0)
defenseOrder: order to prioritize defensive unums (do not include 0)
"""
self._name = name
self._binary_path = binaryPath
self._lib_dir = libDir
self._options = options
self._offense_order = offenseOrder
self._defense_order = defenseOrder
def launch_npc(self, player_num):
"""
Abstract method that should be overrided by subclasses. Launches an npc with player number player_num.
The method that overrides this should call start_npc_process. See examples below.
"""
pass
def start_npc_proc(self, launchOpts=None):
"""Launches a player using the team-specific binary
launchOpts should be used to append player specific options
(e.g., helios uses '-g' to signify launching a goalie )
Returns a Popen process object
"""
player_cmd = self._binary_path
player_cmd += ' %s' % (self._options)
if launchOpts != None:
player_cmd += ' %s' % (launchOpts)
kwargs = {'stdout':open('/dev/null', 'w'),
'stderr':open('/dev/null', 'w')}
env = dict(os.environ)
if self._lib_dir != None:
env['LD_LIBRARY_PATH'] = self._lib_dir
p = subprocess.Popen(player_cmd.split(' '), env=env, shell = False, **kwargs)
return p
class Agent2d(Team):
def __init__(self, name, baseDir, libDir, binaryName, logDir, record, host='localhost', port=6000):
binaryPath = os.path.join(baseDir, binaryName)
options = '-t %s -p %i --config_dir %s/config/formations-dt --log_dir %s --player-config %s/config/player.conf' % (name, port, baseDir, logDir, baseDir)
if record:
options += ' --record'
offenseOrder = [11,7,8,9,10,6,3,2,4,5]
defenseOrder = [2,3,4,5,6,7,8,11,9,10]
super(Agent2d, self).__init__(name, binaryPath, libDir, options, offenseOrder, defenseOrder)
def launch_npc(self, player_num):
launchOpts = None
if player_num == 1:
launchOpts = '-g'
print 'Launch npc %s-%d' % (self._name, player_num)
return self.start_npc_proc(launchOpts)
class Helios(Team):
def __init__(self, name, baseDir, libDir, binaryName, host='localhost', port=6000):
binaryPath = os.path.join(baseDir, binaryName)
options = '--player-config %s/player.conf -h %s -t %s --formation-conf-dir %s/data/formations --role-conf %s/data/role.conf --ball-table %s/data/ball_table.dat --chain-search-method BestFirstSearch --evaluator-name Default --max-chain-length 4 --max-evaluate-size 1000 --sirm-evaluator-param-dir %s/data/sirm_evaluator/ --goalie-position-dir %s/data/goalie_position/ --intercept-conf-dir %s/data/intercept_probability/ --opponent-data-dir %s/data/opponent_data/ -p %d' % (baseDir, host, name, baseDir, baseDir, baseDir, baseDir, baseDir, baseDir, baseDir, port)
offenseOrder = [11,7,8,9,10,6,3,2,4,5]
defenseOrder = [2,3,4,5,6,7,8,11,9,10]
super(Helios, self).__init__(name, binaryPath, libDir, options, offenseOrder, defenseOrder)
def launch_npc(self, player_num):
launchOpts = None
if player_num == 1:
launchOpts = '-g'
print 'Launch npc %s-%d' % (self._name, player_num)
return self.start_npc_proc(launchOpts)
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