<gh_stars>1-10
'''This module implements concrete reset rule for the immobilization'''

import markov.agent_ctrl.constants as const

from markov.reset.abstract_reset_rule import AbstractResetRule
from markov.reset.constants import AgentCtrlStatus, AgentPhase
from markov.metrics.constants import EpisodeStatus


class ImmobilizedResetRule(AbstractResetRule):
    name = EpisodeStatus.IMMOBILIZED.value

    def __init__(self):
        super(ImmobilizedResetRule, self).__init__(ImmobilizedResetRule.name)
        self._immobilize_count = 0
        self._last_x = 0.0
        self._last_y = 0.0

    def _update(self, agent_status):
        '''Update the immobilized reset rule done flag

        Args:
            agent_status (dict): agent status dictionary
        '''
        agent_phase = agent_status[AgentCtrlStatus.AGENT_PHASE.value]
        x = agent_status[AgentCtrlStatus.X.value]
        y = agent_status[AgentCtrlStatus.Y.value]
        dist = ((((x - self._last_x)**2) + ((y - self._last_y)**2))**0.5)
        # If car is moving at 0.05 m/s with a step rate of 1/15 per second,
        # dist should be 0.05/15 = 0.003 (m), by using a scale factor ~10,
        # we will use distance between each step less than 0.0003 (m) as
        # immobilized.
        # Also, when car is at 0 m/s, its distance between each step call
        # is at the level between 1e-8 (m) and 1e-6 (m). This can capture the true
        # immobilization if car is not moving.
        if agent_phase == AgentPhase.RUN.value and dist <= 0.0003:
            self._immobilize_count += 1
        else:
            self._immobilize_count = 0
        if self._immobilize_count >= const.NUM_STEPS_TO_CHECK_STUCK:
            self._immobilize_count = 0
            self._done = True
        self._last_x, self._last_y = x, y
