irsim.env ========= .. py:module:: irsim.env Submodules ---------- .. toctree:: :maxdepth: 1 /api/irsim/env/env_base/index /api/irsim/env/env_base3d/index /api/irsim/env/env_config/index /api/irsim/env/env_logger/index /api/irsim/env/env_plot/index /api/irsim/env/env_plot3d/index Classes ------- .. autoapisummary:: irsim.env.EnvBase irsim.env.EnvBase3D Package Contents ---------------- .. py:class:: EnvBase(world_name: Optional[str] = None, display: bool = True, disable_all_plot: bool = False, save_ani: bool = False, full: bool = False, log_file: Optional[str] = None, log_level: str = 'INFO', seed: Optional[int] = None) The base class for simulation environments in IR-SIM. This class serves as the foundation for creating and managing robotic simulation environments. It reads YAML configuration files (through ``EnvConfig``) to create worlds, robots, obstacles, and map objects, and provides the core simulation loop functionality. The environment supports in-place reload of YAML configuration to update the scene in the existing figure without opening a new window. :param world_name: Path to the world YAML configuration file. If None, the environment will attempt to find a default configuration or use a minimal setup. :type world_name: str, optional :param display: Whether to display the environment visualization. Set to False for headless operation. Default is True. :type display: bool :param disable_all_plot: Whether to disable all plots and figures completely. When True, no visualization will be created even if display is True. Default is False. :type disable_all_plot: bool :param save_ani: Whether to save the simulation as an animation file. Useful for creating videos of simulation runs. Default is False. :type save_ani: bool :param full: Whether to display the visualization in full screen mode. Only effective on supported platforms. Default is False. :type full: bool :param log_file: Path to the log file for saving simulation logs. If None, logs will only be output to console. :type log_file: str, optional :param log_level: Logging level for the environment. Options include 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'. Default is 'INFO'. :type log_level: str :param seed: Seed for the random number generator. Default is None. If None, the seed will be set to a random value, which will make the simulation non-reproducible. If a fixed seed is provided, the random simulation scenario will be reproducible. :type seed: int, optional .. attribute:: display Whether to display the environment visualization. :type: bool .. attribute:: disable_all_plot Whether all plotting is disabled. :type: bool .. attribute:: save_ani Whether to save animation during simulation. :type: bool .. attribute:: env_config Configuration loader managing YAML parsing and object creation. :type: EnvConfig .. attribute:: keyboard Keyboard input handler for manual control. :type: KeyboardControl .. attribute:: mouse Mouse input handler for zoom and pan. :type: MouseControl .. attribute:: pause_flag Internal flag indicating if simulation is paused. :type: bool .. attribute:: quit_flag Internal flag indicating if simulation should quit. :type: bool .. attribute:: debug_flag Internal flag for debug mode (frame-by-frame stepping). :type: bool .. attribute:: debug_count Counter for debug mode frames. :type: int .. attribute:: reset_flag Internal flag for environment reset. :type: bool .. attribute:: reload_flag Internal flag for YAML reload. :type: bool .. attribute:: save_figure_flag Internal flag to save current figure. :type: bool .. rubric:: Example >>> # Create a basic environment >>> env = EnvBase("my_world.yaml") >>> >>> # Create headless environment for training >>> env = EnvBase("world.yaml", display=False, log_level="WARNING") >>> >>> # Create environment with animation saving >>> env = EnvBase("world.yaml", save_ani=True, full=True) >>> >>> # Create environment with a fixed seed for reproducibility >>> env = EnvBase("world.yaml", seed=42) .. py:attribute:: display :value: True .. py:attribute:: disable_all_plot :value: False .. py:attribute:: save_ani :value: False .. py:attribute:: mouse .. py:attribute:: pause_flag :value: False .. py:attribute:: quit_flag :value: False .. py:attribute:: debug_flag :value: False .. py:attribute:: debug_count :value: 0 .. py:attribute:: reset_flag :value: False .. py:attribute:: reload_flag :value: False .. py:attribute:: save_figure_flag :value: False .. py:method:: step(action: Optional[Union[numpy.ndarray, list[Any]]] = None, action_id: Optional[Union[int, list[int]]] = 0) -> None Perform a single simulation step in the environment. This method advances the simulation by one time step, applying the given actions to the specified robots and updating all objects in the environment. :param action: Action(s) to be performed in the environment. Can be a single action or a list of actions. Action format depends on robot type: - **Differential robot**: [linear_velocity, angular_velocity] - **Omnidirectional robot**: [velocity_x, velocity_y] - **Ackermann robot**: [linear_velocity, steering_angle] If None, robots will use their default behavior or keyboard control if enabled. :type action: Union[np.ndarray, list], optional Note - Priority Order: 1. Apply keyboard control for the specified ``action_id`` if enabled. 2. Apply the provided ``action`` (list of numpy arrays) to robots by ``action_id`` (int or list of int). 3. For remaining robots, fall back to their configured behaviors when ``action`` is ``None``. action_id (Union[int, list], optional): ID(s) of the robot(s) to apply the action(s) to. Can be a single robot ID or a list of IDs. Default is 0 (first robot). If action is a list and action_id is a single int, all actions will be applied to robots sequentially starting from action_id. .. note:: - If the environment is paused, this method returns without performing any updates. - The method automatically handles collision detection, status updates, and plotting. - In keyboard control mode, the action parameter is ignored and keyboard input is used. .. rubric:: Example >>> # Move first robot with differential drive >>> env.step([1.0, 0.5]) # 1.0 m/s forward, 0.5 rad/s turn >>> >>> # Move specific robot by ID >>> env.step([0.8, 0.0], action_id=2) # Move robot with ID 2 >>> >>> # Move multiple robots >>> actions = [[1.0, 0.0], [0.5, 0.3]] >>> env.step(actions, action_id=[0, 1]) # Move robots 0 and 1 .. py:method:: render(interval: float = 0.01, figure_kwargs: Optional[dict[str, Any]] = None, mode: str = 'dynamic', **kwargs: Any) -> None Render the environment. :param interval: Time interval between frames in seconds. :type interval: float :param figure_kwargs: Additional keyword arguments for saving figures, see `savefig `_ for details. :type figure_kwargs: dict :param mode: One of {"dynamic", "static", "all"} specifying which types of objects to draw and clear each frame. :type mode: str :param kwargs: Additional keyword arguments for drawing components. See :py:meth:`.ObjectBase.plot` for details. .. py:method:: show() -> None Show the environment figure. .. py:method:: draw_trajectory(traj: list[Any], traj_type: str = 'g-', **kwargs: Any) -> None Draw the trajectory on the environment figure. :param traj: List of trajectory points. Each point is a 2x1 vector or an array of shape (2, N). :type traj: list :param traj_type: Matplotlib line style (e.g., "g-", "r--"). :type traj_type: str :param \*\*kwargs: Additional keyword arguments; forwarded to :py:meth:`.EnvPlot.draw_trajectory`. .. py:method:: draw_points(points: list[Any], s: int = 30, c: str = 'b', refresh: bool = True, **kwargs: Any) -> None Draw points on the environment figure. :param points: Either a list of 2x1 points or a numpy array with shape (2, N). :type points: list | np.ndarray :param s: Marker size. :type s: int :param c: Marker color. :type c: str :param refresh: Whether to clear previous points before drawing. :type refresh: bool :param \*\*kwargs: Additional keyword arguments, forwarded to `Axes.scatter `_. .. py:method:: draw_box(vertex: numpy.ndarray, refresh: bool = False, color: str = '-b') -> None Draw a box by the vertices. :param vertex: Vertices matrix with shape (point_dim, num_vertices). :type vertex: np.ndarray :param refresh: Whether to clear previous boxes before drawing. Default is False. :type refresh: bool :param color: Line style/color for the box (e.g., "-b"). :type color: str .. py:method:: draw_quiver(point: Any, refresh: bool = False, **kwargs: Any) -> None Draw a single quiver (arrow) on the environment figure. :param point: A tuple ``(x, y, u, v)`` or compatible structure defining the arrow's origin and vector. :param refresh: Whether to clear previous quiver before drawing. Default False. :type refresh: bool :param \*\*kwargs: Additional keyword arguments for drawing the quiver. .. py:method:: draw_quivers(points: Any, refresh: bool = False, **kwargs: Any) -> None Draw multiple quivers (arrows) on the environment figure. :param points: Iterable of tuples/lists/arrays compatible with ``(x, y, u, v)`` per arrow. :param refresh: Whether to clear previous quivers before drawing. Default False. :type refresh: bool :param \*\*kwargs: Additional keyword arguments for drawing the quivers. .. py:method:: end(ending_time: float = 3.0, **kwargs: Any) -> None End the simulation, save the animation, and close the environment. :param ending_time: Time in seconds to wait before closing the figure, default is 3 seconds. :type ending_time: float :param \*\*kwargs: Additional keyword arguments for saving the animation, see :py:meth:`.EnvPlot.save_animate` for detail. .. py:method:: quit() -> None Quit the environment. .. py:method:: done(mode: str = 'all') -> Optional[bool] Check if the simulation should terminate based on robot completion status. This method evaluates whether robots in the environment have reached their goals or completed their tasks, using different criteria based on the mode. :param mode: Termination condition mode. Options are: - "all": Simulation is done when ALL robots have completed their tasks - "any": Simulation is done when ANY robot has completed its task Default is "all". :type mode: str :returns: True if the termination condition is met based on the specified mode, False otherwise. Returns False if no robots are present in the environment. :rtype: bool .. rubric:: Example >>> # Check if all robots have reached their goals >>> if env.done(mode="all"): ... print("All robots completed!") >>> >>> # Check if any robot has completed >>> if env.done(mode="any"): ... print("At least one robot completed!") .. py:method:: pause() -> None Pause the simulation execution. When paused, calls to :py:meth:`step` will return immediately without performing any simulation updates. The environment status is set to "Pause". .. rubric:: Example >>> env.pause() >>> env.step([1.0, 0.0]) # This will have no effect while paused .. py:method:: resume() -> None Resume the simulation execution after being paused. Re-enables simulation updates and sets the environment status back to "Running". Subsequent calls to :py:meth:`step` will function normally. .. rubric:: Example >>> env.pause() >>> # ... some time later ... >>> env.resume() >>> env.step([1.0, 0.0]) # This will now work again .. py:method:: reset() -> None Reset the environment to its initial state. This method resets all objects, robots, obstacles, and the world to their initial configurations. It also resets the visualization and sets the environment status to "Reset". The reset process includes: - Resetting all objects to their initial positions and states - Clearing accumulated trajectories and sensor data - Resetting the world timer and status - Refreshing the visualization plot .. rubric:: Example >>> # Reset environment after simulation >>> env.reset() >>> # Environment is now ready for a new simulation run .. py:method:: reset_plot() -> None Reset the environment figure in-place. Re-initializes drawing on the current figure/axes using the existing ``EnvPlot`` instance; does not create a new figure window. .. py:method:: random_obstacle_position(range_low: Union[list[float], numpy.ndarray, None] = None, range_high: Union[list[float], numpy.ndarray, None] = None, ids: Optional[list[int]] = None, non_overlapping: bool = False) -> None Random obstacle positions in the environment. :param range_low: Lower bound of the random range for the obstacle states. Default is [0, 0, -3.14]. :type range_low: list [x, y, theta] :param range_high: Upper bound of the random range for the obstacle states. Default is [10, 10, 3.14]. :type range_high: list [x, y, theta] :param ids: A list of IDs of objects for which to set random positions. Default is None. :type ids: list :param non_overlapping: If set, the obstacles that will be reset to random obstacles will not overlap with other obstacles. Default is False. :type non_overlapping: bool .. py:method:: random_polygon_shape(center_range: Optional[list[float]] = None, avg_radius_range: Optional[list[float]] = None, irregularity_range: Optional[list[float]] = None, spikeyness_range: Optional[list[float]] = None, num_vertices_range: Optional[list[int]] = None) -> None Random polygon shapes for the obstacles in the environment. :param center_range: Range of the center of the polygon. Default is [0, 0, 10, 10]. :type center_range: list :param avg_radius_range: Range of the average radius of the polygon. Default is [0.1, 1]. :type avg_radius_range: list :param irregularity_range: Range of the irregularity of the polygon. Default is [0, 1]. :type irregularity_range: list :param spikeyness_range: Range of the spikeyness of the polygon. Default is [0, 1]. :type spikeyness_range: list :param num_vertices_range: Range of the number of vertices of the polygon. Default is [4, 10]. :type num_vertices_range: list :param center: a pair representing the center of the circumference used to generate the polygon. :type center: Tuple[float, float] :param avg_radius: the average radius (distance of each generated vertex to the center of the circumference) used to generate points with a normal distribution. :type avg_radius: float :param irregularity: 0 - 1 variance of the spacing of the angles between consecutive vertices. :type irregularity: float :param spikeyness: 0 - 1 variance of the distance of each vertex to the center of the circumference. :type spikeyness: float :param num_vertices: the number of vertices of the polygon. :type num_vertices: int .. py:method:: reload(world_name: Optional[str] = None) -> None Reload the environment from YAML and update the current figure. This re-parses the YAML and re-creates world/objects, then refreshes drawing on the existing figure/axes (no new window is created). :param world_name: Optional name/path of the world YAML to reload. If ``None``, the previous YAML file is used. :type world_name: str .. py:method:: create_obstacle(**kwargs: Any) Create an obstacle in the environment. :param \*\*kwargs: Additional parameters for obstacle creation. see ObjectFactory.create_obstacle for detail :returns: An instance of an obstacle. :rtype: Obstacle .. py:method:: add_object(obj: irsim.world.ObjectBase) -> None Add the object to the environment, enforcing unique names. :param obj: The object to be added to the environment. :type obj: ObjectBase .. py:method:: add_objects(objs: list[irsim.world.ObjectBase]) -> None Add the objects to the environment, enforcing unique names (both within the new list and against existing objects). :param objs: List of objects to be added to the environment. :type objs: list .. py:method:: delete_object(target_id: int) -> None Delete the object with the given id. :param target_id: ID of the object to be deleted. :type target_id: int .. py:method:: delete_objects(target_ids: list[int]) -> None Delete the objects with the given ids. :param target_ids: List of IDs of objects to be deleted. :type target_ids: list .. py:method:: build_tree() -> None Build the geometry tree for the objects in the environment to detect the possible collision objects. .. py:method:: validate_unique_names() -> None Validate that all object names are unique. :raises ValueError: If duplicates exist. .. py:method:: get_robot_state() -> numpy.ndarray Get the current state of the robot. :returns: 3*1 vector [x, y, theta] :rtype: state .. py:method:: get_lidar_scan(id: int = 0) -> dict[str, Any] Get the LiDAR scan of the robot with the given id. :param id: Id of the robot. :type id: int :returns: Dict of lidar scan points, see :py:meth:`.world.sensors.lidar2d.Lidar2D.get_scan` for detail. :rtype: Dict .. py:method:: get_lidar_offset(id: int = 0) -> list[float] Get the LiDAR offset of the robot with the given id. :param id: Id of the robot. :type id: int :returns: Lidar offset of the robot, [x, y, theta] :rtype: list of float .. py:method:: get_obstacle_info_list() -> list[Any] Get the information of the obstacles in the environment. :returns: List of obstacle information, see :py:meth:`.ObjectBase.get_obstacle_info` for detail. :rtype: list of ObstacleInfo .. py:method:: get_robot_info(id: int = 0) -> Any Get the information of the robot with the given id. :param id: Id of the robot. :type id: int :returns: see :py:meth:`.ObjectBase.get_info` for detail .. py:method:: get_robot_info_list() -> list[Any] Get the information of the robots in the environment. :returns: List of robot information, see :py:meth:`.ObjectBase.get_info` for detail. :rtype: list of ObjectInfo .. py:method:: get_map(resolution: float = 0.1) -> Any Get the map of the environment with the given resolution. :param resolution: Resolution of the map. Default is 0.1. :type resolution: float :returns: The map of the environment with the specified resolution. .. py:method:: get_group_by_name(group_name: str) -> list[irsim.world.ObjectBase] Get the objects with the given group name. :param group_name: Group name of the robot. :type group_name: str :returns: The object list with the given group name. :rtype: list[ObjectBase] .. py:method:: get_object_by_name(name: str) -> Optional[irsim.world.ObjectBase] Get the object with the given name. .. py:method:: get_object_by_id(target_id: int) -> Optional[irsim.world.ObjectBase] Get the object with the given id. .. py:method:: set_title(title: str) -> None Set the title of the plot. .. py:method:: set_random_seed(seed: Optional[int] = None) -> None Set IR-SIM's random seed for reproducibility. :param seed: Seed for IR-SIM's project RNG. If ``None``, a new unseeded generator is created (non-reproducible). This controls randomness that goes through IR-SIM's RNG. Custom code using ``np.random.*`` or Python ``random`` must be seeded separately or migrated to use IR-SIM's RNG. :type seed: int, optional .. py:method:: set_status(status: str) -> None Set the status of the environment. .. py:method:: save_figure(save_name: Optional[str] = None, include_index: bool = False, save_gif: bool = False, **kwargs: Any) -> None Save the current figure. :param save_name: Name of the file with format to save the figure. Default is None. :type save_name: str :param include_index: Flag to include index in the saved file name. Default is False. :type include_index: bool :param save_gif: Flag to save as GIF format. Default is False. :type save_gif: bool :param \*\*kwargs: Additional keyword arguments for saving the figure, see `savefig `_ function for detail. .. py:method:: load_behavior(behaviors: str = 'behavior_methods') -> None Load behavior parameters from the script. Please refer to the behavior_methods.py file for more details. Please make sure the python file is placed in the same folder with the implemented script. This method imports the specified module and reinitializes all behaviors (both individual and group) so that newly registered behaviors are available. :param behaviors: name of the behavior script. :type behaviors: str .. py:property:: robot_list :type: list[irsim.world.ObjectBase] Get the list of robots in the environment. :returns: List of robot objects []. :rtype: list .. py:property:: obstacle_list :type: list[irsim.world.ObjectBase] Get the list of obstacles in the environment. :returns: List of obstacle objects. :rtype: list .. py:property:: objects :type: list[irsim.world.ObjectBase] Get all objects in the environment. :returns: List of all objects in the environment. :rtype: list .. py:property:: static_objects :type: list[irsim.world.ObjectBase] Get all static objects in the environment. :returns: List of static objects in the environment. :rtype: list .. py:property:: dynamic_objects :type: list[irsim.world.ObjectBase] Get all dynamic objects in the environment. :returns: List of dynamic objects in the environment. :rtype: list .. py:property:: step_time :type: float Get the step time of the simulation. :returns: Step time of the simulation from the world. :rtype: float .. py:property:: world_param Get the world parameters of the simulation. :returns: World parameters including time, control_mode, collision_mode, step_time, and count. :rtype: WorldParam .. py:property:: env_param Get the environment parameters. :returns: Environment parameters including logger and objects. :rtype: EnvParam .. py:property:: path_param Get the path manager for the simulation. :returns: Path manager including root_path, ani_buffer_path, ani_path, and fig_path. :rtype: PathManager .. py:property:: time :type: float Get the time of the simulation. .. py:property:: status :type: str Get the status of the environment. .. py:property:: robot :type: irsim.world.ObjectBase Get the first robot in the environment. :returns: The first robot object in the robot list. :rtype: Robot :raises IndexError: If no robots exist in the environment. .. py:property:: obstacle_number :type: int Get the number of obstacles in the environment. :returns: Number of obstacles in the environment. :rtype: int .. py:property:: robot_number :type: int Get the number of robots in the environment. :returns: Number of robots in the environment. :rtype: int .. py:property:: logger :type: irsim.env.env_logger.EnvLogger Get the environment logger. :returns: The logger instance for the environment. :rtype: EnvLogger .. py:property:: key_vel :type: Any Get current keyboard velocity command. :returns: A 2x1 vector ``[[linear], [angular]]`` from keyboard input. :rtype: Any .. py:property:: key_id :type: int Get current keyboard-controlled robot id. :returns: The robot id currently controlled by keyboard. :rtype: int .. py:property:: mouse_pos :type: Any Get current mouse position on the canvas. :returns: Mouse coordinates ``(x, y)`` or ``None`` if outside axes. :rtype: Any .. py:property:: mouse_left_pos :type: Any Get last left-click position. :returns: Position array or ``None`` if not set. :rtype: Any .. py:property:: mouse_right_pos :type: Any Get last right-click position. :returns: Position array or ``None`` if not set. :rtype: Any .. py:property:: names :type: list[str] Get the names of all objects in the environment. .. py:property:: object_factory :type: irsim.world.ObjectFactory Get the object factory of the environment. .. py:class:: EnvBase3D(world_name: Optional[str], **kwargs: Any) Bases: :py:obj:`irsim.env.EnvBase` This class is the 3D version of the environment class. It inherits from the :py:class:`.EnvBase` class to provide the 3D plot environment. Initialize a 3D environment with world and objects parsed from YAML. :param world_name: Path to the world configuration YAML. :type world_name: str | None :param \*\*kwargs: Additional environment options forwarded to ``EnvBase``.