parameters: (self, start_jm_state, goal_jm_state)
return_statement: return joint_action_plan, end_jm_state, plan_lengths
docstring: Returns pre-computed plan from initial joint motion state
          to a goal joint motion state.
          
          Args:
              start_jm_state (tuple): starting pos & orients ((pos1, or1), (pos2, or2))
              goal_jm_state (tuple): goal pos & orients ((pos1, or1), (pos2, or2))
          
          Returns:
              joint_action_plan (list): joint actions to be executed to reach end_jm_state
              end_jm_state (tuple): the pair of (pos, or) tuples corresponding
                  to the ending timestep (this will usually be different from 
                  goal_jm_state, as one agent will end before other).
              plan_lengths (tuple): lengths for each agent's plan
docstring_summary: Returns pre-computed plan from initial joint motion state
          to a goal joint motion state.
          
          Args:
              start_jm_state (tuple): starting pos & orients ((pos1, or1), (pos2, or2))
              goal_jm_state (tuple): goal pos & orients ((pos1, or1), (pos2, or2))
          
          Returns:
              joint_action_plan (list): joint actions to be executed to reach end_jm_state
              end_jm_state (tuple): the pair of (pos, or) tuples corresponding
                  to the ending timestep (this will usually be different from 
                  goal_jm_state, as one agent will end before other).
              plan_lengths (tuple): lengths for each agent's plan
docstring_tokens: Returns pre - computed plan from initial joint motion state to a goal joint motion state . Args : start_jm_state ( tuple ) : starting pos & orients (( pos1 or1 ) ( pos2 or2 )) goal_jm_state ( tuple ) : goal pos & orients (( pos1 or1 ) ( pos2 or2 )) Returns : joint_action_plan ( list ) : joint actions to be executed to reach end_jm_state end_jm_state ( tuple ) : the pair of ( pos or ) tuples corresponding to the ending timestep ( this will usually be different from goal_jm_state as one agent will end before other ) . plan_lengths ( tuple ) : lengths for each agent s plan
function: def get_low_level_action_plan(self, start_jm_state, goal_jm_state):
          """
          Returns pre-computed plan from initial joint motion state
          to a goal joint motion state.
          
          Args:
              start_jm_state (tuple): starting pos & orients ((pos1, or1), (pos2, or2))
              goal_jm_state (tuple): goal pos & orients ((pos1, or1), (pos2, or2))
          
          Returns:
              joint_action_plan (list): joint actions to be executed to reach end_jm_state
              end_jm_state (tuple): the pair of (pos, or) tuples corresponding
                  to the ending timestep (this will usually be different from 
                  goal_jm_state, as one agent will end before other).
              plan_lengths (tuple): lengths for each agent's plan
          """
          assert self.is_valid_joint_motion_pair(start_jm_state, goal_jm_state), \
              "start: {} \t end: {} was not a valid motion goal pair".format(start_jm_state, goal_jm_state)
  
          if self.start_orientations:
              plan_key = (start_jm_state, goal_jm_state)
          else:
              starting_positions = tuple(player_pos_and_or[0] for player_pos_and_or in start_jm_state)
              goal_positions = tuple(player_pos_and_or[0] for player_pos_and_or in goal_jm_state)
              # If beginning positions are equal to end positions, the pre-stored
              # plan (not dependent on initial positions) will likely return a 
              # wrong answer, so we compute it from scratch.
              # 
              # This is because we only compute plans with starting orientations
              # (North, North), so if one of the two agents starts at location X
              # with orientation East it's goal is to get to location X with
              # orientation North. The precomputed plan will just tell that agent
              # that it is already at the goal, so no actions (or just 'interact')
              # are necessary.
              #
              # We also compute the plan for any shared motion goal with SAFE_RUN,
              # as there are some minor edge cases that could not be accounted for
              # but I expect should not make a difference in nearly all scenarios
              if any([s == g for s, g in zip(starting_positions, goal_positions)]) or (SAFE_RUN and goal_positions[0] == goal_positions[1]):
                  return self._obtain_plan(start_jm_state, goal_jm_state)
  
              dummy_orientation = Direction.NORTH
              dummy_start_jm_state = tuple((pos, dummy_orientation) for pos in starting_positions)
              plan_key = (dummy_start_jm_state, goal_jm_state)
  
          if plan_key not in self.all_plans:
              num_player = len(goal_jm_state)
              return [], None, [np.inf] * num_player
          joint_action_plan, end_jm_state, plan_lengths = self.all_plans[plan_key]
          return joint_action_plan, end_jm_state, plan_lengths
function_tokens: def get_low_level_action_plan ( self , start_jm_state , goal_jm_state ) : assert self . is_valid_joint_motion_pair ( start_jm_state , goal_jm_state ) , "start: {} \t end: {} was not a valid motion goal pair" . format ( start_jm_state , goal_jm_state ) if self . start_orientations : plan_key = ( start_jm_state , goal_jm_state ) else : starting_positions = tuple ( player_pos_and_or [ 0 ] for player_pos_and_or in start_jm_state ) goal_positions = tuple ( player_pos_and_or [ 0 ] for player_pos_and_or in goal_jm_state ) # If beginning positions are equal to end positions, the pre-stored # plan (not dependent on initial positions) will likely return a  # wrong answer, so we compute it from scratch. #  # This is because we only compute plans with starting orientations # (North, North), so if one of the two agents starts at location X # with orientation East it's goal is to get to location X with # orientation North. The precomputed plan will just tell that agent # that it is already at the goal, so no actions (or just 'interact') # are necessary. # # We also compute the plan for any shared motion goal with SAFE_RUN, # as there are some minor edge cases that could not be accounted for # but I expect should not make a difference in nearly all scenarios if any ( [ s == g for s , g in zip ( starting_positions , goal_positions ) ] ) or ( SAFE_RUN and goal_positions [ 0 ] == goal_positions [ 1 ] ) : return self . _obtain_plan ( start_jm_state , goal_jm_state ) dummy_orientation = Direction . NORTH dummy_start_jm_state = tuple ( ( pos , dummy_orientation ) for pos in starting_positions ) plan_key = ( dummy_start_jm_state , goal_jm_state ) if plan_key not in self . all_plans : num_player = len ( goal_jm_state ) return [ ] , None , [ np . inf ] * num_player joint_action_plan , end_jm_state , plan_lengths = self . all_plans [ plan_key ] return joint_action_plan , end_jm_state , plan_lengths