class_docstr: An wrapper stacking the observations of multiple subsequent time steps.
  
  Provides functionality for:
  
      - selecting which observations to stack
      - how many past observations should be stacked
      - stacking deltas with the current step observation (instead of the observations itself)
  
  :param env: Environment/wrapper to wrap.
  :param stack_config: The observation stacking configuration.
  
      observation:        The name (key) of the respective observation
      keep_original:      Bool, indicates weather to keep or remove the original observation from the dictionary.
      tag:                Optional[str], tag to add to observation (e.g. stacked)
      delta:              Bool, if true deltas are stacked to the previous observation
      stack_steps:        Int, number of past steps to be stacked
docstr: Stack observations.
  
  :param observation: The observation to be stacked.
  :return: The sacked observation.
docstr_tok: ["Stack","observations",".",":","param","observation",":","The","observation","to","be","stacked",".",":","return",":","The","sacked","observation","."]
code: def observation(
      self, observation: Dict[str, np.ndarray]
  ) -> Dict[str, np.ndarray]:
      """Stack observations.
  
      :param observation: The observation to be stacked.
      :return: The sacked observation.
      """
  
      # iteratively process observations
      for config in self.stack_config:
          # extract config
          obs_key = config["observation"]
          keep_original = config["keep_original"]
          tag = config["tag"]
          delta = config["delta"]
          stack_steps = config["stack_steps"]
  
          # update observation stack
          if obs_key in observation:
              self._observation_stack[obs_key].append(
                  observation[obs_key]
              )
              self._observation_stack[
                  obs_key
              ] = self._observation_stack[obs_key][-self.max_steps :]
  
          # nothing to do
          if stack_steps < 2 or obs_key not in observation:
              continue
  
          # compute delta stack
          if delta:
              stacked = np.stack(self._observation_stack[obs_key])
              if stacked.shape[0] > 1:
                  diff = np.diff(stacked, axis=0)
                  stacked[-(len(diff) + 1) : -1] = diff
  
          # just stack
          else:
              stacked = np.stack(self._observation_stack[obs_key])
  
          # pad with zeros if necessary
          shape = [stack_steps] + list(
              self._flat_observation_space[obs_key].shape
          )
          observation_stack = np.zeros(shape=shape, dtype=np.float32)
          observation_stack[-len(stacked) :] = stacked
  
          # drop original observation
          if not keep_original:
              del observation[obs_key]
  
          # put observation into dictionary
          full_tag = obs_key if tag is None else f"{obs_key}-{tag}"
          observation[full_tag] = observation_stack
  
      return observation
  
imports: import copy
  from collections import defaultdict
  from typing import Any, Dict, List, Tuple, Union, Optional
  import numpy
  from gym import spaces
  from maze.core.annotations import override
  from maze.core.env.maze_action import MazeActionType
  from maze.core.env.maze_env import MazeEnv
  from maze.core.env.maze_state import MazeStateType
  from maze.core.env.simulated_env_mixin import SimulatedEnvMixin
  from maze.core.env.structured_env_spaces_mixin import StructuredEnvSpacesMixin
  from maze.core.utils.structured_env_utils import flat_structured_space
  from maze.core.wrappers.wrapper import ObservationWrapper, Wrapper
label_desc: Use image node_id 2 for calling the ObservationStackWrapper obj's underlying member method code with example usage: obj.observation(observation) and returns: observation