diff --git a/pyrobosim/pyrobosim/core/room.py b/pyrobosim/pyrobosim/core/room.py index f6e58343..2391f495 100644 --- a/pyrobosim/pyrobosim/core/room.py +++ b/pyrobosim/pyrobosim/core/room.py @@ -11,6 +11,7 @@ from ..utils.pose import Pose from ..utils.polygon import inflate_polygon, polygon_and_height_from_footprint from ..utils.search_graph import Node +from ..utils.general import parse_color class Room: @@ -44,7 +45,7 @@ def __init__( """ self.name = name self.wall_width = wall_width - self.viz_color = self._parse_color(color) + self.viz_color = parse_color(color) # Entities associated with the room self.hallways = [] @@ -74,29 +75,6 @@ def __init__( else: self.nav_poses = [Pose.from_list(self.centroid)] - def _parse_color(self, color): - """ - Parses a color input and returns an RGB tuple. - - :param color: Input color as a list, string, or hexadecimal. - :type color: list[float] | str - :return: RGB tuple in range (0.0, 1.0). - :rtype: list[float] - """ - if isinstance(color, list) and len(color) == 3: - return color - elif isinstance(color, str): - if color in CSS4_COLORS: - return list(to_rgb(CSS4_COLORS[color])) - try: - return list(to_rgb(color)) - except ValueError: - raise ValueError(f"Invalid color string or hex: {color}") - else: - raise ValueError( - f"Unsupported color format. Supported types are list[float] and string" - ) - def update_collision_polygons(self, inflation_radius=0): """ Updates the collision polygons using the specified inflation radius. diff --git a/pyrobosim/pyrobosim/utils/general.py b/pyrobosim/pyrobosim/utils/general.py index 36e764f5..ac3b62e6 100644 --- a/pyrobosim/pyrobosim/utils/general.py +++ b/pyrobosim/pyrobosim/utils/general.py @@ -2,6 +2,8 @@ import os import yaml +import re +from matplotlib.colors import CSS4_COLORS, to_rgb def get_data_folder(): @@ -99,3 +101,30 @@ def replace_special_yaml_tokens(in_text, root_dir=None): out_text = out_text.replace("$PWD", root_dir) return out_text + + +def parse_color(color): + """ + Parses a color input and returns an RGB tuple. + + :param color: Input color as a list, string, or hexadecimal. + :type color: list[float] | str + :return: RGB tuple in range (0.0, 1.0). + :rtype: list[float] + """ + if isinstance(color, list) and len(color) == 3: + return color + + if isinstance(color, str): + if color in CSS4_COLORS: + return list(to_rgb(CSS4_COLORS[color])) + + hex_pattern = r"^#(?:[0-9a-fA-F]{3}){1,2}$" + if re.match(hex_pattern, color): + return list(to_rgb(color)) + + raise ValueError(f"Invalid color string or hex: {color}") + + raise ValueError( + f"Unsupported color format. Supported types are list[float] and string" + )