Source code for pomdp_py.problems.tag.models.components.motion_policy
import pomdp_py
import random
from pomdp_py.utils.math import euclidean_dist
import pomdp_py.problems.tag.constants as constants
from pomdp_py.problems.tag.models.transition_model import TagTransitionModel
[docs]
class TagTargetMotionPolicy(pomdp_py.GenerativeDistribution):
def __init__(
self, grid_map, pr_stay=0.2
): # With 1.0 - pr_stay chance, the target moves away
self._grid_map = grid_map
self._pr_stay = pr_stay
def _compute_candidate_actions(
self, robot_position, target_position, valid_target_motion_actions
):
candidate_actions = set({})
cur_dist = euclidean_dist(robot_position, target_position)
for action in valid_target_motion_actions:
next_target_position = TagTransitionModel.if_move_by(
self._grid_map, target_position, action
)
next_dist = euclidean_dist(robot_position, next_target_position)
if next_dist > cur_dist:
candidate_actions.add(action)
return candidate_actions
[docs]
def probability(
self,
next_target_position,
target_position,
robot_position,
valid_target_motion_actions,
):
# If it is impossible to go from target position to the next,
# then it is a zero probability event.
diff_x = abs(next_target_position[0] - target_position[0])
diff_y = abs(next_target_position[1] - target_position[1])
if not (
(diff_x == 1 and diff_y == 0)
or (diff_x == 0 and diff_y == 1)
or (diff_x == 0 and diff_y == 0)
):
return constants.EPSILON
candidate_actions = self._compute_candidate_actions(
robot_position, target_position, valid_target_motion_actions
)
if len(candidate_actions) == 0:
# No action possible, yet next_target_position is a valid
# transition from current.
if next_target_position == target_position:
# That means the target is either
# stuck or staying. Either way, this is the only thing that
# can happen
return 1.0 - constants.EPSILON
else:
return constants.EPSILON
else:
# There are candidate actions
if next_target_position == target_position:
# The object is staying
return self._pr_stay
else:
# The object has taken an adversarial action.
for action in candidate_actions:
if (
target_position[0] + action.motion[0],
target_position[1] + action.motion[1],
) == next_target_position:
return (1.0 - self._pr_stay) / len(candidate_actions)
return constants.EPSILON
[docs]
def random(
self, robot_position, target_position, valid_target_motion_actions, mpe=False
):
if mpe or random.uniform(0, 1) > self._pr_stay:
# Move away; Pick motion actions that makes the target moves away from the robot
candidate_actions = self._compute_candidate_actions(
robot_position, target_position, valid_target_motion_actions
)
if len(candidate_actions) == 0:
return target_position
chosen_action = random.sample(candidate_actions, 1)[0]
return TagTransitionModel.if_move_by(
self._grid_map, target_position, chosen_action
)
else:
# stay
return target_position
[docs]
def mpe(self, robot_position, target_position, valid_target_motion_actions):
return self.random(
robot_position, target_position, valid_target_motion_actions, mpe=True
)