Commit 5f99d8fe authored by Matthew Hausknecht's avatar Matthew Hausknecht Committed by GitHub

Merge pull request #29 from drallensmith/master

Cmake revisions; uniform nums; testing scripts - hopefully working with travis
parents 61507f0e 8f9b158f
...@@ -14,12 +14,16 @@ install: ...@@ -14,12 +14,16 @@ install:
brew install cartr/qt4/qt brew install cartr/qt4/qt
; ;
fi fi
- sudo -H pip install nose numpy
os: os:
- linux - linux
- osx - osx
compiler: compiler:
- clang - clang
- gcc - gcc
env:
- PYTHONPATH="."
script: script:
- mkdir build && cd build - mkdir build && cd build
- cmake -DCMAKE_BUILD_TYPE=Release .. && make -j4 && make install - cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo .. && make -j4 && make install
- cd .. && pip install --user . && nosetests --exe tests/test_basic.py
...@@ -16,7 +16,7 @@ include_directories(${Boost_INCLUDE_DIRS}) ...@@ -16,7 +16,7 @@ include_directories(${Boost_INCLUDE_DIRS})
ExternalProject_Add(rcssserver ExternalProject_Add(rcssserver
GIT_REPOSITORY "https://github.com/mhauskn/rcssserver.git" GIT_REPOSITORY "https://github.com/mhauskn/rcssserver.git"
GIT_TAG "master" GIT_TAG "master"
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release CMAKE_ARGS -DCMAKE_BUILD_TYPE=MinSizeRel
UPDATE_COMMAND "" UPDATE_COMMAND ""
INSTALL_COMMAND "") INSTALL_COMMAND "")
ExternalProject_Get_Property(rcssserver SOURCE_DIR) ExternalProject_Get_Property(rcssserver SOURCE_DIR)
...@@ -27,7 +27,7 @@ set(RCSSSERVER_BINARY_DIR ${BINARY_DIR}/bin) ...@@ -27,7 +27,7 @@ set(RCSSSERVER_BINARY_DIR ${BINARY_DIR}/bin)
ExternalProject_Add(librcsc ExternalProject_Add(librcsc
GIT_REPOSITORY "https://github.com/mhauskn/librcsc.git" GIT_REPOSITORY "https://github.com/mhauskn/librcsc.git"
GIT_TAG "master" GIT_TAG "master"
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
UPDATE_COMMAND "" UPDATE_COMMAND ""
INSTALL_COMMAND "") INSTALL_COMMAND "")
ExternalProject_Get_Property(librcsc SOURCE_DIR) ExternalProject_Get_Property(librcsc SOURCE_DIR)
...@@ -46,7 +46,7 @@ if(BUILD_SOCCERWINDOW) ...@@ -46,7 +46,7 @@ if(BUILD_SOCCERWINDOW)
DEPENDS librcsc DEPENDS librcsc
GIT_REPOSITORY "https://github.com/mhauskn/soccerwindow2.git" GIT_REPOSITORY "https://github.com/mhauskn/soccerwindow2.git"
GIT_TAG "master" GIT_TAG "master"
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DLIBRCSC_INCLUDE_DIR=${LIBRCSC_INCLUDE_DIR} -DLIBRCSC_LINK_DIR=${LIBRCSC_LINK_DIR} CMAKE_ARGS -DCMAKE_BUILD_TYPE=MinSizeRel -DLIBRCSC_INCLUDE_DIR=${LIBRCSC_INCLUDE_DIR} -DLIBRCSC_LINK_DIR=${LIBRCSC_LINK_DIR}
UPDATE_COMMAND "" UPDATE_COMMAND ""
INSTALL_COMMAND "") INSTALL_COMMAND "")
ExternalProject_Get_Property(soccerwindow2 BINARY_DIR) ExternalProject_Get_Property(soccerwindow2 BINARY_DIR)
......
...@@ -16,9 +16,10 @@ RoboCup 2D Half Field Offense ...@@ -16,9 +16,10 @@ RoboCup 2D Half Field Offense
- numpy - numpy
## Install ## Install
Note: There is no need for 'sudo' with 'make install' - the files will be installed below the starting directory.
``` ```
mkdir build && cd build mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo ..
make -j4 make -j4
make install make install
``` ```
......
from hfo_py.hfo import * try:
from hfo_py.hfo import *
except ImportError:
from hfo import *
import os import os
def get_hfo_path(): def get_hfo_path():
......
...@@ -7,7 +7,8 @@ hfo_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), ...@@ -7,7 +7,8 @@ hfo_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__),
'libhfo_c.so')) 'libhfo_c.so'))
''' Possible feature sets ''' ''' Possible feature sets '''
LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(2)) NUM_FEATURE_SETS = 2
LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(NUM_FEATURE_SETS))
''' An enum of the possible HFO actions ''' An enum of the possible HFO actions
[Low-Level] Dash(power, relative_direction) [Low-Level] Dash(power, relative_direction)
...@@ -25,8 +26,9 @@ LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(2)) ...@@ -25,8 +26,9 @@ LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(2))
[High-Level] Catch(): Catch the ball (Goalie Only) [High-Level] Catch(): Catch the ball (Goalie Only)
NOOP(): Do Nothing NOOP(): Do Nothing
QUIT(): Quit the game ''' QUIT(): Quit the game '''
NUM_HFO_ACTIONS = 19
DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \ DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \
MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT, REDUCE_ANGLE_TO_GOAL,MARK_PLAYER,DEFEND_GOAL,GO_TO_BALL = list(range(19)) MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT, REDUCE_ANGLE_TO_GOAL,MARK_PLAYER,DEFEND_GOAL,GO_TO_BALL = list(range(NUM_HFO_ACTIONS))
''' Possible game status ''' Possible game status
[IN_GAME] Game is currently active [IN_GAME] Game is currently active
...@@ -36,7 +38,8 @@ DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \ ...@@ -36,7 +38,8 @@ DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \
[OUT_OF_TIME] Trial has ended due to time limit [OUT_OF_TIME] Trial has ended due to time limit
[SERVER_DOWN] Server is not alive [SERVER_DOWN] Server is not alive
''' '''
IN_GAME, GOAL, CAPTURED_BY_DEFENSE, OUT_OF_BOUNDS, OUT_OF_TIME, SERVER_DOWN = list(range(6)) NUM_GAME_STATUS_STATES = 6
IN_GAME, GOAL, CAPTURED_BY_DEFENSE, OUT_OF_BOUNDS, OUT_OF_TIME, SERVER_DOWN = list(range(NUM_GAME_STATUS_STATES))
''' Possible sides ''' ''' Possible sides '''
RIGHT, NEUTRAL, LEFT = list(range(-1,2)) RIGHT, NEUTRAL, LEFT = list(range(-1,2))
......
...@@ -16,6 +16,7 @@ LowLevelFeatureExtractor::LowLevelFeatureExtractor(int num_teammates, ...@@ -16,6 +16,7 @@ LowLevelFeatureExtractor::LowLevelFeatureExtractor(int num_teammates,
assert(numOpponents >= 0); assert(numOpponents >= 0);
numFeatures = num_basic_features + numFeatures = num_basic_features +
features_per_player * (numTeammates + numOpponents); features_per_player * (numTeammates + numOpponents);
numFeatures += numTeammates + numOpponents; // Uniform numbers
feature_vec.resize(numFeatures); feature_vec.resize(numFeatures);
} }
...@@ -184,6 +185,38 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures( ...@@ -184,6 +185,38 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures(
addFeature(0); addFeature(0);
} }
} }
// ========================= UNIFORM NUMBERS ========================== //
detected_teammates = 0;
for (PlayerPtrCont::const_iterator it = teammates.begin();
it != teammates.end(); ++it) {
PlayerObject* teammate = *it;
if (teammate->pos().x > 0 && teammate->unum() > 0 &&
detected_teammates < numTeammates) {
addFeature(teammate->unum()/100.0);
detected_teammates++;
}
}
// Add -2 features for any missing teammates
for (int i=detected_teammates; i<numTeammates; ++i) {
addFeature(FEAT_MIN);
}
detected_opponents = 0;
for (PlayerPtrCont::const_iterator it = opponents.begin();
it != opponents.end(); ++it) {
PlayerObject* opponent = *it;
if (opponent->pos().x > 0 && opponent->unum() > 0 &&
detected_opponents < numOpponents) {
addFeature(opponent->unum()/100.0);
detected_opponents++;
}
}
// Add -2 features for any missing opponents
for (int i=detected_opponents; i<numOpponents; ++i) {
addFeature(FEAT_MIN);
}
assert(featIndx == numFeatures); assert(featIndx == numFeatures);
checkFeatures(); checkFeatures();
return feature_vec; return feature_vec;
......
...@@ -17,7 +17,7 @@ public: ...@@ -17,7 +17,7 @@ public:
protected: protected:
// Number of features for non-player objects. // Number of features for non-player objects.
const static int num_basic_features = 58; const static int num_basic_features = 58;
// Number of features for each player or opponent in game. // Number of features for each player or opponent in game, not including uniform numbers.
const static int features_per_player = 8; const static int features_per_player = 8;
}; };
......
"""Very basic tests, only of functions available sans server"""
#from __future__ import print_function
import hfo
def test_basic():
hfo_env = hfo.HFOEnvironment()
for action in range(hfo.NUM_HFO_ACTIONS):
assert len(hfo_env.actionToString(action))
for state in range(hfo.NUM_GAME_STATUS_STATES):
assert len(hfo_env.statusToString(state))
if __name__ == '__main__':
test_basic()
"""A few tests using a server"""
from __future__ import print_function
import os
import subprocess
import sys
import time
import hfo
hfo_env = hfo.HFOEnvironment()
def try_step(): # if a game ends within ~20 frames, something is wrong...
status = hfo_env.step()
assert (status ==
hfo.IN_GAME), ("Status is {!s} ({!r}), not IN_GAME".
format(hfo_env.statusToString(status),status))
return hfo_env.getState()
def test_with_server():
test_dir = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
binary_dir = os.path.normpath(test_dir + "/../bin")
conf_dir = os.path.join(binary_dir, 'teams/base/config/formations-dt')
bin_HFO = os.path.join(binary_dir, "HFO")
popen_list = [sys.executable, "-x", bin_HFO,
"--offense-agents=1", "--defense-npcs=2",
"--offense-npcs=2", "--trials=1", "--headless"]
HFO_process = subprocess.Popen(popen_list)
time.sleep(0.2)
assert (HFO_process.poll() is
None), "Failed to start HFO with command '{}'".format(" ".join(popen_list))
time.sleep(3)
try:
hfo_env.connectToServer(config_dir=conf_dir) # using defaults otherwise
min_state_size = 58+(9*4)
state_size = hfo_env.getStateSize()
assert (state_size >=
min_state_size), "State size is {!s}, not {!s}+".format(state_size,min_state_size)
print("State size is {!s}".format(state_size))
my_unum = hfo_env.getUnum()
assert ((my_unum > 0) and (my_unum <= 11)), "Wrong self uniform number ({!r})".format(my_unum)
print("My unum is {!s}".format(my_unum))
had_ok_unum = False
had_ok_unum_set_my_side = set()
had_ok_unum_set_their_side = set();
hfo_env.act(hfo.NOOP)
state = try_step()
for x in range(0,20):
if int(state[12]) == 1: # can kick the ball
hfo_env.act(hfo.DRIBBLE)
elif (x % 2) != 0:
hfo_env.act(hfo.MOVE)
elif int(state[50]) == 1: # can see the ball
hfo_env.act(hfo.GO_TO_BALL)
else:
hfo_env.act(hfo.MOVE)
state = try_step()
for n in range((state_size-4), state_size):
their_unum = state[n]
if ((their_unum > 0) and (their_unum <= 0.11)):
print("{!s}: OK uniform number ({!r}) for {!s}".format(x,their_unum,n))
had_ok_unum = True
if n > (state_size-3):
had_ok_unum_set_their_side.add(their_unum)
else:
had_ok_unum_set_my_side.add(their_unum)
elif x > 3:
print("{!s}: Wrong other uniform number ({!r}) for {!s}".format(x,their_unum,n))
if (len(had_ok_unum_set_my_side) > 1) and (len(had_ok_unum_set_their_side) > 1):
break
assert had_ok_unum, "Never saw OK other uniform number"
try:
hfo_env.act(hfo.MOVE_TO)
except AssertionError:
pass
else:
raise AssertionError("Should have got AssertionError")
HFO_process.terminate()
hfo_env.act(hfo.QUIT)
time.sleep(1.2)
status = hfo_env.step()
assert (status ==
hfo.SERVER_DOWN), ("Status is {!s} ({!r}), not SERVER_DOWN".
format(hfo_env.statusToString(status), status))
finally:
if HFO_process.poll() is None:
HFO_process.terminate()
os.system("killall -9 rcssserver")
if __name__ == '__main__':
test_with_server()
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