gym库中CartPole-v0环境代码详解

代码源码在gym\envs\classic_control\cartpole中
针对源码的详细解释都备注在下方代码块具体程序里

class CartPoleEnv (gym.Env)

  • 初始化
def __init__(self):
    self.gravity = 9.8
    self.masscart = 1.0
    self.masspole = 0.1
    self.total_mass = (self.masspole + self.masscart)
    self.length = 0.5 # actually half the pole's length
    self.polemass_length = (self.masspole * self.length) # 力与力矩
    self.force_mag = 10.0 #车的推力大小,表示平衡车向左或向右施加的力的幅度
    self.tau = 0.02  # 状态更新的时间间隔 以秒为单位

    # 阈值:超过此值表示任务失败
    self.theta_threshold_radians = 12 * 2 * math.pi / 360 # 倒立摆的倾斜角阈值
    self.x_threshold = 2.4 # 车的距离阈值

    # Angle limit set to 2 * theta_threshold_radians so failing observation is still within bounds
    # high为numpy数组,定义了观测空间的边界
    # 观测空间定义了agent可以观察到的状态的范围
    high = np.array([
        self.x_threshold * 2,             # 平衡车的位置维度 -x_threshold~x_threshold
        np.finfo(np.float32).max,         # 平衡车的速度维度 -∞~+∞
        self.theta_threshold_radians * 2, # 倒立摆的角度纬度 -theta_threshold_radians
                                          #             ~ +theta_threshold_radians
        np.finfo(np.float32).max])        # 倒立摆的角速度纬度 -∞~+∞

    # 定义了动作空间,包含两个动作:0 和 1,别表示向左和向右的移动
    self.action_space = spaces.Discrete(2) 
    # 定义了环境的观测空间。观测空间通常包含了智能体可以观察到的环境状态的范围
    # box是一种数据类型,用来描述连续的多维数值空间
    self.observation_space = spaces.Box(-high, high)

    # 随机数生成器的种子
    self._seed()
    # 可视化工具
    self.viewer = None
    # 存储环境的当前中通,none表示当前状态尚未被定义
    self.state = None
    # 跟踪任务失败后的附加步骤数,当任务失败后,记录agent继续执行动作的步骤数
    self.steps_beyond_done = None
  • seed()函数

随机数生成器,以便在实验中获得可重复的结果

def _seed(self, seed=None):
    self.np_random, seed = seeding.np_random(seed)
    return [seed]
  • step()函数

执行一个时间步(time step):

​ 接受agent的动作、计算下一时刻状态和奖励、检查任务是否已完成

def _step(self, action):
    
    # 确保agent执行的动作在允许的动作空间内,否则触发assert警告
    assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action))
    
    # 获取当前环境状态(x, x_dot, theta, theta_dot)
    state = self.state 
    x, x_dot, theta, theta_dot = state
    
    # 根据agent采取的动作确定平衡车的力的大小
    # 基于平衡车和倒立摆的物理模型,更新状态s'=(x', x_dot', theta', theta_dot')
    force = self.force_mag if action==1 else -self.force_mag
    costheta = math.cos(theta)
    sintheta = math.sin(theta)
    temp = (force + self.polemass_length * theta_dot * theta_dot * sintheta) / self.total_mass
    thetaacc = (self.gravity * sintheta - costheta* temp) / (self.length * (4.0/3.0 - self.masspole * costheta * costheta / self.total_mass))
    xacc  = temp - self.polemass_length * thetaacc * costheta / self.total_mass
    x  = x + self.tau * x_dot
    x_dot = x_dot + self.tau * xacc
    theta = theta + self.tau * theta_dot
    theta_dot = theta_dot + self.tau * thetaacc
    
    # 将刚计算出的新状态更新到环境中
    self.state = (x,x_dot,theta,theta_dot)
    # 检查任务是否完成,任务失败的条件是平衡车的位置或倒立摆角度超出阈值
    done =  x < -self.x_threshold \
            or x > self.x_threshold \
            or theta < -self.theta_threshold_radians \
            or theta > self.theta_threshold_radians
    done = bool(done) # 将done转化为布尔值:Ture or False

    # 计算奖励值
    # steps_beyond_done可以看作为标识符用来判断任务是在本次结束的还是在之前的时间步结束的
    #情况1:任务还没完成,奖励1.0鼓励agent继续保持以完成任务
    if not done:
        reward = 1.0 
    #情况2:任务完成,且在当前时间步终止,奖励1.0
    elif self.steps_beyond_done is None:
        # Pole just fell!
        self.steps_beyond_done = 0
        reward = 1.0
    #情况2:任务完成,但agent仍在继续采取动作,奖励0.0并记录警告日志   
    else:
        if self.steps_beyond_done == 0:
            logger.warning("You are calling 'step()' even though this environment has already returned done = True. You should always call 'reset()' once you receive 'done = True' -- any further steps are undefined behavior.") # 记录警告日志
        self.steps_beyond_done += 1
        reward = 0.0
	
    # 最终step函数返回(s',r,done)以更新策略和价值函数,{}用于传递警告日志
    return np.array(self.state), reward, done, {}
  • reset()函数

当agent完成任务或任务失败后将环境重置为初始状态,以便进行新一轮训练

def _reset(self):
    # 重置后的初始状态是在(-0.05,0.05)内均匀分布的随机数,size为状态总数
    self.state = self.np_random.uniform(low=-0.05, high=0.05, size=(4,))
    # 任务flag:表示尚未完成
    self.steps_beyond_done = None
    # 将state转化为numpy数组并返回
    return np.array(self.state)
  • render()函数

用于可视化环境状态,一般直接调用就行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值