Source code for genesis.engine.materials.rigid

from typing import TYPE_CHECKING, Annotated, Any, Literal

from pydantic import Field, StrictBool, model_validator

import genesis as gs
from genesis.typing import NonNegativeFloat, PositiveFloat, StrictInt, StrArrayType, ValidFloat

from .kinematic import Kinematic

if TYPE_CHECKING:
    from genesis.engine.entities.rigid_entity import RigidEntity

CoupType = Literal["two_way_soft_constraint", "external_articulation", "ipc_only"]


[docs]class Rigid(Kinematic["RigidEntity"]): """ The Rigid class represents a material used in rigid body simulation. Note ---- This class is intended for use with the rigid solver and provides parameters relevant to physical interactions such as friction, density, and signed distance fields (SDFs). Parameters ---------- rho : float or None, optional The density of the material used to estimate mass if necessary. When None, the default depends on context: 1000 kg/m^3 if MuJoCo compatibility is enabled (``RigidOptions.enable_mujoco_compatibility``), otherwise 600 kg/m^3 for basic rigid objects (mug, table...) vs 1500 kg/m^3 for poly-articulated robots. Default is None. friction : float, optional Friction coefficient within the rigid solver. If None, a default of 1.0 may be used or parsed from file. needs_coup : bool, optional Whether the material participates in coupling with other solvers. Default is True. coup_friction : float, optional Friction used during coupling. Must be non-negative. Default is 0.1. coup_softness : float, optional Softness of coupling interaction. Must be non-negative. Default is 0.002. coup_restitution : float, optional Restitution coefficient in collision coupling. Should be between 0 and 1. Default is 0.0. sdf_cell_size : float, optional Cell size in SDF grid in meters. Defines grid resolution. Default is 0.005. sdf_min_res : int, optional Minimum resolution of the SDF grid. Must be at least 16. Default is 32. sdf_max_res : int, optional Maximum resolution of the SDF grid. Must be >= sdf_min_res. Default is 128. gravity_compensation : float, optional Compensation factor for gravity. 1.0 cancels gravity. Default is 0. coup_type : str or None, optional Coupling mode for this entity. Only used by the IPC coupler. Requires ``needs_coup=True``. If None, auto-selected based on entity type: ``'external_articulation'`` for fixed-base articulated robots, ``'two_way_soft_constraint'`` for floating-base robots, and ``'ipc_only'`` for non-articulated objects. Valid values: - 'two_way_soft_constraint': Two-way soft coupling. - 'external_articulation': Joint-level coupling for articulated bodies. Joint positions will be coupled at the DOF level. - 'ipc_only': IPC controls entity, transforms copied to Genesis (one-way). Only supported by rigid non-articulated objects. Default is None. coup_links : tuple of str or None, optional Tuple of link names to include in coupling. When set, only the named links participate in coupling; other links are excluded. Only supported with needs_coup=True and ``two_way_soft_constraint`` type in IPC. Default is None. enable_coup_collision : bool, optional Whether coupler collision is enabled for this entity's links. Only used by the IPC coupler. Unlike ``needs_coup=False`` (which removes the entity from the coupler entirely), setting this to False keeps the entity in the coupler for coupling forces but disables contact response. Default is True. coup_collision_links : tuple of str or None, optional Tuple of link names whose geoms participate in coupler collision. Only used by the IPC coupler. Only effective when ``enable_coup_collision=True``. If None, all coupled links have collision. When set, only the named links get coupler collision; other links are marked no-collision. Default is None. contact_resistance : float or None, optional IPC coupling contact resistance/stiffness override for this entity. ``None`` means use ``IPCCouplerOptions.contact_resistance``. Default is None. """ use_visual_raycasting: StrictBool = False rho: ValidFloat | None = None friction: Annotated[ValidFloat, Field(ge=0.01, le=5.0)] | None = None needs_coup: StrictBool = True coup_friction: NonNegativeFloat = 0.1 coup_softness: NonNegativeFloat = 0.002 coup_restitution: Annotated[ValidFloat, Field(ge=0.0, le=1.0)] = 0.0 sdf_cell_size: PositiveFloat = 0.005 sdf_min_res: Annotated[StrictInt, Field(ge=16)] = 32 sdf_max_res: Annotated[StrictInt, Field(ge=16)] = 128 gravity_compensation: ValidFloat = 0.0 coup_type: CoupType | None = None coup_links: StrArrayType | None = None enable_coup_collision: StrictBool = True coup_collision_links: StrArrayType | None = None contact_resistance: PositiveFloat | None = None @model_validator(mode="before") @classmethod def _resolve_defaults(cls, data: dict) -> dict: # ipc_only entities have their dynamics fully controlled by IPC (gravity + collision). # Genesis gravity must be disabled to avoid double-counting. if data.get("coup_type") == "ipc_only": grav_comp = data.get("gravity_compensation") if grav_comp is not None and grav_comp != 0.0: gs.raise_exception( "`gravity_compensation` must be 0 with coup_type='ipc_only'. " "IPC controls gravity for ipc_only entities." ) data["gravity_compensation"] = 0.0 return data
[docs] def model_post_init(self, context: Any) -> None: if self.coup_type is not None and not self.needs_coup: gs.raise_exception( "`coup_type` is only supported with needs_coup=True. " f"Got needs_coup={self.needs_coup}, coup_type={self.coup_type!r}." ) if self.coup_links is not None and ( not self.needs_coup or self.coup_type not in (None, "two_way_soft_constraint") ): gs.raise_exception( "`coup_links` is only supported with needs_coup=True and " f"'two_way_soft_constraint' type in IPC. " f"Got needs_coup={self.needs_coup}, coup_type={self.coup_type!r}." ) if self.coup_collision_links is not None and not self.enable_coup_collision: gs.raise_exception( "`coup_collision_links` is only effective when `enable_coup_collision=True`. " "Set `enable_coup_collision=False` to disable collision for all links." ) if self.sdf_min_res > self.sdf_max_res: gs.raise_exception("`sdf_min_res` must be smaller than or equal to `sdf_max_res`.") if self.coup_restitution != 0: gs.logger.warning("Non-zero `coup_restitution` could lead to instability. Use with caution.")