From 76b97b126e7f0e4a3de044ac4c485ba054e98ebc Mon Sep 17 00:00:00 2001 From: romue Date: Wed, 9 Jun 2021 13:21:30 +0200 Subject: [PATCH] better agent visualization --- environments/factory/assets/agents/idle.png | Bin 0 -> 1631 bytes .../factory/assets/agents/invalid.png | Bin 0 -> 1599 bytes environments/factory/assets/agents/valid.png | Bin 0 -> 1530 bytes environments/factory/renderer.py | 39 +++++++++++------- environments/factory/simple_factory.py | 15 +++---- 5 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 environments/factory/assets/agents/idle.png create mode 100644 environments/factory/assets/agents/invalid.png create mode 100644 environments/factory/assets/agents/valid.png diff --git a/environments/factory/assets/agents/idle.png b/environments/factory/assets/agents/idle.png new file mode 100644 index 0000000000000000000000000000000000000000..152f27a6380e7b40dec0b6f41b43660dc2a96197 GIT binary patch literal 1631 zcmV-l2B7(gP)Ptnz7ZFr^kZd#?i(kzK!Ilawh)|H0ilP?r0}(%vswftV zSP-E?ODjlrTR*6|X|t;jqJsD$DE39A4`MfDO}0&Tj?BHgH=FEc_kPSKcX#KKhrrI9 zd**j%&z?DR=3GJqt`n1!8?O-SZk1Br48|=Gbd!|wIsjJ+P#=SO0TuvB0?$kE9Ds{L zh(96uR}g*{Lj3Zdy!_LS;o-ts4~f=Ffm7CZ_evojgv9+|xdlWs1X>6123A_J{RiRv z>t5<33BXpI0J1-%Sq5JQb3aI&hrpM-z+a5rllW>a#EptZJs`0nCEv-6G~c zY_*AK8Pqdpe%Le@D;^;5(+tc5*w|u*Uc?s&=w;A5eWm!pty^!O_R`63o0dRLPv)K> z=2sacm5ubPRO{Q*EP(|Ry_6ard|UVZv_e%j6M_#D(N$n<(ygp^d4y?Z{uh$=>a@Aq zpk}P>VFv96I0|2LpZuvn;G?6-#9p5r>oyM!^>ZtGTMTp@#GAp9u$#fS5DH+rPy+9K zD4F;%m=LE|D5&X)>~0W!;yC7=a*+h{qp6X^(V!y=4E2nscZf*ra-8?hyOe*c77xtw)3K4e_WK>7Zzk!9sUsjf4A6kzo3&qi z&V%t;YGi1SAKiUHb!I5->JFe4jGSj?Uo+M-RNIDvp9RnbGqh%2<^||2uQt{bRQp$6 z-~(p#d+OllyV3@2Z5vCNfy6#9UO`hvWk2-$&T^ZAK1q@#@Ey(k*rrg^R_-@|ZwRVJ z=k=rCQ^~;_8;z?WRD0=3*xlAECEZVzP#{LbCGCn(oq#f(Y|pj4Zj#I8QGq3IUnvN) zGE{5o4+3pzwR-I;pTXzHl0(YPe|@zH4_m9|qP( zP5r3qL%^juTDZD;GjR!2+mV7;-a;h~l%<|Rs7 zxspkg2oH2o0!d0+Su;s>GF4G3GgCDaRYyIIP1Oh0wW;RUUmsNW*WdW5`k>klmGV=~ zib^BY%8JUY{q;dzT>G0Sl{Ttwl*+_YwJ}wKoOr5<{A+|-iTs;ADveN4-lMXin%&gU zWNUU)?IJN)IBxd+!?5K%OR`gcOomDrj^(~}GgKVAYI3Q9@?9~P%4GcoMQZn}pY>Os zttLM;7~A^!sWw!TNgV`f<4kIk^Y5Q&)13eELcp9(@yyo4=@cc)oTKtgRAo$iJ4fZ( zR&(O7F?Pm`cAjbVEU{@?%X+>MFFMp;ly>>gkJAwLz@}VN9L>kk!*yGS%jd z6wTePKrPI>QvzZ0*2%o(#~Y`>t<3wV0;BWR(FWW@547sdX+nzAsz{7CZS=O%`s*K5 dwN87--~YGb literal 0 HcmV?d00001 diff --git a/environments/factory/assets/agents/invalid.png b/environments/factory/assets/agents/invalid.png new file mode 100644 index 0000000000000000000000000000000000000000..4cf34c02a23e8ec6695e7c9f57140a93db73fc99 GIT binary patch literal 1599 zcmV-F2Eh4=P)YI@4M%%juKk}l|2eDfc(j;}~$lUC1H)*naKPK7D_U!Y_xo3Ved+wPt zXU-*h;CC{gANB?ZixA#I4+V!6YcZ znECmMU12!W?IE#S3RDWkI{~>@h`UMdFe1|g1^{e<)k801FnRIOF!O zof{ZJ9NYN__-Ke6E|6taaMf)840Dt*M2i)p`y4MPR{c0B??#C*DZ&s8l>o6@tSc z_OUxYXPR*)?jwNRJbb!yvh;Y;&WWLhL2wiz4*=|j6Q6W^8QV)0Cq&D5<#^q zl$3n}jwI@sM57*RySU|*st6OU*w}2W4K*U9Fgc|z6uL9iIv0++mH&DNN zSn;=fxpY%IwcE0?TTcRG8+oVXdd})QueMv-RiV~{BPVRg&b4BFAaBMP?pZAevntfk z5B?yqV2a>XyPA=DC8o!7IG&%TEw4fqKgKUnlrvk4Ef!jrXiT-rHF&ztF1K5~z!Zbc6p0 zFxYF__o_Yw=4%V{SGOJ}E`e%osR3WM(feKEiZrPa1Bff@$EUn00h9sT%I z7i|cLzw@QiwT)g)es#a}vo4*>#~(#+wyYY%hZ=rs6Kd%Dp99>}n>udi?$Tz=4M zdJ$?NIInJ0hRGAm(MK{ z@4t*~ru+UaWCm&$Qnss>oCpcZdq zkody1*81xVHZjyFKA=@8+mcNMb#W`J^;1_Pn;L4|ZIt*t}TY@lJ=fAUqki3O{ks>*>SUvRHDX}o6YouTKNyjaAFZ~`>Y*gtQTEIEV xJ!|#lG=N{*A~ET-%ht>3+dr);{q~K&{{cdRCM)`vXKDZd002ovPDHLkV1ju$5CQ-I literal 0 HcmV?d00001 diff --git a/environments/factory/assets/agents/valid.png b/environments/factory/assets/agents/valid.png new file mode 100644 index 0000000000000000000000000000000000000000..ae7c768f910fad2411ae7284a662b041dc12e50b GIT binary patch literal 1530 zcmVNC95ft1hxG0%a#Eq2-7DOmYXW|cP5q}Wz2dRobc~jJa z6e_e>HzGDObRpUN7O64j)goP48w<{H0ge6hI}8mUVb7y;u4-)L zy92dSdIr^3L297eZ3eQjGGcsi4w09bD7@|a-hQDPpNSp?xf*n*@4@=lCv%{GgBo;$kKi$p7=fs z+-y+G(E;E%O0K7qP!3}8)?9% zgL&I#?#!iPp+v_lTX=Om~tJjJJfP?47eYuuZCRj*e~+&nt>|tIr-v2mtng> z-5M6!%Fo$i?V-j#lxGLtLR*n8TkKo5KGqIuJj+W7)MSCS=r5kU3N}$eXQ)XW`rUwq zP40$~WWQ?2(jA@R*v?SP(J#Pm_fZV&6~B@%-n8D+tq--Im!92vrxr`vwV|5ii0J9Q zUV3&DtjfN%k}&H)jee_db98HH{jPVGeDTJ1578cKoDb#2{z%{T>fOj3!fWmFv8$mb z8T)gFQ9ECF#kywkiD55iqq|Io;2msY+t0Gt(a+;=C7=?(PG8mFhH;Q;#Q5 zO?pq+9cKLuFFeV&#%Vzz3HZ$h*H8wP;nIY_5~DIMRHD03z6ha|7rQVeoA(Ljr~q;# zto40BjdKBqg-YpTl!GBY^#axS)nh`r^bP2pK2!!Bag_S4`S%YQe!tc*E0m|r(U}nR zdjqRgW2y5Yf9j2>QM6#7F4YfydDXmymDLPXmy=*yn3esb2TQeQWh)t5YVfJHxa{PN zPYtub9V=U@WcCknsx2=&ITNRb6_p(;TPd@m3TuB`S{8EBSo?=8l?5$Jk;_@CkWaNF zW+PV5r-sbG4J=!kdgkAVhdnA=Xlu(g?NJ%Au$!74s?pH2n`)ZG)Z|py_s_sK?%9%* z{)7sZ3>;f7ZK+U+T|lU%O3!!ATB=a>mmaD)7~HPv&uFZK`c!AI>(-~nP(vlPGt`ci z)S>3znW@>6TEFH$SqOyFDb{FhPNx`U;T)AUQo!;YRl~Q26Mr4xx}5lHs0up*oh;Vz zY-;RV!zt=Dsm6`L(ww4B;@19cHP^|`(*8ZudH-cM5K7mZUqHsr6tT629x5?YuRT)h>Ur9TNB)U2jAH>im#2)+I~EeovBw+d|yi*@et*TCd% zsZBmM^iOSPlfjtV$FV3pWC?DX4sMWHA4Dr3!NsVmj>^ODwL>FF}}_=DO=!h}Bm zT{?^&zDVI>*bcJc+bIsPTt&lIeq4z;%7^b!IRbMPj{(>AcJ0e)SMZf-65~27AM$=@ g|Fk0-uy6eR51$@p(^EXAg8%>k07*qoM6N<$f=ku)L;wH) literal 0 HcmV?d00001 diff --git a/environments/factory/renderer.py b/environments/factory/renderer.py index fdb56d2..b439eaa 100644 --- a/environments/factory/renderer.py +++ b/environments/factory/renderer.py @@ -1,22 +1,24 @@ import sys -from dataclasses import dataclass import numpy as np from pathlib import Path from collections import deque import pygame +from typing import NamedTuple -@dataclass -class Entity: + +class Entity(NamedTuple): name: str pos: np.array value: float = 1 value_operation: str = 'none' + state: str = None class Renderer: BG_COLOR = (178, 190, 195) # (99, 110, 114) WHITE = (223, 230, 233) # (200, 200, 200) AGENT_VIEW_COLOR = (9, 132, 227) + ASSETS = Path(__file__).parent / 'assets' def __init__(self, grid_w=16, grid_h=16, cell_size=40, fps=4, grid_lines=True, view_radius=2): self.grid_h = grid_h @@ -29,7 +31,7 @@ class Renderer: self.screen_size = (grid_w*cell_size, grid_h*cell_size) self.screen = pygame.display.set_mode(self.screen_size) self.clock = pygame.time.Clock() - assets = list((Path(__file__).parent / 'assets').rglob('*.png')) + assets = list(self.ASSETS.rglob('*.png')) self.assets = {path.stem: self.load_asset(str(path), 1) for path in assets} self.fill_bg() @@ -64,25 +66,29 @@ class Renderer: wall_img = pygame.transform.smoothscale(wall_img, (s, s)) return wall_img - def render(self, pos_dict): + def render(self, entities): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() self.fill_bg() blits = deque() - for asset, entities in pos_dict.items(): - for entity in entities: - bp = self.blit_params(entity) - if 'agent' in entity.name and self.view_radius > 0: - visibility_rect = bp['dest'].inflate((self.view_radius*2)*self.cell_size, (self.view_radius*2)*self.cell_size) - shape_surf = pygame.Surface(visibility_rect.size, pygame.SRCALPHA) - pygame.draw.rect(shape_surf, self.AGENT_VIEW_COLOR, shape_surf.get_rect()) - shape_surf.set_alpha(64) - blits.appendleft(dict(source=shape_surf, dest=visibility_rect)) - blits.append(bp) + for entity in entities: + bp = self.blit_params(entity) + blits.append(bp) + if 'agent' in entity.name and self.view_radius > 0: + visibility_rect = bp['dest'].inflate((self.view_radius*2)*self.cell_size, (self.view_radius*2)*self.cell_size) + shape_surf = pygame.Surface(visibility_rect.size, pygame.SRCALPHA) + pygame.draw.rect(shape_surf, self.AGENT_VIEW_COLOR, shape_surf.get_rect()) + shape_surf.set_alpha(64) + blits.appendleft(dict(source=shape_surf, dest=visibility_rect)) + agent_state_blits = self.blit_params(Entity(entity.state, (entity.pos[0]+0.11, entity.pos[1]), 0.48, 'scale')) + blits.append(agent_state_blits) + for blit in blits: self.screen.blit(**blit) + + pygame.display.flip() self.clock.tick(self.fps) @@ -90,5 +96,6 @@ class Renderer: if __name__ == '__main__': renderer = Renderer(fps=2, cell_size=40) for i in range(15): - renderer.render({'agent': [(5, i)], 'wall': [(0, i), (i, 0)], 'dirt': [(3,3), (3,4)]}) + entity = Entity('agent', [5, i], 1, 'idle', 'idle') + renderer.render([entity]) diff --git a/environments/factory/simple_factory.py b/environments/factory/simple_factory.py index c1f052d..bcc7fcb 100644 --- a/environments/factory/simple_factory.py +++ b/environments/factory/simple_factory.py @@ -58,15 +58,16 @@ class SimpleFactory(BaseFactory): if 'agent' in cols: return 'agent_collision' elif not agent.action_valid or 'level' in cols or 'agent' in cols: - return f'agent{agent.i + 1}violation' + return f'agent{agent.i + 1}', 'invalid' elif self._is_clean_up_action(agent.action): - return f'agent{agent.i + 1}valid' + return f'agent{agent.i + 1}', 'valid' else: - return f'agent{agent.i + 1}' - - agents = {f'agent{i+1}': [Entity(asset_str(agent), agent.pos)] - for i, agent in enumerate(self._agent_states)} - self._renderer.render(OrderedDict(dirt=dirt, wall=walls, **agents)) + return f'agent{agent.i + 1}', 'idle' + agents = [] + for i, agent in enumerate(self._agent_states): + name, state = asset_str(agent) + agents.append(Entity(name, agent.pos, 1, 'none', state)) + self._renderer.render(dirt+walls+agents) def spawn_dirt(self) -> None: if not np.argwhere(self._state[DIRT_INDEX] != h.IS_FREE_CELL).shape[0] > self.dirt_properties.max_global_amount: