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
59c57e88
Commit
59c57e88
authored
Aug 11, 2017
by
drallensmith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Try at putting action_status into state vector
parent
5df1cd17
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
121 additions
and
179 deletions
+121
-179
hfo/hfo.py
hfo/hfo.py
+0
-12
src/HFO.cpp
src/HFO.cpp
+0
-4
src/HFO.hpp
src/HFO.hpp
+0
-2
src/agent.cpp
src/agent.cpp
+72
-107
src/agent.h
src/agent.h
+14
-15
src/bhv_basic_move.cpp
src/bhv_basic_move.cpp
+11
-18
src/bhv_basic_move.h
src/bhv_basic_move.h
+0
-1
src/common.hpp
src/common.hpp
+0
-18
src/feature_extractor.h
src/feature_extractor.h
+2
-0
src/highlevel_feature_extractor.cpp
src/highlevel_feature_extractor.cpp
+8
-0
src/highlevel_feature_extractor.h
src/highlevel_feature_extractor.h
+2
-0
src/lowlevel_feature_extractor.cpp
src/lowlevel_feature_extractor.cpp
+10
-2
src/lowlevel_feature_extractor.h
src/lowlevel_feature_extractor.h
+2
-0
No files found.
hfo/hfo.py
View file @
59c57e88
...
@@ -114,8 +114,6 @@ hfo_lib.getNumTeammates.argtypes = [c_void_p]
...
@@ -114,8 +114,6 @@ hfo_lib.getNumTeammates.argtypes = [c_void_p]
hfo_lib
.
getNumTeammates
.
restype
=
c_int
hfo_lib
.
getNumTeammates
.
restype
=
c_int
hfo_lib
.
getNumOpponents
.
argtypes
=
[
c_void_p
]
hfo_lib
.
getNumOpponents
.
argtypes
=
[
c_void_p
]
hfo_lib
.
getNumOpponents
.
restype
=
c_int
hfo_lib
.
getNumOpponents
.
restype
=
c_int
hfo_lib
.
getLastActionStatus
.
argtypes
=
[
c_void_p
,
c_int
]
hfo_lib
.
getLastActionStatus
.
restype
=
c_int
class
HFOEnvironment
(
object
):
class
HFOEnvironment
(
object
):
def
__init__
(
self
):
def
__init__
(
self
):
...
@@ -207,16 +205,6 @@ class HFOEnvironment(object):
...
@@ -207,16 +205,6 @@ class HFOEnvironment(object):
""" Returns the number of opponents of the agent """
""" Returns the number of opponents of the agent """
return
hfo_lib
.
getNumOpponents
(
self
.
obj
)
return
hfo_lib
.
getNumOpponents
(
self
.
obj
)
def
getLastActionStatus
(
self
,
last_action
):
"""
If last_action is the last action with a recorded status,
returns ACTION_STATUS_MAYBE for possible success,
ACTION_STATUS_BAD for no possibility of success,
or ACTION_STATUS_UNKNOWN if unknown. If it is not the
last action with a recorded status, returns ACTION_STATUS_UNKNOWN.
"""
return
hfo_lib
.
getLastActionStatus
(
self
.
obj
,
last_action
)
def
actionStatusToString
(
self
,
status
):
def
actionStatusToString
(
self
,
status
):
"""Returns a string representation of an action status."""
"""Returns a string representation of an action status."""
return
ACTION_STATUS_STRINGS
[
status
]
return
ACTION_STATUS_STRINGS
[
status
]
src/HFO.cpp
View file @
59c57e88
...
@@ -123,10 +123,6 @@ int HFOEnvironment::getNumOpponents() {
...
@@ -123,10 +123,6 @@ int HFOEnvironment::getNumOpponents() {
return
agent
->
getNumOpponents
();
return
agent
->
getNumOpponents
();
}
}
action_status_t
HFOEnvironment
::
getLastActionStatus
(
action_t
last_action
)
{
return
agent
->
getLastActionStatus
(
last_action
);
}
Player
HFOEnvironment
::
playerOnBall
()
{
Player
HFOEnvironment
::
playerOnBall
()
{
return
agent
->
getPlayerOnBall
();
return
agent
->
getPlayerOnBall
();
}
}
...
...
src/HFO.hpp
View file @
59c57e88
...
@@ -55,8 +55,6 @@ class HFOEnvironment {
...
@@ -55,8 +55,6 @@ class HFOEnvironment {
// Returns the number of opponents
// Returns the number of opponents
virtual
int
getNumOpponents
();
virtual
int
getNumOpponents
();
virtual
action_status_t
getLastActionStatus
(
action_t
last_action
);
// Get the current player holding the ball
// Get the current player holding the ball
virtual
Player
playerOnBall
();
virtual
Player
playerOnBall
();
...
...
src/agent.cpp
View file @
59c57e88
...
@@ -151,9 +151,8 @@ Agent::Agent()
...
@@ -151,9 +151,8 @@ Agent::Agent()
// set communication planner
// set communication planner
M_communication
=
Communication
::
Ptr
(
new
SampleCommunication
());
M_communication
=
Communication
::
Ptr
(
new
SampleCommunication
());
// setup last_action variables
// setup last_action variable
last_action_with_status
=
NOOP
;
last_action_status
=
false
;
last_action_status
=
ACTION_STATUS_UNKNOWN
;
}
}
Agent
::~
Agent
()
{
Agent
::~
Agent
()
{
...
@@ -166,27 +165,11 @@ int Agent::getUnum() {
...
@@ -166,27 +165,11 @@ int Agent::getUnum() {
return
world
().
self
().
unum
();
return
world
().
self
().
unum
();
}
}
action_status_t
Agent
::
getLastActionStatus
(
action_t
last_action
)
{
void
Agent
::
setLastActionStatusCollision
(
bool
may_fix
,
bool
likely_success
)
{
if
(
l
ast_action
==
last_action_with_status
)
{
if
(
l
ikely_success
||
may_fix
)
{
return
last_action_status
;
last_action_status
=
true
;
}
else
{
}
else
{
return
ACTION_STATUS_UNKNOWN
;
last_action_status
=
false
;
}
}
void
Agent
::
addLastActionStatus
(
action_t
last_action
,
action_status_t
action_status
)
{
last_action_with_status
=
last_action
;
last_action_status
=
action_status
;
}
void
Agent
::
addLastActionStatusCollision
(
action_t
last_action
,
bool
may_fix
,
bool
likely_success
)
{
last_action_with_status
=
last_action
;
if
(
likely_success
)
{
last_action_status
=
ACTION_STATUS_MAYBE
;
}
else
if
(
may_fix
)
{
last_action_status
=
ACTION_STATUS_UNKNOWN
;
}
else
{
last_action_status
=
ACTION_STATUS_BAD
;
}
}
}
}
...
@@ -287,28 +270,27 @@ void Agent::actionImpl() {
...
@@ -287,28 +270,27 @@ void Agent::actionImpl() {
switch
(
requested_action
)
{
switch
(
requested_action
)
{
case
DASH
:
case
DASH
:
addLastActionStatusCollision
(
DASH
,
may_fix
,
this
->
doDash
(
params
[
0
],
params
[
1
]));
setLastActionStatusCollision
(
may_fix
,
this
->
doDash
(
params
[
0
],
params
[
1
]));
break
;
break
;
case
TURN
:
case
TURN
:
addLastActionStatusCollision
(
TURN
,
may_fix
,
this
->
doTurn
(
params
[
0
]));
setLastActionStatusCollision
(
may_fix
,
this
->
doTurn
(
params
[
0
]));
break
;
break
;
case
TACKLE
:
case
TACKLE
:
addLastActionStatus
(
TACKLE
,
BooleanToActionStatus
(
this
->
doTackle
(
params
[
0
],
false
)
));
setLastActionStatus
(
this
->
doTackle
(
params
[
0
],
false
));
break
;
break
;
case
KICK
:
case
KICK
:
addLastActionStatus
(
KICK
,
BooleanToActionStatus
(
this
->
doKick
(
params
[
0
],
params
[
1
])
));
setLastActionStatus
(
this
->
doKick
(
params
[
0
],
params
[
1
]
));
break
;
break
;
case
KICK_TO
:
case
KICK_TO
:
if
(
feature_extractor
!=
NULL
)
{
if
(
feature_extractor
!=
NULL
)
{
addLastActionStatus
(
KICK_TO
,
setLastActionStatus
(
Body_SmartKick
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
BooleanToActionStatus
(
Body_SmartKick
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
feature_extractor
->
absoluteYPos
(
params
[
1
])),
feature_extractor
->
absoluteYPos
(
params
[
1
])),
params
[
2
],
params
[
2
]
*
0.99
,
3
).
execute
(
this
)
));
params
[
2
],
params
[
2
]
*
0.99
,
3
).
execute
(
this
));
}
}
break
;
break
;
case
MOVE_TO
:
case
MOVE_TO
:
if
(
feature_extractor
!=
NULL
)
{
if
(
feature_extractor
!=
NULL
)
{
addLastActionStatusCollision
(
MOVE_TO
,
may_fix
,
setLastActionStatusCollision
(
may_fix
,
Body_GoToPoint
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
Body_GoToPoint
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
feature_extractor
->
absoluteYPos
(
params
[
1
])),
0.25
,
feature_extractor
->
absoluteYPos
(
params
[
1
])),
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
));
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
));
...
@@ -316,50 +298,51 @@ void Agent::actionImpl() {
...
@@ -316,50 +298,51 @@ void Agent::actionImpl() {
break
;
break
;
case
DRIBBLE_TO
:
case
DRIBBLE_TO
:
if
(
feature_extractor
!=
NULL
)
{
if
(
feature_extractor
!=
NULL
)
{
addLastActionStatusCollision
(
DRIBBLE_TO
,
may_fix
,
setLastActionStatusCollision
(
may_fix
,
Body_Dribble
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
Body_Dribble
(
Vector2D
(
feature_extractor
->
absoluteXPos
(
params
[
0
]),
feature_extractor
->
absoluteYPos
(
params
[
1
])),
1.0
,
feature_extractor
->
absoluteYPos
(
params
[
1
])),
1.0
,
ServerParam
::
i
().
maxDashPower
(),
2
).
execute
(
this
));
ServerParam
::
i
().
maxDashPower
(),
2
).
execute
(
this
));
}
}
break
;
break
;
case
INTERCEPT
:
case
INTERCEPT
:
addLastActionStatusCollision
(
INTERCEPT
,
may_fix
,
Body_Intercept
().
execute
(
this
));
setLastActionStatusCollision
(
may_fix
,
Body_Intercept
().
execute
(
this
));
break
;
break
;
case
MOVE
:
case
MOVE
:
addLastActionStatus
(
MOVE
,
this
->
doMove
());
setLastActionStatus
(
this
->
doMove
());
break
;
break
;
case
SHOOT
:
case
SHOOT
:
addLastActionStatus
(
SHOOT
,
this
->
doSmartKick
());
setLastActionStatus
(
this
->
doSmartKick
());
break
;
break
;
case
PASS
:
case
PASS
:
addLastActionStatus
(
PASS
,
this
->
doPassTo
(
int
(
params
[
0
])));
setLastActionStatus
(
this
->
doPassTo
(
int
(
params
[
0
])));
break
;
break
;
case
DRIBBLE
:
case
DRIBBLE
:
addLastActionStatus
(
DRIBBLE
,
this
->
doDribble
());
setLastActionStatus
(
this
->
doDribble
());
break
;
break
;
case
CATCH
:
case
CATCH
:
addLastActionStatus
(
CATCH
,
BooleanToActionStatus
(
this
->
doCatch
()
));
setLastActionStatus
(
this
->
doCatch
(
));
break
;
break
;
case
NOOP
:
case
NOOP
:
setLastActionStatus
(
false
);
break
;
break
;
case
QUIT
:
case
QUIT
:
std
::
cout
<<
"Got quit from agent."
<<
std
::
endl
;
std
::
cout
<<
"Got quit from agent."
<<
std
::
endl
;
handleExit
();
handleExit
();
return
;
return
;
case
REDUCE_ANGLE_TO_GOAL
:
case
REDUCE_ANGLE_TO_GOAL
:
addLastActionStatus
(
REDUCE_ANGLE_TO_GOAL
,
this
->
doReduceAngleToGoal
());
setLastActionStatus
(
this
->
doReduceAngleToGoal
());
break
;
break
;
case
MARK_PLAYER
:
case
MARK_PLAYER
:
addLastActionStatus
(
MARK_PLAYER
,
this
->
doMarkPlayer
(
int
(
params
[
0
])));
setLastActionStatus
(
this
->
doMarkPlayer
(
int
(
params
[
0
])));
break
;
break
;
case
DEFEND_GOAL
:
case
DEFEND_GOAL
:
addLastActionStatus
(
DEFEND_GOAL
,
this
->
doDefendGoal
());
setLastActionStatus
(
this
->
doDefendGoal
());
break
;
break
;
case
GO_TO_BALL
:
case
GO_TO_BALL
:
addLastActionStatus
(
GO_TO_BALL
,
this
->
doGoToBall
());
setLastActionStatus
(
this
->
doGoToBall
());
break
;
break
;
case
REORIENT
:
case
REORIENT
:
addLastActionStatus
(
REORIENT
,
this
->
doReorient
());
setLastActionStatus
(
this
->
doReorient
());
break
;
break
;
default:
default:
std
::
cerr
<<
"ERROR: Unsupported Action: "
std
::
cerr
<<
"ERROR: Unsupported Action: "
...
@@ -745,7 +728,7 @@ Agent::doPreprocess()
...
@@ -745,7 +728,7 @@ Agent::doPreprocess()
Alternative high-level action to always doing "Move"; usable by either side, although
Alternative high-level action to always doing "Move"; usable by either side, although
probably more useful for offense. Variant of doPreprocess (above), which is called by doDribble.
probably more useful for offense. Variant of doPreprocess (above), which is called by doDribble.
*/
*/
action_status_t
bool
Agent
::
doReorient
()
Agent
::
doReorient
()
{
{
// check tackle expires
// check tackle expires
...
@@ -767,11 +750,8 @@ Agent::doReorient()
...
@@ -767,11 +750,8 @@ Agent::doReorient()
__FILE__
": tackle wait. expires= %d"
,
__FILE__
": tackle wait. expires= %d"
,
wm
.
self
().
tackleExpires
()
);
wm
.
self
().
tackleExpires
()
);
if
(
Bhv_Emergency
().
execute
(
this
))
{
// includes change view
Bhv_Emergency
().
execute
(
this
);
// includes change view
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
{
return
ACTION_STATUS_UNKNOWN
;
}
}
}
//
//
...
@@ -785,7 +765,7 @@ Agent::doReorient()
...
@@ -785,7 +765,7 @@ Agent::doReorient()
Vector2D
move_point
=
Strategy
::
i
().
getPosition
(
wm
.
self
().
unum
()
);
Vector2D
move_point
=
Strategy
::
i
().
getPosition
(
wm
.
self
().
unum
()
);
Bhv_CustomBeforeKickOff
(
move_point
).
execute
(
this
);
Bhv_CustomBeforeKickOff
(
move_point
).
execute
(
this
);
this
->
setViewAction
(
new
View_Tactical
()
);
this
->
setViewAction
(
new
View_Tactical
()
);
return
ACTION_STATUS_MAYBE
;
return
true
;
}
}
//
//
...
@@ -800,11 +780,8 @@ Agent::doReorient()
...
@@ -800,11 +780,8 @@ Agent::doReorient()
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": invalid my vel"
);
__FILE__
": invalid my vel"
);
}
}
if
(
Bhv_Emergency
().
execute
(
this
))
{
// includes change view
Bhv_Emergency
().
execute
(
this
);
// includes change view
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
{
return
ACTION_STATUS_UNKNOWN
;
}
}
}
//
//
...
@@ -826,11 +803,8 @@ Agent::doReorient()
...
@@ -826,11 +803,8 @@ Agent::doReorient()
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": search ball"
);
__FILE__
": search ball"
);
if
(
Bhv_NeckBodyToBall
().
execute
(
this
))
{
Bhv_NeckBodyToBall
().
execute
(
this
);
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
{
return
ACTION_STATUS_UNKNOWN
;
}
}
}
...
@@ -839,7 +813,7 @@ Agent::doReorient()
...
@@ -839,7 +813,7 @@ Agent::doReorient()
//
//
if
(
doHeardPassReceive
()
)
if
(
doHeardPassReceive
()
)
{
{
return
ACTION_STATUS_MAYBE
;
return
true
;
}
}
const
BallObject
&
ball
=
wm
.
ball
();
const
BallObject
&
ball
=
wm
.
ball
();
...
@@ -847,11 +821,8 @@ Agent::doReorient()
...
@@ -847,11 +821,8 @@ Agent::doReorient()
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": search ball"
);
__FILE__
": search ball"
);
if
(
Bhv_NeckBodyToBall
().
execute
(
this
))
{
Bhv_NeckBodyToBall
().
execute
(
this
);
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
{
return
ACTION_STATUS_UNKNOWN
;
}
}
}
//
//
...
@@ -861,17 +832,17 @@ Agent::doReorient()
...
@@ -861,17 +832,17 @@ Agent::doReorient()
{
{
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": do queued intention"
);
__FILE__
": do queued intention"
);
return
ACTION_STATUS_MAYBE
;
return
true
;
}
}
return
ACTION_STATUS_BAD
;
return
false
;
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*!
/*!
*/
*/
action_status_t
bool
Agent
::
doShoot
()
Agent
::
doShoot
()
{
{
const
WorldModel
&
wm
=
this
->
world
();
const
WorldModel
&
wm
=
this
->
world
();
...
@@ -886,23 +857,23 @@ Agent::doShoot()
...
@@ -886,23 +857,23 @@ Agent::doShoot()
// reset intention
// reset intention
this
->
setIntention
(
static_cast
<
SoccerIntention
*
>
(
0
)
);
this
->
setIntention
(
static_cast
<
SoccerIntention
*
>
(
0
)
);
return
ACTION_STATUS_MAYBE
;
return
true
;
}
}
return
ACTION_STATUS_BAD
;
return
false
;
}
}
action_status_t
bool
Agent
::
doSmartKick
()
Agent
::
doSmartKick
()
{
{
const
ShootGenerator
::
Container
&
cont
=
const
ShootGenerator
::
Container
&
cont
=
ShootGenerator
::
instance
().
courses
(
this
->
world
(),
false
);
ShootGenerator
::
instance
().
courses
(
this
->
world
(),
false
);
ShootGenerator
::
Container
::
const_iterator
best_shoot
ShootGenerator
::
Container
::
const_iterator
best_shoot
=
std
::
min_element
(
cont
.
begin
(),
cont
.
end
(),
ShootGenerator
::
ScoreCmp
());
=
std
::
min_element
(
cont
.
begin
(),
cont
.
end
(),
ShootGenerator
::
ScoreCmp
());
return
Bo
oleanToActionStatus
(
Bo
dy_SmartKick
(
best_shoot
->
target_point_
,
return
Body_SmartKick
(
best_shoot
->
target_point_
,
best_shoot
->
first_ball_speed_
,
best_shoot
->
first_ball_speed_
,
best_shoot
->
first_ball_speed_
*
0.99
,
best_shoot
->
first_ball_speed_
*
0.99
,
3
).
execute
(
this
)
);
3
).
execute
(
this
);
}
}
...
@@ -919,19 +890,19 @@ Agent::doPass()
...
@@ -919,19 +890,19 @@ Agent::doPass()
return
true
;
return
true
;
}
}
action_status_t
bool
Agent
::
doPassTo
(
int
receiver
)
Agent
::
doPassTo
(
int
receiver
)
{
{
Force_Pass
pass
;
Force_Pass
pass
;
pass
.
get_pass_to_player
(
this
->
world
(),
receiver
);
pass
.
get_pass_to_player
(
this
->
world
(),
receiver
);
return
BooleanToActionStatus
(
pass
.
execute
(
this
)
);
return
pass
.
execute
(
this
);
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*!
/*!
*/
*/
action_status_t
bool
Agent
::
doDribble
()
Agent
::
doDribble
()
{
{
bool
success
=
false
;
bool
success
=
false
;
...
@@ -945,9 +916,9 @@ Agent::doDribble()
...
@@ -945,9 +916,9 @@ Agent::doDribble()
success
=
doPreprocess
();
success
=
doPreprocess
();
ActionChainHolder
::
instance
().
update
(
world
()
);
ActionChainHolder
::
instance
().
update
(
world
()
);
if
(
Bhv_ChainAction
(
ActionChainHolder
::
instance
().
graph
()).
execute
(
this
))
{
if
(
Bhv_ChainAction
(
ActionChainHolder
::
instance
().
graph
()).
execute
(
this
))
{
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
{
}
else
{
return
BooleanToActionStatus
(
success
)
;
return
success
;
}
}
}
}
...
@@ -955,19 +926,19 @@ Agent::doDribble()
...
@@ -955,19 +926,19 @@ Agent::doDribble()
/*!
/*!
*/
*/
action_status_t
bool
Agent
::
doMove
()
Agent
::
doMove
()
{
{
Strategy
::
instance
().
update
(
world
()
);
Strategy
::
instance
().
update
(
world
()
);
int
role_num
=
Strategy
::
i
().
roleNumber
(
world
().
self
().
unum
());
// Unused?
int
role_num
=
Strategy
::
i
().
roleNumber
(
world
().
self
().
unum
());
// Unused?
return
Bhv_BasicMove
().
action_
execute
(
this
);
return
Bhv_BasicMove
().
execute
(
this
);
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*!
/*!
* This Action marks the player with the specified uniform number.
* This Action marks the player with the specified uniform number.
*/
*/
action_status_t
Agent
::
doMarkPlayer
(
int
unum
)
{
bool
Agent
::
doMarkPlayer
(
int
unum
)
{
const
WorldModel
&
wm
=
this
->
world
();
const
WorldModel
&
wm
=
this
->
world
();
Vector2D
kicker_pos
=
Vector2D
::
INVALIDATED
;
Vector2D
kicker_pos
=
Vector2D
::
INVALIDATED
;
Vector2D
player_pos
=
Vector2D
::
INVALIDATED
;
Vector2D
player_pos
=
Vector2D
::
INVALIDATED
;
...
@@ -991,26 +962,24 @@ action_status_t Agent::doMarkPlayer(int unum) {
...
@@ -991,26 +962,24 @@ action_status_t Agent::doMarkPlayer(int unum) {
if
(
!
player_pos
.
isValid
())
{
if
(
!
player_pos
.
isValid
())
{
//Player to be marked not found
//Player to be marked not found
return
ACTION_STATUS_BAD
;
return
false
;
}
}
if
(
!
kicker_pos
.
isValid
())
{
if
(
!
kicker_pos
.
isValid
())
{
//Kicker not found
//Kicker not found
return
ACTION_STATUS_BAD
;
return
false
;
}
}
if
(
unum
==
kicker_unum
||
kicker_pos
.
equals
(
player_pos
))
{
if
(
unum
==
kicker_unum
||
kicker_pos
.
equals
(
player_pos
))
{
//Player to be marked is kicker
//Player to be marked is kicker
return
ACTION_STATUS_BAD
;
return
false
;
}
}
double
x
=
player_pos
.
x
+
(
kicker_pos
.
x
-
player_pos
.
x
)
*
0.1
;
double
x
=
player_pos
.
x
+
(
kicker_pos
.
x
-
player_pos
.
x
)
*
0.1
;
double
y
=
player_pos
.
y
+
(
kicker_pos
.
y
-
player_pos
.
y
)
*
0.1
;
double
y
=
player_pos
.
y
+
(
kicker_pos
.
y
-
player_pos
.
y
)
*
0.1
;
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
if
(
Body_GoToPoint
(
Vector2D
(
x
,
y
),
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
if
(
Body_GoToPoint
(
Vector2D
(
x
,
y
),
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
if
(
may_fix
)
{
return
ACTION_STATUS_UNKNOWN
;
}
else
{
}
else
{
return
ACTION_STATUS_BAD
;
return
may_fix
;
}
}
}
}
...
@@ -1020,12 +989,12 @@ action_status_t Agent::doMarkPlayer(int unum) {
...
@@ -1020,12 +989,12 @@ action_status_t Agent::doMarkPlayer(int unum) {
* This action cuts off the angle between the shooter and the goal the players always move to a dynamic line in between the kicker and the goal.
* This action cuts off the angle between the shooter and the goal the players always move to a dynamic line in between the kicker and the goal.
*/
*/
/* Comparator for sorting teammate
d
based on y positions.*/
/* Comparator for sorting teammate
s
based on y positions.*/
bool
compare_y_pos
(
PlayerObject
*
i
,
PlayerObject
*
j
)
{
bool
compare_y_pos
(
PlayerObject
*
i
,
PlayerObject
*
j
)
{
return
i
->
pos
().
y
<
j
->
pos
().
y
;
return
i
->
pos
().
y
<
j
->
pos
().
y
;
}
}
action_status_t
Agent
::
doReduceAngleToGoal
()
{
bool
Agent
::
doReduceAngleToGoal
()
{
const
WorldModel
&
wm
=
this
->
world
();
const
WorldModel
&
wm
=
this
->
world
();
Vector2D
goal_pos1
(
-
ServerParam
::
i
().
pitchHalfLength
(),
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos1
(
-
ServerParam
::
i
().
pitchHalfLength
(),
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos2
(
-
ServerParam
::
i
().
pitchHalfLength
(),
-
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos2
(
-
ServerParam
::
i
().
pitchHalfLength
(),
-
ServerParam
::
i
().
goalHalfWidth
()
);
...
@@ -1034,7 +1003,7 @@ action_status_t Agent::doReduceAngleToGoal() {
...
@@ -1034,7 +1003,7 @@ action_status_t Agent::doReduceAngleToGoal() {
const
BallObject
&
ball
=
wm
.
ball
();
const
BallObject
&
ball
=
wm
.
ball
();
if
(
!
ball
.
rposValid
())
{
if
(
!
ball
.
rposValid
())
{
return
ACTION_STATUS_BAD
;
return
false
;
}
}
Vector2D
ball_pos
=
ball
.
pos
();
Vector2D
ball_pos
=
ball
.
pos
();
...
@@ -1105,11 +1074,9 @@ action_status_t Agent::doReduceAngleToGoal() {
...
@@ -1105,11 +1074,9 @@ action_status_t Agent::doReduceAngleToGoal() {
Vector2D
target
=
targetLineEnd1
*
ratio
+
targetLineEnd2
*
(
1
-
ratio
);
Vector2D
target
=
targetLineEnd1
*
ratio
+
targetLineEnd2
*
(
1
-
ratio
);
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
if
(
Body_GoToPoint
(
target
,
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
if
(
Body_GoToPoint
(
target
,
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
if
(
may_fix
)
{
return
ACTION_STATUS_UNKNOWN
;
}
else
{
}
else
{
return
ACTION_STATUS_BAD
;
return
may_fix
;
}
}
}
}
...
@@ -1120,7 +1087,7 @@ action_status_t Agent::doReduceAngleToGoal() {
...
@@ -1120,7 +1087,7 @@ action_status_t Agent::doReduceAngleToGoal() {
* This action cuts off the angle between the shooter and the goal; the player always moves on a fixed line.
* This action cuts off the angle between the shooter and the goal; the player always moves on a fixed line.
*/
*/
action_status_t
Agent
::
doDefendGoal
()
{
bool
Agent
::
doDefendGoal
()
{
const
WorldModel
&
wm
=
this
->
world
();
const
WorldModel
&
wm
=
this
->
world
();
Vector2D
goal_pos1
(
-
ServerParam
::
i
().
pitchHalfLength
()
+
ServerParam
::
i
().
goalAreaLength
(),
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos1
(
-
ServerParam
::
i
().
pitchHalfLength
()
+
ServerParam
::
i
().
goalAreaLength
(),
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos2
(
-
ServerParam
::
i
().
pitchHalfLength
()
+
ServerParam
::
i
().
goalAreaLength
(),
-
ServerParam
::
i
().
goalHalfWidth
()
);
Vector2D
goal_pos2
(
-
ServerParam
::
i
().
pitchHalfLength
()
+
ServerParam
::
i
().
goalAreaLength
(),
-
ServerParam
::
i
().
goalHalfWidth
()
);
...
@@ -1137,11 +1104,9 @@ action_status_t Agent::doDefendGoal() {
...
@@ -1137,11 +1104,9 @@ action_status_t Agent::doDefendGoal() {
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
bool
may_fix
=
wm
.
self
().
collidesWithPost
();
if
(
Body_GoToPoint
(
target
,
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
if
(
Body_GoToPoint
(
target
,
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
))
{
return
ACTION_STATUS_MAYBE
;
return
true
;
}
else
if
(
may_fix
)
{
return
ACTION_STATUS_UNKNOWN
;
}
else
{
}
else
{
return
ACTION_STATUS_BAD
;
return
may_fix
;
}
}
}
}
...
@@ -1153,13 +1118,13 @@ action_status_t Agent::doDefendGoal() {
...
@@ -1153,13 +1118,13 @@ action_status_t Agent::doDefendGoal() {
*/
*/
action_status_t
Agent
::
doGoToBall
()
{
bool
Agent
::
doGoToBall
()
{
const
WorldModel
&
wm
=
this
->
world
();
const
WorldModel
&
wm
=
this
->
world
();
const
BallObject
&
ball
=
wm
.
ball
();
const
BallObject
&
ball
=
wm
.
ball
();
if
(
!
ball
.
rposValid
())
{
if
(
!
ball
.
rposValid
())
{
return
ACTION_STATUS_BAD
;
return
false
;
}
}
return
Bo
oleanToActionStatus
(
Body_GoToPoint
(
ball
.
pos
(),
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
)
);
return
Bo
dy_GoToPoint
(
ball
.
pos
(),
0.25
,
ServerParam
::
i
().
maxDashPower
()).
execute
(
this
);
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
...
...
src/agent.h
View file @
59c57e88
...
@@ -65,8 +65,7 @@ protected:
...
@@ -65,8 +65,7 @@ protected:
std
::
vector
<
float
>
params
;
// Parameters of current action
std
::
vector
<
float
>
params
;
// Parameters of current action
int
num_teammates
;
// Number of teammates
int
num_teammates
;
// Number of teammates
int
num_opponents
;
// Number of opponents
int
num_opponents
;
// Number of opponents
hfo
::
action_t
last_action_with_status
;
// Last action with a recorded return status
bool
last_action_status
;
// Recorded return status of last action
hfo
::
action_status_t
last_action_status
;
// Recorded return status of last action
public:
public:
inline
const
std
::
vector
<
float
>&
getState
()
{
return
state
;
}
inline
const
std
::
vector
<
float
>&
getState
()
{
return
state
;
}
...
@@ -76,7 +75,7 @@ protected:
...
@@ -76,7 +75,7 @@ protected:
int
getUnum
();
// Returns the uniform number of the player
int
getUnum
();
// Returns the uniform number of the player
inline
int
getNumTeammates
()
{
return
num_teammates
;
}
inline
int
getNumTeammates
()
{
return
num_teammates
;
}
inline
int
getNumOpponents
()
{
return
num_opponents
;
}
inline
int
getNumOpponents
()
{
return
num_opponents
;
}
hfo
::
action_status_t
getLastActionStatus
(
hfo
::
action_t
last_action
);
// if last_action is correct, returns status if available
inline
bool
getLastActionStatus
()
{
return
last_action_status
;
}
inline
void
setFeatureSet
(
hfo
::
feature_set_t
fset
)
{
feature_set
=
fset
;
}
inline
void
setFeatureSet
(
hfo
::
feature_set_t
fset
)
{
feature_set
=
fset
;
}
inline
std
::
vector
<
float
>*
mutable_params
()
{
return
&
params
;
}
inline
std
::
vector
<
float
>*
mutable_params
()
{
return
&
params
;
}
...
@@ -85,23 +84,23 @@ protected:
...
@@ -85,23 +84,23 @@ protected:
private:
private:
bool
doPreprocess
();
bool
doPreprocess
();
hfo
::
action_status_t
doReorient
();
bool
doReorient
();
hfo
::
action_status_t
doSmartKick
();
bool
doSmartKick
();
hfo
::
action_status_t
doShoot
();
bool
doShoot
();
bool
doPass
();
bool
doPass
();
hfo
::
action_status_t
doPassTo
(
int
receiver
);
bool
doPassTo
(
int
receiver
);
hfo
::
action_status_t
doDribble
();
bool
doDribble
();
hfo
::
action_status_t
doMove
();
bool
doMove
();
bool
doForceKick
();
bool
doForceKick
();
bool
doHeardPassReceive
();
bool
doHeardPassReceive
();
hfo
::
action_status_t
doMarkPlayer
(
int
unum
);
bool
doMarkPlayer
(
int
unum
);
bool
doMarkPlayerNearIndex
(
int
near_index
);
bool
doMarkPlayerNearIndex
(
int
near_index
);
hfo
::
action_status_t
doReduceAngleToGoal
();
bool
doReduceAngleToGoal
();
hfo
::
action_status_t
doDefendGoal
();
bool
doDefendGoal
();
hfo
::
action_status_t
doGoToBall
();
bool
doGoToBall
();
bool
doNewAction1
();
bool
doNewAction1
();
void
addLastActionStatus
(
hfo
::
action_t
last_action
,
hfo
::
action_status_t
action_status
);
inline
void
setLastActionStatus
(
bool
likely_success
)
{
last_action_status
=
likely_success
;
}
void
addLastActionStatusCollision
(
hfo
::
action_t
last_action
,
bool
may_fix
,
bool
likely_success
);
void
setLastActionStatusCollision
(
bool
may_fix
,
bool
likely_success
);
Communication
::
Ptr
M_communication
;
Communication
::
Ptr
M_communication
;
...
...
src/bhv_basic_move.cpp
View file @
59c57e88
...
@@ -52,32 +52,23 @@
...
@@ -52,32 +52,23 @@
using
namespace
rcsc
;
using
namespace
rcsc
;
bool
Bhv_BasicMove
::
execute
(
PlayerAgent
*
agent
)
{
if
(
Bhv_BasicMove
::
action_execute
(
agent
)
==
hfo
::
ACTION_STATUS_MAYBE
)
{
return
true
;
}
else
{
return
false
;
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/*!
/*!
*/
*/
hfo
::
action_status_t
bool
Bhv_BasicMove
::
action_execute
(
PlayerAgent
*
agent
)
Bhv_BasicMove
::
action_execute
(
PlayerAgent
*
agent
)
{
{
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": Bhv_BasicMove"
);
__FILE__
": Bhv_BasicMove"
);
hfo
::
action_status_t
success
=
hfo
::
ACTION_STATUS_UNKNOWN
;
bool
success
=
false
;
bool
maybe_success
=
true
;
//-----------------------------------------------
//-----------------------------------------------
// tackle
// tackle
if
(
Bhv_BasicTackle
(
0.8
,
80.0
).
execute
(
agent
)
)
if
(
Bhv_BasicTackle
(
0.8
,
80.0
).
execute
(
agent
)
)
{
{
return
hfo
::
ACTION_STATUS_MAYBE
;
return
true
;
}
}
const
WorldModel
&
wm
=
agent
->
world
();
const
WorldModel
&
wm
=
agent
->
world
();
...
@@ -96,7 +87,7 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
...
@@ -96,7 +87,7 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
{
{
dlog
.
addText
(
Logger
::
TEAM
,
dlog
.
addText
(
Logger
::
TEAM
,
__FILE__
": intercept"
);
__FILE__
": intercept"
);
success
=
hfo
::
BooleanToActionStatus
(
Body_Intercept
().
execute
(
agent
)
);
success
=
Body_Intercept
().
execute
(
agent
);
agent
->
setNeckAction
(
new
Neck_OffensiveInterceptNeck
()
);
agent
->
setNeckAction
(
new
Neck_OffensiveInterceptNeck
()
);
return
success
;
return
success
;
}
}
...
@@ -107,7 +98,7 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
...
@@ -107,7 +98,7 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
const
BallObject
&
ball
=
wm
.
ball
();
const
BallObject
&
ball
=
wm
.
ball
();
if
(
!
ball
.
rposValid
())
{
if
(
!
ball
.
rposValid
())
{
if
(
!
wm
.
self
().
collidesWithPost
())
{
if
(
!
wm
.
self
().
collidesWithPost
())
{
success
=
hfo
::
ACTION_STATUS_BAD
;
maybe_success
=
false
;
}
}
}
}
...
@@ -127,10 +118,12 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
...
@@ -127,10 +118,12 @@ Bhv_BasicMove::action_execute( PlayerAgent * agent )
).
execute
(
agent
)
)
).
execute
(
agent
)
)
{
{
if
(
!
Body_TurnToBall
().
execute
(
agent
))
{
if
(
!
Body_TurnToBall
().
execute
(
agent
))
{
success
=
hfo
::
ACTION_STATUS_BAD
;
success
=
false
;
}
else
{
success
=
maybe_success
;
}
}
}
else
if
(
success
!=
hfo
::
ACTION_STATUS_BAD
)
{
}
else
{
success
=
hfo
::
ACTION_STATUS_MAYBE
;
success
=
maybe_success
;
}
}
if
(
wm
.
existKickableOpponent
()
&&
if
(
wm
.
existKickableOpponent
()
&&
...
...
src/bhv_basic_move.h
View file @
59c57e88
...
@@ -38,7 +38,6 @@ public:
...
@@ -38,7 +38,6 @@ public:
{
}
{
}
bool
execute
(
rcsc
::
PlayerAgent
*
agent
);
bool
execute
(
rcsc
::
PlayerAgent
*
agent
);
hfo
::
action_status_t
action_execute
(
rcsc
::
PlayerAgent
*
agent
);
private:
private:
double
getDashPower
(
const
rcsc
::
PlayerAgent
*
agent
);
double
getDashPower
(
const
rcsc
::
PlayerAgent
*
agent
);
...
...
src/common.hpp
View file @
59c57e88
...
@@ -53,24 +53,6 @@ enum status_t
...
@@ -53,24 +53,6 @@ enum status_t
SERVER_DOWN
// Server is not alive
SERVER_DOWN
// Server is not alive
};
};
// Action status
enum
action_status_t
{
ACTION_STATUS_UNKNOWN
=
-
1
,
// cannot tell or invalid action # in status request
ACTION_STATUS_BAD
=
0
,
// definitely not OK
ACTION_STATUS_MAYBE
=
1
,
// may be OK, may not
};
/**
* Translates from boolean false (bad) or true (maybe OK) to action status
*/
inline
action_status_t
BooleanToActionStatus
(
const
bool
status
)
{
if
(
status
)
{
return
ACTION_STATUS_MAYBE
;
}
else
{
return
ACTION_STATUS_BAD
;
}
}
// Configuration of the HFO domain including the team names and player
// Configuration of the HFO domain including the team names and player
// numbers for each team. This struct is populated by ParseConfig().
// numbers for each team. This struct is populated by ParseConfig().
struct
Config
{
struct
Config
{
...
...
src/feature_extractor.h
View file @
59c57e88
// -*-c++-*-
#ifndef FEATURE_EXTRACTOR_H
#ifndef FEATURE_EXTRACTOR_H
#define FEATURE_EXTRACTOR_H
#define FEATURE_EXTRACTOR_H
...
...
src/highlevel_feature_extractor.cpp
View file @
59c57e88
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#include "highlevel_feature_extractor.h"
#include "highlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>
#include <rcsc/common/server_param.h>
#include "agent.h"
using
namespace
rcsc
;
using
namespace
rcsc
;
...
@@ -16,6 +17,7 @@ HighLevelFeatureExtractor::HighLevelFeatureExtractor(int num_teammates,
...
@@ -16,6 +17,7 @@ HighLevelFeatureExtractor::HighLevelFeatureExtractor(int num_teammates,
assert
(
numOpponents
>=
0
);
assert
(
numOpponents
>=
0
);
numFeatures
=
num_basic_features
+
features_per_teammate
*
numTeammates
numFeatures
=
num_basic_features
+
features_per_teammate
*
numTeammates
+
features_per_opponent
*
numOpponents
;
+
features_per_opponent
*
numOpponents
;
numFeatures
++
;
// action status
feature_vec
.
resize
(
numFeatures
);
feature_vec
.
resize
(
numFeatures
);
}
}
...
@@ -178,6 +180,12 @@ const std::vector<float>& HighLevelFeatureExtractor::ExtractFeatures(
...
@@ -178,6 +180,12 @@ const std::vector<float>& HighLevelFeatureExtractor::ExtractFeatures(
addFeature
(
FEAT_INVALID
);
addFeature
(
FEAT_INVALID
);
}
}
if
(
getLastActionStatus
())
{
addFeature
(
FEAT_MAX
);
}
else
{
addFeature
(
FEAT_MIN
);
}
assert
(
featIndx
==
numFeatures
);
assert
(
featIndx
==
numFeatures
);
// checkFeatures();
// checkFeatures();
return
feature_vec
;
return
feature_vec
;
...
...
src/highlevel_feature_extractor.h
View file @
59c57e88
// -*-c++-*-
#ifndef HIGHLEVEL_FEATURE_EXTRACTOR_H
#ifndef HIGHLEVEL_FEATURE_EXTRACTOR_H
#define HIGHLEVEL_FEATURE_EXTRACTOR_H
#define HIGHLEVEL_FEATURE_EXTRACTOR_H
...
...
src/lowlevel_feature_extractor.cpp
View file @
59c57e88
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#include "lowlevel_feature_extractor.h"
#include "lowlevel_feature_extractor.h"
#include <rcsc/common/server_param.h>
#include <rcsc/common/server_param.h>
#include "agent.h"
using
namespace
rcsc
;
using
namespace
rcsc
;
...
@@ -17,6 +18,7 @@ LowLevelFeatureExtractor::LowLevelFeatureExtractor(int num_teammates,
...
@@ -17,6 +18,7 @@ LowLevelFeatureExtractor::LowLevelFeatureExtractor(int num_teammates,
numFeatures
=
num_basic_features
+
numFeatures
=
num_basic_features
+
features_per_player
*
(
numTeammates
+
numOpponents
);
features_per_player
*
(
numTeammates
+
numOpponents
);
numFeatures
+=
numTeammates
+
numOpponents
;
// Uniform numbers
numFeatures
+=
numTeammates
+
numOpponents
;
// Uniform numbers
numFeatures
++
;
// action state
feature_vec
.
resize
(
numFeatures
);
feature_vec
.
resize
(
numFeatures
);
}
}
...
@@ -197,7 +199,7 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures(
...
@@ -197,7 +199,7 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures(
detected_teammates
++
;
detected_teammates
++
;
}
}
}
}
// Add -
2
features for any missing teammates
// Add -
1
features for any missing teammates
for
(
int
i
=
detected_teammates
;
i
<
numTeammates
;
++
i
)
{
for
(
int
i
=
detected_teammates
;
i
<
numTeammates
;
++
i
)
{
addFeature
(
FEAT_MIN
);
addFeature
(
FEAT_MIN
);
}
}
...
@@ -212,11 +214,17 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures(
...
@@ -212,11 +214,17 @@ const std::vector<float>& LowLevelFeatureExtractor::ExtractFeatures(
detected_opponents
++
;
detected_opponents
++
;
}
}
}
}
// Add -
2
features for any missing opponents
// Add -
1
features for any missing opponents
for
(
int
i
=
detected_opponents
;
i
<
numOpponents
;
++
i
)
{
for
(
int
i
=
detected_opponents
;
i
<
numOpponents
;
++
i
)
{
addFeature
(
FEAT_MIN
);
addFeature
(
FEAT_MIN
);
}
}
if
(
getLastActionStatus
())
{
addFeature
(
FEAT_MAX
);
}
else
{
addFeature
(
FEAT_MIN
);
}
assert
(
featIndx
==
numFeatures
);
assert
(
featIndx
==
numFeatures
);
checkFeatures
();
checkFeatures
();
return
feature_vec
;
return
feature_vec
;
...
...
src/lowlevel_feature_extractor.h
View file @
59c57e88
// -*-c++-*-
#ifndef LOWLEVEL_FEATURE_EXTRACTOR_H
#ifndef LOWLEVEL_FEATURE_EXTRACTOR_H
#define LOWLEVEL_FEATURE_EXTRACTOR_H
#define 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