irsim.world.map =============== .. py:module:: irsim.world.map Submodules ---------- .. toctree:: :maxdepth: 1 /api/irsim/world/map/grid_map_generator_base/index /api/irsim/world/map/image_map_generator/index /api/irsim/world/map/obstacle_map/index /api/irsim/world/map/perlin_map_generator/index Classes ------- .. autoapisummary:: irsim.world.map.GridMapGenerator irsim.world.map.ImageGridGenerator irsim.world.map.ObstacleMap irsim.world.map.PerlinGridGenerator irsim.world.map.EnvGridMap irsim.world.map.Map Functions --------- .. autoapisummary:: irsim.world.map.resolve_obstacle_map irsim.world.map.build_grid_from_generator Package Contents ---------------- .. py:class:: GridMapGenerator(**kwargs: Any) Bases: :py:obj:`abc.ABC` Abstract base for procedural grid map generators. Subclasses must implement _build_grid() and set class attributes name (for YAML) and yaml_param_names (allowed constructor params from YAML). Subclasses accept their own parameters via kwargs. .. py:attribute:: registry :type: ClassVar[dict[str, type[GridMapGenerator]]] .. py:attribute:: name :type: str :value: '' .. py:attribute:: yaml_param_names :type: tuple[str, Ellipsis] :value: () .. py:method:: generate() -> GridMapGenerator Build the grid and return self. Call _build_grid() and set _grid. .. py:property:: grid :type: numpy.ndarray Occupancy grid (0-100). Generates on first access if needed. .. py:method:: save_as_image(filepath: str, invert: bool = True) -> None Save grid as grayscale PNG for use with World.gen_grid_map(). .. py:method:: preview(title: str = 'Grid Map', cmap: str = 'gray_r') -> None Display the occupancy grid with matplotlib. .. py:class:: ImageGridGenerator(path: str, **kwargs: Any) Bases: :py:obj:`irsim.world.map.grid_map_generator_base.GridMapGenerator` Load obstacle grid from an image file (path). Subclasses accept their own parameters via kwargs. .. py:attribute:: name :value: 'image' .. py:attribute:: yaml_param_names :value: ('path',) .. py:attribute:: path .. py:class:: ObstacleMap(shape: dict | None = None, color: str = 'k', static: bool = True, grid_map: numpy.ndarray | None = None, grid_reso: numpy.ndarray | None = None, world_offset: list[float] | None = None, **kwargs: Any) Bases: :py:obj:`irsim.world.object_base.ObjectBase` Base class representing a generic object in the robot simulator. This class encapsulates common attributes and behaviors for all objects, including robots and obstacles, managing their state, velocity, goals, and kinematics. :param shape: Parameters defining the shape of the object for geometry creation. The dictionary should contain keys and values required by the GeometryFactory to create the object's geometry, such as 'type' (e.g., 'circle', 'rectangle') and associated parameters. Defaults to None. :type shape: dict :param kinematics: Parameters defining the kinematics of the object. Includes kinematic model and any necessary parameters. If None, no kinematics model is applied. Defaults to None. :type kinematics: dict :param state: Initial state vector [x, y, theta, ...]. The state can have more dimensions depending on `state_dim`. Excess dimensions are truncated, and missing dimensions are filled with zeros. Defaults to [0, 0, 0]. :type state: list of float :param velocity: Initial velocity vector [vx, vy] or according to the kinematics model. Defaults to [0, 0]. :type velocity: list of float :param goal: Goal state vector [x, y, theta, ...] or [[x, y, theta], [x, y, theta], ...] for multiple goals Used by behaviors to determine the desired movement. Defaults to [10, 10, 0]. :type goal: list of float or list of list of float :param role: Role of the object in the simulation, e.g., "robot" or "obstacle". Defaults to "obstacle". :type role: str :param color: Color of the object when plotted. Defaults to "k" (black). :type color: str :param static: Indicates if the object is static (does not move). Defaults to False. :type static: bool :param vel_min: Minimum velocity limits for each control dimension. Used to constrain the object's velocity. Defaults to [-1, -1]. :type vel_min: list of float :param vel_max: Maximum velocity limits for each control dimension. Used to constrain the object's velocity. Defaults to [1, 1]. :type vel_max: list of float :param acce: Acceleration limits, specifying the maximum change in velocity per time step. Defaults to [inf, inf]. :type acce: list of float :param angle_range: Allowed range of orientation angles [min, max] in radians. The object's orientation will be wrapped within this range. Defaults to [-pi, pi]. :type angle_range: list of float :param behavior: Behavioral mode or configuration of the object. Can be a behavior name (str) or a dictionary with behavior parameters. If None, default behavior is applied. Defaults to {'name': 'dash'}, moving to the goal directly. :type behavior: dict or str :param group_behavior: Shared behavior defaults for objects in the same group. When an object's own behavior configuration is empty or missing, the group behavior will be used as a fallback and exposed via `beh_config`. :type group_behavior: dict :param goal_threshold: Threshold distance to determine if the object has reached its goal. When the object is within this distance to the goal, it's considered to have arrived. Defaults to 0.1. :type goal_threshold: float :param sensors: List of sensor configurations attached to the object. Each sensor configuration is a dictionary specifying sensor type and parameters. Defaults to None. :type sensors: list of dict :param arrive_mode: Mode for arrival detection, either "position" or "state". Determines how arrival at the goal is evaluated. Defaults to "position". :type arrive_mode: str :param description: Description or label for the object. Can be used for identification or attaching images in plotting. Defaults to None. :type description: str :param group: Group identifier for organizational purposes, allowing objects to be grouped. Defaults to 0. :type group: int :param state_dim: Dimension of the state vector. If None, it is inferred from the class attribute `state_shape`. Defaults to None. :type state_dim: int :param vel_dim: Dimension of the velocity vector. If None, it is inferred from the class attribute `vel_shape`. Defaults to None. :type vel_dim: int :param unobstructed: Indicates if the object should be considered to have an unobstructed path, ignoring obstacles in certain scenarios. Defaults to False. :type unobstructed: bool :param fov: Field of view angles in radians for the object's sensors. Defaults to None. If set lidar, the default value is angle range of lidar. :type fov: float :param fov_radius: Field of view radius for the object's sensors. Defaults to None. If set lidar, the default value is range_max of lidar. :type fov_radius: float :param \*\*kwargs: Additional keyword arguments for extended functionality. - plot (dict): Plotting options for the object. May include 'show_goal', 'show_text', 'show_arrow', 'show_uncertainty', 'show_trajectory', 'trail_freq', etc. :raises ValueError: If dimension parameters do not match the provided shapes or if input parameters are invalid. .. attribute:: state_dim Dimension of the state vector. :type: int .. attribute:: state_shape Shape of the state array. :type: tuple .. attribute:: vel_dim Dimension of the velocity vector. :type: int .. attribute:: vel_shape Shape of the velocity array. :type: tuple .. attribute:: state Current state of the object. :type: np.ndarray .. attribute:: _init_state Initial state of the object. :type: np.ndarray .. attribute:: _velocity Current velocity of the object. :type: np.ndarray .. attribute:: _init_velocity Initial velocity of the object. :type: np.ndarray .. attribute:: _goal Goal state of the object. :type: np.ndarray .. attribute:: _init_goal Initial goal state of the object. :type: np.ndarray .. attribute:: _geometry Geometry representation of the object. :type: any .. attribute:: group Group identifier for the object. :type: int .. attribute:: stop_flag Flag indicating if the object should stop. :type: bool .. attribute:: arrive_flag Flag indicating if the object has arrived at the goal. :type: bool .. attribute:: collision_flag Flag indicating a collision has occurred. :type: bool .. attribute:: unobstructed Indicates if the object has an unobstructed path. :type: bool .. attribute:: static Indicates if the object is static. :type: bool .. attribute:: vel_min Minimum velocity limits. :type: np.ndarray .. attribute:: vel_max Maximum velocity limits. :type: np.ndarray .. attribute:: color Color of the object. :type: str .. attribute:: role Role of the object (e.g., "robot", "obstacle"). :type: str .. attribute:: info Information container for the object. :type: ObjectInfo .. attribute:: wheelbase Distance between the front and rear wheels. Specified for ackermann robots. :type: float .. attribute:: fov Field of view angles in radians. :type: float .. attribute:: fov_radius Field of view radius. :type: float Create an obstacle map object from a set of line segments. :param shape: Map shape configuration with keys like ``{"name": "map", "reso": float, "points": array}``. :type shape: dict | None :param color: Display color. Default "k". :type color: str :param static: Whether the object is static. Default True. :type static: bool :param grid_map: Grid map array for fast collision detection. :type grid_map: np.ndarray | None :param grid_reso: Resolution [x_reso, y_reso] of the grid. :type grid_reso: np.ndarray | None :param world_offset: World offset [x, y]. :type world_offset: list | None :param \*\*kwargs: Forwarded to ``ObjectBase`` constructor. .. py:attribute:: linestrings .. py:attribute:: geometry_tree .. py:attribute:: grid_map :value: None .. py:attribute:: grid_reso :value: None .. py:attribute:: world_offset :value: None .. py:method:: check_grid_collision(geometry) -> bool Check collision using grid array lookup. Uses a two-phase approach: 1. Quick bounding box check for early rejection 2. Precise check: verify if geometry actually intersects occupied cells :param geometry: Shapely geometry object to check collision for. :returns: True if collision detected, False otherwise. :rtype: bool .. py:method:: is_collision(geometry) -> bool Check collision against grid (if present) and map geometry. .. py:class:: PerlinGridGenerator(width: int, height: int, complexity: float = 0.142857, fill: float = 0.38, fractal: int = 1, attenuation: float = 0.5, seed: int | None = None) Bases: :py:obj:`irsim.world.map.grid_map_generator_base.GridMapGenerator` Perlin noise based 2D occupancy grid map. Holds width, height, and a grid of occupancy values (0-100; values > 50 are obstacles). Parameter semantics follow GCOPTER map_gen (https://github.com/ZJU-FAST-Lab/GCOPTER). Output can be saved as PNG for use with World.gen_grid_map(). Initialize map parameters. :param width: Map width in grid cells. :type width: int :param height: Map height in grid cells. :type height: int :param complexity: Base noise frequency. Default 0.142857. :type complexity: float :param fill: Obstacle ratio in [0, 1]. Default 0.38. :type fill: float :param fractal: Number of octave layers. Default 1. Must be >= 1. :type fractal: int :param attenuation: Amplitude decay per octave. Default 0.5. Must be > 0. :type attenuation: float :param seed: Random seed for reproducibility. :type seed: int | None .. py:attribute:: name :value: 'perlin' .. py:attribute:: yaml_param_names :value: ('complexity', 'fill', 'fractal', 'attenuation', 'seed') .. py:attribute:: width .. py:attribute:: height .. py:attribute:: complexity :value: 0.142857 .. py:attribute:: fill :value: 0.38 .. py:attribute:: fractal :value: 1 .. py:attribute:: attenuation :value: 0.5 .. py:attribute:: seed :value: None .. py:method:: preview(title: str = 'Perlin 2D Map', cmap: str = 'gray_r') -> None Preview the grid with matplotlib. .. py:class:: EnvGridMap Bases: :py:obj:`Protocol` Structural type accepted by all path planners. Any object that exposes the attributes below (including :class:`Map`) is a valid ``EnvGridMap``. Planners should annotate their *env_map* parameter with this protocol instead of the concrete :class:`Map` class to support duck-typed map objects. Collision precedence (adopted by every planner): 1. Grid lookup (O(1) per cell) when *grid* is not ``None``; if the grid reports occupied, the point is in collision. 2. When the grid reports free or is unavailable, Shapely geometry intersection with *obstacle_list* is used. Planners therefore combine grid and obstacle_list when both are present. .. py:attribute:: width :type: float .. py:attribute:: height :type: float .. py:attribute:: resolution :type: float .. py:attribute:: obstacle_list :type: list .. py:attribute:: grid :type: numpy.ndarray | None .. py:attribute:: world_offset :type: tuple[float, float] .. py:property:: grid_resolution :type: tuple[float, float] | None Actual cell size ``(x_reso, y_reso)`` derived from *grid* shape and world size. .. py:method:: grid_occupied(x: float, y: float, margin_x: float = 0.0, margin_y: float = 0.0, threshold: float = 50.0) -> bool | None Check if any grid cell within the bounding box is occupied. .. py:method:: is_collision(geometry) -> bool Check collision for a Shapely geometry against the map. .. py:function:: resolve_obstacle_map(obstacle_map: str | numpy.ndarray | dict[str, Any] | None = None, world_width: float | None = None, world_height: float | None = None) -> numpy.ndarray | None Resolve obstacle_map to None or a float64 occupancy grid ndarray. Accepted types: ``None``, ndarray, or a generator spec **dict** with ``name`` (e.g. ``"image"`` or ``"perlin"``). For backward compatibility, a **str** is treated as ``{"name": "image", "path": obstacle_map}``. - ``name == "image"``: only ``path`` is required; grid size comes from the image. - Other names (e.g. ``"perlin"``): require ``resolution`` and world size (``world_width`` / ``world_height``); grid size = world size / resolution. :returns: None, or ndarray (0-100 grid, dtype float64). .. py:function:: build_grid_from_generator(spec: dict[str, Any], world_width: float, world_height: float) -> numpy.ndarray Build a grid map from a YAML grid_generator spec (name + resolution + params). Grid size is always computed from world size and ``resolution`` (meters per cell): (world_width / resolution, world_height / resolution) cells. :param spec: Dict from YAML, e.g. ``{name: perlin, resolution: 0.1, ...}``. :param world_width: World width in meters. :param world_height: World height in meters. :returns: Occupancy grid (0-100) as float64 ndarray. .. py:class:: Map(width: float = 10, height: float = 10, resolution: float = 0.1, obstacle_list: list | None = None, grid: numpy.ndarray | None = None, world_offset: tuple[float, float] | list[float] | None = None) Map data container for navigation / path-planning. Satisfies the :class:`EnvGridMap` protocol so that it can be passed to any planner that expects ``EnvGridMap``. Collision precedence (shared by all planners): 1. Grid lookup (O(1) per cell) when *grid* is not ``None``. 2. Shapely geometry intersection when *grid* is unavailable. Initialize the Map. :param width: Width of the world (metres). :param height: Height of the world (metres). :param resolution: Planner discretisation cell size (metres/cell). :param obstacle_list: Obstacle objects for Shapely collision detection. :param grid: Occupancy grid (0-100) for grid-based collision detection. :param world_offset: World origin (x, y) for grid indexing. When non-zero, geometry and positions are interpreted in world coordinates so grid lookups align with ObstacleMap. Default (0, 0). .. py:attribute:: width :value: 10 .. py:attribute:: height :value: 10 .. py:attribute:: resolution :value: 0.1 .. py:attribute:: obstacle_list :value: None .. py:attribute:: grid :value: None .. py:attribute:: world_offset .. py:property:: grid_resolution :type: tuple[float, float] | None Actual cell size ``(x_reso, y_reso)`` derived from *grid* shape and world size. Returns ``None`` when no grid is present. .. py:method:: grid_occupied(x: float, y: float, margin_x: float = 0.0, margin_y: float = 0.0, threshold: float = 50.0) -> bool | None Check if any grid cell within the bounding box around ``(x, y)`` is occupied. The bounding box extends *margin_x* / *margin_y* (in world metres) in each direction. Grid cells whose occupancy exceeds *threshold* are considered occupied. :returns: ``None`` when no grid is present (caller should fall back to Shapely or another collision method). ``True`` / ``False`` otherwise. Points outside the world bounds are treated as occupied so planners cannot escape the map. .. py:method:: is_collision(geometry) -> bool Check collision for a Shapely geometry against grid + obstacles. Collision precedence: 1. Grid lookup when *grid* is not None; if occupied, collision. 2. When the grid reports free or is unavailable, Shapely geometry intersection with *obstacle_list*.