错误:
Traceback (most recent call last):
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\__init__.py", line 511, in _get_domain
domain = domain_map[key]
KeyError: (('v2f', 'c3B'), 7, False, 4)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:/SoftWare/Project/Python/robot_arm/env/env.py", line 148, in <module>
env.render()
File "D:/SoftWare/Project/Python/robot_arm/env/env.py", line 53, in render
self.viewer = Viewer(self.arm_info, self.goal)
File "D:/SoftWare/Project/Python/robot_arm/env/env.py", line 85, in __init__
('c3B', (86, 109, 249)*4)) # color
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\__init__.py", line 425, in add
domain = self._get_domain(False, mode, group, formats)
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\__init__.py", line 514, in _get_domain
domain = vertexdomain.create_domain(shader_program, *formats, indexed=indexed)
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\vertexdomain.py", line 131, in create_domain
attribute_usages = [create_attribute_usage(shader_program, f) for f in attribute_usage_formats]
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\vertexdomain.py", line 131, in <listcomp>
attribute_usages = [create_attribute_usage(shader_program, f) for f in attribute_usage_formats]
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\vertexdomain.py", line 113, in create_attribute_usage
attribute = vertexattribute.create_attribute(shader_program, attribute_format)
File "D:\SoftWare\AI\Python3.7\lib\site-packages\pyglet\graphics\vertexattribute.py", line 225, in create_attribute
assert attribute_meta, f"No '{name}' attribute found in {shader_program}.\n"\
AssertionError: No 'v' attribute found in ShaderProgram(id=4).
Valid attibutes are: {'colors': Attribute('colors', program=4, location=1, count=4, format=f), 'position': Attribute('position', program=4, location=0, count=3, format=f), 'tex_coords': Attribute('tex_coords', program=4, location=2, count=3, format=f)}
源代码为下
import pyglet
import numpy as np
class ArmEnv(object):
viewer = None
dt = 0.1 # 转动的速度和 dt 有关
action_bound = [-1, 1] # 转动的角度范围
goal = {'x': 100., 'y': 100., 'l': 40} # 蓝色 goal 的 x,y 坐标和长度 l
state_dim = 2 # 两个观测值 两个角度
action_dim = 2 # 两个动作 两个关节
def __init__(self):
self.arm_info = np.zeros(
2, dtype=[('l', np.float32), ('r', np.float32)])
# 生成出 (2,2) 的矩阵
self.arm_info['l'] = 100 # 两段手臂都 100 长
self.arm_info['r'] = np.pi/6 # 两段手臂的端点角度
def step(self, action):
done = False
r = 0.
# 计算单位时间 dt 内旋转的角度, 将角度限制在360度以内
action = np.clip(action, *self.action_bound)
self.arm_info['r'] += action * self.dt
self.arm_info['r'] %= np.pi * 2 # normalize
# 我们可以将两截手臂的角度信息当做一个 state (之后会变)
s = self.arm_info['r']
# 如果手指接触到蓝色的 goal, 我们判定结束回合 (done)
# 所以需要计算 finger 的坐标
(a1l, a2l) = self.arm_info['l'] # radius, arm length
(a1r, a2r) = self.arm_info['r'] # radian, angle
a1xy = np.array([200., 200.]) # a1 start (x0, y0)
a1xy_ = np.array([np.cos(a1r), np.sin(a1r)]) * a1l + a1xy # a1 end and a2 start (x1, y1)
finger = np.array([np.cos(a1r + a2r), np.sin(a1r + a2r)]) * a2l + a1xy_ # a2 end (x2, y2)
# 根据 finger 和 goal 的坐标得出 done and reward
if self.goal['x'] - self.goal['l'] / 2 < finger[0] < self.goal['x'] + self.goal['l'] / 2:
if self.goal['y'] - self.goal['l'] / 2 < finger[1] < self.goal['y'] + self.goal['l'] / 2:
done = True
r = 1. # finger 在 goal 以内
return s, r, done
def reset(self):
# reset转角信息
self.arm_info['r'] = 2 * np.pi * np.random.rand(2)
return self.arm_info['r']
def render(self):
if self.viewer is None:
self.viewer = Viewer(self.arm_info, self.goal)
self.viewer.render()
def sample_action(self):
return np.random.rand(2)-0.5 # two radians
class Viewer(pyglet.window.Window):
bar_thc = 5 # 手臂的厚度
def __init__(self, arm_info, goal):
# 创建窗口的继承
# vsync 如果是 True, 按屏幕频率刷新, 反之不按那个频率
super(Viewer, self).__init__(width=400, height=400, resizable=False, caption='Arm', vsync=False)
# 窗口背景颜色
pyglet.gl.glClearColor(1, 1, 1, 1)
# 添加 arm 信息
self.arm_info = arm_info
# 添加窗口中心点, 手臂的根
self.center_coord = np.array([200, 200])
# 将手臂的作图信息放入这个 batch
self.batch = pyglet.graphics.Batch() # display whole batch at once
# 蓝色 goal 的信息包括他的 x, y 坐标, goal 的长度 l
self.point = self.batch.add(
4, pyglet.gl.GL_QUADS, None, # 4 corners
('v2f', [goal['x'] - goal['l'] / 2, goal['y'] - goal['l'] / 2,
goal['x'] - goal['l'] / 2, goal['y'] + goal['l'] / 2,
goal['x'] + goal['l'] / 2, goal['y'] + goal['l'] / 2,
goal['x'] + goal['l'] / 2, goal['y'] - goal['l'] / 2]),
('c3B', (86, 109, 249)*4)) # color
# 添加一条手臂
self.arm1 = self.batch.add(
4, pyglet.gl.GL_QUADS, None,
('v2f', [250, 250, # 同上, 点信息
250, 300,
260, 300,
260, 250]),
('c3B', (249, 86, 86) * 4,)) # color
# 按理添加第二条手臂...
self.arm2 = self.batch.add(
4, pyglet.gl.GL_QUADS, None,
('v2f', [100, 250, # 同上, 点信息
100, 160,
200, 160,
200, 150]),
('c3B', (249, 86, 86) * 4,)) # color
def render(self):
self._update_arm() # 更新手臂内容 (暂时没有变化)
self.switch_to()
self.dispatch_events()
self.dispatch_event('on_draw')
self.flip()
def on_draw(self):
self.clear() # 清屏
self.batch.draw() # 画上 batch 里面的内容
def _update_arm(self):
# 更新手臂的位置信息
(a1l, a2l) = self.arm_info['l'] # radius, arm length
(a1r, a2r) = self.arm_info['r'] # radian, angle
a1xy = self.center_coord # a1 start (x0, y0)
a1xy_ = np.array([np.cos(a1r), np.sin(a1r)]) * a1l + a1xy # a1 end and a2 start (x1, y1)
a2xy_ = np.array([np.cos(a1r + a2r), np.sin(a1r + a2r)]) * a2l + a1xy_ # a2 end (x2, y2)
# 第一段手臂的4个点信息
a1tr, a2tr = np.pi / 2 - self.arm_info['r'][0], np.pi / 2 - self.arm_info['r'].sum()
xy01 = a1xy + np.array([-np.cos(a1tr), np.sin(a1tr)]) * self.bar_thc
xy02 = a1xy + np.array([np.cos(a1tr), -np.sin(a1tr)]) * self.bar_thc
xy11 = a1xy_ + np.array([np.cos(a1tr), -np.sin(a1tr)]) * self.bar_thc
xy12 = a1xy_ + np.array([-np.cos(a1tr), np.sin(a1tr)]) * self.bar_thc
# 第二段手臂的4个点信息
xy11_ = a1xy_ + np.array([np.cos(a2tr), -np.sin(a2tr)]) * self.bar_thc
xy12_ = a1xy_ + np.array([-np.cos(a2tr), np.sin(a2tr)]) * self.bar_thc
xy21 = a2xy_ + np.array([-np.cos(a2tr), np.sin(a2tr)]) * self.bar_thc
xy22 = a2xy_ + np.array([np.cos(a2tr), -np.sin(a2tr)]) * self.bar_thc
# 将点信息都放入手臂显示中
self.arm1.vertices = np.concatenate((xy01, xy02, xy11, xy12))
self.arm2.vertices = np.concatenate((xy11_, xy12_, xy21, xy22))
if __name__ == "__main__":
env = ArmEnv()
while True:
s = env.reset()
for i in range(40):
env.render()
env.step(env.sample_action())