想要源码可以点赞关注收藏后评论区留下QQ邮箱
本次利用gym搭建一个扫地机器人环境,描述如下:
在一个5×5的扫地机器人环境中,有一个垃圾和一个充电桩,到达[5,4]即图标19处机器人捡到垃圾,并结束游戏。同时获得+3的奖赏。左下角[1,1]处有一个充电桩,机器人到达充电桩可以充电且不再行走,获得+1的奖赏。环境中间[3,3]处有一个障碍物,机器人无法通过。
扫地机器人具体流程如下
1:每局游戏开始 机器人初始位置位于左上角 即[1,5]处
2:游戏进行过程中 机器人将在地图上不断进行探索
3:机器人遇到障碍物时无法通过 保持原地不动 获得-10的奖赏
4:地图上有两个终止状态,一个为捡到垃圾,获得+5的奖赏,另一个为达到充电桩进行充电进行充电 获得+1奖赏
5:扫地机器人到达终止状态 即一个情节结束 机器人回到初始位置
代码运行效果如下
扫地机器人环境搭建
部分代码如下
# 深度强化学习——原理、算法与PyTorch实战,代码名称:代02-搭建扫地机器人的Gym环境.py
import gym
from gym import spaces
from gym.utils import seeding
import sys
from time import sleep
import signal
class Grid(object):
def __init__(
self,
x: int = None, # 坐标x
y: int = None, # 坐标y
grid_type: int = 0, # 类别值(0:空;1:障碍或边界)
enter_reward: float = 0.0): # 进入该格子的即时奖励
self.x = x
self.y = y
self.grid_type = grid_type
self.enter_reward = enter_reward
self.name = "X{0}-Y{1}".format(self.x, self.y)
def __str__(self):
return "Grid: {name:{3}, x:{0}, y:{1}, grid_type:{2}}".format(self.x, self.y, self.grid_type, self.name)
class GridMatrix(object):
def __init__(
self,
n_width: int, # 水平方向格子数
n_height: int, # 竖直方向格子数
default_type: int = 0, # 默认类型,0-空
default_reward: float = 0.0, # 默认即时奖励值
):
self.n_height = n_height
self.n_width = n_width
self.default_reward = default_reward
self.default_type = default_type
self.grids = None # list(Grid) 将二维的格子世界中的格子存储在一维的列表中
self.len = n_width * n_height # 格子数
self.reset()
def reset(self):
self.grids = []
for x in range(self.n_height):
for y in range(self.n_width):
self.grids.append(Grid(x, y, self.default_type, self.default_reward))
def get_grid(self, x, y=None):
"""
获取一个格子信息
args: 坐标信息,由x,y表示或仅有一个类型为tuple的x表示
return: grid object
"""
xx, yy = None, None
if isinstance(x, int):
xx, yy = x, y
elif isinstance(x, tuple):
xx, yy = x[0], x[1]
assert (0 <= xx < self.n_width and 0 <= yy < self.n_height) # 任意坐标值应在合理区间
index = yy * self.n_width + xx # 二维坐标展开为一维线性坐标
return self.grids[index]
def set_reward(self, x, y, reward):
grid = self.get_grid(x, y)
if grid is not None:
grid.enter_reward = reward
else:
raise ("grid doesn't exist")
def set_type(self, x, y, grid_type):
grid = self.get_grid(x, y)
if grid is not None:
grid.grid_type = grid_type
else:
raise ("grid doesn't exist")
def get_reward(self, x, y):
grid = self.get_grid(x, y)
if grid is None:
return None
return grid.enter_reward
def get_type(self, x, y):
grid = self.get_grid(x, y)
if grid is None:
return None
return grid.grid_type
class GridWorldEnv(gym.Env):
metadata = {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 30}
def __init__(
self,
n_width: int = 5, # 格子世界宽度(以格子数计)
n_height: int = 5, # 高度
u_size=40, # 当前格子绘制尺寸
default_reward: float = 0,
default_type=0):
self.n_width = n_width
self.n_height = n_height
self.default_reward = default_reward
self.default_type = default_type
self.u_size = u_size
self.screen_width = u_size * n_width # 场景宽度
self.screen_height = u_size * n_height # 场景长度
self.grids = GridMatrix(n_width=self.n_width,
n_height=self.n_height,
default_reward=self.default_reward,
default_type=self.default_type)
self.reward = 0 # for rendering
self.action = None # for rendering
# 0,1,2,3 represent left, right, up, down
self.action_space = spaces.Discrete(4)
# 观察空间由low和high决定
self.observation_space = spaces.Discrete(self.n_height * self.n_width)
self.state = None # 格子世界的当前状态
self.ends = [(0, 0), (4, 3)] # 终止格子坐标,可以有多个
self.start = (0, 4) # 起始格子坐标,只有一个
self.types = [(2, 2, 1)]
self.rewards = [(0, 0, 1), (4, 3, 5), (2, 2, -10)]
self.refresh_setting()
self.viewer = None # 图形接口对象
self.seed() # 产生一个随机子
self.reset()