Commit 80f16cdc authored by Matthew Hausknecht's avatar Matthew Hausknecht Committed by GitHub

Merge pull request #32 from drallensmith/master

Update manual; avoid tabs in python files; get hand_coded_defense_agent working reliably
parents 734cd0e0 28d0a206
*.py whitespace=tab-in-indent
...@@ -73,6 +73,7 @@ example/mid_level_move_agent ...@@ -73,6 +73,7 @@ example/mid_level_move_agent
example/mid_level_kick_agent example/mid_level_kick_agent
example/mid_level_dribble_agent example/mid_level_dribble_agent
example/communication_agent example/communication_agent
example/hand_coded_defense_agent
# Dependency directories # Dependency directories
librcsc-prefix/ librcsc-prefix/
......
...@@ -2,7 +2,13 @@ ...@@ -2,7 +2,13 @@
# encoding: utf-8 # encoding: utf-8
from __future__ import print_function from __future__ import print_function
import subprocess, os, time, numpy, sys import atexit
import numpy
import os
import time
import signal
import subprocess
import sys
# Global list of all/essential running processes # Global list of all/essential running processes
processes, necProcesses = [], [] processes, necProcesses = [], []
...@@ -12,6 +18,16 @@ SERVER_BIN = 'rcssserver' ...@@ -12,6 +18,16 @@ SERVER_BIN = 'rcssserver'
# Command to run the monitor. Edit as needed; ditto to the above re directories. # Command to run the monitor. Edit as needed; ditto to the above re directories.
MONITOR_BIN = 'soccerwindow2' MONITOR_BIN = 'soccerwindow2'
def cleanup():
"""Cleanup even if doing SystemExit, as with term."""
for p in reversed(processes):
p.terminate()
time.sleep(0.1)
p.kill()
def term(received_signal, ignored_stack):
sys.exit("Signal {0!r} received; exiting".format(received_signal))
def launch(cmd, name = 'Unknown', necessary = True, suppressOutput = True): def launch(cmd, name = 'Unknown', necessary = True, suppressOutput = True):
"""Launch a process. """Launch a process.
...@@ -22,8 +38,8 @@ def launch(cmd, name = 'Unknown', necessary = True, suppressOutput = True): ...@@ -22,8 +38,8 @@ def launch(cmd, name = 'Unknown', necessary = True, suppressOutput = True):
""" """
kwargs = {} kwargs = {}
if suppressOutput: if suppressOutput:
kwargs = {'stdout': open('/dev/null', 'w'), kwargs = {'stdout': open(os.devnull, 'w'),
'stderr': open('/dev/null', 'w')} 'stderr': open(os.devnull, 'w')}
try: try:
p = subprocess.Popen(cmd.split(' '), shell = False, **kwargs) p = subprocess.Popen(cmd.split(' '), shell = False, **kwargs)
except (IOError, OSError): except (IOError, OSError):
...@@ -69,6 +85,13 @@ def main(args): ...@@ -69,6 +85,13 @@ def main(args):
args.min_ball_x, args.max_ball_x, args.messageSize, args.min_ball_x, args.max_ball_x, args.messageSize,
args.verbose) args.verbose)
try:
signal.signal(signal.SIGTERM, term)
except (ValueError, AttributeError):
print("Not able to catch sigterm")
atexit.register(cleanup)
try: try:
# Launch the Server # Launch the Server
server = launch(serverCommand + serverOptions, name='server', server = launch(serverCommand + serverOptions, name='server',
......
...@@ -83,7 +83,7 @@ export LC_ALL ?= C ...@@ -83,7 +83,7 @@ export LC_ALL ?= C
# #
# If you list files or wildcards here, they will *not* be cleaned - default is # If you list files or wildcards here, they will *not* be cleaned - default is
# to allow everything to be cleaned. # to allow everything to be cleaned.
#neverclean ?= *.pdf neverclean ?= *.pdf
# #
# Alternatively (recommended), you can add those lines to a Makefile.ini file # Alternatively (recommended), you can add those lines to a Makefile.ini file
# and it will get picked up automatically without your having to edit this # and it will get picked up automatically without your having to edit this
......
No preview for this file type
...@@ -33,14 +33,14 @@ Installation with CMake: ...@@ -33,14 +33,14 @@ Installation with CMake:
\begin{verbatim} \begin{verbatim}
> mkdir build && cd build > mkdir build && cd build
> cmake -DCMAKE_BUILD_TYPE=Release .. > cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo ..
> make -j4 # Replace 4 with the number of cores on your machine > make -j4 # Replace 4 with the number of cores on your machine
> make install # This just copies binaries to the HFO directory; no sudo required > make install # This just copies binaries to the HFO directory; no sudo required
\end{verbatim} \end{verbatim}
HFO installation has been tested on Ubuntu Linux and OSX. Successful HFO installation has been tested on Ubuntu Linux and OSX. Successful
installation depends on installation depends on
\verb+CMake, Boost-system, Boost-filesystem, flex+. \verb+CMake, Boost-system, Boost-filesystem,+ and \verb+flex+.
These depedencies can be installed on Ubuntu using the following These depedencies can be installed on Ubuntu using the following
command:\\ command:\\
...@@ -51,7 +51,7 @@ By default, the soccerwindow2 visualizer is also built and requires ...@@ -51,7 +51,7 @@ By default, the soccerwindow2 visualizer is also built and requires
the visualizer. To disable this component, use the following cmake the visualizer. To disable this component, use the following cmake
command:\\ command:\\
\noindent \verb+ > cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SOCCERWINDOW=False ..+ \noindent \verb+ > cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo -DBUILD_SOCCERWINDOW=False ..+
\subsection{Python Interface} \subsection{Python Interface}
...@@ -66,6 +66,9 @@ or ...@@ -66,6 +66,9 @@ or
if you have limited permissions on the machine. if you have limited permissions on the machine.
Successful installation depends on
\verb+Python 2.7, 3.2, or above+ (tested with 2.7 and 3.5) and \verb+numpy+.
\section{Uninstall} \section{Uninstall}
The install is completely contained in the HFO directory. Simply The install is completely contained in the HFO directory. Simply
...@@ -170,8 +173,8 @@ compatibility. ...@@ -170,8 +173,8 @@ compatibility.
\section{Recording} \section{Recording}
It is possible to record the low-level state perceptions, actions, and It is possible to record the state perceptions (low- or high-level depending on
game status of all players:\\ the player), low-level actions, and game status of all players:\\
\noindent \verb+ > ./bin/HFO --record + \\ \noindent \verb+ > ./bin/HFO --record + \\
...@@ -388,6 +391,8 @@ changes in $\theta$. ...@@ -388,6 +391,8 @@ changes in $\theta$.
Given an angular feature $\langle \alpha_1, \alpha_2 \rangle$ we can Given an angular feature $\langle \alpha_1, \alpha_2 \rangle$ we can
recover the original angle $\theta$ (in radians) by taking the recover the original angle $\theta$ (in radians) by taking the
$cos^{-1}(\alpha_2)$ and multiplying by the sign of $\alpha_1$. $cos^{-1}(\alpha_2)$ and multiplying by the sign of $\alpha_1$.
Another method uses the common 'atan2' function as
$atan2(\alpha_1, \alpha_2)$.
\begin{figure*}[htp] \begin{figure*}[htp]
\centering \centering
......
#!/bin/bash
# HAS TO BE RUN FROM EXAMPLE DIR DUE TO hand_coded_defense_agent CONFIG!
../bin/HFO --offense-npcs=2 --defense-agents=1 --defense-npcs=1 --trials 20 --headless --port=7000 &
# The below sleep period is needed to avoid the agent connecting in before the
# Trainer.py script gets the base/Helios goalie connected in; if that happens,
# the agent gets assigned unum 1 and there is a mixup in which agent is
# supposed to be the goalie (some portions of the various programs go by unum,
# others go by a goalie flag).
sleep 15
./hand_coded_defense_agent &> agent1.txt &
sleep 5
# The magic line
# $$ holds the PID for this script
# Negation means kill by process group id instead of PID
trap "kill -TERM -$$" SIGINT
wait
\ No newline at end of file
...@@ -208,7 +208,8 @@ int main(int argc, char** argv) { ...@@ -208,7 +208,8 @@ int main(int argc, char** argv) {
HFOEnvironment hfo; HFOEnvironment hfo;
int random = 0; int random = 0;
double numGoals = 0; double numGoals = 0;
double numEpisodes = 5000; int numEpisodes = 5000;
double actualNumEpisodes = 0;
// Connect to the server and request high-level feature set. See // Connect to the server and request high-level feature set. See
// manual for more information on feature sets. // manual for more information on feature sets.
hfo.connectToServer(features, config_dir, port, server_addr, hfo.connectToServer(features, config_dir, port, server_addr,
...@@ -233,15 +234,15 @@ int main(int argc, char** argv) { ...@@ -233,15 +234,15 @@ int main(int argc, char** argv) {
string s = hfo::ActionToString(a.action) + " " +to_string(a.param) + "\n"; string s = hfo::ActionToString(a.action) + " " +to_string(a.param) + "\n";
// std::cout << s; // std::cout << s;
} else { } else {
std::cout <<"Randm"; std::cout <<"Random";
action_t a = get_random_high_lv_action(); action_t a = get_random_high_lv_action();
if (a == hfo :: MARK_PLAYER) { if (a == hfo :: MARK_PLAYER) {
hfo.act(NOOP); hfo.act(NOOP); // why not MOVE?
} else { } else {
hfo.act(a); hfo.act(a);
} }
} }
//hfo.act(hfo::INTERCEPT); //hfo.act(hfo::INTERCEPT);
status = hfo.step(); status = hfo.step();
} }
if (status==GOAL) if (status==GOAL)
...@@ -249,8 +250,14 @@ int main(int argc, char** argv) { ...@@ -249,8 +250,14 @@ int main(int argc, char** argv) {
// Check what the outcome of the episode was // Check what the outcome of the episode was
cout << "Episode " << episode << " ended with status: " cout << "Episode " << episode << " ended with status: "
<< StatusToString(status) << std::endl; << StatusToString(status) << std::endl;
if (status==SERVER_DOWN) {
break;
} else {
actualNumEpisodes++;
}
} }
double cost = numGoals/numEpisodes; double cost = numGoals/actualNumEpisodes;
hfo.act(QUIT); hfo.act(QUIT);
//write_cost(cost); //write_cost(cost);
}; };
......
# Run this file to create an executable of hand_coded_defense_agent.cpp
g++ -c hand_coded_defense_agent.cpp -I ../src/ -std=c++0x -pthread
g++ -L ../lib/ hand_coded_defense_agent.o -lhfo -pthread -o hand_coded_defense_agent -Wl,-rpath,../lib
...@@ -804,8 +804,10 @@ bool Agent::doMarkPlayer(int unum) { ...@@ -804,8 +804,10 @@ bool Agent::doMarkPlayer(int unum) {
int count = 0; int count = 0;
for ( PlayerPtrCont::const_iterator it = wm.opponentsFromSelf().begin(); it != o_end; ++it ) { for ( PlayerPtrCont::const_iterator it = wm.opponentsFromSelf().begin(); it != o_end; ++it ) {
if ( (*it)->distFromBall() < 5 ) { if ( (*it)->distFromBall() < 5 ) {
if ((kicker_unum == -1) || (kicker_unum != unum)) { // try to obey action instruction
kicker_pos = (*it)->pos(); kicker_pos = (*it)->pos();
kicker_unum = (*it)->unum(); kicker_unum = (*it)->unum();
}
} }
} }
......
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