Commit 61507f0e authored by Matthew Hausknecht's avatar Matthew Hausknecht Committed by GitHub

Merge pull request #27 from drallensmith/master

setup.py, README.md clarifications; HFO, python_agents_3v3.sh misc improvements; prevention of endless loop for high_level_custom_agent.py
parents d56ba025 851d2059
...@@ -11,6 +11,10 @@ RoboCup 2D Half Field Offense ...@@ -11,6 +11,10 @@ RoboCup 2D Half Field Offense
- Boost-system, filesystem - Boost-system, filesystem
- Qt4 [Required for SoccerWindow2 visualizer]: To not build the visualizer, add cmake flag `-DBUILD_SOCCERWINDOW=False` - Qt4 [Required for SoccerWindow2 visualizer]: To not build the visualizer, add cmake flag `-DBUILD_SOCCERWINDOW=False`
## Python Dependencies
- Python 2.7 or 3.2+ (tested with 2.7 and 3.5)
- numpy
## Install ## Install
``` ```
mkdir build && cd build mkdir build && cd build
...@@ -65,7 +69,7 @@ for (int episode=0; episode<5; episode++) { ...@@ -65,7 +69,7 @@ for (int episode=0; episode<5; episode++) {
```python ```python
hfo = hfo.HFOEnvironment() hfo = hfo.HFOEnvironment()
hfo.connectServer(...) hfo.connectServer(...)
for episode in xrange(5): for episode in range(5): # replace with xrange(5) for Python 2.X
status = IN_GAME status = IN_GAME
while status == IN_GAME: while status == IN_GAME:
features = hfo.getState() features = hfo.getState()
......
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
from __future__ import print_function
import subprocess, os, time, numpy, sys import subprocess, os, time, numpy, sys
# Global list of all/essential running processes # Global list of all/essential running processes
processes, necProcesses = [], [] processes, necProcesses = [], []
# Command to run the rcssserver. Edit as needed.
# Command to run the rcssserver. Edit as needed; the below assumes running in the same directory as HFO
SERVER_BIN = 'rcssserver' SERVER_BIN = 'rcssserver'
# Command to run the monitor. Edit as needed. # Command to run the monitor. Edit as needed; ditto to the above re directories.
MONITOR_BIN = 'soccerwindow2' MONITOR_BIN = 'soccerwindow2'
def launch(cmd, name = 'Unknown', necessary = True, supressOutput = True): def launch(cmd, name = 'Unknown', necessary = True, suppressOutput = True):
"""Launch a process. """Launch a process.
Appends to list of processes and (optionally) necProcesses if Appends to list of processes and (optionally) necProcesses if
...@@ -19,10 +21,14 @@ def launch(cmd, name = 'Unknown', necessary = True, supressOutput = True): ...@@ -19,10 +21,14 @@ def launch(cmd, name = 'Unknown', necessary = True, supressOutput = True):
Returns: The launched process. Returns: The launched process.
""" """
kwargs = {} kwargs = {}
if supressOutput: if suppressOutput:
kwargs = {'stdout': open('/dev/null', 'w'), kwargs = {'stdout': open('/dev/null', 'w'),
'stderr': open('/dev/null', 'w')} 'stderr': open('/dev/null', 'w')}
try:
p = subprocess.Popen(cmd.split(' '), shell = False, **kwargs) p = subprocess.Popen(cmd.split(' '), shell = False, **kwargs)
except (IOError, OSError):
print("ERROR: Unsuccessful launch of process {!r}".format(cmd), file=sys.stderr)
raise
processes.append(p) processes.append(p)
if necessary: if necessary:
necProcesses.append([p,name]) necProcesses.append([p,name])
...@@ -66,7 +72,7 @@ def main(args): ...@@ -66,7 +72,7 @@ def main(args):
try: try:
# Launch the Server # Launch the Server
server = launch(serverCommand + serverOptions, name='server', server = launch(serverCommand + serverOptions, name='server',
supressOutput=not args.verbose) suppressOutput=not args.verbose)
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\"' \
......
...@@ -36,7 +36,7 @@ def main(): ...@@ -36,7 +36,7 @@ def main():
# Quit if the server goes down # Quit if the server goes down
if status == SERVER_DOWN: if status == SERVER_DOWN:
hfo.act(QUIT) hfo.act(QUIT)
break exit()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -29,7 +29,7 @@ def main(): ...@@ -29,7 +29,7 @@ def main():
# Quit if the server goes down # Quit if the server goes down
if status == SERVER_DOWN: if status == SERVER_DOWN:
hfo.act(QUIT) hfo.act(QUIT)
break exit()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -29,7 +29,7 @@ def main(): ...@@ -29,7 +29,7 @@ def main():
# Quit if the server goes down # Quit if the server goes down
if status == SERVER_DOWN: if status == SERVER_DOWN:
hfo.act(QUIT) hfo.act(QUIT)
break exit()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -52,11 +52,14 @@ def get_action(state,hfo_env,num_teammates): ...@@ -52,11 +52,14 @@ def get_action(state,hfo_env,num_teammates):
curr_goal_angle = goal_op_angle): curr_goal_angle = goal_op_angle):
hfo_env.act(PASS, teammate_uniform_number) hfo_env.act(PASS, teammate_uniform_number)
return return
# not sure if below check is needed - doDribble in agent.cpp includes
# (via doPreprocess) doForceKick, which may cover this situation depending
# on what existKickableOpponent returns.
if can_dribble(dist_to_op = state[9]): if can_dribble(dist_to_op = state[9]):
hfo_env.act(DRIBBLE) hfo_env.act(DRIBBLE)
return return
# If nothing can be done pass # If nothing can be done, do not do anything
hfo_env.act(PASS) hfo_env.act(NOOP)
def main(): def main():
...@@ -86,7 +89,7 @@ def main(): ...@@ -86,7 +89,7 @@ def main():
#print(status) #print(status)
if status == SERVER_DOWN: if status == SERVER_DOWN:
hfo_env.act(QUIT) hfo_env.act(QUIT)
break exit()
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -32,7 +32,7 @@ def main(): ...@@ -32,7 +32,7 @@ def main():
# Quit if the server goes down # Quit if the server goes down
if status == SERVER_DOWN: if status == SERVER_DOWN:
hfo.act(QUIT) hfo.act(QUIT)
break exit()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless & ./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless &
sleep 5 sleep 5
/usr/bin/python2.7 ./example/high_level_custom_agent.py --numTeammates=2 --numOpponents=3 --port 6000 &> agent1.txt & # -x is needed to skip first line - otherwise whatever default python version is will run
python2.7 -x ./example/high_level_custom_agent.py --numTeammates=2 --numOpponents=3 --port 6000 &> agent1.txt &
sleep 5 sleep 5
/usr/bin/python3 ./example/high_level_custom_agent.py --numTeammates=2 --numOpponents=3 --port 6000 &> agent2.txt & python3 -x ./example/high_level_custom_agent.py --numTeammates=2 --numOpponents=3 --port 6000 &> agent2.txt &
# The magic line # The magic line
# $$ holds the PID for this script # $$ holds the PID for this script
......
...@@ -116,14 +116,12 @@ class HFOEnvironment(object): ...@@ -116,14 +116,12 @@ class HFOEnvironment(object):
hfo_lib.getState(self.obj, as_ctypes(state_data)) hfo_lib.getState(self.obj, as_ctypes(state_data))
return state_data return state_data
def act(self, *args): def act(self, action_type, *args):
""" Performs an action in the environment """ """ Performs an action in the environment """
assert len(args) > 0, 'Not enough arguments provided to act'
action_type = args[0]
n_params = hfo_lib.numParams(action_type) n_params = hfo_lib.numParams(action_type)
assert n_params == len(args) - 1, 'Incorrect number of params to act: '\ assert n_params == len(args), 'Incorrect number of params to act: '\
'Required %d, provided %d'%(n_params, len(args)-1) 'Required %d, provided %d'%(n_params, len(args))
params = np.asarray(args[1:], dtype=np.float32) params = np.asarray(args, dtype=np.float32)
hfo_lib.act(self.obj, action_type, params.ctypes.data_as(POINTER(c_float))) hfo_lib.act(self.obj, action_type, params.ctypes.data_as(POINTER(c_float)))
def say(self, message): def say(self, message):
...@@ -144,11 +142,11 @@ class HFOEnvironment(object): ...@@ -144,11 +142,11 @@ class HFOEnvironment(object):
def actionToString(self, action): def actionToString(self, action):
""" Returns a string representation of an action """ """ Returns a string representation of an action """
return hfo_lib.actionToString(action.decode('utf-8')) return hfo_lib.actionToString(action).decode('utf-8')
def statusToString(self, status): def statusToString(self, status):
""" Returns a string representation of a game status """ """ Returns a string representation of a game status """
return hfo_lib.statusToString(status) return hfo_lib.statusToString(status).decode('utf-8')
def getUnum(self): def getUnum(self):
""" Return the uniform number of the agent """ """ Return the uniform number of the agent """
......
...@@ -26,8 +26,16 @@ setup(name = 'hfo', ...@@ -26,8 +26,16 @@ setup(name = 'hfo',
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
'Intended Audience :: Science/Research', 'Intended Audience :: Science/Research',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent', 'Operating System :: OS Independent', # except for shell scripts
'Programming Language :: C++',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.2', # not tested
'Programming Language :: Python :: 3.3', # not tested
'Programming Language :: Python :: 3.4', # not tested
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', # not tested
], ],
requires=['numpy'],
# packages=find_packages(), # packages=find_packages(),
packages=['hfo'], packages=['hfo'],
package_dir={'hfo': 'hfo'}, package_dir={'hfo': 'hfo'},
......
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