MountainCar-v0手动控制异常:未按键时自动左移问题求助
MountainCar-v0手动游玩自动左移问题解决
问题根源
你混淆了MountainCar-v0环境的动作定义:
- 环境原生动作0:向左移动
- 环境原生动作1:无操作
- 环境原生动作2:向右移动
你的代码中错误将"0"映射到动作0(实际是左移),且未指定无按键时的默认动作,play函数默认使用noop=0(即左移),导致小车自动左移。
修正代码
修改动作映射,并明确指定无按键时执行无操作:
import gym from gym.utils import play # 正确映射:无按键/按"0"→无操作(1),按"1"→左移(0),按"2"→右移(2) keys_to_action = { (): 1, # 无按键时执行无操作 ("0",): 1, ("1",): 0, ("2",): 2 } # 无需调用.env,gym.make已返回封装好的环境 play.play(gym.make('MountainCar-v0', render_mode='rgb_array'), zoom=1, keys_to_action=keys_to_action)
gym/utils/play.py核心代码翻译
import pygame import numpy as np from gym import Env def play(env: Env, transpose: bool = True, fps: int = None, zoom: float = 1.0, keys_to_action: dict = None, callback=None, noop: int = 0): """ 允许用户通过键盘与OpenAI Gym环境交互。 参数: env: 要交互的Gym环境 transpose: 是否转置渲染后的帧(默认True,适配大多数Atari游戏) fps: 每秒帧率,默认为环境的metadata['render_fps'] zoom: 渲染窗口的缩放倍数 keys_to_action: 按键组合到动作的映射,键为按键名称的元组,值为对应的动作索引 若未提供,将尝试使用环境的get_keys_to_action方法,或使用默认的方向键映射 callback: 回调函数,参数为(obs_t, obs_tp1, action, rew, done, info) 当done为True时会被调用 noop: 无按键输入时执行的默认动作 """ env.reset() rendered = env.render() if keys_to_action is None: if hasattr(env, 'get_keys_to_action'): keys_to_action = env.get_keys_to_action() elif isinstance(env.action_space, Discrete): # 离散动作空间默认使用方向键映射 keys = { (pygame.K_LEFT,): 0, (pygame.K_RIGHT,): 1, } if env.action_space.n == 3: keys[(pygame.K_DOWN,)] = 2 keys_to_action = keys else: raise ValueError("环境未提供默认的按键映射,请手动指定keys_to_action") # 初始化Pygame pygame.init() screen = pygame.display.set_mode( (int(rendered.shape[1] * zoom), int(rendered.shape[0] * zoom)) ) pygame.display.set_caption(env.spec.id) if fps is None: fps = env.metadata.get('render_fps', 30) clock = pygame.time.Clock() obs_t = env.reset() done = False keys_pressed = set() while not done: # 处理Pygame事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() return elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() return keys_pressed.add(pygame.key.name(event.key)) elif event.type == pygame.KEYUP: if pygame.key.name(event.key) in keys_pressed: keys_pressed.remove(pygame.key.name(event.key)) # 确定当前要执行的动作 action = keys_to_action.get(tuple(sorted(keys_pressed)), noop) obs_tp1, rew, done, info = env.step(action) # 渲染画面 rendered = env.render() if transpose: rendered = np.transpose(rendered, (1, 0, 2)) surf = pygame.surfarray.make_surface(rendered) surf = pygame.transform.scale(surf, screen.get_size()) screen.blit(surf, (0, 0)) pygame.display.flip() # 调用回调函数 if callback is not None: callback(obs_t, obs_tp1, action, rew, done, info) obs_t = obs_tp1 clock.tick(fps) pygame.quit()
内容的提问来源于stack exchange,提问作者Hisham Mohammed
相关产品推荐
相关产品推荐

