Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
Seminar-HFO
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Shashank Suhas
Seminar-HFO
Commits
ed4c009f
Commit
ed4c009f
authored
May 30, 2015
by
Matthew Hausknecht
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored features. Added higher level actions.
parent
57f30d7f
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
591 additions
and
399 deletions
+591
-399
bin/Trainer.py
bin/Trainer.py
+7
-0
bin/start.py
bin/start.py
+12
-3
bin/start.sh
bin/start.sh
+6
-0
bin/start_agent.sh
bin/start_agent.sh
+11
-5
hfo/hfo.py
hfo/hfo.py
+9
-5
src/HFO.hpp
src/HFO.hpp
+9
-5
src/agent.cpp
src/agent.cpp
+93
-333
src/agent.h
src/agent.h
+6
-48
src/highlevel_feature_extractor.cpp
src/highlevel_feature_extractor.cpp
+192
-0
src/highlevel_feature_extractor.h
src/highlevel_feature_extractor.h
+27
-0
src/lowlevel_feature_extractor.cpp
src/lowlevel_feature_extractor.cpp
+192
-0
src/lowlevel_feature_extractor.h
src/lowlevel_feature_extractor.h
+27
-0
No files found.
bin/Trainer.py
View file @
ed4c009f
...
...
@@ -36,6 +36,7 @@ class Trainer(object):
self
.
_serverPort
=
args
.
port
+
1
# The port the server is listening on
self
.
_coachPort
=
args
.
port
+
2
# The coach port to talk with the server
self
.
_logDir
=
args
.
logDir
# Directory to store logs
self
.
_record
=
args
.
record
# Record states + actions
self
.
_numOffense
=
args
.
numOffense
# Number offensive players
self
.
_numDefense
=
args
.
numDefense
# Number defensive players
self
.
_maxTrials
=
args
.
numTrials
# Maximum number of trials to play
...
...
@@ -67,6 +68,7 @@ class Trainer(object):
self
.
_agentNumInt
=
-
1
# Agent's internal team number
self
.
_agentNumExt
=
-
1
# Agent's external team number
self
.
_agentServerPort
=
args
.
port
# Port for agent's server
self
.
_agentOnBall
=
args
.
agent_on_ball
# If true, agent starts with the ball
# =============== MISC =============== #
self
.
_offenseTeam
=
''
# Name of the offensive team
self
.
_defenseTeam
=
''
# Name of the defensive team
...
...
@@ -107,6 +109,8 @@ class Trainer(object):
%
(
self
.
_agentTeam
,
self
.
_agentNumExt
,
self
.
_serverPort
,
self
.
_coachPort
,
self
.
_logDir
,
numTeammates
,
numOpponents
,
self
.
_agent_play_offense
,
self
.
_agentServerPort
)
if
self
.
_record
:
agentCmd
+=
' --record'
agentCmd
=
os
.
path
.
join
(
binary_dir
,
agentCmd
)
agentCmd
=
agentCmd
.
split
(
' '
)
# Ignore stderr because librcsc continually prints to it
...
...
@@ -527,6 +531,9 @@ class Trainer(object):
# Move the rest of the offense
for
i
in
xrange
(
1
,
self
.
_numOffense
+
1
):
self
.
movePlayer
(
self
.
_offenseTeam
,
i
,
self
.
getOffensiveResetPosition
())
# Move the agent to the ball
if
self
.
_agent
and
self
.
_agentOnBall
:
self
.
movePlayer
(
self
.
_offenseTeam
,
1
,
self
.
_ballPosition
)
# Move the defensive goalie
if
self
.
_numDefense
>
0
:
self
.
movePlayer
(
self
.
_defenseTeam
,
0
,
[
0.5
*
self
.
PITCH_LENGTH
,
0
])
...
...
bin/start.py
View file @
ed4c009f
...
...
@@ -11,10 +11,13 @@ SERVER_CMD = 'rcssserver'
# Command to run the monitor. Edit as needed.
MONITOR_CMD
=
'rcssmonitor'
def
getAgentDirCmd
(
binary_dir
,
teamname
,
server_port
=
6000
,
coach_port
=
6002
,
logDir
=
'/tmp'
):
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
...
...
@@ -53,8 +56,10 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
args
.
logDir
,
args
.
logDir
)
if
args
.
sync
:
serverOptions
+=
' server::synch_mode=on'
team1
,
team1Cmd
=
getAgentDirCmd
(
binary_dir
,
team1
,
server_port
,
coach_port
,
args
.
logDir
)
team2
,
team2Cmd
=
getAgentDirCmd
(
binary_dir
,
team2
,
server_port
,
coach_port
,
args
.
logDir
)
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
)
try
:
# Launch the Server
server
=
launch
(
SERVER_CMD
+
serverOptions
,
name
=
'server'
)
...
...
@@ -114,6 +119,10 @@ def parseArgs(args=None):
' will be incrementally allocated the following ports.'
)
p
.
add_argument
(
'--log-dir'
,
dest
=
'logDir'
,
default
=
'log/'
,
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.'
)
return
p
.
parse_args
(
args
=
args
)
if
__name__
==
'__main__'
:
...
...
bin/start.sh
View file @
ed4c009f
...
...
@@ -66,6 +66,7 @@ usage()
echo
" --log-dir DIRECTORY specifies debug log directory (default: /tmp)"
echo
" --debug-log-ext EXTENSION specifies debug log file extension (default: .log)"
echo
" --fullstate FULLSTATE_TYPE specifies fullstate model handling"
echo
" --record records actions (default: off)"
echo
" FULLSTATE_TYPE is one of [ignore|reference|override]."
)
1>&2
}
...
...
@@ -162,6 +163,10 @@ do
offline_mode
=
"on"
;;
--record
)
record
=
"--record"
;;
--debug
)
debugopt
=
"
${
debugopt
}
--debug"
coachdebug
=
"
${
coachdebug
}
--debug"
...
...
@@ -277,6 +282,7 @@ opt="${opt} --debug_server_host ${debug_server_host}"
opt
=
"
${
opt
}
--debug_server_port
${
debug_server_port
}
"
opt
=
"
${
opt
}
${
offline_logging
}
"
opt
=
"
${
opt
}
${
debugopt
}
"
opt
=
"
${
opt
}
${
record
}
"
ping
-c
1
$host
...
...
bin/start_agent.sh
View file @
ed4c009f
...
...
@@ -64,6 +64,7 @@ usage()
echo
" --log-dir DIRECTORY specifies debug log directory (default: /tmp)"
echo
" --debug-log-ext EXTENSION specifies debug log file extension (default: .log)"
echo
" --fullstate FULLSTATE_TYPE specifies fullstate model handling"
echo
" --record records actions (default: off)"
echo
" FULLSTATE_TYPE is one of [ignore|reference|override]."
echo
" --offensePlayers player1 ... specifies the numbers of the offense players"
echo
" --defensePlayers player1 ... specifies the numbers of the defense players"
...
...
@@ -176,6 +177,10 @@ do
offline_mode
=
"on"
;;
--record
)
record
=
"--record"
;;
--record_stats_file
)
if
[
$#
-lt
2
]
;
then
usage
...
...
@@ -426,6 +431,7 @@ opt="${opt} --debug_server_host ${debug_server_host}"
opt
=
"
${
opt
}
--debug_server_port
${
debug_server_port
}
"
opt
=
"
${
opt
}
${
offline_logging
}
"
opt
=
"
${
opt
}
${
debugopt
}
"
opt
=
"
${
opt
}
${
record
}
"
ping
-c
1
$host
...
...
hfo/hfo.py
View file @
ed4c009f
...
...
@@ -3,14 +3,18 @@ import socket, struct, thread, time
class
HFO_Actions
:
''' An enum of the possible HFO actions
Dash(power, relative_direction)
Turn(direction)
Tackle(direction)
Kick(power, direction)
[Low-Level] Dash(power, relative_direction)
[Low-Level] Turn(direction)
[Low-Level] Tackle(direction)
[Low-Level] Kick(power, direction)
[High-Level] Move(): Reposition player according to strategy
[High-Level] Shoot(): Shoot the ball
[High-Level] Pass(): Pass to the most open teammate
[High-Level] Dribble(): Offensive dribble
QUIT
'''
DASH
,
TURN
,
TACKLE
,
KICK
,
QUIT
=
range
(
5
)
DASH
,
TURN
,
TACKLE
,
KICK
,
MOVE
,
SHOOT
,
PASS
,
DRIBBLE
,
QUIT
=
range
(
8
)
class
HFO_Status
:
''' Current status of the HFO game. '''
...
...
src/HFO.hpp
View file @
ed4c009f
...
...
@@ -6,10 +6,14 @@
// The actions available to the agent
enum
action_t
{
DASH
,
// Dash(power, relative_direction)
TURN
,
// Turn(direction)
TACKLE
,
// Tackle(direction)
KICK
,
// Kick(power, direction)
DASH
,
// [Low-Level] Dash(power, relative_direction)
TURN
,
// [Low-Level] Turn(direction)
TACKLE
,
// [Low-Level] Tackle(direction)
KICK
,
// [Low-Level] Kick(power, direction)
MOVE
,
// [High-Level] Move(): Reposition player according to strategy
SHOOT
,
// [High-Level] Shoot(): Shoot the ball
PASS
,
// [High-Level] Pass(): Pass to the most open teammate
DRIBBLE
,
// [High-Level] Dribble(): Offensive dribble
QUIT
// Special action to quit the game
};
...
...
src/agent.cpp
View file @
ed4c009f
...
...
@@ -41,6 +41,7 @@
#include "sample_communication.h"
#include "keepaway_communication.h"
#include "bhv_chain_action.h"
#include "bhv_penalty_kick.h"
#include "bhv_set_play.h"
#include "bhv_set_play_kick_in.h"
...
...
@@ -48,16 +49,30 @@
#include "bhv_custom_before_kick_off.h"
#include "bhv_strict_check_shoot.h"
#include "bhv_basic_move.h"
#include "view_tactical.h"
#include "intention_receive.h"
#include "lowlevel_feature_extractor.h"
#include "highlevel_feature_extractor.h"
#include "actgen_cross.h"
#include "actgen_direct_pass.h"
#include "actgen_self_pass.h"
#include "actgen_strict_check_pass.h"
#include "actgen_short_dribble.h"
#include "actgen_simple_dribble.h"
#include "actgen_shoot.h"
#include "actgen_action_chain_length_filter.h"
#include <rcsc/action/basic_actions.h>
#include <rcsc/action/bhv_emergency.h>
#include <rcsc/action/body_go_to_point.h>
#include <rcsc/action/body_intercept.h>
#include <rcsc/action/body_kick_one_step.h>
#include <rcsc/action/body_pass.h>
#include <rcsc/action/body_dribble.h>
#include <rcsc/action/neck_scan_field.h>
#include <rcsc/action/neck_turn_to_ball_or_scan.h>
#include <rcsc/action/view_synch.h>
...
...
@@ -120,11 +135,10 @@ Agent::Agent()
M_communication
(),
M_field_evaluator
(
createFieldEvaluator
()),
M_action_generator
(
createActionGenerator
()),
numTeammates
(
-
1
),
numOpponents
(
-
1
),
numFeatures
(
-
1
),
lastTrainerMessageTime
(
-
1
),
maxHFORadius
(
-
1
),
server_port
(
6008
),
server_running
(
false
)
server_running
(
false
),
record
(
false
)
{
boost
::
shared_ptr
<
AudioMemory
>
audio_memory
(
new
AudioMemory
);
...
...
@@ -173,6 +187,7 @@ Agent::Agent()
}
Agent
::~
Agent
()
{
delete
feature_extractor
;
std
::
cout
<<
"[Agent Server] Closing Server."
<<
std
::
endl
;
close
(
newsockfd
);
close
(
sockfd
);
...
...
@@ -184,12 +199,15 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) {
// read additional options
result
&=
Strategy
::
instance
().
init
(
cmd_parser
);
int
numTeammates
,
numOpponents
;
bool
playingOffense
;
rcsc
::
ParamMap
my_params
(
"Additional options"
);
my_params
.
add
()(
"numTeammates"
,
""
,
&
numTeammates
,
"number of teammates"
);
my_params
.
add
()(
"numOpponents"
,
""
,
&
numOpponents
,
"number of opponents"
);
my_params
.
add
()(
"playingOffense"
,
""
,
&
playingOffense
,
"are we playing offense or defense"
);
my_params
.
add
()(
"serverPort"
,
""
,
&
server_port
,
"Port to start server on"
);
record
=
cmd_parser
.
count
(
"record"
)
>
0
;
cmd_parser
.
parse
(
my_params
);
if
(
cmd_parser
.
count
(
"help"
)
>
0
)
{
...
...
@@ -220,249 +238,12 @@ bool Agent::initImpl(CmdLineParser & cmd_parser) {
assert
(
numTeammates
>=
0
);
assert
(
numOpponents
>=
0
);
numFeatures
=
num_basic_features
+
features_per_player
*
(
numTeammates
+
numOpponents
);
feature_vec
.
resize
(
numFeatures
);
const
ServerParam
&
SP
=
ServerParam
::
i
();
// Grab the field dimensions
pitchLength
=
SP
.
pitchLength
();
pitchWidth
=
SP
.
pitchWidth
();
pitchHalfLength
=
SP
.
pitchHalfLength
();
pitchHalfWidth
=
SP
.
pitchHalfWidth
();
goalHalfWidth
=
SP
.
goalHalfWidth
();
penaltyAreaLength
=
SP
.
penaltyAreaLength
();
penaltyAreaWidth
=
SP
.
penaltyAreaWidth
();
// Maximum possible radius in HFO
maxHFORadius
=
sqrtf
(
pitchHalfLength
*
pitchHalfLength
+
pitchHalfWidth
*
pitchHalfWidth
);
feature_extractor
=
new
LowLevelFeatureExtractor
(
numTeammates
,
numOpponents
,
playingOffense
);
return
true
;
}
void
Agent
::
updateStateFeatures
()
{
featIndx
=
0
;
const
ServerParam
&
SP
=
ServerParam
::
i
();
const
WorldModel
&
wm
=
this
->
world
();
// ======================== SELF FEATURES ======================== //
const
SelfObject
&
self
=
wm
.
self
();
const
Vector2D
&
self_pos
=
self
.
pos
();
const
AngleDeg
&
self_ang
=
self
.
body
();
// Absolute (x,y) position of the agent.
addFeature
(
self
.
posValid
()
?
FEAT_MAX
:
FEAT_MIN
);
// ADD_FEATURE(self_pos.x);
// ADD_FEATURE(self_pos.y);
// Direction and speed of the agent.
addFeature
(
self
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
self
.
velValid
())
{
addAngFeature
(
self_ang
-
self
.
vel
().
th
());
addNormFeature
(
self
.
speed
(),
0.
,
observedSelfSpeedMax
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Global Body Angle -- 0:right -90:up 90:down 180/-180:left
addAngFeature
(
self_ang
);
// Neck Angle -- We probably don't need this unless we are
// controlling the neck manually.
// std::cout << "Face Error: " << self.faceError() << std::endl;
// if (self.faceValid()) {
// std::cout << "FaceAngle: " << self.face() << std::endl;
// }
addNormFeature
(
self
.
stamina
(),
0.
,
observedStaminaMax
);
addFeature
(
self
.
isFrozen
()
?
FEAT_MAX
:
FEAT_MIN
);
// Probabilities - Do we want these???
// std::cout << "catchProb: " << self.catchProbability() << std::endl;
// std::cout << "tackleProb: " << self.tackleProbability() << std::endl;
// std::cout << "fouldProb: " << self.foulProbability() << std::endl;
// Features indicating if we are colliding with an object
addFeature
(
self
.
collidesWithBall
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPlayer
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPost
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
isKickable
()
?
FEAT_MAX
:
FEAT_MIN
);
// inertiaPoint estimates the ball point after a number of steps
// self.inertiaPoint(n_steps);
// ======================== LANDMARK FEATURES ======================== //
// Top Bottom Center of Goal
rcsc
::
Vector2D
goalCenter
(
pitchHalfLength
,
0
);
addLandmarkFeatures
(
goalCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostTop
(
pitchHalfLength
,
-
goalHalfWidth
);
addLandmarkFeatures
(
goalPostTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostBot
(
pitchHalfLength
,
goalHalfWidth
);
addLandmarkFeatures
(
goalPostBot
,
self_pos
,
self_ang
);
// Top Bottom Center of Penalty Box
rcsc
::
Vector2D
penaltyBoxCenter
(
pitchHalfLength
-
penaltyAreaLength
,
0
);
addLandmarkFeatures
(
penaltyBoxCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxTop
(
pitchHalfLength
-
penaltyAreaLength
,
-
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxBot
(
pitchHalfLength
-
penaltyAreaLength
,
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxBot
,
self_pos
,
self_ang
);
// Corners of the Playable Area
rcsc
::
Vector2D
centerField
(
0
,
0
);
addLandmarkFeatures
(
centerField
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopLeft
(
0
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopLeft
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopRight
(
pitchHalfLength
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotRight
(
pitchHalfLength
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotLeft
(
0
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotLeft
,
self_pos
,
self_ang
);
// Distances to the edges of the playable area
if
(
self
.
posValid
())
{
// Distance to Left field line
addDistFeature
(
self_pos
.
x
,
pitchHalfLength
);
// Distance to Right field line
addDistFeature
(
pitchHalfLength
-
self_pos
.
x
,
pitchHalfLength
);
// Distance to top field line
addDistFeature
(
pitchHalfWidth
+
self_pos
.
y
,
pitchWidth
);
// Distance to Bottom field line
addDistFeature
(
pitchHalfWidth
-
self_pos
.
y
,
pitchWidth
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// ======================== BALL FEATURES ======================== //
const
BallObject
&
ball
=
wm
.
ball
();
// Angle and distance to the ball
addFeature
(
ball
.
rposValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
rposValid
())
{
addAngFeature
(
ball
.
angleFromSelf
());
addDistFeature
(
ball
.
distFromSelf
(),
maxHFORadius
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Velocity and direction of the ball
addFeature
(
ball
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
velValid
())
{
// SeverParam lists ballSpeedMax a 2.7 which is too low
addNormFeature
(
ball
.
vel
().
r
(),
0.
,
observedBallSpeedMax
);
addAngFeature
(
ball
.
vel
().
th
());
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
assert
(
featIndx
==
num_basic_features
);
// ======================== TEAMMATE FEATURES ======================== //
// Vector of PlayerObject pointers sorted by increasing distance from self
int
detected_teammates
=
0
;
const
PlayerPtrCont
&
teammates
=
wm
.
teammatesFromSelf
();
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
)
{
addPlayerFeatures
(
*
teammate
,
self_pos
,
self_ang
);
detected_teammates
++
;
}
}
// Add zero features for any missing teammates
for
(
int
i
=
detected_teammates
;
i
<
numTeammates
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
// ======================== OPPONENT FEATURES ======================== //
int
detected_opponents
=
0
;
const
PlayerPtrCont
&
opponents
=
wm
.
opponentsFromSelf
();
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
)
{
addPlayerFeatures
(
*
opponent
,
self_pos
,
self_ang
);
detected_opponents
++
;
}
}
// Add zero features for any missing opponents
for
(
int
i
=
detected_opponents
;
i
<
numOpponents
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
assert
(
featIndx
==
numFeatures
);
for
(
int
i
=
0
;
i
<
numFeatures
;
++
i
)
{
if
(
feature_vec
[
i
]
<
FEAT_MIN
||
feature_vec
[
i
]
>
FEAT_MAX
)
{
std
::
cout
<<
"Invalid Feature! Indx:"
<<
i
<<
" Val:"
<<
feature_vec
[
i
]
<<
std
::
endl
;
exit
(
1
);
}
}
}
void
Agent
::
addAngFeature
(
const
rcsc
::
AngleDeg
&
ang
)
{
addFeature
(
ang
.
sin
());
addFeature
(
ang
.
cos
());
}
void
Agent
::
addDistFeature
(
float
dist
,
float
maxDist
)
{
float
proximity
=
1.
f
-
std
::
max
(
0.
f
,
std
::
min
(
1.
f
,
dist
/
maxDist
));
addNormFeature
(
proximity
,
0.
,
1.
);
}
// Add the angle and distance to the landmark to the feature_vec
void
Agent
::
addLandmarkFeatures
(
const
rcsc
::
Vector2D
&
landmark
,
const
rcsc
::
Vector2D
&
self_pos
,
const
rcsc
::
AngleDeg
&
self_ang
)
{
if
(
self_pos
==
Vector2D
::
INVALIDATED
)
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
else
{
Vector2D
vec_to_landmark
=
landmark
-
self_pos
;
addAngFeature
(
self_ang
-
vec_to_landmark
.
th
());
addDistFeature
(
vec_to_landmark
.
r
(),
maxHFORadius
);
}
}
void
Agent
::
addPlayerFeatures
(
rcsc
::
PlayerObject
&
player
,
const
rcsc
::
Vector2D
&
self_pos
,
const
rcsc
::
AngleDeg
&
self_ang
)
{
assert
(
player
.
posValid
());
// Angle dist to player.
addLandmarkFeatures
(
player
.
pos
(),
self_pos
,
self_ang
);
// Player's body angle
addAngFeature
(
player
.
body
());
if
(
player
.
velValid
())
{
// Player's speed
addNormFeature
(
player
.
vel
().
r
(),
0.
,
observedPlayerSpeedMax
);
// Player's velocity direction
addAngFeature
(
player
.
vel
().
th
());
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
}
void
Agent
::
startServer
(
int
server_port
)
{
std
::
cout
<<
"Starting Server on Port "
<<
server_port
<<
std
::
endl
;
struct
sockaddr_in
serv_addr
,
cli_addr
;
...
...
@@ -503,6 +284,7 @@ void Agent::clientHandshake() {
error
(
"[Agent Server] Handshake failed. Improper float recieved."
);
}
// Send the number of features
int
numFeatures
=
feature_extractor
->
getNumFeatures
();
assert
(
numFeatures
>
0
);
if
(
send
(
newsockfd
,
&
numFeatures
,
sizeof
(
int
),
0
)
<
0
)
{
error
(
"[Agent Server] ERROR sending from socket"
);
...
...
@@ -518,22 +300,6 @@ void Agent::clientHandshake() {
std
::
cout
<<
"[Agent Server] Handshake complete"
<<
std
::
endl
;
}
void
Agent
::
addFeature
(
float
val
)
{
assert
(
featIndx
<
numFeatures
);
feature_vec
[
featIndx
++
]
=
val
;
}
void
Agent
::
addNormFeature
(
float
val
,
float
min_val
,
float
max_val
)
{
assert
(
featIndx
<
numFeatures
);
if
(
val
<
min_val
||
val
>
max_val
)
{
std
::
cout
<<
"Feature "
<<
featIndx
<<
" Violated Feature Bounds: "
<<
val
<<
" Expected min/max: ["
<<
min_val
<<
", "
<<
max_val
<<
"]"
<<
std
::
endl
;
val
=
std
::
min
(
std
::
max
(
val
,
min_val
),
max_val
);
}
feature_vec
[
featIndx
++
]
=
((
val
-
min_val
)
/
(
max_val
-
min_val
))
*
(
FEAT_MAX
-
FEAT_MIN
)
+
FEAT_MIN
;
}
hfo_status_t
Agent
::
getGameStatus
()
{
hfo_status_t
game_status
=
IN_GAME
;
if
(
audioSensor
().
trainerMessageTime
().
cycle
()
>
lastTrainerMessageTime
)
{
...
...
@@ -572,9 +338,15 @@ void Agent::actionImpl() {
}
// Update and send the state features
updateStateFeatures
();
if
(
send
(
newsockfd
,
&
(
feature_vec
.
front
()),
numFeatures
*
sizeof
(
float
),
0
)
<
0
)
{
const
std
::
vector
<
float
>&
features
=
feature_extractor
->
ExtractFeatures
(
this
->
world
());
if
(
record
)
{
elog
.
addText
(
Logger
::
WORLD
,
"GameStatus %d"
,
game_status
);
elog
.
flush
();
feature_extractor
->
LogFeatures
();
}
if
(
send
(
newsockfd
,
&
(
features
.
front
()),
features
.
size
()
*
sizeof
(
float
),
0
)
<
0
)
{
error
(
"[Agent Server] ERROR sending state features from socket"
);
}
...
...
@@ -596,6 +368,18 @@ void Agent::actionImpl() {
case
KICK
:
this
->
doKick
(
action
.
arg1
,
action
.
arg2
);
break
;
case
MOVE
:
this
->
doMove
();
break
;
case
SHOOT
:
this
->
doShoot
();
break
;
case
PASS
:
this
->
doPass
();
break
;
case
DRIBBLE
:
this
->
doDribble
();
break
;
case
QUIT
:
std
::
cout
<<
"[Agent Server] Got quit from agent."
<<
std
::
endl
;
exit
(
0
);
...
...
@@ -608,68 +392,6 @@ void Agent::actionImpl() {
// For now let's not worry about turning the neck or setting the vision.
this
->
setViewAction
(
new
View_Tactical
());
this
->
setNeckAction
(
new
Neck_TurnToBallOrScan
());
// ======================== Actions ======================== //
// 0: Dash(power, relative_direction)
// 1: Turn(direction)
// 2: Tackle(direction)
// 3: Kick(power, direction)
// Dash with power [-100,100]. Negative values move backwards. The
// relative_dir [-180,180] is the direction to dash in. This should
// be set every step.
// this->doDash(1., 0);
// std::cout << " DefaultDashPowerRate: " << SP.defaultDashPowerRate()
// << " minDashAngle: " << SP.minDashAngle()
// << " maxDashAngle: " << SP.maxDashAngle()
// << " dashAngleStep: " << SP.dashAngleStep()
// << " sideDashRate: " << SP.sideDashRate()
// << " backDashRate: " << SP.backDashRate()
// << " maxDashPower: " << SP.maxDashPower()
// << " minDashPower: " << SP.minDashPower() << std::endl;
// Tackle player for ball. If player config version is greater than
// 12 (we are 14) then power_or_dir is actually just direction.
// Power_dir [-180,180] direction of tackle.
// Foul - should we intentionally foul? No for now...
// this->doTackle(0., false);
// std::cout << "PlayerConfigVersion: " << this->config().version() << std::endl;
// std::cout << " tackleDist: " << SP.tackleDist()
// << " tackleBackDist: " << SP.tackleBackDist()
// << " tackleWidth: " << SP.tackleWidth()
// << " tackleExponent: " << SP.tackleExponent()
// << " tackleCycles: " << SP.tackleCycles()
// << " tacklePowerRate: " << SP.tacklePowerRate()
// << " maxTacklePower: " << SP.maxTacklePower()
// << " maxBackTacklePower: " << SP.maxBackTacklePower()
// << " tackleRandFactor: " << SP.tackleRandFactor() << std::endl;
// Kick with power [0,100] and direction [-180,180] (left to right)
// this->doKick(100., 0);
// ======================== IGNORED ACTIONS ======================== //
// Only available to goalie.
// this->doCatch();
// Not sure if we want to point yet...
// this->doPointto(x,y);
// this->doPointtoOff();
// Attention is mainly used for communication. Lets not worry about it for now.
// this->doAttentionto(...);
// this->doAttentionOff();
// Intention seems to be a way of queing actions. Lets not worry about it.
// this->setInetion(...);
// this->doIntention();
// Dribble is omitted because it consists of dashes, turns, and kicks
// sleep(1);
// static int i=0;
// i++;
// if (i % 2 == 0) {
// this->doDash(10., 0);
// } else {
// this->doKick(2., 0);
// this->doTurn(5);
// }
}
/*-------------------------------------------------------------------*/
...
...
@@ -1004,6 +726,53 @@ Agent::doShoot()
return
false
;
}
/*-------------------------------------------------------------------*/
/*!
*/
bool
Agent
::
doPass
()
{
rcsc
::
Body_Pass
pass
;
pass
.
get_best_pass
(
this
->
world
(),
NULL
,
NULL
,
NULL
);
pass
.
execute
(
this
);
return
true
;
}
/*-------------------------------------------------------------------*/
/*!
*/
bool
Agent
::
doDribble
()
{
Strategy
::
instance
().
update
(
world
()
);
M_field_evaluator
=
createFieldEvaluator
();
CompositeActionGenerator
*
g
=
new
CompositeActionGenerator
();
g
->
addGenerator
(
new
ActGen_MaxActionChainLengthFilter
(
new
ActGen_ShortDribble
(),
1
));
M_action_generator
=
ActionGenerator
::
ConstPtr
(
g
);
ActionChainHolder
::
instance
().
setFieldEvaluator
(
M_field_evaluator
);
ActionChainHolder
::
instance
().
setActionGenerator
(
M_action_generator
);
doPreprocess
();
ActionChainHolder
::
instance
().
update
(
world
()
);
Bhv_ChainAction
(
ActionChainHolder
::
instance
().
graph
()).
execute
(
this
);
return
true
;
}
/*-------------------------------------------------------------------*/
/*!
*/
bool
Agent
::
doMove
()
{
Strategy
::
instance
().
update
(
world
()
);
int
role_num
=
Strategy
::
i
().
roleNumber
(
world
().
self
().
unum
());
Bhv_BasicMove
().
execute
(
this
);
return
true
;
}
/*-------------------------------------------------------------------*/
/*!
...
...
@@ -1127,15 +896,6 @@ Agent::createFieldEvaluator() const
/*-------------------------------------------------------------------*/
/*!
*/
#include "actgen_cross.h"
#include "actgen_direct_pass.h"
#include "actgen_self_pass.h"
#include "actgen_strict_check_pass.h"
#include "actgen_short_dribble.h"
#include "actgen_simple_dribble.h"
#include "actgen_shoot.h"
#include "actgen_action_chain_length_filter.h"
ActionGenerator
::
ConstPtr
Agent
::
createActionGenerator
()
const
{
...
...
src/agent.h
View file @
ed4c009f
...
...
@@ -31,6 +31,7 @@
#include "field_evaluator.h"
#include "communication.h"
#include "HFO.hpp"
#include "feature_extractor.h"
#include <rcsc/player/player_agent.h>
#include <vector>
...
...
@@ -59,72 +60,29 @@ protected:
virtual
FieldEvaluator
::
ConstPtr
createFieldEvaluator
()
const
;
virtual
ActionGenerator
::
ConstPtr
createActionGenerator
()
const
;
// Updated the state features stored in feature_vec
void
updateStateFeatures
();
// Get the current game status
hfo_status_t
getGameStatus
();
// Encodes an angle feature as the sin and cosine of that angle,
// effectively transforming a single angle into two features.
void
addAngFeature
(
const
rcsc
::
AngleDeg
&
ang
);
// Encodes a proximity feature which is defined by a distance as
// well as a maximum possible distance, which acts as a
// normalizer. Encodes the distance as [0-far, 1-close]. Ignores
// distances greater than maxDist or less than 0.
void
addDistFeature
(
float
dist
,
float
maxDist
);
// Add the angle and distance to the landmark to the feature_vec
void
addLandmarkFeatures
(
const
rcsc
::
Vector2D
&
landmark
,
const
rcsc
::
Vector2D
&
self_pos
,
const
rcsc
::
AngleDeg
&
self_ang
);
// Add features corresponding to another player.
void
addPlayerFeatures
(
rcsc
::
PlayerObject
&
player
,
const
rcsc
::
Vector2D
&
self_pos
,
const
rcsc
::
AngleDeg
&
self_ang
);
// Start the server and listen for a connection.
void
startServer
(
int
server_port
=
6008
);
// Transmit information to the client and ensure it can recieve.
void
clientHandshake
();
// Add a feature without normalizing
void
addFeature
(
float
val
);
// Add a feature and normalize to the range [FEAT_MIN, FEAT_MAX]
void
addNormFeature
(
float
val
,
float
min_val
,
float
max_val
);
protected:
int
numTeammates
;
// Number of teammates in HFO
int
numOpponents
;
// Number of opponents in HFO
bool
playingOffense
;
// Are we playing offense or defense?
int
numFeatures
;
// Total number of features
// Number of features for non-player objects.
const
static
int
num_basic_features
=
58
;
// Number of features for each player or opponent in game.
const
static
int
features_per_player
=
8
;
int
featIndx
;
// Feature being populated
std
::
vector
<
float
>
feature_vec
;
// Contains the current features
// Observed values of some parameters.
const
static
float
observedSelfSpeedMax
=
0.46
;
const
static
float
observedPlayerSpeedMax
=
0.75
;
const
static
float
observedStaminaMax
=
8000.
;
const
static
float
observedBallSpeedMax
=
5.0
;
float
maxHFORadius
;
// Maximum possible distance in HFO playable region
// Useful measures defined by the Server Parameters
float
pitchLength
,
pitchWidth
,
pitchHalfLength
,
pitchHalfWidth
,
goalHalfWidth
,
penaltyAreaLength
,
penaltyAreaWidth
;
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?
int
sockfd
,
newsockfd
;
// Server sockets
bool
record
;
// Record states + actions
private:
bool
doPreprocess
();
bool
doShoot
();
bool
doPass
();
bool
doDribble
();
bool
doMove
();
bool
doForceKick
();
bool
doHeardPassReceive
();
...
...
src/highlevel_feature_extractor.cpp
0 → 100644
View file @
ed4c009f
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "highlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>
using
namespace
rcsc
;
HighLevelFeatureExtractor
::
HighLevelFeatureExtractor
(
int
num_teammates
,
int
num_opponents
,
bool
playing_offense
)
:
FeatureExtractor
(),
numTeammates
(
num_teammates
),
numOpponents
(
num_opponents
),
playingOffense
(
playing_offense
)
{
assert
(
numTeammates
>=
0
);
assert
(
numOpponents
>=
0
);
numFeatures
=
num_basic_features
+
features_per_player
*
(
numTeammates
+
numOpponents
);
feature_vec
.
resize
(
numFeatures
);
}
HighLevelFeatureExtractor
::~
HighLevelFeatureExtractor
()
{}
const
std
::
vector
<
float
>&
HighLevelFeatureExtractor
::
ExtractFeatures
(
const
WorldModel
&
wm
)
{
featIndx
=
0
;
const
ServerParam
&
SP
=
ServerParam
::
i
();
// ======================== SELF FEATURES ======================== //
const
SelfObject
&
self
=
wm
.
self
();
const
Vector2D
&
self_pos
=
self
.
pos
();
const
AngleDeg
&
self_ang
=
self
.
body
();
addFeature
(
self
.
posValid
()
?
FEAT_MAX
:
FEAT_MIN
);
// ADD_FEATURE(self_pos.x);
// ADD_FEATURE(self_pos.y);
// Direction and speed of the agent.
addFeature
(
self
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
self
.
velValid
())
{
addAngFeature
(
self_ang
-
self
.
vel
().
th
());
addNormFeature
(
self
.
speed
(),
0.
,
observedSelfSpeedMax
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Global Body Angle -- 0:right -90:up 90:down 180/-180:left
addAngFeature
(
self_ang
);
// Neck Angle -- We probably don't need this unless we are
// controlling the neck manually.
// std::cout << "Face Error: " << self.faceError() << std::endl;
// if (self.faceValid()) {
// std::cout << "FaceAngle: " << self.face() << std::endl;
// }
addNormFeature
(
self
.
stamina
(),
0.
,
observedStaminaMax
);
addFeature
(
self
.
isFrozen
()
?
FEAT_MAX
:
FEAT_MIN
);
// Probabilities - Do we want these???
// std::cout << "catchProb: " << self.catchProbability() << std::endl;
// std::cout << "tackleProb: " << self.tackleProbability() << std::endl;
// std::cout << "fouldProb: " << self.foulProbability() << std::endl;
// Features indicating if we are colliding with an object
addFeature
(
self
.
collidesWithBall
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPlayer
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPost
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
isKickable
()
?
FEAT_MAX
:
FEAT_MIN
);
// inertiaPoint estimates the ball point after a number of steps
// self.inertiaPoint(n_steps);
// ======================== LANDMARK FEATURES ======================== //
// Top Bottom Center of Goal
rcsc
::
Vector2D
goalCenter
(
pitchHalfLength
,
0
);
addLandmarkFeatures
(
goalCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostTop
(
pitchHalfLength
,
-
goalHalfWidth
);
addLandmarkFeatures
(
goalPostTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostBot
(
pitchHalfLength
,
goalHalfWidth
);
addLandmarkFeatures
(
goalPostBot
,
self_pos
,
self_ang
);
// Top Bottom Center of Penalty Box
rcsc
::
Vector2D
penaltyBoxCenter
(
pitchHalfLength
-
penaltyAreaLength
,
0
);
addLandmarkFeatures
(
penaltyBoxCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxTop
(
pitchHalfLength
-
penaltyAreaLength
,
-
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxBot
(
pitchHalfLength
-
penaltyAreaLength
,
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxBot
,
self_pos
,
self_ang
);
// Corners of the Playable Area
rcsc
::
Vector2D
centerField
(
0
,
0
);
addLandmarkFeatures
(
centerField
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopLeft
(
0
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopLeft
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopRight
(
pitchHalfLength
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotRight
(
pitchHalfLength
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotLeft
(
0
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotLeft
,
self_pos
,
self_ang
);
// Distances to the edges of the playable area
if
(
self
.
posValid
())
{
// Distance to Left field line
addDistFeature
(
self_pos
.
x
,
pitchHalfLength
);
// Distance to Right field line
addDistFeature
(
pitchHalfLength
-
self_pos
.
x
,
pitchHalfLength
);
// Distance to top field line
addDistFeature
(
pitchHalfWidth
+
self_pos
.
y
,
pitchWidth
);
// Distance to Bottom field line
addDistFeature
(
pitchHalfWidth
-
self_pos
.
y
,
pitchWidth
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// ======================== BALL FEATURES ======================== //
const
BallObject
&
ball
=
wm
.
ball
();
// Angle and distance to the ball
addFeature
(
ball
.
rposValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
rposValid
())
{
addAngFeature
(
ball
.
angleFromSelf
());
addDistFeature
(
ball
.
distFromSelf
(),
maxHFORadius
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Velocity and direction of the ball
addFeature
(
ball
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
velValid
())
{
// SeverParam lists ballSpeedMax a 2.7 which is too low
addNormFeature
(
ball
.
vel
().
r
(),
0.
,
observedBallSpeedMax
);
addAngFeature
(
ball
.
vel
().
th
());
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
assert
(
featIndx
==
num_basic_features
);
// ======================== TEAMMATE FEATURES ======================== //
// Vector of PlayerObject pointers sorted by increasing distance from self
int
detected_teammates
=
0
;
const
PlayerPtrCont
&
teammates
=
wm
.
teammatesFromSelf
();
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
)
{
addPlayerFeatures
(
*
teammate
,
self_pos
,
self_ang
);
detected_teammates
++
;
}
}
// Add zero features for any missing teammates
for
(
int
i
=
detected_teammates
;
i
<
numTeammates
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
// ======================== OPPONENT FEATURES ======================== //
int
detected_opponents
=
0
;
const
PlayerPtrCont
&
opponents
=
wm
.
opponentsFromSelf
();
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
)
{
addPlayerFeatures
(
*
opponent
,
self_pos
,
self_ang
);
detected_opponents
++
;
}
}
// Add zero features for any missing opponents
for
(
int
i
=
detected_opponents
;
i
<
numOpponents
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
assert
(
featIndx
==
numFeatures
);
checkFeatures
();
return
feature_vec
;
}
src/highlevel_feature_extractor.h
0 → 100644
View file @
ed4c009f
#ifndef HIGHLEVEL_FEATURE_EXTRACTOR_H
#define HIGHLEVEL_FEATURE_EXTRACTOR_H
#include <rcsc/player/player_agent.h>
#include "feature_extractor.h"
#include <vector>
class
HighLevelFeatureExtractor
:
public
FeatureExtractor
{
public:
HighLevelFeatureExtractor
(
int
num_teammates
,
int
num_opponents
,
bool
playing_offense
);
virtual
~
HighLevelFeatureExtractor
();
// Updated the state features stored in feature_vec
virtual
const
std
::
vector
<
float
>&
ExtractFeatures
(
const
rcsc
::
WorldModel
&
wm
);
protected:
// Number of features for non-player objects.
const
static
int
num_basic_features
=
58
;
// Number of features for each player or opponent in game.
const
static
int
features_per_player
=
8
;
int
numTeammates
;
// Number of teammates in HFO
int
numOpponents
;
// Number of opponents in HFO
bool
playingOffense
;
// Are we playing offense or defense?
};
#endif // HIGHLEVEL_FEATURE_EXTRACTOR_H
src/lowlevel_feature_extractor.cpp
0 → 100644
View file @
ed4c009f
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "lowlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>
using
namespace
rcsc
;
LowLevelFeatureExtractor
::
LowLevelFeatureExtractor
(
int
num_teammates
,
int
num_opponents
,
bool
playing_offense
)
:
FeatureExtractor
(),
numTeammates
(
num_teammates
),
numOpponents
(
num_opponents
),
playingOffense
(
playing_offense
)
{
assert
(
numTeammates
>=
0
);
assert
(
numOpponents
>=
0
);
numFeatures
=
num_basic_features
+
features_per_player
*
(
numTeammates
+
numOpponents
);
feature_vec
.
resize
(
numFeatures
);
}
LowLevelFeatureExtractor
::~
LowLevelFeatureExtractor
()
{}
const
std
::
vector
<
float
>&
LowLevelFeatureExtractor
::
ExtractFeatures
(
const
WorldModel
&
wm
)
{
featIndx
=
0
;
const
ServerParam
&
SP
=
ServerParam
::
i
();
// ======================== SELF FEATURES ======================== //
const
SelfObject
&
self
=
wm
.
self
();
const
Vector2D
&
self_pos
=
self
.
pos
();
const
AngleDeg
&
self_ang
=
self
.
body
();
addFeature
(
self
.
posValid
()
?
FEAT_MAX
:
FEAT_MIN
);
// ADD_FEATURE(self_pos.x);
// ADD_FEATURE(self_pos.y);
// Direction and speed of the agent.
addFeature
(
self
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
self
.
velValid
())
{
addAngFeature
(
self_ang
-
self
.
vel
().
th
());
addNormFeature
(
self
.
speed
(),
0.
,
observedSelfSpeedMax
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Global Body Angle -- 0:right -90:up 90:down 180/-180:left
addAngFeature
(
self_ang
);
// Neck Angle -- We probably don't need this unless we are
// controlling the neck manually.
// std::cout << "Face Error: " << self.faceError() << std::endl;
// if (self.faceValid()) {
// std::cout << "FaceAngle: " << self.face() << std::endl;
// }
addNormFeature
(
self
.
stamina
(),
0.
,
observedStaminaMax
);
addFeature
(
self
.
isFrozen
()
?
FEAT_MAX
:
FEAT_MIN
);
// Probabilities - Do we want these???
// std::cout << "catchProb: " << self.catchProbability() << std::endl;
// std::cout << "tackleProb: " << self.tackleProbability() << std::endl;
// std::cout << "fouldProb: " << self.foulProbability() << std::endl;
// Features indicating if we are colliding with an object
addFeature
(
self
.
collidesWithBall
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPlayer
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
collidesWithPost
()
?
FEAT_MAX
:
FEAT_MIN
);
addFeature
(
self
.
isKickable
()
?
FEAT_MAX
:
FEAT_MIN
);
// inertiaPoint estimates the ball point after a number of steps
// self.inertiaPoint(n_steps);
// ======================== LANDMARK FEATURES ======================== //
// Top Bottom Center of Goal
rcsc
::
Vector2D
goalCenter
(
pitchHalfLength
,
0
);
addLandmarkFeatures
(
goalCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostTop
(
pitchHalfLength
,
-
goalHalfWidth
);
addLandmarkFeatures
(
goalPostTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
goalPostBot
(
pitchHalfLength
,
goalHalfWidth
);
addLandmarkFeatures
(
goalPostBot
,
self_pos
,
self_ang
);
// Top Bottom Center of Penalty Box
rcsc
::
Vector2D
penaltyBoxCenter
(
pitchHalfLength
-
penaltyAreaLength
,
0
);
addLandmarkFeatures
(
penaltyBoxCenter
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxTop
(
pitchHalfLength
-
penaltyAreaLength
,
-
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxTop
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
penaltyBoxBot
(
pitchHalfLength
-
penaltyAreaLength
,
penaltyAreaWidth
/
2.
);
addLandmarkFeatures
(
penaltyBoxBot
,
self_pos
,
self_ang
);
// Corners of the Playable Area
rcsc
::
Vector2D
centerField
(
0
,
0
);
addLandmarkFeatures
(
centerField
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopLeft
(
0
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopLeft
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerTopRight
(
pitchHalfLength
,
-
pitchHalfWidth
);
addLandmarkFeatures
(
cornerTopRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotRight
(
pitchHalfLength
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotRight
,
self_pos
,
self_ang
);
rcsc
::
Vector2D
cornerBotLeft
(
0
,
pitchHalfWidth
);
addLandmarkFeatures
(
cornerBotLeft
,
self_pos
,
self_ang
);
// Distances to the edges of the playable area
if
(
self
.
posValid
())
{
// Distance to Left field line
addDistFeature
(
self_pos
.
x
,
pitchHalfLength
);
// Distance to Right field line
addDistFeature
(
pitchHalfLength
-
self_pos
.
x
,
pitchHalfLength
);
// Distance to top field line
addDistFeature
(
pitchHalfWidth
+
self_pos
.
y
,
pitchWidth
);
// Distance to Bottom field line
addDistFeature
(
pitchHalfWidth
-
self_pos
.
y
,
pitchWidth
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// ======================== BALL FEATURES ======================== //
const
BallObject
&
ball
=
wm
.
ball
();
// Angle and distance to the ball
addFeature
(
ball
.
rposValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
rposValid
())
{
addAngFeature
(
ball
.
angleFromSelf
());
addDistFeature
(
ball
.
distFromSelf
(),
maxHFORadius
);
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
// Velocity and direction of the ball
addFeature
(
ball
.
velValid
()
?
FEAT_MAX
:
FEAT_MIN
);
if
(
ball
.
velValid
())
{
// SeverParam lists ballSpeedMax a 2.7 which is too low
addNormFeature
(
ball
.
vel
().
r
(),
0.
,
observedBallSpeedMax
);
addAngFeature
(
ball
.
vel
().
th
());
}
else
{
addFeature
(
0
);
addFeature
(
0
);
addFeature
(
0
);
}
assert
(
featIndx
==
num_basic_features
);
// ======================== TEAMMATE FEATURES ======================== //
// Vector of PlayerObject pointers sorted by increasing distance from self
int
detected_teammates
=
0
;
const
PlayerPtrCont
&
teammates
=
wm
.
teammatesFromSelf
();
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
)
{
addPlayerFeatures
(
*
teammate
,
self_pos
,
self_ang
);
detected_teammates
++
;
}
}
// Add zero features for any missing teammates
for
(
int
i
=
detected_teammates
;
i
<
numTeammates
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
// ======================== OPPONENT FEATURES ======================== //
int
detected_opponents
=
0
;
const
PlayerPtrCont
&
opponents
=
wm
.
opponentsFromSelf
();
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
)
{
addPlayerFeatures
(
*
opponent
,
self_pos
,
self_ang
);
detected_opponents
++
;
}
}
// Add zero features for any missing opponents
for
(
int
i
=
detected_opponents
;
i
<
numOpponents
;
++
i
)
{
for
(
int
j
=
0
;
j
<
features_per_player
;
++
j
)
{
addFeature
(
0
);
}
}
assert
(
featIndx
==
numFeatures
);
checkFeatures
();
return
feature_vec
;
}
src/lowlevel_feature_extractor.h
0 → 100644
View file @
ed4c009f
#ifndef LOWLEVEL_FEATURE_EXTRACTOR_H
#define LOWLEVEL_FEATURE_EXTRACTOR_H
#include <rcsc/player/player_agent.h>
#include "feature_extractor.h"
#include <vector>
class
LowLevelFeatureExtractor
:
public
FeatureExtractor
{
public:
LowLevelFeatureExtractor
(
int
num_teammates
,
int
num_opponents
,
bool
playing_offense
);
virtual
~
LowLevelFeatureExtractor
();
// Updated the state features stored in feature_vec
virtual
const
std
::
vector
<
float
>&
ExtractFeatures
(
const
rcsc
::
WorldModel
&
wm
);
protected:
// Number of features for non-player objects.
const
static
int
num_basic_features
=
58
;
// Number of features for each player or opponent in game.
const
static
int
features_per_player
=
8
;
int
numTeammates
;
// Number of teammates in HFO
int
numOpponents
;
// Number of opponents in HFO
bool
playingOffense
;
// Are we playing offense or defense?
};
#endif // LOWLEVEL_FEATURE_EXTRACTOR_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment