Beispiel #1
0
    def set_display_info(self) -> List[MapDisplay]:
        ret: List[MapDisplay] = super().set_display_info()

        if not self.SIMPLE_ANIMATIONS:
            if self.__is_local_anim and self.__local_kernel_anim:
                ret += self.__local_kernel_anim.instance.set_display_info()

            if not self.__is_local_anim and self.__global_kernel_anim:
                ret += self.__global_kernel_anim.instance.set_display_info()

        visited_colour = self._services.state.views.add_colour(
            "visited", Colour(0.19, 0.19, 0.2, 0.8))
        waypoint_colour = self._services.state.views.add_colour(
            "waypoint", Colour(0, 1, 1))

        ret.append(
            SolidIterableMapDisplay(self._services,
                                    self.display_info_data[0],
                                    visited_colour,
                                    z_index=70))
        ret.append(
            SolidIterableMapDisplay(self._services,
                                    self.display_info_data[1],
                                    visited_colour,
                                    z_index=65))
        ret.append(
            SolidIterableMapDisplay(self._services,
                                    self.way_points,
                                    waypoint_colour,
                                    z_index=200))
        return ret
Beispiel #2
0
    def __init__(self, services: Services, testing: BasicTesting = None):
        super().__init__(services, testing)

        self.mem = CGDS.InternalMemory(self._services)

        self.pq_colour_max = self._services.state.views.add_colour("explored max", BLUE)
        self.pq_colour_min = self._services.state.views.add_colour("explored min", Colour(0.27, 0.33, 0.35, 0.2))
        self.visited_colour = self._services.state.views.add_colour("visited", Colour(0.19, 0.19, 0.2, 0.8))

        self.__map_displays = [SolidIterableMapDisplay(self._services, self.mem.visited, self.visited_colour, z_index=50),
                               GradientListMapDisplay(self._services, self.mem.dequeVisual, min_colour=self.pq_colour_min,
                                                  max_colour=self.pq_colour_max, z_index=49, inverted=True)
                               ]
Beispiel #3
0
    def __init__(self,
                 name: str,
                 visibility_callback: Callable[[str, bool], None],
                 colour_callback: Callable[[str, Colour], None],
                 cv_clicked_callback: Callable[['ViewElement'], None],
                 parent: DirectFrame,
                 visible: bool = True,
                 colour: Colour = Colour(0.2, 0.3, 0.4, 0.5),
                 mouse1_press_callbacks: List[Callable[[], None]] = []):
        self.__name = name
        self.__visible = visible
        self.__visibility_callback = None
        self.__colour_callback = None
        self.__cv_clicked_callback = None

        self.__frame = DirectFrame(parent=parent, frameColor=WINDOW_BG_COLOUR)

        self.__cv = ColourView(self.__frame, colour)
        self.__cv.frame.set_scale((0.15, 1.0, 0.15))
        self.__cv.frame.set_pos((-0.65, 1.0, 0.0))

        self.__cv_btn = DirectButton(parent=self.__cv.frame,
                                     frameColor=TRANSPARENT,
                                     borderWidth=(0, 0),
                                     frameSize=self.__cv.view["frameSize"],
                                     scale=self.__cv.view["scale"],
                                     pos=self.__cv.view["pos"],
                                     command=self.__cv_clicked)

        self.__label = DirectLabel(parent=self.__frame,
                                   text=self.__name,
                                   text_fg=WHITE,
                                   text_bg=WINDOW_BG_COLOUR,
                                   frameColor=WINDOW_BG_COLOUR,
                                   text_align=TextNode.ALeft,
                                   borderWidth=(.0, .0),
                                   pos=(-0.3, 0.0, -0.03),
                                   scale=(0.1, 1.0, 0.1))

        visibility_filename = os.path.join(GUI_DATA_PATH, "visible.png")
        self.__visibility_btn = DirectButton(parent=self.__frame,
                                             image=visibility_filename,
                                             frameColor=TRANSPARENT,
                                             pos=(-0.92, 0.0, 0.0),
                                             scale=(0.09, 1.0, 0.06),
                                             command=self.__toggle_visible)

        self.__visibility_bar = DirectFrame(parent=self.__frame,
                                            borderWidth=(.0, .0),
                                            frameColor=WINDOW_BG_COLOUR,
                                            frameSize=(-0.1, 0.1, -0.01, 0.01),
                                            pos=(-0.92, 0.0, 0.0),
                                            hpr=(40, 0, 40))

        self.visible = self.__visible  # trigger UI update

        self.__visibility_callback = visibility_callback
        self.__colour_callback = colour_callback
        self.__cv_clicked_callback = cv_clicked_callback
Beispiel #4
0
 def __colour_picked_callback(self, colour: Colour):
     n = 3
     r, g, b, _ = colour
     self.__r.update(r)
     self.__g.update(g)
     self.__b.update(b)
     self.__cv_picked.colour = Colour(r, g, b, self.__cv_picked.colour.a)
     self.__dirty_rem_no_hide = 3  # something fishy is going on
     self.__callback(self.__cv_picked.colour)
Beispiel #5
0
def blend_colours(src: Colour, dst: Colour):
    wda = dst.a * (1 - src.a)  # weighted dst alpha
    cs = np.multiply(src.values, src.a) + np.multiply(dst.values, wda)

    a = src.a + wda
    if a != 0:
        cs = np.divide(cs, a)

    return Colour(*cs)
Beispiel #6
0
    def __init__(self,
                 base: ShowBase,
                 parent: DirectFrame,
                 callback: Callable[[Colour], None],
                 mouse1_press_callbacks: List[Callable[[], None]],
                 colour: Colour = Colour(0.25, 0.5, 0.75, 1.0)):
        self.__base = base
        self.__colour = colour
        self.__callback = callback
        self.__enabled = True

        self.__frame = DirectFrame(parent=parent)

        self.__colour_picker = ColourPicker(self.__base,
                                            self.__colour_picked_callback,
                                            parent=self.__frame,
                                            relief=DGG.SUNKEN,
                                            borderWidth=(.0, .0),
                                            image_scale=(1., 1., 1.),
                                            frameColor=WIDGET_BG_COLOUR,
                                            frameSize=(-1., 1., -1., 1.),
                                            scale=(1.0, 1.0, 0.75),
                                            pos=(0.0, 0.0, 0.15))

        self.__cv_picked = ColourView(self.__frame, self.__colour)
        self.__cv_picked.frame.set_pos(-0.74, 0.0, -1.41)
        self.__cv_hovered = ColourView(self.__frame)
        self.__cv_hovered.frame.set_pos(-0.74, 0.0, -0.89)

        def update_cv_hovered(task):
            c = self.__colour_picker.colour_under_mouse()
            self.__cv_hovered.colour = c
            return task.cont

        self.__base.taskMgr.add(update_cv_hovered, 'update_cv_hovered')

        c = self.__colour
        f = self.__frame
        sc = self.__colour_channel_slider_edit_callback
        ec = self.__colour_channel_entry_edit_callback
        self.__r = ColourChannel(f, "R", c[0], sc, ec, mouse1_press_callbacks)
        self.__g = ColourChannel(f, "G", c[1], sc, ec, mouse1_press_callbacks)
        self.__b = ColourChannel(f, "B", c[2], sc, ec, mouse1_press_callbacks)
        self.__a = ColourChannel(f, "A", c[3], sc, ec, mouse1_press_callbacks)

        x = 0.14
        y_base = -0.8
        y_inc = -0.25
        self.__r.frame.set_pos((x, 0.0, y_base))
        self.__g.frame.set_pos((x, 0.0, y_base + y_inc))
        self.__b.frame.set_pos((x, 0.0, y_base + y_inc * 2))
        self.__a.frame.set_pos((x, 0.0, y_base + y_inc * 3))

        self.__dirty_rem_no_hide = 0
    def __init__(self,
                 services: Services,
                 ray_colour: Optional[DynamicColour] = None,
                 bearing_colour: Optional[DynamicColour] = None,
                 custom_map: Map = None):
        super().__init__(services, z_index=250, custom_map=custom_map)

        self.ray_colour = self._services.state.views.add_colour(
            "ray", RED) if ray_colour is None else ray_colour
        self.bearing_colour = self._services.state.views.add_colour(
            "bearing", Colour(1, 0,
                              1)) if bearing_colour is None else bearing_colour
Beispiel #8
0
    def __colour_channel_entry_edit_callback(self, chn: ColourChannel,
                                             value: float):
        if chn != self.__a:
            if self.__dirty_rem_no_hide:
                self.__dirty_rem_no_hide -= 1
            else:
                self.__colour_picker.marker.hide()

        chn.update_slider(value)
        self.__cv_picked.colour = Colour(self.__r.value, self.__g.value,
                                         self.__b.value, self.__a.value)
        self.__callback(self.__cv_picked.colour)
Beispiel #9
0
    def __create_lines(self, c: Colour, wfc: Colour) -> Tuple[bytes, bytes, bytes]:
        def conv(f): return int(round(f * 255))
        def to_pixel(c): return (conv(c.b), conv(c.g), conv(c.r), conv(c.a))

        wfd2 = int(self.wf_thickness // 2)

        if wfd2 != self.wf_line_cnt:
            bc = blend_colours(wfc.with_a(wfc.a * ((self.wf_thickness / 2) - wfd2)), c)
            tpixel = to_pixel(bc)
        else:
            bc = None

        pixel = to_pixel(c)
        wfpixel = to_pixel(blend_colours(wfc, c))

        line = array.array('B')
        for _ in range(wfd2):
            line.extend(wfpixel)
        if bc is not None:
            line.extend(tpixel)
        for _ in range(self.square_size - 2 * self.wf_line_cnt):
            line.extend(pixel)
        if bc is not None:
            line.extend(tpixel)
        for _ in range(wfd2):
            line.extend(wfpixel)
        lbytes = line.tobytes()

        wfline = array.array('B')
        for _ in range(self.square_size):
            wfline.extend(wfpixel)
        wflbytes = wfline.tobytes()

        if bc is None:
            tlbytes = wflbytes
        else:
            tline = array.array('B')
            for _ in range(wfd2):
                tline.extend(wfpixel)
            tline.extend(tpixel)
            for _ in range(self.square_size - 2 * self.wf_line_cnt):
                tline.extend(tpixel)
            tline.extend(tpixel)
            for _ in range(wfd2):
                tline.extend(wfpixel)
            tlbytes = tline.tobytes()

        self.__lines[(c, wfc)] = (lbytes, wflbytes, tlbytes)
        return lbytes, wflbytes, tlbytes
Beispiel #10
0
    def get_colour(self, val: float) -> Optional[Colour]:
        mag = (val - self.min_val)

        d = (self.max_val - self.min_val)
        if d != 0:
            mag /= d

        # catch NaN in addition to out-of-bounds
        if not (mag >= 0 and mag <= 1):
            return None

        cmag = Colour(mag, mag, mag, mag)
        cmin = self.__deduced_min_colour
        cmax = self.__deduced_max_colour
        cvec: Colour = cmax - cmin
        clr = (cmax - cmag * cvec) if self.inverted else (cmin + cmag * cvec)

        return clr
    def set_display_info(self):
        active_kernel_displays = []

        if self.__active_kernel:
            active_kernel_displays = [
                # *self.__active_kernel.instance.set_display_info(),
                OnlineLSTMMapDisplay(self._services,
                                     custom_map=self.__active_kernel.map),
                EntitiesMapDisplay(self._services,
                                   custom_map=self.__active_kernel.map),
            ]

        trace_colour = self._services.state.views.add_colour(
            "trace", Colour(0, 0.9, 0))

        return super().set_display_info() + [
            *active_kernel_displays,
            SolidIterableMapDisplay(
                self._services, self.__total_path, trace_colour, z_index=80),
        ]
Beispiel #12
0
    def __init__(self, services: Services, model: Model, root_view: Optional[View]) -> None:
        super().__init__(services, model, root_view)
        self.__displays = []
        self.__tracked_data = []

        self.__cube_update_displays = []
        self.__previous_cube_update_displays = []
        self.__previous_cube_update_displays_rendered = []
        self.__cubes_requiring_update = set()
        self.__cube_colour = None

        # world (dummy node)
        self.__world = self._services.graphics.window.render.attach_new_node("world")

        # MAP #
        extended_walls: bool = False
        map_size = self._services.algorithm.map.size
        map_data = np.empty((*map_size, 1) if map_size.n_dim == 2 else map_size, dtype=np.uint8)
        self.__cube_modified = np.empty(map_data.shape, dtype=bool)
        for x, y, z in np.ndindex(map_data.shape):
            p = Point(x, y) if map_size.n_dim == 2 else Point(x, y, z)
            i = self._services.algorithm.map.at(p)
            if i == Map.WALL_ID:
                map_data[x, y, z] = MapData.OBSTACLE_MASK
                self.__cube_modified[x, y, z] = False
            elif i == Map.EXTENDED_WALL_ID:
                map_data[x, y, z] = MapData.EXTENDED_WALL_MASK | MapData.TRAVERSABLE_MASK
                self.__cube_modified[x, y, z] = True
                extended_walls = True
            elif i == Map.UNMAPPED_ID:
                map_data[x, y, z] = MapData.UNMAPPED_MASK
                self.__cube_modified[x, y, z] = False
            else:
                map_data[x, y, z] = MapData.TRAVERSABLE_MASK
                self.__cube_modified[x, y, z] = True

        if map_size.n_dim == 2:
            self.__map = FlatMap(self._services, map_data, self.world)
            self.__set_cube_colour = lambda p, c, wfc: self.map.render_square(p, c, wfc)
        else:
            self.__map = VoxelMap(self._services, map_data, self.world)
            self.__set_cube_colour = lambda p, c, *discard: self.map.traversables_mesh.set_cube_colour(p, c)
        self.__map.center()

        self.__overlay = self.map.root.attach_new_node("overlay")
        self.__scratch = self.map.root.attach_new_node("scratch")
        self.renderer.push_root(self.__scratch)

        self.__entities_map_display = None
        self.__weight_grid_display = None
        self.__extended_walls_display = None

        self.__persistent_displays = [EntitiesMapDisplay(self._services)]
        self.__entities_map_display = self.__persistent_displays[-1]

        if extended_walls:
            grid = TrackedGrid(self.map.data, copy=False)
            dc = self._services.state.views.add_colour("extended wall", Colour(0.5).with_a(0.5))
            self.__persistent_displays.append(SolidGridMapDisplay(self._services, grid, dc, z_index=0, comparator=lambda x: bool(x & MapData.EXTENDED_WALL_MASK)))
            self.__extended_walls_display = self.__persistent_displays[-1]

        if hasattr(self._services.algorithm.map, "weight_grid"):
            mp = self._services.algorithm.map
            wg = TrackedGrid(mp.weight_grid, copy=False)
            dc_min = self._services.state.views.add_colour("min occupancy", BLACK.with_a(0))
            dc_max = self._services.state.views.add_colour("max occupancy", BLACK)
            display = GradientGridMapDisplay(self._services, wg, min_colour=dc_min, max_colour=dc_max, value_bounds=(0.1, mp.traversable_threshold))
            self.__persistent_displays.append(display)
            self.__weight_grid_display = self.__persistent_displays[-1]

        self.__deduced_traversables_colour = self._services.state.views.effective_view.colours[MapData.TRAVERSABLES]()
        self.__deduced_traversables_wf_colour = self._services.state.views.effective_view.colours[MapData.TRAVERSABLES_WF]()

        self.__sphere_scale = 0.2
        """
        def rescale_sphere(dim):
            while (self.__sphere_scale < 0.75) and ((self.__sphere_scale * dim) < 8):
                self.__sphere_scale *= 1.25
        rescale_sphere(self.map.logical_w)
        rescale_sphere(self.map.logical_h)
        rescale_sphere(self.map.logical_d)
        """

        self.__circle_filled_radius = 0.06

        def resize_circle_filled(dim):
            if dim < 40:
                pass
            elif dim < 75:
                dim /= 1.5
            elif dim < 100:
                dim /= 2
            while (self.__circle_filled_radius < 1) and (dim / self.__circle_filled_radius > 250):
                self.__circle_filled_radius *= 1.25

        resize_circle_filled(self.map.logical_w)
        resize_circle_filled(self.map.logical_h)
        resize_circle_filled(self.map.logical_d)

        self.__line_thickness = 2.5

        def change_line_thickness(dim):
            while (self.__line_thickness < 4) and (dim / self.__line_thickness > 160):
                self.__line_thickness *= 1.25

        change_line_thickness(self.map.logical_w)
        change_line_thickness(self.map.logical_h)
        change_line_thickness(self.map.logical_d)
        self.renderer.line_segs.set_thickness(self.__line_thickness)

        self.__update_view(True)
        self._services.ev_manager.broadcast(StateInitialisedEvent())
Beispiel #13
0
from structures import Colour
from utility.compatibility import Final

WINDOW_BG_COLOUR: Final[Colour] = Colour(0.5, 0.5, 0.5, 1.0)
WIDGET_BG_COLOUR: Final[Colour] = Colour(0.3, 0.3, 0.3, 1.0)
 def get_cube_colour(self, p: Point) -> Colour:
     return Colour(*self.__cubes[p.values].get_color())
Beispiel #15
0
class MapData(ABC):
    _services: Services
    __name: Final[str]
    __root: Final[NodePath]
    __colour_callbacks: Dict[str, Callable[[DynamicColour], None]]

    TRAVERSABLE_MASK: Final = np.uint8(1 << 0)
    OBSTACLE_MASK: Final = np.uint8(1 << 1)
    UNMAPPED_MASK: Final = np.uint8(1 << 2)
    EXTENDED_WALL_MASK: Final = np.uint8(1 << 3)

    data: Final[NDArray[(Any, Any, Any), np.uint8]]

    # REQUIRED COLOURS / COMPONENTS #
    BG: Final[str] = "background"

    # OPTIONAL COLOURS / COMPONENTS #
    TRAVERSABLES: Final[str] = "traversables"
    TRAVERSABLES_WF: Final[str] = "traversables w.f."
    OBSTACLES: Final[str] = "obstacles"
    OBSTACLES_WF: Final[str] = "obstacles w.f."
    AGENT: Final[str] = "agent"
    TRACE: Final[str] = "trace"
    GOAL: Final[str] = "goal"

    _DEFAULTS: Final[Dict[str, Colour]] = {
        BG: Colour(0, 0, 0.2, 1),
        TRAVERSABLES: WHITE,
        TRAVERSABLES_WF: BLACK,
        OBSTACLES: BLACK,
        OBSTACLES_WF: WHITE,
        AGENT: Colour(0.8, 0, 0),
        TRACE: Colour(0, 0.9, 0),
        GOAL: Colour(0, 0.9, 0)
    }

    logical_w: Final[int]  # x-axis (width)
    logical_h: Final[int]  # y-axis (height)
    logical_d: Final[int]  # z-axis (depth)

    def __init__(self,
                 services: Services,
                 data: NDArray[(Any, Any, Any), bool],
                 parent: NodePath,
                 name: str = "map"):
        self._services = services
        self.__name = name
        self.__colour_callbacks = {}

        self.data = data

        self.logical_w = int(self.data.shape[0])
        self.logical_h = int(self.data.shape[1])
        self.logical_d = int(self.data.shape[2])

        self._services.ev_manager.register_listener(self)

        self.__root = parent.attach_new_node(self.name)
        self.root.set_transparency(TransparencyAttrib.M_alpha)

        self._add_colour(MapData.BG,
                         callback=lambda dc: self._services.graphics.window.
                         set_background_color(*dc()))

    def notify(self, event: Event) -> None:
        if isinstance(event, ColourUpdateEvent):
            if event.colour.name in self.__colour_callbacks:
                self.__colour_callbacks[event.colour.name](event.colour)

    @property
    @abstractmethod
    def dim(self) -> int:
        ...

    @property
    def root(self) -> NodePath:
        return self.__root

    @property
    def name(self) -> NodePath:
        return self.__name

    def _add_colour(
        self,
        name: str,
        default_colour: Optional[Colour] = None,
        default_visible: bool = True,
        invoke_callback: bool = True,
        callback: Optional[Callable[[DynamicColour], None]] = None
    ) -> DynamicColour:
        if default_colour is None:
            default_colour = MapData._DEFAULTS[name]
        dc = self._services.state.views.add_colour(name, default_colour,
                                                   default_visible)
        if callback is None:
            return dc
        if name not in self.__colour_callbacks:
            self.__colour_callbacks[name] = callback
        if invoke_callback:
            callback(dc)
        return dc

    def center(self) -> None:
        world = self.root.get_parent()
        (x1, y1, z1), (x2, y2, z2) = self.root.get_tight_bounds()
        self.root.set_pos(world.getX() - (x2 - x1) / 2,
                          world.getY() - (y2 - y1) / 2,
                          world.getZ() - (z2 - z1) / 2)

    def destroy(self) -> None:
        self.__root.remove_node()
        self._services.ev_manager.unregister_listener(self)
 def _from_json(self, data: Dict[str, Any]) -> None:
     for n, c in data["colours"].items():
         colour = Colour(*c["colour"])
         visible = bool(c["visible"])
         self.colours[n] = DynamicColour(colour, n, self.__colour_callback, visible)