You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于gym.make('env')内部实现与自定义DQN复杂环境的技术咨询

1. 找到gym.make()的内部实现逻辑

gym.make()并不是在单个环境文件(比如cartpole.py)里实现的,它属于Gym的环境注册系统核心逻辑。你可以去gym/envs/registration.py文件里找make函数的具体实现——这个函数的作用是根据你传入的环境ID(比如'CartPole-v0'),去查找预注册的环境元数据,然后实例化对应的环境类。

补充一下注册流程:像CartPole这类环境,是在gym/envs/classic_control/__init__.py里通过register()函数完成注册的,把环境ID和对应的CartPoleEnv类绑定起来。你可以看这个注册文件,就能明白整个“注册-实例化”的完整链路。

2. 非Gym的复杂状态环境示例(非Atari类)

下面给你一个**自适应巡航控制(ACC)**的自定义环境示例,完全不依赖Gym,状态是多维度连续变量,比Atari的像素环境更贴近复杂控制场景:

import numpy as np

class AdaptiveCruiseControlEnv:
    def __init__(self):
        # 状态空间:[自车速度, 前车速度, 车间距, 自车加速度, 前车加速度]
        self.state_dim = 5
        # 动作空间:[-1.0, 1.0] 对应刹车到加速的归一化控制量
        self.action_dim = 1
        
        self.reset()
    
    def reset(self):
        # 随机初始化场景状态
        self.current_speed = np.random.uniform(20, 30)  # 自车初始速度(m/s)
        self.lead_speed = np.random.uniform(20, 35)     # 前车初始速度
        self.headway = np.random.uniform(10, 20)        # 初始车间距(m)
        self.self_accel = 0.0                           # 自车初始加速度
        self.lead_accel = np.random.uniform(-0.5, 0.5)  # 前车初始加速度
        
        return self._get_state()
    
    def _get_state(self):
        # 返回当前完整状态向量
        return np.array([
            self.current_speed,
            self.lead_speed,
            self.headway,
            self.self_accel,
            self.lead_accel
        ])
    
    def step(self, action):
        # 把归一化动作映射为实际加速度(-4m/s²到2m/s²)
        actual_accel = action * 3 - 1
        
        # 更新前车状态(模拟前车随机加减速)
        self.lead_accel = np.clip(self.lead_accel + np.random.normal(0, 0.1), -2, 2)
        self.lead_speed = np.clip(self.lead_speed + self.lead_accel * 0.1, 0, 40)
        
        # 更新自车状态
        self.self_accel = np.clip(actual_accel, -4, 2)
        self.current_speed = np.clip(self.current_speed + self.self_accel * 0.1, 0, 40)
        
        # 更新车间距
        delta_speed = self.lead_speed - self.current_speed
        self.headway += delta_speed * 0.1
        
        # 计算奖励:鼓励保持安全车间距(15m)+ 跟上车速
        reward = -abs(self.headway - 15) - 0.1 * abs(self.current_speed - self.lead_speed)
        
        # 终止条件:车间距过小(<2m)或过大(>50m)
        done = self.headway < 2 or self.headway > 50
        
        return self._get_state(), reward, done, {}

3. 处理依赖多个历史状态的step函数实现

当状态t+1需要依赖历史状态(比如t-1、t-2的状态/动作)时,最直接的方案是扩展当前状态空间,把历史信息包含进去。比如在自适应控制问题中,模型参考自适应控制(MRAC)需要跟踪过去的误差和控制输入,我们可以维护历史缓冲区,或者直接将历史变量作为状态的一部分。

下面是一个二阶系统的自适应控制示例,状态包含当前位置、速度,以及上一步的误差和控制量:

import numpy as np

class AdaptiveSecondOrderEnv:
    def __init__(self):
        # 状态空间:[当前位置, 当前速度, 上一步误差, 上一步控制量]
        self.state_dim = 4
        
        # 未知系统参数
        self.mass = 1.5  # 质量
        self.damping = 0.8  # 阻尼系数
        
        self.reset()
    
    def reset(self):
        # 初始状态:位置0,速度0,初始误差0,初始控制量0
        self.pos = 0.0
        self.vel = 0.0
        self.last_error = 0.0
        self.last_action = 0.0
        
        # 参考轨迹(正弦曲线)
        self.ref_trajectory = lambda t: np.sin(0.5 * t)
        self.time_step = 0.0
        
        return self._get_state()
    
    def _get_state(self):
        # 返回包含历史信息的完整状态
        return np.array([
            self.pos,
            self.vel,
            self.last_error,
            self.last_action
        ])
    
    def step(self, action):
        dt = 0.1  # 时间步长
        
        # 计算当前参考轨迹值和误差
        ref_pos = self.ref_trajectory(self.time_step)
        current_error = ref_pos - self.pos
        
        # 二阶系统动力学:mass*dv/dt = action - damping*vel
        dv_dt = (action - self.damping * self.vel) / self.mass
        self.vel += dv_dt * dt
        self.pos += self.vel * dt
        
        # 更新历史信息:保存当前误差和动作作为下一轮的历史
        self.last_error = current_error
        self.last_action = action
        
        # 奖励设计:跟踪误差越小越好,同时惩罚过大的控制量
        reward = -abs(current_error) - 0.01 * abs(action)
        
        # 终止条件:运行100步后结束
        self.time_step += dt
        done = self.time_step >= 10.0
        
        return self._get_state(), reward, done, {"reference_pos": ref_pos}

如果需要依赖更多历史步(比如3步),只需要扩展状态空间,加入前2步的误差和动作,同时在reset和step中维护对应的历史缓冲区即可。


内容的提问来源于stack exchange,提问作者Sa Ra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:42:55