diff --git a/docs/sphinx/source/changelog.md b/docs/sphinx/source/changelog.md
index a0e4c4894..feae06cee 100644
--- a/docs/sphinx/source/changelog.md
+++ b/docs/sphinx/source/changelog.md
@@ -42,6 +42,16 @@ PyPI 版本变更与未发布变更;发布日期采用 PyPI 上传日期。完
### Changed / 变更
+- Raised the base and optional SuperDex UniSim requirements to
+ `unisim-core>=1.7.1`. The released packages contain portable MJCF profile
+ v1 and the IsaacSim worker dependency-isolation fix, so consumer acceptance
+ no longer uses the provisional local-checkout skip and validates the
+ robot/object/table/mirror fixture from PyPI dependencies (#1609; UniSim
+ #154/#155).
+ 将基础与可选 SuperDex 的 UniSim 依赖提升到 `unisim-core>=1.7.1`。已发布
+ 包包含 portable MJCF profile v1 与 IsaacSim worker 依赖隔离修复,因此
+ 消费验收不再使用临时本地 checkout skip,并基于 PyPI 依赖验证
+ robot/object/table/mirror fixture(#1609;UniSim #154/#155)。
- Raised the base UniSim requirement to `unisim-core>=1.4.1` to consume the
published IsaacGym fixed-variant adapter. The optional `superdex` extra's
own `>=1.4.0` constraint is unchanged: the base requirement already forces
diff --git a/docs/sphinx/source/en/4-developer_guide/2-contracts/2-backend_contract.md b/docs/sphinx/source/en/4-developer_guide/2-contracts/2-backend_contract.md
index 7800055fc..9ee86a82f 100644
--- a/docs/sphinx/source/en/4-developer_guide/2-contracts/2-backend_contract.md
+++ b/docs/sphinx/source/en/4-developer_guide/2-contracts/2-backend_contract.md
@@ -42,7 +42,7 @@ A mapped logical root must name its physical entity's declared root exactly. Bin
The existing `ResetStateTransaction` stages one public `SceneResetRequest` for mapped scenes. Missing fields and unselected entities/environments remain unchanged. Per-environment defaults come from `get_entity_default_state`, and `restore_default_controls` restores keyframe controls in the same commit; controls need not equal joint positions. No engine-private tensors or asset parsing enter manager terms. Scalar hinge/slide joints and a common selected environment set per transaction are the current consumer boundary; unsupported mixed DR/mocap or row patterns fail explicitly.
-`tests/envs/test_multi_entity_consumer.py` registers one primitive task with the same pickleable EnvFactory for MuJoCo and IsaacSim. It checks observation/action dimensions, passive joints, selected resets, variants and a kinematic mirror. The native IsaacSim cases require `UNILAB_TEST_M2_ISAACSIM=1`. The consumer requires released `unisim-core>=1.5.0`; normal and ROCm lock profiles resolve the PyPI package without a Git source override. `UNILAB_LOCAL_UNISIM` remains an explicit alternative for local development. See [UniSim roadmap #108](https://github.com/unilabsim/unisim/issues/108) for implementation and verification scope.
+`tests/envs/test_multi_entity_consumer.py` registers one primitive task with the same pickleable EnvFactory for MuJoCo and IsaacSim. It checks observation/action dimensions, passive joints, selected resets, variants and a kinematic mirror. The portable-profile fixture also combines a robot, passive object, table and collision-free mirror with the non-round-robin N5/K2 assignment `[1,1,0,1,0]`. The native IsaacSim cases require `UNILAB_TEST_M2_ISAACSIM=1`. The consumer requires released `unisim-core>=1.7.1`; normal and ROCm lock profiles resolve the PyPI package without a Git source override. `UNILAB_LOCAL_UNISIM` remains an explicit alternative for local development. See [UniSim roadmap #154](https://github.com/unilabsim/unisim/issues/154) and [UniSim contract #155](https://github.com/unilabsim/unisim/issues/155) for implementation and verification scope.
## Evidence In Repo
diff --git a/docs/sphinx/source/zh_CN/4-developer_guide/2-contracts/2-backend_contract.md b/docs/sphinx/source/zh_CN/4-developer_guide/2-contracts/2-backend_contract.md
index 401b4b59b..1e78108a8 100644
--- a/docs/sphinx/source/zh_CN/4-developer_guide/2-contracts/2-backend_contract.md
+++ b/docs/sphinx/source/zh_CN/4-developer_guide/2-contracts/2-backend_contract.md
@@ -37,7 +37,7 @@ Issue #1599 的 M2 消费层将 UniSim 物理实体声明与 UniLab 逻辑 selec
既有 `ResetStateTransaction` 为 mapped scene 暂存一次公共 `SceneResetRequest`。缺失字段、未选实体和环境保持不变。逐环境默认值来自 `get_entity_default_state`,`restore_default_controls` 在同次提交中恢复 keyframe control,控制值不必等于关节位置。Manager term 不接触引擎私有 tensor 或资产解析。当前消费边界为标量 hinge/slide 和一次事务共用选中环境集合;不支持的 DR/mocap 混写或行模式明确拒绝。
-`tests/envs/test_multi_entity_consumer.py` 为 MuJoCo 和 IsaacSim 注册同一个 primitive task,并使用同一个可 pickle 的 EnvFactory。测试检查观测/动作维度、被动关节、局部 reset、variants 和 kinematic mirror。原生 IsaacSim case 通过 `UNILAB_TEST_M2_ISAACSIM=1` 启用。消费层要求已发布的 `unisim-core>=1.5.0`;标准与 ROCm 锁文件均解析 PyPI 包,不使用 Git source 覆盖。`UNILAB_LOCAL_UNISIM` 仍是显式本地开发替代方案。实现和验证边界见 [UniSim roadmap #108](https://github.com/unilabsim/unisim/issues/108)。
+`tests/envs/test_multi_entity_consumer.py` 为 MuJoCo 和 IsaacSim 注册同一个 primitive task,并使用同一个可 pickle 的 EnvFactory。测试检查观测/动作维度、被动关节、局部 reset、variants 和 kinematic mirror。portable-profile fixture 还组合 robot、被动 object、table 与 collision-free mirror,并使用非 round-robin 的 N5/K2 assignment `[1,1,0,1,0]`。原生 IsaacSim case 通过 `UNILAB_TEST_M2_ISAACSIM=1` 启用。消费层要求已发布的 `unisim-core>=1.7.1`;标准与 ROCm 锁文件均解析 PyPI 包,不使用 Git source 覆盖。`UNILAB_LOCAL_UNISIM` 仍是显式本地开发替代方案。实现和验证边界见 [UniSim roadmap #154](https://github.com/unilabsim/unisim/issues/154) 与 [UniSim contract #155](https://github.com/unilabsim/unisim/issues/155)。
## 仓库中的证据
diff --git a/pyproject.toml b/pyproject.toml
index de6eb2d0f..fd1c553d6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -42,8 +42,9 @@ dependencies = [
# unisim-core package. Version 1.5.0 provides the M2 physical entity,
# immutable variant, layout and selected-reset contracts; 1.5.1 adds
# get_motion_body_ids on the newton/genesis adapters; 1.6.0 adds Newton
- # CUDA graph execution.
- "unisim-core>=1.6.0",
+ # CUDA graph execution; 1.7.0 adds the portable MJCF scene profile and
+ # 1.7.1 isolates the IsaacSim worker from host compiled dependencies.
+ "unisim-core>=1.7.1",
# RL algorithms and async runtimes (PPO/APPO/SAC/TD3 runners,
# collectors, IPC, logging) live in the independently released uni-rl
# package (distribution name ``unilab-rl``), consumed via the injected
@@ -159,7 +160,7 @@ genesis = [
"genesis-world==1.3.3",
]
viser = ["viser>=1.0.26", "trimesh>=3.21.7"]
-# SuperDex Physics/Robotics 1.0.0 ships as published wheels; the exact pins and
+# SuperDex Physics/Robotics 1.1.0 ships as published wheels; the exact pins and
# the temporary superdex-uni build names are owned by unisim-core's superdex
# extra (they revert to superdex-physics/-robotics once the upstream
# project_superdex release lands). That extra already carries plain `mujoco`
@@ -171,7 +172,7 @@ viser = ["viser>=1.0.26", "trimesh>=3.21.7"]
# required-environments; elsewhere the extra is empty and the CLI reports a
# targeted runtime diagnostic.
superdex = [
- "unisim-core[superdex]>=1.6.0 ; python_version >= '3.12' and sys_platform == 'linux' and platform_machine == 'x86_64'",
+ "unisim-core[superdex]>=1.7.1 ; python_version >= '3.12' and sys_platform == 'linux' and platform_machine == 'x86_64'",
]
[dependency-groups]
diff --git a/tests/base/test_backend_pre_step_control.py b/tests/base/test_backend_pre_step_control.py
index 283c9ae6e..c53ea20bb 100644
--- a/tests/base/test_backend_pre_step_control.py
+++ b/tests/base/test_backend_pre_step_control.py
@@ -292,6 +292,7 @@ def _fake_motrix_backend(pre_step_control_fn=None):
from unisim.backend.motrix.backend import MotrixBackend
backend = object.__new__(MotrixBackend)
+ backend._portable_mode = False
backend._pre_step_control_fn = pre_step_control_fn
backend._model = _FakeMotrixModel()
backend._data = SimpleNamespace(
@@ -383,6 +384,7 @@ def sync(self, *, data, wait=False):
monkeypatch.setattr(mod, "RenderSettings", FakeRenderSettings, raising=False)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = FakeModel()
backend._data = object()
backend._num_envs = 3
@@ -468,6 +470,7 @@ def launch(self, model, *, batch, render_offset, render_settings):
monkeypatch.setattr(mod, "RenderSettings", FakeRenderSettings, raising=False)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = FakeModel()
backend._num_envs = 4
backend._render_app = None
@@ -561,6 +564,7 @@ def sync(self, *, data, wait=False):
monkeypatch.setattr(mod, "RenderSettings", FakeRenderSettings, raising=False)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = FakeModel()
backend._data = object()
backend._num_envs = 3
@@ -652,6 +656,7 @@ def set_main_camera(self, camera):
monkeypatch.setattr(mod, "RenderSettings", FakeRenderSettings, raising=False)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = FakeModel()
backend._num_envs = 1
backend._render_app = None
@@ -707,6 +712,7 @@ def launch(self, model, *, batch, render_offset, render_settings):
monkeypatch.setattr(mod, "RenderSettings", FakeRenderSettings, raising=False)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = FakeModel()
backend._num_envs = 4
backend._render_app = None
diff --git a/tests/base/test_entity_scene_consumer.py b/tests/base/test_entity_scene_consumer.py
index 5e9380aa6..9443fa90f 100644
--- a/tests/base/test_entity_scene_consumer.py
+++ b/tests/base/test_entity_scene_consumer.py
@@ -174,6 +174,8 @@ def test_per_environment_entity_defaults_are_not_broadcast_from_first_variant():
for entity in cfg.scene.entity_assets:
if entity.name == "object":
continue
+ if entity.source is None:
+ continue
path = Path(entity.source.model_file)
key = (
''
diff --git a/tests/base/test_genesis_backend.py b/tests/base/test_genesis_backend.py
index 48138881b..02e89ec89 100644
--- a/tests/base/test_genesis_backend.py
+++ b/tests/base/test_genesis_backend.py
@@ -73,7 +73,7 @@
-
+
diff --git a/tests/base/test_isaacsim_backend.py b/tests/base/test_isaacsim_backend.py
index 283ceb4da..11abd457c 100644
--- a/tests/base/test_isaacsim_backend.py
+++ b/tests/base/test_isaacsim_backend.py
@@ -19,6 +19,7 @@
import pytest
from unisim.backend.base import CameraCfg, RenderClosedError
from unisim.backend.isaacgym.backend import IsaacGymWorkerError
+from unisim.backend.isaacsim import dependencies as isaacsim_dependencies
from unisim.backend.isaacsim.backend import (
IsaacSimBackend,
IsaacSimRenderError,
@@ -165,7 +166,10 @@ def test_dependencies_resolve_default_layout(
env = build_worker_env(runtime)
assert env["LD_LIBRARY_PATH"].split(":")[0] == str(tmp_path / "venv" / "lib")
assert env["PATH"].split(":")[0] == str(tmp_path / "venv" / "bin")
- assert env["PYTHONPATH"].split(":")[0] == str(tmp_path / "IsaacLab" / "source")
+ python_paths = env["PYTHONPATH"].split(":")
+ host_package_root = Path(isaacsim_dependencies.__file__).resolve().parents[3]
+ assert python_paths[0] == str(tmp_path / "IsaacLab" / "source")
+ assert str(host_package_root) not in python_paths
assert env["OMNI_KIT_ACCEPT_EULA"] == "1"
@@ -220,7 +224,7 @@ def test_contact_sensor_is_explicitly_unsupported(backend: IsaacSimBackend) -> N
metadata = backend._scene_metadata
assert metadata is not None
assert "foot_contact" in metadata.unsupported_sensors
- with pytest.raises(NotImplementedError, match="contact-force reporting"):
+ with pytest.raises(NotImplementedError, match="PhysX collision-pair force reporter"):
backend.get_sensor_data("foot_contact")
# Non-contact sensors remain available through the inherited cached path.
assert backend.get_sensor_data("base_gyro").shape == (NUM_ENVS, 3)
diff --git a/tests/base/test_motrix_backend_options.py b/tests/base/test_motrix_backend_options.py
index f90147256..87b1201fb 100644
--- a/tests/base/test_motrix_backend_options.py
+++ b/tests/base/test_motrix_backend_options.py
@@ -270,6 +270,7 @@ def test_motrix_backend_dr_capabilities_include_pd_gains_when_overrides_availabl
import unisim.backend.motrix.backend as mod
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._supports_position_actuator_gains = True
backend._supports_geom_friction_override = True
backend._supports_gravity_override = True
@@ -290,6 +291,7 @@ def test_motrix_backend_uses_cached_batch_link_velocities() -> None:
import unisim.backend.motrix.backend as mod
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._link_velocities = np.arange(2 * 3 * 6, dtype=np.float32).reshape(2, 3, 6)
backend._link_velocity_cache_valid = True
@@ -319,6 +321,7 @@ def test_motrix_copy_body_state_uses_cached_state_and_reuses_scratch() -> None:
)
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._num_envs = num_envs
backend._np_dtype = np.float32
backend._link_poses = poses
@@ -362,6 +365,7 @@ def test_motrix_backend_get_body_pose_w_slices_cached_poses_once() -> None:
import unisim.backend.motrix.backend as mod
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._link_poses = np.asarray(
[
[
@@ -390,6 +394,7 @@ def test_motrix_root_layout_uses_selected_body_floating_base_indices() -> None:
"floating": SimpleNamespace(floatingbase=floating_base),
}
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._model = SimpleNamespace(get_body=lambda name: bodies.get(name))
layout = backend.get_root_state_layout("floating")
@@ -427,6 +432,7 @@ def test_motrix_backend_applies_body_mass_and_ipos_reset_payload() -> None:
link1.index = 1
link1.name = "object"
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend.backend_type = "motrix"
backend._model = SimpleNamespace(num_links=2)
backend._links_by_id = {0: link0, 1: link1}
@@ -462,6 +468,7 @@ def test_motrix_backend_applies_geom_friction_reset_payload() -> None:
geom1 = _FakeMotrixGeom(name="object")
geom1.index = 1
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend.backend_type = "motrix"
backend._model = SimpleNamespace(num_links=1, num_geoms=2)
backend._geoms_by_id = {0: geom0, 1: geom1}
@@ -524,6 +531,7 @@ def test_motrix_backend_applies_gravity_reset_payload() -> None:
fake_model = _FakeMotrixModel()
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend.backend_type = "motrix"
backend._model = fake_model
backend._supports_gravity_override = True
@@ -548,6 +556,7 @@ def test_motrix_backend_interval_body_force_uses_link_external_force_delta() ->
link = _FakeMotrixLink()
backend = object.__new__(mod.MotrixBackend)
+ backend._portable_mode = False
backend._num_envs = 2
backend._data = object()
backend._links_by_id = {0: link}
diff --git a/tests/envs/test_multi_entity_consumer.py b/tests/envs/test_multi_entity_consumer.py
index d3684ad85..b852dc6c1 100644
--- a/tests/envs/test_multi_entity_consumer.py
+++ b/tests/envs/test_multi_entity_consumer.py
@@ -16,6 +16,7 @@
import pytest
from unisim.dr.types import FixedVariantPlan, ModelSourceDescriptor
from unisim.entities import EntityInitialState, EntityVariantBinding, SceneEntitySpec
+from unisim.scene_compiler import PORTABLE_MJCF_PROFILE_ID
from unilab.base import registry
from unilab.base.entity import EntityCfg
@@ -103,7 +104,7 @@ def make_fixture_cfg():
return build_fixture_cfg(passive=True)
-def build_fixture_cfg(*, passive, num_envs=2):
+def build_fixture_cfg(*, passive: bool, num_envs: int = 2, mirror: bool | None = None):
robot, variants, table = _sources(passive)
entities = [
SceneEntitySpec(
@@ -139,7 +140,8 @@ def build_fixture_cfg(*, passive, num_envs=2):
root_body_name="table/base", physical_entity="table", joint_names=(), actuator_names=()
),
}
- if not passive:
+ include_mirror = not passive if mirror is None else mirror
+ if include_mirror:
entities.append(
SceneEntitySpec(
"target",
@@ -215,6 +217,59 @@ def test_registry_factory_mujoco_multi_entity_reset_isolation(num_envs):
env.close()
+def test_registry_factory_mujoco_consumes_portable_profile_operation_fixture():
+ assert PORTABLE_MJCF_PROFILE_ID == "portable-mjcf-v1"
+ factory = pickle.loads(pickle.dumps(registry_env_factory(TASK, "mujoco")))
+ env = factory(
+ num_envs=5,
+ env_cfg_override={"scene": build_fixture_cfg(passive=True, num_envs=5, mirror=True).scene},
+ )
+ try:
+ state = env.init_state()
+ assert state.obs["obs"].shape == (5, 4)
+ assert env.action_space.shape == (1,)
+ assert env.scene["object"].data.joint_pos.shape == (5, 1)
+
+ mirror_before = env.scene["target"].data.root_link_pose_w.copy()
+ with env._reset_state.scoped(np.array([3])):
+ env.scene["object"].write_root_link_pose_to_sim(
+ np.array([[0.4, -0.2, 1.5, 1.0, 0.0, 0.0, 0.0]]), env_ids=np.array([3])
+ )
+ np.testing.assert_allclose(env.scene["object"].data.root_link_pos_w[3], [0.4, -0.2, 1.5])
+ np.testing.assert_array_equal(env.scene["target"].data.root_link_pose_w, mirror_before)
+
+ env.step(np.full((5, 1), 0.25, dtype=np.float32))
+ np.testing.assert_allclose(env._control, 0.25)
+ env.reset(env_ids=np.array([2]))
+ np.testing.assert_allclose(env._control[:, 0], [0.25, 0.25, 0.0, 0.25, 0.25])
+
+ report = env._backend.get_import_report()
+ entity_fields = [field for field in report.fields if field.field.startswith("entity.")]
+ assert {field.scope.entity for field in entity_fields} == {
+ "robot",
+ "object",
+ "table",
+ "target",
+ }
+ assert all(field.effective is not None for field in entity_fields)
+
+ masses = []
+ for env_index in range(5):
+ playback = env.get_playback_model(env_index)
+ masses.append(float(np.asarray(playback.body("object/base").mass).reshape(-1)[0]))
+ for geom_name in ("target/object_geom", "target/lid_geom"):
+ mirror = playback.geom(geom_name)
+ np.testing.assert_array_equal(
+ (np.asarray(mirror.contype).item(), np.asarray(mirror.conaffinity).item()),
+ (0, 0),
+ )
+ for entity_name in ("robot", "object", "table", "target"):
+ assert playback.body(f"{entity_name}/base")
+ np.testing.assert_allclose(masses, [2.0, 2.0, 1.0, 2.0, 1.0])
+ finally:
+ env.close()
+
+
def test_factory_can_be_unpickled_in_a_fresh_process_without_parent_registry():
encoded = base64.b64encode(pickle.dumps(registry_env_factory(TASK, "mujoco"))).decode()
script = """
diff --git a/tests/training/test_training_helpers.py b/tests/training/test_training_helpers.py
index a0f670cc2..8e7ed3b62 100644
--- a/tests/training/test_training_helpers.py
+++ b/tests/training/test_training_helpers.py
@@ -538,6 +538,7 @@ class FakeEnv:
cfg = type("Cfg", (), {"render_spacing": 1.0, "ctrl_dt": 0.02})()
backend = MotrixBackend.__new__(MotrixBackend)
+ backend._portable_mode = False
backend.init_renderer = lambda **kwargs: None
def _render():
@@ -566,6 +567,7 @@ class FakeEnv:
cfg = type("Cfg", (), {"render_spacing": 1.0, "ctrl_dt": 0.02})()
backend = MotrixBackend.__new__(MotrixBackend)
+ backend._portable_mode = False
backend.init_renderer = lambda **kwargs: None
def _capture_video_frame():
diff --git a/uv.lock b/uv.lock
index 183a9ee1f..b68c30dbf 100644
--- a/uv.lock
+++ b/uv.lock
@@ -4556,7 +4556,7 @@ wheels = [
[[package]]
name = "superdex-physics-uni"
-version = "1.0.0"
+version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "imageio", extra = ["ffmpeg"] },
@@ -4574,20 +4574,20 @@ dependencies = [
{ name = "unrealcv" },
]
wheels = [
- { url = "https://files.pythonhosted.org/packages/5a/1f/deaaf137a3bd4e233c58702005d65a71abec953d22be00605e449859b094/superdex_physics_uni-1.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:29fc2d2a063244c0bb90a181c0dc418db25ded3db2b75262cb921c294da4d832", size = 11930457, upload-time = "2026-09-09T13:04:13.814Z" },
- { url = "https://files.pythonhosted.org/packages/66/53/e2fc09c2c3d45a853f811e3fc216cf52fdb6f4a82dbdda688994b7c54451/superdex_physics_uni-1.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e3832675306f5a34580d46a86618db44b9e45bb26b0a2ec178b2aa6c48e5e4d4", size = 11930880, upload-time = "2026-09-09T14:46:45.279Z" },
+ { url = "https://files.pythonhosted.org/packages/58/88/e20f0dab44dbdb2a98e02a1ff8c2297f21d60be039cd95eddcae723ee7d5/superdex_physics_uni-1.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:802ad6a306c40dbf752d8842e8849a3aad96ef74e3b30150861438befa6a6ab4", size = 11968570, upload-time = "2026-09-19T05:37:01.505Z" },
+ { url = "https://files.pythonhosted.org/packages/27/01/124c793d0041616f33cbd00b17242f6e6475880aca2d21f168f1571ec5e3/superdex_physics_uni-1.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:421f884fcb7592b1b95fe520c46ee6e28bf8a69ec431589652086fdb567c9c8e", size = 11968674, upload-time = "2026-09-19T05:37:08.101Z" },
]
[[package]]
name = "superdex-robotics-uni"
-version = "1.0.0"
+version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "superdex-physics-uni" },
]
wheels = [
- { url = "https://files.pythonhosted.org/packages/a3/00/d670077fcbf7324bf0137e55dee51255084379aeb48494fe2b4350879138/superdex_robotics_uni-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb31135b39451862af8213feb2053c2482337e7f58ae36544093e723c9e5bfc", size = 1043255, upload-time = "2026-09-09T13:04:17.66Z" },
- { url = "https://files.pythonhosted.org/packages/77/3f/a854c6d94019279e68c4259348ac3ab46bd9f975bf30d718df6f4254af87/superdex_robotics_uni-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f61140e76c8809a22b58787dbbe5710ad074e44727b7dfa8b29009d335d7251c", size = 1043319, upload-time = "2026-09-09T14:46:47.57Z" },
+ { url = "https://files.pythonhosted.org/packages/20/5d/0b911ebe20da57797bcb058ed4a16ea1f7334d66ee9ec7d4eaf65f6ea25f/superdex_robotics_uni-1.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cd36fe93b2c1baea06570edb5506e3f2897fad03b91767ddde13215324f83d6", size = 1043475, upload-time = "2026-09-19T05:37:12.105Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/61/1fff02bc141627fde36e526758d9f36658eb37a8651be1f77a2fd252dfbc/superdex_robotics_uni-1.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60e531b7e680b167a3daadc35ca209da171aacba27635b2d4a2bb05a4100842c", size = 1043573, upload-time = "2026-09-19T05:37:14.692Z" },
]
[[package]]
@@ -5240,8 +5240,8 @@ requires-dist = [
{ name = "trimesh", marker = "extra == 'viser'", specifier = ">=3.21.7" },
{ name = "typing-extensions" },
{ name = "unilab-rl", specifier = "==1.3.0" },
- { name = "unisim-core", specifier = ">=1.6.0" },
- { name = "unisim-core", extras = ["superdex"], marker = "python_full_version >= '3.12' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'superdex'", specifier = ">=1.6.0" },
+ { name = "unisim-core", specifier = ">=1.7.1" },
+ { name = "unisim-core", extras = ["superdex"], marker = "python_full_version >= '3.12' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'superdex'", specifier = ">=1.7.1" },
{ name = "viser", marker = "extra == 'viser'", specifier = ">=1.0.26" },
{ name = "wandb" },
{ name = "warp-lang", marker = "extra == 'mjwarp'", specifier = "==1.16.0" },
@@ -5284,13 +5284,13 @@ wheels = [
[[package]]
name = "unisim-core"
-version = "1.6.0"
+version = "1.7.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
{ name = "numpy", version = "2.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/df/d2/6802ddbfea15f27e165f8565faae39eeb6ab31a484384b64a3fc459f269a/unisim_core-1.6.0.tar.gz", hash = "sha256:72dbc11170e9516909a9ec81c353aad17222b52a0aa24f0fc63f5290aee3cf51", size = 363157, upload-time = "2026-09-17T10:25:30.036Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/68/95/8be00e6aa8dfebece0421a2f9216a9f6159455476ac97c4e6eb3d616e31f/unisim_core-1.7.1.tar.gz", hash = "sha256:d9a26a8cbf239cc6ae1b3dde35bcb6b844efd71ac2b23c86037d644c18780338", size = 459983, upload-time = "2026-09-19T06:11:01.577Z" }
[package.optional-dependencies]
superdex = [