From dfb258369a7755947462772dc5225ec19e36a875 Mon Sep 17 00:00:00 2001 From: "Egli Adrian (IT-SCI-API-PFI)" <adrian.egli@sbb.ch> Date: Tue, 4 Jun 2019 11:41:23 +0200 Subject: [PATCH] target and agent : selected hightlieght PILSV --- flatland/utils/editor.py | 1 + flatland/utils/graphics_layer.py | 4 +- flatland/utils/graphics_pil.py | 33 +++++++++--- flatland/utils/rendertools.py | 11 +++- notebooks/Editor2.ipynb | 20 +++---- svg/Selected_Agent.svg | 92 ++++++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 24 deletions(-) create mode 100644 svg/Selected_Agent.svg diff --git a/flatland/utils/editor.py b/flatland/utils/editor.py index 671faf3a..8b2233e5 100644 --- a/flatland/utils/editor.py +++ b/flatland/utils/editor.py @@ -765,6 +765,7 @@ class EditorModel(object): # No - select the agent self.iSelectedAgent = iAgent + self.init_agents_static = None self.redraw() def add_target(self, rcCell): diff --git a/flatland/utils/graphics_layer.py b/flatland/utils/graphics_layer.py index 327cf4f6..de88b023 100644 --- a/flatland/utils/graphics_layer.py +++ b/flatland/utils/graphics_layer.py @@ -68,7 +68,7 @@ class GraphicsLayer(object): def get_cmap(self, *args, **kwargs): return plt.get_cmap(*args, **kwargs) - def setRailAt(self, row, col, binTrans, iTarget=None): + def setRailAt(self, row, col, binTrans, iTarget=None,isSelected=False): """ Set the rail at cell (row, col) to have transitions binTrans. The target argument can contain the index of the agent to indicate that agent's target is at that cell, so that a station can be @@ -76,7 +76,7 @@ class GraphicsLayer(object): """ pass - def setAgentAt(self, iAgent, row, col, iDirIn, iDirOut): + def setAgentAt(self, iAgent, row, col, iDirIn, iDirOut,isSelected=False): pass def resize(self, env): diff --git a/flatland/utils/graphics_pil.py b/flatland/utils/graphics_pil.py index 5726a0b5..0593543c 100644 --- a/flatland/utils/graphics_pil.py +++ b/flatland/utils/graphics_pil.py @@ -193,6 +193,13 @@ class PILGL(GraphicsLayer): img = Image.new("RGBA", (self.widthPx, self.heightPx), (255, 255, 255, opacity)) return img + def clear_layer(self,iLayer=0, opacity = None): + if opacity is None: + opacity = 0 if iLayer > 0 else 255 + self.layers[iLayer] = img = self.create_image(opacity) + # We also need to maintain a Draw object for each layer + self.draws[iLayer] = ImageDraw.Draw(img) + def create_layer(self, iLayer=0, clear=True): # If we don't have the layers already, create them if len(self.layers) <= iLayer: @@ -207,14 +214,13 @@ class PILGL(GraphicsLayer): else: # We do already have this iLayer. Clear it if requested. if clear: - opacity = 0 if iLayer > 0 else 255 - self.layers[iLayer] = img = self.create_image(opacity) - # We also need to maintain a Draw object for each layer - self.draws[iLayer] = ImageDraw.Draw(img) + self.clear_layer(iLayer) def create_layers(self, clear=True): - self.create_layer(0, clear=clear) - self.create_layer(1, clear=clear) + self.create_layer(0, clear=clear) # rail / background (scene) + self.create_layer(1, clear=clear) # agents + self.create_layer(2, clear=clear) # drawing layer for selected agent + self.create_layer(3, clear=clear) # drawing layer for selected agent's target class PILSVG(PILGL): @@ -373,7 +379,7 @@ class PILSVG(PILGL): return dPil - def setRailAt(self, row, col, binTrans, iTarget=None): + def setRailAt(self, row, col, binTrans, iTarget=None,isSelected=False): if iTarget is None: if binTrans in self.dPilRail: pilTrack = self.dPilRail[binTrans] @@ -387,6 +393,12 @@ class PILSVG(PILGL): else: print("Illegal target rail:", row, col, format(binTrans, "#018b")[2:]) + if isSelected: + svgBG = self.pilFromSvgFile("./svg/Selected_Agent.svg") + self.clear_layer(3,0) + self.drawImageRC(svgBG,(row,col),layer=3) + + def recolorImage(self, pil, a3BaseColor, ltColors): rgbaImg = array(pil) lPils = [] @@ -435,7 +447,7 @@ class PILSVG(PILGL): for iColor, pilZug3 in enumerate(lPils): self.dPilZug[(iDirIn2, iDirOut2, iColor)] = lPils[iColor] - def setAgentAt(self, iAgent, row, col, iDirIn, iDirOut): + def setAgentAt(self, iAgent, row, col, iDirIn, iDirOut,isSelected): delta_dir = (iDirOut - iDirIn) % 4 iColor = iAgent % self.nAgentColors # when flipping direction at a dead end, use the "iDirOut" direction. @@ -444,6 +456,11 @@ class PILSVG(PILGL): pilZug = self.dPilZug[(iDirIn % 4, iDirOut % 4, iColor)] self.drawImageRC(pilZug, (row, col), layer=1) + if isSelected: + svgBG = self.pilFromSvgFile("./svg/Selected_Agent.svg") + self.clear_layer(2,0) + self.drawImageRC(svgBG,(row,col),layer=2) + def main2(): gl = PILSVG(10, 10) diff --git a/flatland/utils/rendertools.py b/flatland/utils/rendertools.py index 1c2185b6..787ce10f 100644 --- a/flatland/utils/rendertools.py +++ b/flatland/utils/rendertools.py @@ -757,10 +757,13 @@ class RenderTool(object): # store the targets dTargets = {} + dSelected = {} for iAgent, agent in enumerate(self.env.agents_static): if agent is None: continue dTargets[tuple(agent.target)] = iAgent + dSelected[tuple(agent.target)] = (iAgent==iSelectedAgent) + # Draw each cell independently for r in range(env.height): @@ -768,9 +771,13 @@ class RenderTool(object): binTrans = env.rail.grid[r, c] if (r, c) in dTargets: target = dTargets[(r, c)] + isSelected = dSelected[(r, c)] + print("isSelected=", isSelected) else: target = None - self.gl.setRailAt(r, c, binTrans, iTarget=target) + isSelected = False + + self.gl.setRailAt(r, c, binTrans, iTarget=target,isSelected=isSelected) for iAgent, agent in enumerate(self.env.agents): @@ -788,7 +795,7 @@ class RenderTool(object): # setAgentAt uses the agent index for the color # cmap = self.gl.get_cmap('hsv', lut=max(len(self.env.agents), len(self.env.agents_static) + 1)) - self.gl.setAgentAt(iAgent, *position, old_direction, direction) # ,color=cmap(iAgent)) + self.gl.setAgentAt(iAgent, *position, old_direction, direction, iSelectedAgent==iAgent) # ,color=cmap(iAgent)) if show_observations: self.renderObs(range(env.get_num_agents()), env.dev_obs_dict) diff --git a/notebooks/Editor2.ipynb b/notebooks/Editor2.ipynb index 00250ea8..0645909b 100644 --- a/notebooks/Editor2.ipynb +++ b/notebooks/Editor2.ipynb @@ -78,7 +78,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "<flatland.utils.graphics_pil.PILSVG object at 0x0000021AB01F0198> <class 'flatland.utils.graphics_pil.PILSVG'>\n", + "<flatland.utils.graphics_pil.PILSVG object at 0x0000022C5FB44198> <class 'flatland.utils.graphics_pil.PILSVG'>\n", "<super: <class 'PILSVG'>, <PILSVG object>> <class 'super'>\n", "Clear rails\n" ] @@ -123,7 +123,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "0f3ff6aff8954f3cb369b80b053f9f1a", + "model_id": "094a0a3e4351403d8d119b0696abaee4", "version_major": 2, "version_minor": 0 }, @@ -135,15 +135,11 @@ "output_type": "display_data" }, { - "ename": "AttributeError", - "evalue": "'EditorModel' object has no attribute 'model'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32mc:\\users\\u216993\\appdata\\local\\programs\\python\\python36\\lib\\site-packages\\flatland_rl-0.1.1-py3.6.egg\\flatland\\utils\\editor.py\u001b[0m in \u001b[0;36mstep\u001b[1;34m(self, event)\u001b[0m\n\u001b[0;32m 386\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 387\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mstep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 388\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 389\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 390\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mstart_run\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mevent\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32mc:\\users\\u216993\\appdata\\local\\programs\\python\\python36\\lib\\site-packages\\flatland_rl-0.1.1-py3.6.egg\\flatland\\utils\\editor.py\u001b[0m in \u001b[0;36mstep\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 771\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mstep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 772\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplayer\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 773\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minit_agents_static\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0menv\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0magents_static\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 774\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplayer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mPlayer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0menv\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 775\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0menv\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mreset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mregen_rail\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mreplace_agents\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mAttributeError\u001b[0m: 'EditorModel' object has no attribute 'model'" + "name": "stdout", + "output_type": "stream", + "text": [ + "<flatland.utils.graphics_pil.PILSVG object at 0x0000022C6066EC50> <class 'flatland.utils.graphics_pil.PILSVG'>\n", + "<super: <class 'PILSVG'>, <PILSVG object>> <class 'super'>\n" ] } ], @@ -161,7 +157,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8df099a612d94e34bc64abd0263ae21f", + "model_id": "98b1504729884d8a9362dbf246d81f78", "version_major": 2, "version_minor": 0 }, diff --git a/svg/Selected_Agent.svg b/svg/Selected_Agent.svg new file mode 100644 index 00000000..15761df8 --- /dev/null +++ b/svg/Selected_Agent.svg @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + id="Ebene_1" + x="0px" + y="0px" + viewBox="0 0 240 240" + style="enable-background:new 0 0 240 240;" + xml:space="preserve" + sodipodi:docname="Selected_Agent.svg" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata + id="metadata11"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs9" /><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1137" + id="namedview7" + showgrid="false" + inkscape:zoom="2.7812867" + inkscape:cx="205.50339" + inkscape:cy="161.549" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" + inkscape:current-layer="Ebene_1" /> +<style + type="text/css" + id="style2"> + .st0{fill:#9CCB89;} +</style> + +<rect + id="rect13" + width="23.389822" + height="23.38983" + x="1.697217e-07" + y="-0.23616901" /><rect + id="rect13-0" + width="23.389822" + height="23.38983" + x="216.82077" + y="0.26172119" /><rect + id="rect13-0-0" + width="23.389822" + height="23.38983" + x="216.75911" + y="216.39955" /><rect + id="rect13-0-0-4" + width="23.389822" + height="23.38983" + x="0.50847793" + y="216.6974" /><rect + id="rect60" + width="2.5168207" + height="198.4693" + x="10.067283" + y="22.474777" /><rect + id="rect60-8" + width="2.5168207" + height="198.4693" + x="228.49136" + y="22.115229" /><rect + id="rect60-8-5" + width="2.5168207" + height="198.4693" + x="-11.868174" + y="19.775019" + transform="rotate(-90)" /><rect + id="rect60-8-5-1" + width="2.5168207" + height="198.4693" + x="-230.11249" + y="20.853657" + transform="rotate(-90)" /></svg> \ No newline at end of file -- GitLab