class_docstr: An exploration that adds Ornstein-Uhlenbeck noise to continuous actions.
  
  If explore=True, returns sampled actions plus a noise term X,
  which changes according to this formula:
  Xt+1 = -theta*Xt + sigma*N[0,stddev], where theta, sigma and stddev are
  constants. Also, some completely random period is possible at the
  beginning.
  If explore=False, returns the deterministic action.
class_docstr_tok: ["An","exploration","that","adds","Ornstein-Uhlenbeck","noise","to","continuous","actions",".","If","explore=True",",","returns","sampled","actions","plus","a","noise","term","X",",","which","changes","according","to","this","formula",":","Xt+1","=","-theta","*","Xt","+","sigma","*","N","[","0",",","stddev","]",",","where","theta",",","sigma","and","stddev","are","constants",".","Also",",","some","completely","random","period","is","possible","at","the","beginning",".","If","explore=False",",","returns","the","deterministic","action","."]
code: def _get_tf_exploration_action_op(
      self,
      action_dist: ActionDistribution,
      explore: Union[bool, TensorType],
      timestep: Union[int, TensorType],
  ):
      ts = timestep if timestep is not None else self.last_timestep
      scale = self.scale_schedule(ts)
  
      # The deterministic actions (if explore=False).
      deterministic_actions = action_dist.deterministic_sample()
  
      # Apply base-scaled and time-annealed scaled OU-noise to
      # deterministic actions.
      gaussian_sample = tf.random.normal(
          shape=[self.action_space.low.size], stddev=self.stddev
      )
      ou_new = (
          self.ou_theta * -self.ou_state
          + self.ou_sigma * gaussian_sample
      )
      if self.framework == "tf2":
          self.ou_state.assign_add(ou_new)
          ou_state_new = self.ou_state
      else:
          ou_state_new = tf1.assign_add(self.ou_state, ou_new)
      high_m_low = self.action_space.high - self.action_space.low
      high_m_low = tf.where(
          tf.math.is_inf(high_m_low),
          tf.ones_like(high_m_low),
          high_m_low,
      )
      noise = scale * self.ou_base_scale * ou_state_new * high_m_low
      stochastic_actions = tf.clip_by_value(
          deterministic_actions + noise,
          self.action_space.low * tf.ones_like(deterministic_actions),
          self.action_space.high * tf.ones_like(deterministic_actions),
      )
  
      # Stochastic actions could either be: random OR action + noise.
      (
          random_actions,
          _,
      ) = self.random_exploration.get_tf_exploration_action_op(
          action_dist, explore
      )
      exploration_actions = tf.cond(
          pred=tf.convert_to_tensor(ts < self.random_timesteps),
          true_fn=lambda: random_actions,
          false_fn=lambda: stochastic_actions,
      )
  
      # Chose by `explore` (main exploration switch).
      action = tf.cond(
          pred=tf.constant(explore, dtype=tf.bool)
          if isinstance(explore, bool)
          else explore,
          true_fn=lambda: exploration_actions,
          false_fn=lambda: deterministic_actions,
      )
      # Logp=always zero.
      logp = zero_logps_from_actions(deterministic_actions)
  
      # Increment `last_timestep` by 1 (or set to `timestep`).
      if self.framework == "tf2":
          if timestep is None:
              self.last_timestep.assign_add(1)
          else:
              self.last_timestep.assign(tf.cast(timestep, tf.int64))
      else:
          assign_op = (
              tf1.assign_add(self.last_timestep, 1)
              if timestep is None
              else tf1.assign(self.last_timestep, timestep)
          )
          with tf1.control_dependencies([assign_op, ou_state_new]):
              action = tf.identity(action)
              logp = tf.identity(logp)
  
      return action, logp
  
file_path: ray/python/ray/rllib/utils/exploration/ornstein_uhlenbeck_noise.py
imports: import numpy
  from typing import Optional, Union
  from ray.rllib.models.action_dist import ActionDistribution
  from ray.rllib.utils.annotations import override, PublicAPI
  from ray.rllib.utils.exploration.gaussian_noise import GaussianNoise
  from ray.rllib.utils.framework import try_import_tf, try_import_torch, get_variable, TensorType
  from ray.rllib.utils.numpy import convert_to_numpy
  from ray.rllib.utils.schedules import Schedule
  from ray.rllib.utils.tf_utils import zero_logps_from_actions
label_desc: Use image node_id 2 for calling the OrnsteinUhlenbeckNoise obj's underlying member method code with example usage: obj._get_tf_exploration_action_op(action_dist, explore, timestep) and returns: action,  logp