class_docstr: A wrapper for reward shaping, note this wrapper must be the first wrapper 
class_docstr_tok: ["A","wrapper","for","reward","shaping",",","note","this","wrapper","must","be","the","first","wrapper"]
code: def step(self, action, **kwargs):
      self.step_count += 1
      obs, r, done, info = self.env.step(action, **kwargs)
      info = self.reward_shaping(obs, r, done, action)
      if info["target_vel"] > 2.75:
          rate = math.sqrt((2.75**2) / (info["target_vel"] ** 2))
          logger.warn(
              "Changing targets, origin targets: {}".format(
                  obs["target_vel"]
              )
          )
          obs["target_vel"][0] = obs["target_vel"][0] * rate
          obs["target_vel"][2] = obs["target_vel"][2] * rate
          logger.warn(
              "Changing targets, new targets: {}".format(
                  obs["target_vel"]
              )
          )
          info["target_vel"] = 2.75
      if info["target_vel"] < -0.25:
          rate = math.sqrt(((-0.25) ** 2) / (info["target_vel"] ** 2))
          logger.warn(
              "Changing targets, origin targets: {}".format(
                  obs["target_vel"]
              )
          )
          obs["target_vel"][0] = obs["target_vel"][0] * rate
          obs["target_vel"][2] = obs["target_vel"][2] * rate
          logger.warn(
              "Changing targets, new targets: {}".format(
                  obs["target_vel"]
              )
          )
          info["target_vel"] = -0.25
  
      delta = 0
      if self.last_target_vel is not None:
          delta = np.absolute(
              np.array(self.last_target_vel)
              - np.array(obs["target_vel"])
          )
      if (self.last_target_vel is None) or np.all(delta < 1e-5):
          info["target_changed"] = False
      else:
          info["target_changed"] = True
          logger.info(
              "[env_wrapper] target_changed, vx:{}   vz:{}".format(
                  obs["target_vel"][0], obs["target_vel"][2]
              )
          )
          self.last_target_change_step = self.step_count
          self.target_change_times += 1
      info["target_change_times"] = self.target_change_times
      self.last_target_vel = obs["target_vel"]
  
      assert "shaping_reward" in info
      timeout = False
      if self.step_count >= MAXTIME_LIMIT:
          timeout = True
      if done and not timeout:
          # penalty for falling down
          info["shaping_reward"] += FALL_PENALTY
      info["timeout"] = timeout
      self.pre_state_desc = obs
      return obs, r, done, info
  
imports: import abc
  import copy
  import gym
  import math
  import numpy
  from collections import OrderedDict
  from osim.env import ProstheticsEnv
  from parl.utils import logger
label_desc: Use image node_id 3 for calling the RewardShaping obj's underlying member method code with example usage: obj.step(action) and returns: obs,  r,  done,  info