Import upstream snapshot c19f713c415a699a79d71cd96aa13c3104a05047
nightly / Test against latest dependencies (py3.10) (push) Has been cancelled
nightly / Test against latest dependencies (py3.13) (push) Has been cancelled
tests / tests (3.13, locked) (push) Has been cancelled
tests / tests (3.13, unlocked) (push) Has been cancelled
tests / pyright (3.10) (push) Has been cancelled
tests / lint-format (push) Has been cancelled
tests / tests (3.10, locked) (push) Has been cancelled
tests / tests (3.11, locked) (push) Has been cancelled
tests / tests (3.12, locked) (push) Has been cancelled
tests / pyright (3.11) (push) Has been cancelled
tests / pyright (3.12) (push) Has been cancelled
tests / pyright (3.13) (push) Has been cancelled
tests / ty-check (3.10) (push) Has been cancelled
tests / ty-check (3.11) (push) Has been cancelled
tests / ty-check (3.12) (push) Has been cancelled
tests / ty-check (3.13) (push) Has been cancelled
tests / stubs (push) Has been cancelled
tests / smoke-test (push) Has been cancelled
Docker / check_paths (push) Has been cancelled
Docker / build (push) Has been cancelled
docs / build (push) Has been cancelled

Upstream: https://github.com/michaelgillett/mjlab
Upstream-Commit: c19f713c415a699a79d71cd96aa13c3104a05047
Upstream-Branch: main
This commit is contained in:
Upstream Snapshot
2026-08-28 15:42:17 +08:00
commit 32a241c28f
513 changed files with 120771 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Generate type stubs for MuJoCo using pybind11-stubgen.
# This helps suppress pyright/ty errors for MuJoCo's C++ bindings.
#
# The output is post-processed by postprocess_stubs.py to make it
# platform-independent (it drops the OpenGL backend stubs, which differ between
# macOS and Linux). This keeps the committed stubs identical on every platform,
# so CI can regenerate them and fail if they drift from the installed mujoco
# version. pybind11-stubgen is pinned so its output is reproducible.
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# --no-sync runs in the already-synced project environment (so mujoco is
# importable) without disturbing it; the conflicting cpu/cu128 extras mean a
# plain "uv run" would re-sync and churn the environment.
STUBGEN_VERSION="2.5.5"
STUBGEN=(uv run --no-sync --with "pybind11-stubgen==${STUBGEN_VERSION}" pybind11-stubgen)
echo "Generating MuJoCo type stubs..."
"${STUBGEN[@]}" mujoco -o "$SCRIPT_DIR" --ignore-all-errors
# mujoco.viewer pulls in GLFW, which may not import on a headless machine.
# Skip it in that case rather than failing; the committed viewer stub is kept.
if ! "${STUBGEN[@]}" mujoco.viewer -o "$SCRIPT_DIR" --ignore-all-errors; then
echo "Warning: could not generate mujoco.viewer stubs (no GLFW?). Skipping."
fi
echo "Post-processing stubs to make them platform-independent..."
uv run --no-sync python "$SCRIPT_DIR/postprocess_stubs.py"
echo "MuJoCo stubs generated successfully in $SCRIPT_DIR/mujoco/"
File diff suppressed because one or more lines are too long
+47
View File
@@ -0,0 +1,47 @@
from __future__ import annotations
import typing
__all__: list[str] = ['get_mjcb_act_bias', 'get_mjcb_act_dyn', 'get_mjcb_act_gain', 'get_mjcb_contactfilter', 'get_mjcb_control', 'get_mjcb_passive', 'get_mjcb_sensor', 'get_mjcb_time', 'get_mju_user_free', 'get_mju_user_malloc', 'get_mju_user_warning', 'set_mjcb_act_bias', 'set_mjcb_act_dyn', 'set_mjcb_act_gain', 'set_mjcb_contactfilter', 'set_mjcb_control', 'set_mjcb_passive', 'set_mjcb_sensor', 'set_mjcb_time', 'set_mju_user_free', 'set_mju_user_malloc', 'set_mju_user_warning']
def get_mjcb_act_bias() -> typing.Any:
...
def get_mjcb_act_dyn() -> typing.Any:
...
def get_mjcb_act_gain() -> typing.Any:
...
def get_mjcb_contactfilter() -> typing.Any:
...
def get_mjcb_control() -> typing.Any:
...
def get_mjcb_passive() -> typing.Any:
...
def get_mjcb_sensor() -> typing.Any:
...
def get_mjcb_time() -> typing.Any:
...
def get_mju_user_free() -> typing.Any:
...
def get_mju_user_malloc() -> typing.Any:
...
def get_mju_user_warning() -> typing.Any:
...
def set_mjcb_act_bias(arg0: typing.Any) -> None:
...
def set_mjcb_act_dyn(arg0: typing.Any) -> None:
...
def set_mjcb_act_gain(arg0: typing.Any) -> None:
...
def set_mjcb_contactfilter(arg0: typing.Any) -> None:
...
def set_mjcb_control(arg0: typing.Any) -> None:
...
def set_mjcb_passive(arg0: typing.Any) -> None:
...
def set_mjcb_sensor(arg0: typing.Any) -> None:
...
def set_mjcb_time(arg0: typing.Any) -> None:
...
def set_mju_user_free(arg0: typing.Any) -> None:
...
def set_mju_user_malloc(arg0: typing.Any) -> None:
...
def set_mju_user_warning(arg0: typing.Any) -> None:
...
+38
View File
@@ -0,0 +1,38 @@
from __future__ import annotations
__all__: list[str] = ['MJTNUM_BYTES', 'mjDISABLESTRING', 'mjENABLESTRING', 'mjFRAMESTRING', 'mjLABELSTRING', 'mjMAXCONPAIR', 'mjMAXFLEXNODES', 'mjMAXIMP', 'mjMAXLIGHT', 'mjMAXLINE', 'mjMAXLINEPNT', 'mjMAXOVERLAY', 'mjMAXPLANEGRID', 'mjMAXTREEDEPTH', 'mjMAXVAL', 'mjMINAWAKE', 'mjMINIMP', 'mjMINMU', 'mjMINVAL', 'mjNBIAS', 'mjNDYN', 'mjNEQDATA', 'mjNFLUID', 'mjNGAIN', 'mjNGROUP', 'mjNIMP', 'mjNISLAND', 'mjNPOLY', 'mjNREF', 'mjNSENS', 'mjNSOLVER', 'mjPI', 'mjRNDSTRING', 'mjTIMERSTRING', 'mjVERSION_HEADER', 'mjVISSTRING']
MJTNUM_BYTES: int = 8
mjDISABLESTRING: tuple = ('Constraint', 'Equality', 'Frictionloss', 'Limit', 'Contact', 'Spring', 'Damper', 'Gravity', 'Clampctrl', 'Warmstart', 'Filterparent', 'Actuation', 'Refsafe', 'Sensor', 'Midphase', 'Eulerdamp', 'AutoReset', 'NativeCCD', 'Island', 'MultiCCD')
mjENABLESTRING: tuple = ('Override', 'Energy', 'Fwdinv', 'InvDiscrete', 'Sleep', 'DiagExact')
mjFRAMESTRING: tuple = ('None', 'Body', 'Geom', 'Site', 'Camera', 'Light', 'Contact', 'World')
mjLABELSTRING: tuple = ('None', 'Body', 'Joint', 'Geom', 'Site', 'Camera', 'Light', 'Tendon', 'Actuator', 'Constraint', 'Flex', 'Skin', 'Selection', 'SelPoint', 'Contact', 'ContactForce', 'Island')
mjMAXCONPAIR: int = 50
mjMAXFLEXNODES: int = 27
mjMAXIMP: float = 0.9999
mjMAXLIGHT: int = 100
mjMAXLINE: int = 100
mjMAXLINEPNT: int = 1001
mjMAXOVERLAY: int = 500
mjMAXPLANEGRID: int = 200
mjMAXTREEDEPTH: int = 50
mjMAXVAL: float = 10000000000.0
mjMINAWAKE: int = 10
mjMINIMP: float = 0.0001
mjMINMU: float = 1e-05
mjMINVAL: float = 1e-15
mjNBIAS: int = 10
mjNDYN: int = 10
mjNEQDATA: int = 11
mjNFLUID: int = 12
mjNGAIN: int = 10
mjNGROUP: int = 6
mjNIMP: int = 5
mjNISLAND: int = 20
mjNPOLY: int = 2
mjNREF: int = 2
mjNSENS: int = 3
mjNSOLVER: int = 200
mjPI: float = 3.141592653589793
mjRNDSTRING: tuple = (('Shadow', '1', 'S'), ('Wireframe', '0', 'W'), ('Reflection', '1', 'R'), ('Additive', '0', 'L'), ('Skybox', '1', 'K'), ('Fog', '0', 'G'), ('Haze', '1', '/'), ('Depth', '0', ''), ('Segment', '0', ','), ('Id Color', '0', ''), ('Cull Face', '1', ''))
mjTIMERSTRING: tuple = ('step', 'forward', 'inverse', 'position', 'velocity', 'actuation', 'constraint', 'advance', 'pos_kinematics', 'pos_inertia', 'pos_collision', 'pos_make', 'pos_project', 'col_broadphase', 'col_narrowphase')
mjVERSION_HEADER: int = 3011000
mjVISSTRING: tuple = (('Convex Hull', '0', 'H'), ('Texture', '1', 'X'), ('Joint', '0', 'J'), ('Camera', '0', 'Q'), ('Actuator', '0', 'U'), ('Activation', '0', ','), ('Light', '0', 'Z'), ('Tendon', '1', 'V'), ('Range Finder', '1', 'Y'), ('Equality', '0', 'E'), ('Inertia', '0', 'I'), ('Scale Inertia', '0', "'"), ('Perturb Force', '0', 'B'), ('Perturb Object', '1', 'O'), ('Contact Point', '0', 'C'), ('Island', '0', 'N'), ('Contact Force', '0', 'F'), ('Contact Split', '0', 'P'), ('Transparent', '0', 'T'), ('Auto Connect', '0', 'A'), ('Center of Mass', '0', 'M'), ('Select Point', '0', ''), ('Static Body', '1', 'D'), ('Skin', '1', ';'), ('Flex Vert', '0', ''), ('Flex Edge', '1', ''), ('Flex Face', '0', ''), ('Flex Skin', '1', ''), ('Body Tree', '0', '`'), ('Mesh Tree', '0', '\\'), ('SDF iters', '0', ''))
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
from __future__ import annotations
from mujoco import FatalError
from mujoco import UnexpectedError
__all__: list[str] = ['FatalError', 'UnexpectedError']
File diff suppressed because it is too large Load Diff
+486
View File
@@ -0,0 +1,486 @@
from __future__ import annotations
import mujoco._structs
import numpy
import numpy.typing
import typing
__all__: list[str] = ['MjrContext', 'MjrRendererInfo', 'mjr_addAux', 'mjr_blitAux', 'mjr_blitBuffer', 'mjr_changeFont', 'mjr_defaultRendererInfo', 'mjr_drawPixels', 'mjr_figure', 'mjr_findRect', 'mjr_finish', 'mjr_getError', 'mjr_getRendererInfo', 'mjr_label', 'mjr_maxViewport', 'mjr_overlay', 'mjr_readPixels', 'mjr_rectangle', 'mjr_render', 'mjr_resizeOffscreen', 'mjr_restoreBuffer', 'mjr_setAux', 'mjr_setBuffer', 'mjr_text', 'mjr_uploadHField', 'mjr_uploadMesh', 'mjr_uploadTexture']
class MjrContext:
@typing.overload
def __init__(self) -> None:
...
@typing.overload
def __init__(self, arg0: mujoco._structs.MjModel, arg1: typing.SupportsInt | typing.SupportsIndex) -> None:
...
def free(self) -> None:
"""
Frees resources in current active OpenGL context, sets struct to default.
"""
@property
def auxColor(self) -> numpy.typing.NDArray[numpy.uint32]:
...
@auxColor.setter
def auxColor(self, arg1: typing.Any) -> None:
...
@property
def auxColor_r(self) -> numpy.typing.NDArray[numpy.uint32]:
...
@auxColor_r.setter
def auxColor_r(self, arg1: typing.Any) -> None:
...
@property
def auxFBO(self) -> numpy.typing.NDArray[numpy.uint32]:
...
@auxFBO.setter
def auxFBO(self, arg1: typing.Any) -> None:
...
@property
def auxFBO_r(self) -> numpy.typing.NDArray[numpy.uint32]:
...
@auxFBO_r.setter
def auxFBO_r(self, arg1: typing.Any) -> None:
...
@property
def auxHeight(self) -> numpy.typing.NDArray[numpy.int32]:
...
@auxHeight.setter
def auxHeight(self, arg1: typing.Any) -> None:
...
@property
def auxSamples(self) -> numpy.typing.NDArray[numpy.int32]:
...
@auxSamples.setter
def auxSamples(self, arg1: typing.Any) -> None:
...
@property
def auxWidth(self) -> numpy.typing.NDArray[numpy.int32]:
...
@auxWidth.setter
def auxWidth(self, arg1: typing.Any) -> None:
...
@property
def baseBuiltin(self) -> int:
...
@baseBuiltin.setter
def baseBuiltin(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def baseFontBig(self) -> int:
...
@baseFontBig.setter
def baseFontBig(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def baseFontNormal(self) -> int:
...
@baseFontNormal.setter
def baseFontNormal(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def baseFontShadow(self) -> int:
...
@baseFontShadow.setter
def baseFontShadow(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def baseHField(self) -> int:
...
@baseHField.setter
def baseHField(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def baseMesh(self) -> int:
...
@baseMesh.setter
def baseMesh(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def basePlane(self) -> int:
...
@basePlane.setter
def basePlane(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def charHeight(self) -> int:
...
@charHeight.setter
def charHeight(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def charHeightBig(self) -> int:
...
@charHeightBig.setter
def charHeightBig(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def charWidth(self) -> numpy.typing.NDArray[numpy.int32]:
...
@charWidth.setter
def charWidth(self, arg1: typing.Any) -> None:
...
@property
def charWidthBig(self) -> numpy.typing.NDArray[numpy.int32]:
...
@charWidthBig.setter
def charWidthBig(self, arg1: typing.Any) -> None:
...
@property
def currentBuffer(self) -> int:
...
@currentBuffer.setter
def currentBuffer(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def fogEnd(self) -> float:
...
@fogEnd.setter
def fogEnd(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def fogRGBA(self) -> numpy.typing.NDArray[numpy.float32]:
...
@fogRGBA.setter
def fogRGBA(self, arg1: typing.Any) -> None:
...
@property
def fogStart(self) -> float:
...
@fogStart.setter
def fogStart(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def fontScale(self) -> int:
...
@fontScale.setter
def fontScale(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def glInitialized(self) -> int:
...
@glInitialized.setter
def glInitialized(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def lineWidth(self) -> float:
...
@lineWidth.setter
def lineWidth(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def mat_texid(self) -> numpy.typing.NDArray[numpy.int32]:
...
@mat_texid.setter
def mat_texid(self, arg1: typing.Any) -> None:
...
@property
def mat_texrepeat(self) -> numpy.typing.NDArray[numpy.float32]:
...
@mat_texrepeat.setter
def mat_texrepeat(self, arg1: typing.Any) -> None:
...
@property
def mat_texuniform(self) -> numpy.typing.NDArray[numpy.int32]:
...
@mat_texuniform.setter
def mat_texuniform(self, arg1: typing.Any) -> None:
...
@property
def nskin(self) -> int:
...
@property
def ntexture(self) -> int:
...
@ntexture.setter
def ntexture(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offColor(self) -> int:
...
@offColor.setter
def offColor(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offColor_r(self) -> int:
...
@offColor_r.setter
def offColor_r(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offDepthStencil(self) -> int:
...
@offDepthStencil.setter
def offDepthStencil(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offDepthStencil_r(self) -> int:
...
@offDepthStencil_r.setter
def offDepthStencil_r(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offFBO(self) -> int:
...
@offFBO.setter
def offFBO(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offFBO_r(self) -> int:
...
@offFBO_r.setter
def offFBO_r(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offHeight(self) -> int:
...
@offHeight.setter
def offHeight(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offSamples(self) -> int:
...
@offSamples.setter
def offSamples(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def offWidth(self) -> int:
...
@offWidth.setter
def offWidth(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def rangeBuiltin(self) -> int:
...
@rangeBuiltin.setter
def rangeBuiltin(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def rangeFont(self) -> int:
...
@rangeFont.setter
def rangeFont(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def rangeHField(self) -> int:
...
@rangeHField.setter
def rangeHField(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def rangeMesh(self) -> int:
...
@rangeMesh.setter
def rangeMesh(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def rangePlane(self) -> int:
...
@rangePlane.setter
def rangePlane(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def readDepthMap(self) -> int:
...
@readDepthMap.setter
def readDepthMap(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def readPixelFormat(self) -> int:
...
@readPixelFormat.setter
def readPixelFormat(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def shadowClip(self) -> float:
...
@shadowClip.setter
def shadowClip(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def shadowFBO(self) -> int:
...
@shadowFBO.setter
def shadowFBO(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def shadowScale(self) -> float:
...
@shadowScale.setter
def shadowScale(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def shadowSize(self) -> int:
...
@shadowSize.setter
def shadowSize(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def shadowTex(self) -> int:
...
@shadowTex.setter
def shadowTex(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def skinfaceVBO(self) -> tuple:
...
@property
def skinnormalVBO(self) -> tuple:
...
@property
def skintexcoordVBO(self) -> tuple:
...
@property
def skinvertVBO(self) -> tuple:
...
@property
def texture(self) -> numpy.typing.NDArray[numpy.uint32]:
...
@texture.setter
def texture(self, arg1: typing.Any) -> None:
...
@property
def textureType(self) -> numpy.typing.NDArray[numpy.int32]:
...
@textureType.setter
def textureType(self, arg1: typing.Any) -> None:
...
@property
def windowAvailable(self) -> int:
...
@windowAvailable.setter
def windowAvailable(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def windowDoublebuffer(self) -> int:
...
@windowDoublebuffer.setter
def windowDoublebuffer(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def windowSamples(self) -> int:
...
@windowSamples.setter
def windowSamples(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
@property
def windowStereo(self) -> int:
...
@windowStereo.setter
def windowStereo(self, arg1: typing.SupportsFloat | typing.SupportsIndex) -> None:
...
class MjrRendererInfo:
__hash__: typing.ClassVar[None] = None
def __copy__(self) -> MjrRendererInfo:
...
def __deepcopy__(self, arg0: dict) -> MjrRendererInfo:
...
def __eq__(self, arg0: typing.Any) -> bool:
...
def __init__(self) -> None:
...
def __repr__(self) -> str:
...
@property
def backend(self) -> str:
...
@property
def renderer(self) -> str:
...
def mjr_addAux(index: typing.SupportsInt | typing.SupportsIndex, width: typing.SupportsInt | typing.SupportsIndex, height: typing.SupportsInt | typing.SupportsIndex, samples: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Add Aux buffer with given index to context; free previous Aux buffer.
"""
def mjr_blitAux(index: typing.SupportsInt | typing.SupportsIndex, src: mujoco._structs.MjrRect, left: typing.SupportsInt | typing.SupportsIndex, bottom: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Blit from Aux buffer to con->currentBuffer.
"""
def mjr_blitBuffer(src: mujoco._structs.MjrRect, dst: mujoco._structs.MjrRect, flg_color: typing.SupportsInt | typing.SupportsIndex, flg_depth: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Blit from src viewpoint in current framebuffer to dst viewport in other framebuffer. If src, dst have different size and flg_depth==0, color is interpolated with GL_LINEAR.
"""
def mjr_changeFont(fontscale: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Change font of existing context.
"""
def mjr_defaultRendererInfo(info: MjrRendererInfo) -> None:
"""
Set default mjrRendererInfo.
"""
def mjr_drawPixels(rgb: typing.Annotated[numpy.typing.NDArray[numpy.uint8], "[m, 1]"] | None, depth: typing.Annotated[numpy.typing.NDArray[numpy.float32], "[m, 1]"] | None, viewport: mujoco._structs.MjrRect, con: MjrContext) -> None:
"""
Draw pixels from client buffer to current OpenGL framebuffer. Viewport is in OpenGL framebuffer; client buffer starts at (0,0).
"""
def mjr_figure(viewport: mujoco._structs.MjrRect, fig: mujoco._structs.MjvFigure, con: MjrContext) -> None:
"""
Draw 2D figure.
"""
def mjr_findRect(x: typing.SupportsInt | typing.SupportsIndex, y: typing.SupportsInt | typing.SupportsIndex, nrect: typing.SupportsInt | typing.SupportsIndex, rect: mujoco._structs.MjrRect) -> int:
"""
Find first rectangle containing mouse, -1: not found.
"""
def mjr_finish() -> None:
"""
Call glFinish.
"""
def mjr_getError() -> int:
"""
Call glGetError and return result.
"""
def mjr_getRendererInfo(info: MjrRendererInfo) -> None:
"""
Get active renderer information.
"""
def mjr_label(viewport: mujoco._structs.MjrRect, font: typing.SupportsInt | typing.SupportsIndex, txt: str, r: typing.SupportsFloat | typing.SupportsIndex, g: typing.SupportsFloat | typing.SupportsIndex, b: typing.SupportsFloat | typing.SupportsIndex, a: typing.SupportsFloat | typing.SupportsIndex, rt: typing.SupportsFloat | typing.SupportsIndex, gt: typing.SupportsFloat | typing.SupportsIndex, bt: typing.SupportsFloat | typing.SupportsIndex, con: MjrContext) -> None:
"""
Draw rectangle with centered text.
"""
def mjr_maxViewport(con: MjrContext) -> mujoco._structs.MjrRect:
"""
Get maximum viewport for active buffer.
"""
def mjr_overlay(font: typing.SupportsInt | typing.SupportsIndex, gridpos: typing.SupportsInt | typing.SupportsIndex, viewport: mujoco._structs.MjrRect, overlay: str, overlay2: str, con: MjrContext) -> None:
"""
Draw text overlay; font is mjtFont; gridpos is mjtGridPos.
"""
def mjr_readPixels(rgb: typing.Annotated[numpy.typing.ArrayLike, numpy.uint8] | None, depth: typing.Annotated[numpy.typing.ArrayLike, numpy.float32] | None, viewport: mujoco._structs.MjrRect, con: MjrContext) -> None:
"""
Read pixels from current OpenGL framebuffer to client buffer. Viewport is in OpenGL framebuffer; client buffer starts at (0,0).
"""
def mjr_rectangle(viewport: mujoco._structs.MjrRect, r: typing.SupportsFloat | typing.SupportsIndex, g: typing.SupportsFloat | typing.SupportsIndex, b: typing.SupportsFloat | typing.SupportsIndex, a: typing.SupportsFloat | typing.SupportsIndex) -> None:
"""
Draw rectangle.
"""
def mjr_render(viewport: mujoco._structs.MjrRect, scn: mujoco._structs.MjvScene, con: MjrContext) -> None:
"""
Render 3D scene.
"""
def mjr_resizeOffscreen(width: typing.SupportsInt | typing.SupportsIndex, height: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Resize offscreen buffers.
"""
def mjr_restoreBuffer(con: MjrContext) -> None:
"""
Make con->currentBuffer current again.
"""
def mjr_setAux(index: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Set Aux buffer for custom OpenGL rendering (call restoreBuffer when done).
"""
def mjr_setBuffer(framebuffer: typing.SupportsInt | typing.SupportsIndex, con: MjrContext) -> None:
"""
Set OpenGL framebuffer for rendering: mjFB_WINDOW or mjFB_OFFSCREEN. If only one buffer is available, set that buffer and ignore framebuffer argument.
"""
def mjr_text(font: typing.SupportsInt | typing.SupportsIndex, txt: str, con: MjrContext, x: typing.SupportsFloat | typing.SupportsIndex, y: typing.SupportsFloat | typing.SupportsIndex, r: typing.SupportsFloat | typing.SupportsIndex, g: typing.SupportsFloat | typing.SupportsIndex, b: typing.SupportsFloat | typing.SupportsIndex) -> None:
"""
Draw text at (x,y) in relative coordinates; font is mjtFont.
"""
def mjr_uploadHField(m: mujoco._structs.MjModel, con: MjrContext, hfieldid: typing.SupportsInt | typing.SupportsIndex) -> None:
"""
Upload height field to GPU, overwriting previous upload if any.
"""
def mjr_uploadMesh(m: mujoco._structs.MjModel, con: MjrContext, meshid: typing.SupportsInt | typing.SupportsIndex) -> None:
"""
Upload mesh to GPU, overwriting previous upload if any.
"""
def mjr_uploadTexture(m: mujoco._structs.MjModel, con: MjrContext, texid: typing.SupportsInt | typing.SupportsIndex) -> None:
"""
Upload texture to GPU, overwriting previous upload if any.
"""
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+145
View File
@@ -0,0 +1,145 @@
"""
Interactive GUI viewer for MuJoCo.
"""
from __future__ import annotations
import abc as abc
import atexit as atexit
import contextlib as contextlib
import glfw as glfw
import math as math
import mujoco as mujoco
from mujoco import _simulate
from mujoco._simulate import Simulate as _Simulate
import numpy as np
import os as os
import queue as queue
import sys as sys
import threading as threading
import time as time
import typing
import weakref as weakref
__all__: list[str] = ['CallbackType', 'Handle', 'KeyCallbackType', 'LoaderType', 'MAX_SYNC_MISALIGN', 'PERCENT_REALTIME', 'SIM_REFRESH_FRACTION', 'abc', 'atexit', 'contextlib', 'glfw', 'launch', 'launch_from_path', 'launch_passive', 'math', 'mujoco', 'np', 'os', 'queue', 'sys', 'threading', 'time', 'weakref']
class Handle:
"""
A handle for interacting with a MuJoCo viewer.
"""
def __enter__(self):
...
def __exit__(self, exc_type, exc_val, exc_tb):
...
def __init__(self, sim: mujoco._simulate.Simulate, cam: mujoco._structs.MjvCamera, opt: mujoco._structs.MjvOption, pert: mujoco._structs.MjvPerturb, user_scn: typing.Optional[mujoco._structs.MjvScene]):
...
def _get_sim(self) -> typing.Optional[mujoco._simulate.Simulate]:
...
def clear_figures(self):
...
def clear_images(self):
...
def clear_texts(self):
...
def close(self):
...
def is_running(self) -> bool:
...
def lock(self):
...
def set_figures(self, viewports_figures: typing.Union[typing.Tuple[mujoco._structs.MjrRect, mujoco._structs.MjvFigure], typing.List[typing.Tuple[mujoco._structs.MjrRect, mujoco._structs.MjvFigure]]]):
"""
Overlay figures on the viewer.
Args:
viewports_figures: Single tuple or list of tuples of (viewport, figure)
viewport: Rectangle defining position and size of the figure
figure: MjvFigure object containing the figure data to display
"""
def set_images(self, viewports_images: typing.Union[typing.Tuple[mujoco._structs.MjrRect, numpy.ndarray], typing.List[typing.Tuple[mujoco._structs.MjrRect, numpy.ndarray]]]):
"""
Overlay images on the viewer.
Args:
viewports_images: Single tuple or list of tuples of (viewport, image)
viewport: Rectangle defining position and size of the image
image: RGB image with shape (height, width, 3)
"""
def set_texts(self, texts: typing.Union[typing.Tuple[typing.Optional[int], typing.Optional[int], typing.Optional[str], typing.Optional[str]], typing.List[typing.Tuple[typing.Optional[int], typing.Optional[int], typing.Optional[str], typing.Optional[str]]]]):
"""
Overlay text on the viewer.
Args:
texts: Single tuple or list of tuples of (font, gridpos, text1, text2)
font: Font style from mujoco.mjtFontScale
gridpos: Position of text box from mujoco.mjtGridPos
text1: Left text column, defaults to empty string if None
text2: Right text column, defaults to empty string if None
"""
def sync(self, state_only: bool = False):
...
def update_hfield(self, hfieldid: int):
...
def update_mesh(self, meshid: int):
...
def update_texture(self, texid: int):
...
@property
def cam(self):
...
@property
def d(self):
...
@property
def m(self):
...
@property
def opt(self):
...
@property
def perturb(self):
...
@property
def user_scn(self):
...
@property
def viewport(self):
...
class _MjPythonBase:
__abstractmethods__: typing.ClassVar[frozenset] # value = frozenset()
_abc_impl: typing.ClassVar[_abc._abc_data] # value = <_abc._abc_data object>
def launch_on_ui_thread(self, model: mujoco._structs.MjModel, data: mujoco._structs.MjData, handle_return: typing.Optional[ForwardRef('queue.Queue[Handle]')], key_callback: typing.Optional[typing.Callable[[int], NoneType]]):
...
def _file_loader(path: str) -> typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]]:
"""
Loads an MJCF model from file path.
"""
def _launch_internal(model: typing.Optional[mujoco._structs.MjModel] = None, data: typing.Optional[mujoco._structs.MjData] = None, *, run_physics_thread: bool, loader: typing.Union[typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]], typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]], NoneType] = None, handle_return: typing.Optional[ForwardRef('queue.Queue[Handle]')] = None, key_callback: typing.Optional[typing.Callable[[int], NoneType]] = None, show_left_ui: bool = True, show_right_ui: bool = True) -> None:
"""
Internal API, so that the public API has more readable type annotations.
"""
def _physics_loop(simulate: mujoco._simulate.Simulate, loader: typing.Union[typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]], typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]], NoneType]):
"""
Physics loop for the GUI, to be run in a separate thread.
"""
def _reload(simulate: mujoco._simulate.Simulate, loader: typing.Union[typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]], typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]]], notify_loaded: typing.Optional[typing.Callable[[], NoneType]] = None) -> typing.Optional[typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]]:
"""
Internal function for reloading a model in the viewer.
"""
def launch(model: typing.Optional[mujoco._structs.MjModel] = None, data: typing.Optional[mujoco._structs.MjData] = None, *, loader: typing.Optional[typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]]] = None, show_left_ui: bool = True, show_right_ui: bool = True) -> None:
"""
Launches the Simulate GUI.
"""
def launch_from_path(path: str) -> None:
"""
Launches the Simulate GUI from file path.
"""
def launch_passive(model: mujoco._structs.MjModel, data: mujoco._structs.MjData, *, key_callback: typing.Optional[typing.Callable[[int], NoneType]] = None, show_left_ui: bool = True, show_right_ui: bool = True) -> Handle:
"""
Launches a passive Simulate GUI without blocking the running thread.
"""
CallbackType: typing._CallableGenericAlias # value = typing.Callable[[mujoco._structs.MjModel, mujoco._structs.MjData], NoneType]
KeyCallbackType: typing._CallableGenericAlias # value = typing.Callable[[int], NoneType]
LoaderType: typing._CallableGenericAlias # value = typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]]
MAX_SYNC_MISALIGN: float = 0.1
PERCENT_REALTIME: tuple = (100, 80, 66, 50, 40, 33, 25, 20, 16, 13, 10, 8, 6.6, 5, 4, 3.3, 2.5, 2, 1.6, 1.3, 1, 0.8, 0.66, 0.5, 0.4, 0.33, 0.25, 0.2, 0.16, 0.13, 0.1)
SIM_REFRESH_FRACTION: float = 0.7
_InternalLoaderType: typing._UnionGenericAlias # value = typing.Union[typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData]], typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]]]
_LoaderWithPathType: typing._CallableGenericAlias # value = typing.Callable[[], typing.Tuple[mujoco._structs.MjModel, mujoco._structs.MjData, str]]
_MJPYTHON = None
+104
View File
@@ -0,0 +1,104 @@
"""Make the generated MuJoCo stubs platform-independent and reproducible.
``pybind11-stubgen`` introspects the installed ``mujoco`` package, producing two
kinds of machine-specific output:
1. The active OpenGL backend is baked in: ``mujoco.cgl`` on macOS,
``mujoco.glfw`` on Linux (or ``mujoco.egl`` / ``mujoco.osmesa`` depending on
``MUJOCO_GL``). mjlab does not type-check against the rendering backend, so we
drop those stubs and the ``__init__.pyi`` imports referencing them.
2. Absolute install paths and live object reprs (memory addresses) are embedded
as default values and ``# value = ...`` comments. These vary by machine and
run, so we strip them.
What remains is a deterministic set of physics-binding stubs that is identical
on every platform, which lets CI regenerate them and fail if they drift from the
installed mujoco version.
"""
from __future__ import annotations
import re
import shutil
from pathlib import Path
STUB_DIR = Path(__file__).parent / "mujoco"
# OpenGL context backends mujoco may expose, only one of which exists per
# platform / MUJOCO_GL setting.
BACKENDS = ("cgl", "egl", "glfw", "glx", "osmesa")
# Backend modules plus the rendering stubs that import them. None are needed to
# type-check mjlab, and all are platform-specific, so remove them entirely.
REMOVE = (*BACKENDS, "gl_context.pyi", "renderer.pyi", "rendering")
# Backend imports in __init__.pyi, e.g. "from mujoco.cgl import GLContext" and
# "from . import cgl", along with the names they contribute to __all__.
DROP_IMPORT = re.compile(
rf"^(?:from mujoco\.(?:{'|'.join(BACKENDS)}) import GLContext"
rf"|from \. import (?:{'|'.join(BACKENDS)}))$"
)
# Module-level constants in __init__.pyi that exist only on some platforms
# (macOS exposes is_rosetta / proc_translated for Rosetta detection; Linux does
# not). Remove them so the stubs match on every platform.
PLATFORM_ONLY = ("is_rosetta", "proc_translated")
PLATFORM_ONLY_DEF = re.compile(rf"^(?:{'|'.join(PLATFORM_ONLY)})\b")
DROP_FROM_ALL = ("GLContext", *BACKENDS, *PLATFORM_ONLY)
# _SYSTEM holds the host platform name ('Darwin' / 'Linux'); drop the value.
SYSTEM_DEFAULT = re.compile(r"^(_SYSTEM: str) = '\w+'$")
# A trailing "# value = ..." comment that captures a live object repr.
VALUE_COMMENT = re.compile(r" {2,}# value = .*$")
# A string constant whose default is an absolute install path.
PATH_DEFAULT = re.compile(
r"^(\s*\w+: str) = '[^']*(?:site-packages|/Users/|/home/)[^']*'\s*$"
)
def remove_backend_stubs() -> None:
for name in REMOVE:
target = STUB_DIR / name
if target.is_dir():
shutil.rmtree(target)
elif target.exists():
target.unlink()
def patch_init() -> None:
init = STUB_DIR / "__init__.pyi"
out = []
for line in init.read_text().splitlines():
if DROP_IMPORT.match(line.strip()) or PLATFORM_ONLY_DEF.match(line):
continue
line = SYSTEM_DEFAULT.sub(r"\1", line)
if line.startswith("__all__"):
for name in DROP_FROM_ALL:
line = line.replace(f"'{name}', ", "")
out.append(line)
init.write_text("\n".join(out) + "\n")
def sanitize_machine_specific() -> None:
for path in STUB_DIR.rglob("*.pyi"):
out = []
for line in path.read_text().splitlines():
if "# value = " in line and ("site-packages" in line or "0x" in line):
line = VALUE_COMMENT.sub("", line)
match = PATH_DEFAULT.match(line)
if match:
line = match.group(1)
out.append(line)
path.write_text("\n".join(out) + "\n")
def main() -> None:
remove_backend_stubs()
patch_init()
sanitize_machine_specific()
if __name__ == "__main__":
main()