Compare commits

...
24 Commits
Author SHA1 Message Date
dodox c6abf8e98d Made path_decay configurable 2023-03-12 18:47:50 +01:00
dodox 6095ca6fec Ignore this commit, ugly hack for rlProject 2023-01-19 12:42:59 +01:00
dodox db6cdeed21 Still had issues with _rand 2023-01-06 17:27:08 +01:00
dodox e0f4aa3c13 Randomization not working reliably for floats 2023-01-06 17:23:58 +01:00
dodox d8e7c4c80f Follow gym 0.25 spec 2022-12-13 20:13:53 +01:00
dodox 048ba027f3 Fixed clipping of entities on edge 2022-12-13 20:13:39 +01:00
dodox 35864d4b38 Fix: StateObservable sometimes having wrong low-bound 2022-12-13 19:50:57 +01:00
dodox f421c92f83 Observation spaces now define dtype to be float64 2022-12-13 19:45:13 +01:00
dodox 164c72504c Pong 2022-12-09 17:05:27 +01:00
dodox 3bb3ffa3a0 More configurability 2022-12-09 17:05:06 +01:00
dodox 5afa8b22b2 Better path visualizations; more agent & path configs 2022-12-09 11:20:15 +01:00
dodox 78ac536bb9 Fixed RayObservable Collisions PreFilter for Rect 2022-12-08 20:27:36 +01:00
dodox 2032d2e91d Register to Gym as Columbus-v1 2022-12-08 19:53:32 +01:00
dodox 292b12c5a1 Config-configurable width / height and minimal docs 2022-12-06 19:11:12 +01:00
dodox ede0f80cea New Unit: au (=36px) 2022-12-06 12:52:32 +01:00
dodox 1bf587c4da Allow units for 'start_pos' (initial agent position) 2022-12-06 12:25:20 +01:00
dodox 6d465c69c9 Minor cleanup and reorganized some class definitions 2022-12-06 12:16:42 +01:00
dodox 8132bb9321 Force Units in px to be integers (rounding down) 2022-12-06 12:09:19 +01:00
dodox bde7869f97 Implemented Units, Updated README, Example file for Units 2022-12-06 12:00:45 +01:00
dodox 7302d59727 Extended README, added Columbus.pdf 2022-11-25 11:28:19 +01:00
dodox f02163d88c MIT License 2022-11-13 20:07:00 +01:00
dodox 06bfcfe065 Adding the envs from my thesis 2022-11-13 20:00:15 +01:00
dodox d8856e7dc9 Added predefined color mappers (based on tanh and atan) 2022-11-05 17:39:13 +01:00
dodox 4fede26967 Confidence-Ellipse: Back to showing 1sigma 2022-11-01 16:25:47 +01:00
14 changed files with 868 additions and 125 deletions
BIN
View File
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Dominik Roth
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+9 -1
View File
@@ -14,6 +14,12 @@ Project Columbus is a framework for trivial 2D OpenAI Gym environments that are
pip install -e . pip install -e .
``` ```
## Overview
Columbus.pdf contains a overview of columbus.
## Layout of the Repo
### env.py ### env.py
![Screenshot](./img_README.png) ![Screenshot](./img_README.png)
@@ -21,7 +27,9 @@ Contains the ColumbusEnv.
There exist two ways to implement new envs: There exist two ways to implement new envs:
- Subclassing ColumbusEnv and expanding _init_ and overriding _setup_. - Subclassing ColumbusEnv and expanding _init_ and overriding _setup_.
- Using the ColumbusConfigDefined with a desired configuration. This makes configuring ColumbusEnvs via ClusterWorks2-configs possible. (See ColumbusConfigDefinedExample.yaml for an example of how the parameters are supposed to look like (uses yaml format), I don't have time to write a better documentation right now...) (To test this run 'python humanPlayer.py', select 5, give path to ColumbusConfigDefinedExample.yaml, select 0) - Using the ColumbusConfigDefined with a desired configuration. This makes configuring ColumbusEnvs via ClusterWorks2-configs possible. (See configs/example.yaml for an example of how the parameters are supposed to look like (uses yaml format)
- We now support using units (px, em, ct) in config files, examples can be found in configs/Example_Units.yaml
- The environments used in my thesis can also be found in configs/
##### Some caveats / infos ##### Some caveats / infos
+178 -6
View File
@@ -19,6 +19,7 @@ class Entity(object):
self.col = (255, 255, 255) self.col = (255, 255, 255)
self.solid = False self.solid = False
self.movable = False # False = Non movable, True = Movable, x>1: lighter movable self.movable = False # False = Non movable, True = Movable, x>1: lighter movable
self.void_collidable = False
self.elasticity = 1 self.elasticity = 1
self.collision_changes_speed = self.env.controll_type == 'ACC' self.collision_changes_speed = self.env.controll_type == 'ACC'
self.collision_elasticity = self.env.default_collision_elasticity self.collision_elasticity = self.env.default_collision_elasticity
@@ -28,6 +29,11 @@ class Entity(object):
self.draw_path = False self.draw_path = False
self.draw_path_col = [int(c/5) for c in self.col] self.draw_path_col = [int(c/5) for c in self.col]
self.draw_path_width = 2 self.draw_path_width = 2
self.draw_path_harm = False
self.draw_path_harm_col = [c for c in self.draw_path_col]
self.draw_path_harm_col[0] += int(255/3)
self.min_speed = 0
self.max_speed = math.inf
def __post_init__(self): def __post_init__(self):
pass pass
@@ -37,8 +43,13 @@ class Entity(object):
vx, vy = self.speed vx, vy = self.speed
ax, ay = self.acc ax, ay = self.acc
vx, vy = vx+ax*self.env.acc_fac, vy+ay*self.env.acc_fac vx, vy = vx+ax*self.env.acc_fac, vy+ay*self.env.acc_fac
speeds = math.sqrt(vx**2 + vy**2)
if speeds < self.min_speed:
vx, vy = vx/speeds*self.min_speed, vy/speeds*self.min_speed
if speeds > self.max_speed:
vx, vy = vx/speeds*self.max_speed, vy/speeds*self.max_speed
x, y = x+vx*self.env.speed_fac, y+vy*self.env.speed_fac x, y = x+vx*self.env.speed_fac, y+vy*self.env.speed_fac
if not self.env.torus_topology: if not self.env.torus_topology and self.void_collidable:
if x > 1 or x < 0: if x > 1 or x < 0:
x, y, vx, vy = self.calc_void_collision(x < 0, x, y, vx, vy) x, y, vx, vy = self.calc_void_collision(x < 0, x, y, vx, vy)
if y > 1 or y < 0: if y > 1 or y < 0:
@@ -63,8 +74,14 @@ class Entity(object):
def _draw_path(self): def _draw_path(self):
if self.draw_path and self.last_pos: if self.draw_path and self.last_pos:
pygame.draw.line(self.env.path_overlay, self.draw_path_col, col = self.draw_path_col
if self.draw_path_harm:
if self.env.gotHarm:
col = self.draw_path_harm_col
pygame.draw.line(self.env.path_overlay, col,
(self.last_pos[0]*self.env.width, self.last_pos[1]*self.env.height), (self.pos[0]*self.env.width, self.pos[1]*self.env.height), self.draw_path_width) (self.last_pos[0]*self.env.width, self.last_pos[1]*self.env.height), (self.pos[0]*self.env.width, self.pos[1]*self.env.height), self.draw_path_width)
pygame.draw.circle(self.env.path_overlay, col,
(self.pos[0]*self.env.width, self.pos[1]*self.env.height), max(0, self.draw_path_width/2-3))
self.last_pos = self.pos[0], self.pos[1] self.last_pos = self.pos[0], self.pos[1]
def on_collision(self, other, depth): def on_collision(self, other, depth):
@@ -83,9 +100,16 @@ class Entity(object):
return return
force_dir = force_dir[0]/force_dir_len, force_dir[1]/force_dir_len force_dir = force_dir[0]/force_dir_len, force_dir[1]/force_dir_len
if not self.env.torus_topology: if not self.env.torus_topology:
if self.env.agent.pos[0] > 0.99 or self.env.agent.pos[0] < 0.01: if self == self.env.agent:
agent = self
elif other == self.env.agent:
agent = other
else:
agent = None
if agent:
if agent.pos[0] > 0.99 or agent.pos[0] < 0.01:
force_dir = force_dir[0], force_dir[1] * 2 force_dir = force_dir[0], force_dir[1] * 2
if self.env.agent.pos[1] > 0.99 or self.env.agent.pos[1] < 0.01: if agent.pos[1] > 0.99 or agent.pos[1] < 0.01:
force_dir = force_dir[0] * 2, force_dir[1] force_dir = force_dir[0] * 2, force_dir[1]
depth *= 1.0*self.movable/(self.movable + other.movable)/2 depth *= 1.0*self.movable/(self.movable + other.movable)/2
depth /= other.elasticity depth /= other.elasticity
@@ -130,6 +154,24 @@ class Entity(object):
def kill(self): def kill(self):
self.env.kill_entity(self) self.env.kill_entity(self)
def getQuasiRadius(self):
raise Exception()
def getTop(self):
raise Exception()
def getBottom(self):
raise Exception()
def getLeft(self):
raise Exception()
def getRight(self):
raise Exception()
def getCenter(self):
raise Exception()
class CircularEntity(Entity): class CircularEntity(Entity):
def __init__(self, env): def __init__(self, env):
@@ -199,6 +241,24 @@ class CircularEntity(Entity):
raise Exception( raise Exception(
'[!] Shape "circle" does not know how to collide with shape "'+str(other.shape)+'"') '[!] Shape "circle" does not know how to collide with shape "'+str(other.shape)+'"')
def getQuasiRadius(self):
return self.radius
def getTop(self):
return self.pos[1]*self.env.height - self.radius
def getBottom(self):
return self.pos[1]*self.env.height + self.radius
def getLeft(self):
return self.pos[0]*self.env.width - self.radius
def getRight(self):
return self.pos[0]*self.env.width + self.radius
def getCenter(self):
return self.pos[0]*self.env.width, self.pos[1]*self.env.height
class RectangularEntity(Entity): class RectangularEntity(Entity):
def __init__(self, env): def __init__(self, env):
@@ -219,6 +279,58 @@ class RectangularEntity(Entity):
raise Exception( raise Exception(
'[!] Collisions in this direction not implemented for shape "rectangle"') '[!] Collisions in this direction not implemented for shape "rectangle"')
def physics_step(self):
x, y = self.pos
vx, vy = self.speed
ax, ay = self.acc
vx, vy = vx+ax*self.env.acc_fac, vy+ay*self.env.acc_fac
speeds = math.sqrt(vx**2 + vy**2)
if speeds < self.min_speed:
vx, vy = vx/speeds*self.min_speed, vy/speeds*self.min_speed
if speeds > self.max_speed:
vx, vy = vx/speeds*self.max_speed, vy/speeds*self.max_speed
x, y = x+vx*self.env.speed_fac, y+vy*self.env.speed_fac
if not self.env.torus_topology and self.void_collidable:
if x+(self.width/self.env.width) > 1 or x < 0:
if x < 0:
x, y, vx, vy = self.calc_void_collision(
x < 0, x, y, vx, vy)
else:
x, y, vx, vy = self.calc_void_collision(
x < 0, x+(self.width/self.env.width), y, vx, vy)
x -= (self.width/self.env.width)
if y+(self.height/self.env.height) > 1 or y < 0:
if y < 0:
x, y, vx, vy = self.calc_void_collision(
2 + (x < 0), x, y, vx, vy)
else:
x, y, vx, vy = self.calc_void_collision(
2 + (x < 0), x, y+(self.height/self.env.height), vx, vy)
y -= (self.height/self.env.height)
else:
x = x % 1
y = y % 1
self.speed = vx/(1+self.drag), vy/(1+self.drag)
self.pos = x, y
def getQuasiRadius(self):
return self.width + self.height
def getTop(self):
return self.pos[1]*self.env.height
def getBottom(self):
return self.pos[1]*self.env.height + self.height
def getLeft(self):
return self.pos[0]*self.env.width
def getRight(self):
return self.pos[0]*self.env.width*self.env.height + self.width
def getCenter(self):
return self.pos[0]*self.env.width+self.width/2, self.pos[1]*self.env.height+self.height/2
class Agent(CircularEntity): class Agent(CircularEntity):
def __init__(self, env): def __init__(self, env):
@@ -229,6 +341,31 @@ class Agent(CircularEntity):
self.controll_type = self.env.controll_type self.controll_type = self.env.controll_type
self.solid = True self.solid = True
self.movable = True self.movable = True
self.void_collidable = True
def controll_step(self):
self._read_input()
self.env.check_collisions_for(self)
def _read_input(self):
if self.controll_type == 'SPEED':
self.speed = self.env.inp[0] - 0.5, self.env.inp[1] - 0.5
elif self.controll_type == 'ACC':
self.acc = self.env.inp[0] - 0.5, self.env.inp[1] - 0.5
else:
raise Exception('Unsupported controll_type')
# Does not work! Don't use!
class PongAgent(RectangularEntity):
def __init__(self, env):
super(PongAgent, self).__init__(env)
self.pos = (0.5, 0.5)
self.col = (0, 0, 255)
self.drag = self.env.agent_drag
self.controll_type = self.env.controll_type
self.solid = True
self.movable = True
def controll_step(self): def controll_step(self):
self._read_input() self._read_input()
@@ -236,9 +373,9 @@ class Agent(CircularEntity):
def _read_input(self): def _read_input(self):
if self.controll_type == 'SPEED': if self.controll_type == 'SPEED':
self.speed = self.env.inp[0] - 0.5, self.env.inp[1] - 0.5 self.speed = 0, self.env.inp[1] - 0.5
elif self.controll_type == 'ACC': elif self.controll_type == 'ACC':
self.acc = self.env.inp[0] - 0.5, self.env.inp[1] - 0.5 self.acc = 0, self.env.inp[1] - 0.5
else: else:
raise Exception('Unsupported controll_type') raise Exception('Unsupported controll_type')
@@ -340,6 +477,33 @@ class Collectable(CircularEntity):
self.env.check_collisions_for(self) self.env.check_collisions_for(self)
class RectCollectable(RectangularEntity):
def __init__(self, env):
super(RectCollectable, self).__init__(env)
self.avaible = True
self.enforce_not_on_barrier = False
self.reward = 10
self.collectors = []
def on_collision(self, other, depth):
super().on_collision(other, depth)
if isinstance(other, Barrier):
self.on_barrier_collision()
else:
for Col in self.collectors:
if isinstance(other, Col):
other.on_collect(self)
self.on_collected()
def on_collected(self):
self.env.new_reward += self.reward
def on_barrier_collision(self):
if self.enforce_not_on_barrier:
self.pos = (self.env.random(), self.env.random())
self.env.check_collisions_for(self)
class Reward(Collectable): class Reward(Collectable):
def __init__(self, env): def __init__(self, env):
super(Reward, self).__init__(env) super(Reward, self).__init__(env)
@@ -470,6 +634,14 @@ class Goal(Collectable):
self.collectors = [Ball] self.collectors = [Ball]
class RectGoal(RectCollectable):
def __init__(self, env):
super(RectGoal, self).__init__(env)
self.col = (0, 200, 0)
self.reward = 500
self.collectors = [Ball]
class TeleportingGoal(Goal): class TeleportingGoal(Goal):
def __init__(self, env): def __init__(self, env):
super(TeleportingGoal, self).__init__(env) super(TeleportingGoal, self).__init__(env)
+197 -104
View File
@@ -6,46 +6,17 @@ import pygame
import random as random_dont_use import random as random_dont_use
from os import urandom from os import urandom
import math import math
from columbus import entities, observables
import torch as th import torch as th
from columbus import entities, observables
def parseObs(obsConf): from columbus.utils import soft_int, parseObs
if type(obsConf) == list:
obs = []
for i, c in enumerate(obsConf):
obs.append(parseObs(c))
if len(obs) == 1:
return obs[0]
else:
return observables.CompositionalObservable(obs)
if obsConf['type'] == 'State':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.StateObservable(**conf)
elif obsConf['type'] == 'Compass':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.CompassObservable(**conf)
elif obsConf['type'] == 'RayCast':
chans = []
for chan in obsConf.get('chans', []):
chans.append(getattr(entities, chan))
conf = {k: v for k, v in obsConf.items() if k not in ['type', 'chans']}
return observables.RayObservable(chans=chans, **conf)
elif obsConf['type'] == 'CNN':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.CnnObservable(**conf)
elif obsConf['type'] == 'Dummy':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.Observable(**conf)
else:
raise Exception('Unknown Observable selected')
class ColumbusEnv(gym.Env): class ColumbusEnv(gym.Env):
metadata = {'render.modes': ['human']} metadata = {'render.modes': ['human'], 'render_modes': [
'human', 'non-human'], 'render_fps': 60}
def __init__(self, observable=observables.Observable(), fps=60, env_seed=3.1, master_seed=None, start_pos=(0.5, 0.5), start_score=0, speed_fac=0.01, acc_fac=0.04, die_on_zero=False, return_on_score=-1, reward_mult=1, agent_drag=0, controll_type='SPEED', aux_reward_max=1, aux_penalty_max=0, aux_reward_discretize=0, void_is_type_barrier=True, void_damage=1, torus_topology=False, default_collision_elasticity=1, terminate_on_reward=False, agent_draw_path=False, clear_path_on_reset=True, max_steps=-1, value_color_mapper=None): def __init__(self, observable=observables.Observable(), fps=60, env_seed=3.1, master_seed=None, start_pos=(0.5, 0.5), start_score=0, speed_fac=0.01, acc_fac=0.04, die_on_zero=False, return_on_score=-1, reward_mult=1, agent_drag=0, controll_type='SPEED', aux_reward_max=1, aux_penalty_max=0, aux_reward_discretize=0, void_is_type_barrier=True, void_damage=1, torus_topology=False, default_collision_elasticity=1, terminate_on_reward=False, agent_draw_path=False, clear_path_on_reset=True, max_steps=-1, value_color_mapper='tanh', width=720, height=720, agent_attrs={}, agent_cls=entities.Agent, exception_for_unsupported_collision=True, path_decay=0.1):
super(ColumbusEnv, self).__init__() super(ColumbusEnv, self).__init__()
self.action_space = spaces.Box( self.action_space = spaces.Box(
low=-1, high=1, shape=(2,), dtype=np.float32) low=-1, high=1, shape=(2,), dtype=np.float32)
@@ -53,14 +24,14 @@ class ColumbusEnv(gym.Env):
observable = parseObs(observable) observable = parseObs(observable)
observable._set_env(self) observable._set_env(self)
self.observable = observable self.observable = observable
self.title = 'Untitled' self.title = 'Columbus Env'
self.fps = fps self.fps = fps
self.env_seed = env_seed self.env_seed = env_seed
self.joystick_offset = (10, 10) self.joystick_offset = (10, 10)
self.surface = None self.surface = None
self.screen = None self.screen = None
self.width = 720 self.width = width
self.height = 720 self.height = height
self.visible = False self.visible = False
self.start_pos = start_pos self.start_pos = start_pos
self.speed_fac = speed_fac/fps*60 self.speed_fac = speed_fac/fps*60
@@ -91,6 +62,19 @@ class ColumbusEnv(gym.Env):
self.terminate_on_reward = terminate_on_reward self.terminate_on_reward = terminate_on_reward
self.agent_draw_path = agent_draw_path self.agent_draw_path = agent_draw_path
self.clear_path_on_reset = clear_path_on_reset self.clear_path_on_reset = clear_path_on_reset
self.path_decay = path_decay
if isinstance(agent_cls, str):
agent_cls = getattr(entities, agent_cls)
self.Agent_cls = agent_cls
self.agent_attrs = agent_attrs
self.exception_for_unsupported_collision = exception_for_unsupported_collision
if value_color_mapper == 'atan':
def value_color_mapper(x): return th.atan(x*2)/0.786/2
elif value_color_mapper == 'tanh':
def value_color_mapper(x): return th.tanh(x*2)/0.762/2
self.value_color_mapper = value_color_mapper self.value_color_mapper = value_color_mapper
self.max_steps = max_steps self.max_steps = max_steps
@@ -111,6 +95,8 @@ class ColumbusEnv(gym.Env):
self._init = False self._init = False
self.is_columbus_env = True
@property @property
def observation_space(self): def observation_space(self):
if not self._init: if not self._init:
@@ -235,11 +221,12 @@ class ColumbusEnv(gym.Env):
self._step_entities() self._step_entities()
observation = self.observable.get_observation() observation = self.observable.get_observation()
gotRew = self.new_reward > 0 or self.new_abs_reward > 0 gotRew = self.new_reward > 0 or self.new_abs_reward > 0
self.gotHarm = self.new_reward < 0 or self.new_abs_reward < 0
reward, self.new_reward, self.new_abs_reward = self.new_reward / \ reward, self.new_reward, self.new_abs_reward = self.new_reward / \
self.fps + self.new_abs_reward, 0, 0 self.fps + self.new_abs_reward, 0, 0
if not self.torus_topology: if not self.torus_topology:
if self.agent.pos[0] < 0.001 or self.agent.pos[0] > 0.999 \ if self.agent.getTop() < 1 or self.agent.getBottom() > self.height-1 \
or self.agent.pos[1] < 0.001 or self.agent.pos[1] > 0.999: or self.agent.getLeft() < 1 or self.agent.getRight() > self.width-1:
reward -= self.void_damage/self.fps reward -= self.void_damage/self.fps
self.score += reward # aux_reward does not count towards the score self.score += reward # aux_reward does not count towards the score
if self.aux_reward_max or self.aux_penalty_max: if self.aux_reward_max or self.aux_penalty_max:
@@ -273,8 +260,10 @@ class ColumbusEnv(gym.Env):
elif shapes == ['circle', 'rect']: elif shapes == ['circle', 'rect']:
return sum([abs(d) for d in e1._get_crash_force_dir(e2)]) return sum([abs(d) for d in e1._get_crash_force_dir(e2)])
else: else:
if self.exception_for_unsupported_collision:
raise Exception( raise Exception(
'Checking for collision between unsupported shapes: '+str(shapes)) 'Checking for collision between unsupported shapes: '+str(shapes))
return 0.0
def kill_entity(self, target): def kill_entity(self, target):
newEntities = [] newEntities = []
@@ -290,6 +279,12 @@ class ColumbusEnv(gym.Env):
self.agent.pos = self.start_pos self.agent.pos = self.start_pos
# Expand this function # Expand this function
def _spawnAgent(self):
self.agent = self.Agent_cls(self)
self.agent.draw_path = self.agent_draw_path
for k, v in self.agent_attrs.items():
setattr(self.agent, k, v)
def reset(self, force_reset_path=False): def reset(self, force_reset_path=False):
pygame.init() pygame.init()
self._init = True self._init = True
@@ -302,11 +297,11 @@ class ColumbusEnv(gym.Env):
# will get rescaled acording to fps (=reward per second) # will get rescaled acording to fps (=reward per second)
self.new_reward = 0 self.new_reward = 0
self.new_abs_reward = 0 # will not get rescaled. should be used for one-time rewards self.new_abs_reward = 0 # will not get rescaled. should be used for one-time rewards
self.gotHarm = False
self.score = self.start_score self.score = self.start_score
self.entities = [] self.entities = []
self.timers = [] self.timers = []
self.agent = entities.Agent(self) self._spawnAgent()
self.agent.draw_path = self.agent_draw_path
self.setup() self.setup()
self.entities.append(self.agent) # add it last, will be drawn on top self.entities.append(self.agent) # add it last, will be drawn on top
self.observable.reset() self.observable.reset()
@@ -344,10 +339,9 @@ class ColumbusEnv(gym.Env):
V = value_func(th.Tensor(np.array(obs))) V = value_func(th.Tensor(np.array(obs)))
V /= max(V.max(), -1*V.min())*2 V /= max(V.max(), -1*V.min())*2
V += 0.5
if color_mapper != None: if color_mapper != None:
V = color_mapper(V) V = color_mapper(V)
V += 0.5
c = 0 c = 0
for i in range(resolution): for i in range(resolution):
@@ -381,13 +375,13 @@ class ColumbusEnv(gym.Env):
pygame.draw.circle(self.screen, smolcol, (20+int(60*x) + pygame.draw.circle(self.screen, smolcol, (20+int(60*x) +
self.joystick_offset[0], 20+int(60*y)+self.joystick_offset[1]), 20, width=0) self.joystick_offset[0], 20+int(60*y)+self.joystick_offset[1]), 20, width=0)
def _draw_confidence_ellipse(self, chol, forceDraw=False, seconds=0.5): def _draw_confidence_ellipse(self, chol, forceDraw=False, seconds=0.1):
# The 'seconds'-parameter only really makes sense, when using control_type='SPEED', # The 'seconds'-parameter only really makes sense, when using control_type='SPEED',
# you can still use it to scale the cov-ellipse when using control_type='ACC', # you can still use it to scale the cov-ellipse when using control_type='ACC',
# but it's relation to 'seconds' is no longer there... # but it's relation to 'seconds' is no longer there...
if self.draw_confidence_ellipse and (self.visible or forceDraw): if self.draw_confidence_ellipse and (self.visible or forceDraw):
col = (255, 255, 255) col = (255, 255, 255)
f = seconds*self.speed_fac*self.fps*max(self.width, self.height) f = seconds*self.speed_fac*self.fps*max(self.height, self.width)
while len(chol.shape) > 2: while len(chol.shape) > 2:
chol = chol[0] chol = chol[0]
@@ -399,9 +393,8 @@ class ColumbusEnv(gym.Env):
L, V = th.linalg.eig(cov) L, V = th.linalg.eig(cov)
L, V = L.real, V.real L, V = L.real, V.real
# 5.911 is the magic-number to get a 95%-confidence interval l1, l2 = int(abs(math.sqrt(L[0].item())*f)) + \
l1, l2 = int(abs(math.sqrt(L[0].item()*5.911)*f)) + \ 1, int(abs(math.sqrt(L[1].item())*f))+1
1, int(abs(math.sqrt(L[1].item()*5.911)*f))+1
if l1 >= l2: if l1 >= l2:
w, h = l1, l2 w, h = l1, l2
@@ -424,6 +417,14 @@ class ColumbusEnv(gym.Env):
self.screen.blit(rotated_surf, rotated_surf.get_rect( self.screen.blit(rotated_surf, rotated_surf.get_rect(
center=rect.center)) center=rect.center))
def _draw_paths(self):
if self.path_decay != 0.0:
s = pygame.Surface((self.width, self.height))
s.set_alpha(soft_int(255*self.path_decay/self.fps))
s.fill((0, 0, 0))
self.path_overlay.blit(s, (0, 0))
self.surface.blit(self.path_overlay, (0, 0))
def _handle_user_input(self): def _handle_user_input(self):
for event in pygame.event.get(): for event in pygame.event.get():
pass pass
@@ -468,7 +469,7 @@ class ColumbusEnv(gym.Env):
if value_func != None: if value_func != None:
self._draw_values(value_func, values_static, self._draw_values(value_func, values_static,
color_mapper=self.value_color_mapper) color_mapper=self.value_color_mapper)
self.surface.blit(self.path_overlay, (0, 0)) self._draw_paths()
if self.draw_entities: if self.draw_entities:
self._draw_entities() self._draw_entities()
else: else:
@@ -491,6 +492,123 @@ class ColumbusEnv(gym.Env):
pygame.quit() pygame.quit()
class ColumbusConfigDefined(ColumbusEnv):
# Allows defining Columbus Environments using dicts.
# Intended to be used in combination with cw2 configuration.
# Look into humanPlayer to see how this is supposed to be interfaced with.
def __init__(self, observable={}, env_seed=None, entities=[], fps=30, **kw):
super().__init__(
observable=observable, fps=fps, env_seed=env_seed, **kw)
self.entities_definitions = entities
self.start_pos = self.conv_unit(self.start_pos[0], target='em', axis='x'), self.conv_unit(
self.start_pos[1], target='em', axis='y')
def is_unit(self, s):
if type(s) in [int, float]:
return True
if s.replace('.', '', 1).replace('-', '0', 1).isdigit():
return True
num, unit = s[:-2], s[-2:]
if unit in ['px', 'em', 'rx', 'ry', 'ct', 'au']:
if num.replace('.', '', 1).replace('-', '0', 1).isdigit():
return True
return False
def conv_unit(self, s, target='px', axis='x'):
assert self.is_unit(s)
if type(s) in [int, float]:
return s
if s.replace('.', '', 1).isdigit():
if target == 'px':
return int(s)
return float(s)
num, unit = s[:-2], s[-2:]
num = float(num)
if unit == 'rx':
unit = 'px'
axis = 'x'
elif unit == 'ry':
unit = 'px'
axis = 'y'
if unit == 'em':
em = num
elif unit == 'px':
em = num / ({'x': self.width, 'y': self.height}[axis])
elif unit == 'au':
em = num * 36 / ({'x': self.width, 'y': self.height}[axis])
elif unit == 'ct':
em = num / 100
else:
raise Exception('Conversion not implemented')
if target == 'em':
return em
elif target == 'px':
return int(em * ({'x': self.width, 'y': self.height}[axis]))
def setup(self):
self.agent.pos = self.start_pos
for i, e in enumerate(self.entities_definitions):
Entity = getattr(entities, e['type'])
for i in range(e.get('num', 1) + int(self.random()*(0.99+e.get('num_rand', 0)))):
entity = Entity(self)
conf = {k: v for k, v in e.items() if str(
k) not in ['num', 'num_rand', 'type']}
for k, v_raw in conf.items():
if k == 'pos':
v = self.conv_unit(v_raw[0], target='em', axis='x'), self.conv_unit(
v_raw[1], target='em', axis='y')
elif k in ['width', 'height', 'radius']:
v = self.conv_unit(
v_raw, target='px', axis='y' if k == 'height' else 'x')
else:
v = v_raw
if k.endswith('_rand'):
v = self.conv_unit(
v_raw, target='px', axis='y' if k == 'height_rand' else 'x')
if isinstance(v, int):
n = k.replace('_rand', '')
cur = getattr(
entity, n)
inc = int((v+0.99)*self.random())
setattr(entity, n, cur + inc)
elif isinstance(v, float):
n = k.replace('_rand', '')
cur = getattr(
entity, n)
inc = v*self.random()
setattr(entity, n, cur + inc)
elif isinstance(v, list):
for vi, ve in enumerate(v):
if isinstance(v, int):
n = k.replace('_rand', '')
cur = getattr(
entity, n)
cur[vi] = int((v+0.99)*self.random())
setattr(entity, n, cur)
elif isinstance(v, float):
n = k.replace('_rand', '')
cur = getattr(
entity, n)
cur[vi] = v*self.random()
setattr(entity, n, cur)
elif k.endswith('_randf'):
n = k.replace('_randf', '')
cur = getattr(
entity, n)
inc = v*self.random()
setattr(entity, n, cur + inc)
else:
setattr(entity, k, v)
self.entities.append(entity)
###
# Custom Env Definitions
class ColumbusTest3_1(ColumbusEnv): class ColumbusTest3_1(ColumbusEnv):
def __init__(self, observable=observables.CnnObservable(out_width=48, out_height=48), fps=30, aux_reward_max=1, **kw): def __init__(self, observable=observables.CnnObservable(out_width=48, out_height=48), fps=30, aux_reward_max=1, **kw):
super(ColumbusTest3_1, self).__init__( super(ColumbusTest3_1, self).__init__(
@@ -830,40 +948,6 @@ class ColumbusFootball(ColumbusEnv):
self.entities.append(entities.FlyingFootballPlayer(self, ball)) self.entities.append(entities.FlyingFootballPlayer(self, ball))
class ColumbusConfigDefined(ColumbusEnv):
def __init__(self, observable={}, env_seed=None, entities=[], fps=30, **kw):
super().__init__(
observable=observable, fps=fps, env_seed=env_seed, **kw)
self.entities_definitions = entities
def setup(self):
self.agent.pos = self.start_pos
for i, e in enumerate(self.entities_definitions):
Entity = getattr(entities, e['type'])
for i in range(e.get('num', 1) + int(self.random()*(0.99+e.get('num_rand', 0)))):
entity = Entity(self)
conf = {k: v for k, v in e.items() if str(
k) not in ['num', 'num_rand', 'type']}
for k, v in conf.items():
if k.endswith('_rand'):
n = k.replace('_rand', '')
cur = getattr(
entity, n)
inc = int((v+0.99)*self.random())
setattr(entity, n, cur + inc)
elif k.endswith('_randf'):
n = k.replace('_randf', '')
cur = getattr(
entity, n)
inc = v*self.random()
setattr(entity, n, cur + inc)
else:
setattr(entity, k, v)
self.entities.append(entity)
class ColumbusBlub(ColumbusEnv): class ColumbusBlub(ColumbusEnv):
def __init__(self, observable=observables.CompositionalObservable([observables.StateObservable(), observables.RayObservable(num_rays=6, chans=[entities.Enemy])]), env_seed=None, entities=[], fps=30, **kw): def __init__(self, observable=observables.CompositionalObservable([observables.StateObservable(), observables.RayObservable(num_rays=6, chans=[entities.Enemy])]), env_seed=None, entities=[], fps=30, **kw):
super().__init__( super().__init__(
@@ -877,7 +961,22 @@ class ColumbusBlub(ColumbusEnv):
enemy.width, enemy.height = 200, 75 enemy.width, enemy.height = 200, 75
self.entities.append(enemy) self.entities.append(enemy)
### ###
# Registering Envs fro Gym
register( # Legacy
id='ColumbusConfigDefined-v0',
entry_point=ColumbusConfigDefined,
max_episode_steps=30*60*2, # 2 min at default (30) fps
)
register(
id='Columbus-v1',
entry_point=ColumbusConfigDefined
)
###
# register( # register(
# id='ColumbusBlub-v0', # id='ColumbusBlub-v0',
# entry_point=ColumbusBlub, # entry_point=ColumbusBlub,
@@ -885,17 +984,17 @@ class ColumbusBlub(ColumbusEnv):
# ) # )
register( # register(
id='ColumbusTestCnn-v0', # id='ColumbusTestCnn-v0',
entry_point=ColumbusTest3_1, # entry_point=ColumbusTest3_1,
max_episode_steps=30*60*2, # max_episode_steps=30*60*2,
) # )
register( # register(
id='ColumbusTestRay-v0', # id='ColumbusTestRay-v0',
entry_point=ColumbusTestRay, # entry_point=ColumbusTestRay,
max_episode_steps=30*60*2, # max_episode_steps=30*60*2,
) # )
# register( # register(
# id='ColumbusRayDrone-v0', # id='ColumbusRayDrone-v0',
@@ -933,11 +1032,11 @@ register(
# max_episode_steps=30*60*2, # max_episode_steps=30*60*2,
# ) # )
register( # register(
id='ColumbusStateWithBarriers-v0', # id='ColumbusStateWithBarriers-v0',
entry_point=ColumbusStateWithBarriers, # entry_point=ColumbusStateWithBarriers,
max_episode_steps=30*60*2, # max_episode_steps=30*60*2,
) # )
# register( # register(
# id='ColumbusCompassWithBarriers-v0', # id='ColumbusCompassWithBarriers-v0',
@@ -969,12 +1068,6 @@ register(
# max_episode_steps=30*60*2, # max_episode_steps=30*60*2,
# ) # )
register(
id='ColumbusConfigDefined-v0',
entry_point=ColumbusConfigDefined,
max_episode_steps=30*60*2,
)
register( register(
id='ColumbusDemoEnvFootball-v0', id='ColumbusDemoEnvFootball-v0',
entry_point=ColumbusDemoEnvFootball, entry_point=ColumbusDemoEnvFootball,
+2 -1
View File
@@ -71,7 +71,8 @@ def chooseEnv():
def value_func(obs): def value_func(obs):
return th.rand(obs.shape[0])-0.5 return obs[:, 0]
# return th.rand(obs.shape[0])-0.5
def playEnv(env): def playEnv(env):
+16 -9
View File
@@ -16,7 +16,7 @@ class Observable():
def get_observation_space(self): def get_observation_space(self):
print("[!] Using dummyObservable. Env won't output anything") print("[!] Using dummyObservable. Env won't output anything")
return spaces.Box(low=0, high=1, return spaces.Box(low=0, high=1,
shape=(1,), dtype=np.float32) shape=(1,), dtype=np.float64)
def get_observation(self): def get_observation(self):
return np.array([0]) return np.array([0])
@@ -45,7 +45,7 @@ class CnnObservable(Observable):
def get_observation_space(self): def get_observation_space(self):
return spaces.Box(low=0, high=255, return spaces.Box(low=0, high=255,
shape=(self.out_width, self.out_height, 3), dtype=np.float32) shape=(self.out_width, self.out_height, 3), dtype=np.float64)
def get_observation(self): def get_observation(self):
if not self.env._rendered: if not self.env._rendered:
@@ -132,24 +132,31 @@ class RayObservable(Observable):
'Can only raycast circular and rectangular entities!') 'Can only raycast circular and rectangular entities!')
return False return False
# Filter out entities, that we sure are out of range
# (so we have to do less work for the ray collisions)
def _get_possible_entities(self): def _get_possible_entities(self):
entities_l = [] entities_l = []
if entities.Void in self.chans or self.env.void_barrier: if entities.Void in self.chans or self.env.void_barrier:
entities_l.append(entities.Void(self.env)) entities_l.append(entities.Void(self.env))
for entity in self.env.entities: for entity in self.env.entities:
if entity.shape == 'rect': if entity.shape == 'rect':
x, y = entity.pos[0]+entity.width/self.env.width / \
2, entity.pos[1]+entity.height/self.env.height/2
radius = (entity.width/2 + entity.height/2)*1.0 radius = (entity.width/2 + entity.height/2)*1.0
elif entity.shape == 'circle': elif entity.shape == 'circle':
x, y = entity.pos[0], entity.pos[1]
radius = entity.radius radius = entity.radius
else: else:
raise Exception( raise Exception(
'Can only raycast circular and rectangular entities!') 'Can only raycast circular and rectangular entities!')
sq_dist = ((self.env.agent.pos[0]-entity.pos[0])*self.env.width) ** 2 \ sq_dist = ((self.env.agent.pos[0]-x)*self.env.width) ** 2 \
+ ((self.env.agent.pos[1]-entity.pos[1])*self.env.height) ** 2 + ((self.env.agent.pos[1]-y)*self.env.height) ** 2
if sq_dist <= (radius + self.env.agent.radius + self.ray_len)**2: if sq_dist <= (radius + self.env.agent.getQuasiRadius() + self.ray_len)**2:
entities_l.append(entity) # cannot use yield here! entities_l.append(entity) # cannot use yield here!
return entities_l return entities_l
# Ugly, inefficient ray casting
# Oh well, it works...
def get_observation(self): def get_observation(self):
entities = self._get_possible_entities() entities = self._get_possible_entities()
self.rays = np.zeros((self.num_rays+self.include_rand, self.num_chans)) self.rays = np.zeros((self.num_rays+self.include_rand, self.num_chans))
@@ -243,8 +250,8 @@ class StateObservable(Observable):
self.reset() self.reset()
num = len(self.entities)*2+len(self._timeoutEntities) + \ num = len(self.entities)*2+len(self._timeoutEntities) + \
self.speedAgent*2 + self.include_rand self.speedAgent*2 + self.include_rand
return spaces.Box(low=0-1*self.coordsRelativeToAgent, high=1, return spaces.Box(low=0-1*(self.coordsRelativeToAgent or self.speedAgent), high=1,
shape=(num,), dtype=np.float32) shape=(num,), dtype=np.float64)
def get_observation(self): def get_observation(self):
obs = [] obs = []
@@ -324,7 +331,7 @@ class CompassObservable(Observable):
self.reset() self.reset()
num = len(self.entities)*2 num = len(self.entities)*2
return spaces.Box(low=-1, high=1, return spaces.Box(low=-1, high=1,
shape=(num,), dtype=np.float32) shape=(num,), dtype=np.float64)
def reset(self): def reset(self):
self._entities = None self._entities = None
@@ -378,7 +385,7 @@ class CompositionalObservable(Observable):
low = np.hstack((low, space.low.reshape((-1)))) low = np.hstack((low, space.low.reshape((-1))))
high = np.hstack((high, space.high.reshape((-1)))) high = np.hstack((high, space.high.reshape((-1))))
return spaces.Box(low=low, high=high, return spaces.Box(low=low, high=high,
shape=(num,), dtype=np.float32) shape=(num,), dtype=np.float64)
def get_observation(self): def get_observation(self):
o = [obs.get_observation().reshape((-1)) o = [obs.get_observation().reshape((-1))
+42
View File
@@ -0,0 +1,42 @@
from columbus import entities, observables
import random as random_dont_use
def parseObs(obsConf):
# Parsing Observable Definitions
if type(obsConf) == list:
obs = []
for i, c in enumerate(obsConf):
obs.append(parseObs(c))
if len(obs) == 1:
return obs[0]
else:
return observables.CompositionalObservable(obs)
if obsConf['type'] == 'State':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.StateObservable(**conf)
elif obsConf['type'] == 'Compass':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.CompassObservable(**conf)
elif obsConf['type'] == 'RayCast':
chans = []
for chan in obsConf.get('chans', []):
chans.append(getattr(entities, chan))
conf = {k: v for k, v in obsConf.items() if k not in ['type', 'chans']}
return observables.RayObservable(chans=chans, **conf)
elif obsConf['type'] == 'CNN':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.CnnObservable(**conf)
elif obsConf['type'] == 'Dummy':
conf = {k: v for k, v in obsConf.items() if k not in ['type']}
return observables.Observable(**conf)
else:
raise Exception('Unknown Observable selected')
def soft_int(num):
i = int(num)
r = num - i
return i + int(random_dont_use.random() < r)
+78
View File
@@ -0,0 +1,78 @@
name: "DEFAULT"
params:
task:
task: columbus
env_name: ColumbusConfigDefined-v0
env_args:
observable:
- type: State
coordsAgent: True
speedAgent: True
coordsRelativeToAgent: False
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: State
coordsAgent: False
speedAgent: False
coordsRelativeToAgent: True
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: Compass
- type: RayCast
num_rays: 6
chans: [Enemy]
entities:
- type: RectBarrier
damage: 1 #1
width: 300
height: 120 # 360 - 5%(720)
pos: [0, 0]
- type: RectBarrier
damage: 1 #1
width: 300
height: 1000
pos: [0, 0.25]
- type: RectBarrier
damage: 1 #1
width: 250
height: 30
pos: [0.55, 0.6]
- type: RectBarrier
damage: 1 #1
width: 30
height: 120
pos: [0.856, 0.475]
- type: RectBarrier
num: 0
damage: 1 #1
width: 50
width_rand: 100
height: 25
height_rand: 100
- type: OnceReward
reward: 100
radius: 20
pos: [0.9, 0.8]
start_pos: [0.1, 0.21]
default_collision_elasticity: 0.8
start_score: 10
speed_fac: 0.01
acc_fac: 0.1
die_on_zero: False #True
agent_drag: 0.1 # 0.05
controll_type: ACC # SPEED
aux_reward_max: 1
aux_penalty_max: 0.01
void_damage: 5 #1
terminate_on_reward: True
agent_draw_path: True
clear_path_on_reset: False
max_steps: 450 # 1800
---
+54
View File
@@ -0,0 +1,54 @@
name: "DEFAULT"
params:
task:
task: columbus
num_envs: 8
env_args:
observable:
- type: State
coordsAgent: True
speedAgent: True
coordsRelativeToAgent: False
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: State
coordsAgent: False
speedAgent: False
coordsRelativeToAgent: True
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: Compass
- type: RayCast
num_rays: 8
chans: [Enemy]
entities:
- type: CircleBarrier
num: 8
num_rand: 6
damage: 20 #20
radius: 25
radius_rand: 75
- type: TeleportingReward
num: 1
reward: 100 #100
radius: 20
default_collision_elasticity: 0.8
start_score: 50
speed_fac: 0.01
acc_fac: 0.1
die_on_zero: True
agent_drag: 0.07 # 0.05
controll_type: ACC # SPEED
aux_reward_max: 1
aux_penalty_max: 0.1
void_damage: 5 #1
#master_seed: 3.14
max_steps: 900 # 30 sec
---
+67
View File
@@ -0,0 +1,67 @@
name: "DEFAULT"
params:
task:
task: columbus
env_name: ColumbusConfigDefined-v0
env_args:
observable:
- type: State
coordsAgent: True
speedAgent: True
coordsRelativeToAgent: False
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: State
coordsAgent: False
speedAgent: False
coordsRelativeToAgent: True
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: RayCast
num_rays: 6
chans: [Enemy]
entities:
- type: RectBarrier
damage: 10 #1
width: 25
height: 120 # 360 - 5%(720)
pos: [0.45, 0]
- type: RectBarrier
damage: 10 #1
width: 25
height: 1000
pos: [0.45, 0.25]
- type: RectBarrier
damage: 10 #1
width: 25
height: 520 # 360 - 5%(720)
pos: [0.55, 0]
- type: RectBarrier
damage: 10 #1
width: 25
height: 200
pos: [0.55, 0.80]
- type: LoopReward
num: 1
reward: 100 #25
radius: 20
loop: [[0.125, 0.5, 0.1, 0.5], [0.875, 0.5, 0.1, 0.5]]
default_collision_elasticity: 0.8
start_score: 10
speed_fac: 0.01
acc_fac: 0.1
die_on_zero: False #True
agent_drag: 0.1 # 0.05
controll_type: ACC # SPEED
aux_reward_max: 1
aux_penalty_max: 0.01
void_damage: 5 #1
agent_draw_path: True
---
+92
View File
@@ -0,0 +1,92 @@
name: "DEFAULT"
# Supported Units:
# px: Pixels
# em: 1em = Full Width / Height
# ct: 100ct = Full Width / Height
# rx: pixels relative to width
# ry: pixels relative to height
# au: 1au = 36px (https://knowyourmeme.com/memes/absolute-unit)
#
# When no unit is given, we use the folowing defaults
# (compatible with legacy behavior)
# pos: em
# all other: px
#
# ct is the recommendet unit.
# If you need a unit, that is not responsive in regards to width/height, use au / px.
params:
task:
task: columbus
env_name: ColumbusConfigDefined-v0
env_args:
observable:
- type: State
coordsAgent: True
speedAgent: True
coordsRelativeToAgent: False
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: State
coordsAgent: False
speedAgent: False
coordsRelativeToAgent: True
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: Compass
- type: RayCast
num_rays: 6
chans: [Enemy]
entities:
- type: RectBarrier
num: 1
width: 50ct
height: 50ct
pos: [0ct, 0ct]
- type: RectBarrier
num: 1
width: 50ct
height: 50ct
pos: [50ct, 50ct]
- type: RectBarrier
num: 1
width: 25rx
height: 25ry
pos: [0.75em, 30px]
- type: RectBarrier
num: 1
width: 25ry
height: 25rx
pos: [0.75em, 60px]
- type: RectBarrier
num: 1
width: 20 # defaults to rx (px scaled from x-axis)
height: 10 # defaults to ry (px scaled from y-axis)
pos: [0.75em, 90px]
- type: OnceReward
reward: 100
radius: 1au
pos: [0.3, 0.8] # defaults to em
start_pos: [90ct, 20ct]
default_collision_elasticity: 0.8
start_score: 10
speed_fac: 0.01
acc_fac: 0.1
die_on_zero: False #True
agent_drag: 0.1 # 0.05
controll_type: ACC # SPEED
aux_reward_max: 1
aux_penalty_max: 0.01
void_damage: 5 #1
terminate_on_reward: True
agent_draw_path: True
clear_path_on_reset: False
max_steps: 450 # 1800
---
+108
View File
@@ -0,0 +1,108 @@
name: "DEFAULT"
params:
task:
task: columbus
env_name: Columbus-v1
env_args:
observable:
- type: State
coordsAgent: True
speedAgent: True
coordsRelativeToAgent: False
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: State
coordsAgent: False
speedAgent: False
coordsRelativeToAgent: True
coordsRewards: True
coordsEnemys: False
enemysNoBarriers: True
rewardsTimeouts: False
include_rand: True
- type: Compass
- type: RayCast
num_rays: 6
chans: [Enemy]
entities:
- type: Ball
radius: 16px
pos: [0.8, 0.5]
speed: [-0.2, -0.1]
speed_rand: [0, 0.2]
solid: True
collision_elasticity: 3
elasticity: 1
movable: 1
collision_changes_speed: True
crash_conservation_of_energy: False
min_speed: 0.2
max_speed: 0.6
draw_path: True
draw_path_width: 32
draw_path_harm: True
drag: 0.00001
- type: RectGoal # Good
height: 1em
width: 10ct
pos: [97ct, 0ct]
skip_agent_col_check: True
col: [0, 255, 0]
reward: 30
solid: True
elasticity: 0.6
void_collidable: False
- type: Goal # Top
radius: 7ct
pos: [100ct, 0ct]
skip_agent_col_check: True
col: [0, 255, 0]
reward: 30
solid: True
elasticity: 0.7
void_collidable: False
- type: Goal # Bottom
radius: 7ct
pos: [100ct, 100ct]
skip_agent_col_check: True
col: [0, 255, 0]
reward: 30
solid: True
elasticity: 0.7
void_collidable: False
- type: RectGoal # Bad
height: 1em
width: 3ct
pos: [0ct, 0ct]
skip_agent_col_check: True
col: [255, 0, 0]
reward: -45
solid: True
elasticity: 1000
void_collidable: False
agent_cls: PongAgent
agent_attrs:
height: 100
width: 30
movable: False
solid: True
elasticity: 0.9
exception_for_unsupported_collision: False
start_pos: [0.05, 0.5]
start_score: 0
speed_fac: 0.05
acc_fac: 0.1
die_on_zero: False #True
agent_drag: 0
controll_type: SPEED
aux_reward_max: 0
aux_penalty_max: 0
void_damage: 0
terminate_on_reward: False
agent_draw_path: False
clear_path_on_reset: False
---