From d896442a7a40a616e42039597c5b082322ad7529 Mon Sep 17 00:00:00 2001 From: TATP-233 Date: Fri, 18 Sep 2026 13:39:40 +0800 Subject: [PATCH 1/2] test: prepare portable scene consumer acceptance --- tests/base/test_entity_scene_consumer.py | 2 + tests/envs/test_multi_entity_consumer.py | 62 +++++++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) 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/envs/test_multi_entity_consumer.py b/tests/envs/test_multi_entity_consumer.py index d3684ad85..94e8f0960 100644 --- a/tests/envs/test_multi_entity_consumer.py +++ b/tests/envs/test_multi_entity_consumer.py @@ -103,7 +103,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 +139,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 +216,63 @@ def test_registry_factory_mujoco_multi_entity_reset_isolation(num_envs): env.close() +def test_registry_factory_mujoco_consumes_portable_profile_operation_fixture(): + scene_compiler = pytest.importorskip( + "unisim.scene_compiler", + reason="UniSim portable MJCF profile is newer than the released 1.6.0 dependency", + ) + assert scene_compiler.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 = """ From 7c59c73966682a40103b8b17b57fb2f16fb15c5f Mon Sep 17 00:00:00 2001 From: TATP-233 Date: Sat, 19 Sep 2026 14:15:54 +0800 Subject: [PATCH 2/2] fix: consume released unisim portable scenes --- docs/sphinx/source/changelog.md | 10 ++++++++++ .../2-contracts/2-backend_contract.md | 2 +- .../2-contracts/2-backend_contract.md | 2 +- pyproject.toml | 9 +++++---- tests/base/test_backend_pre_step_control.py | 6 ++++++ tests/base/test_genesis_backend.py | 2 +- tests/base/test_isaacsim_backend.py | 8 ++++++-- tests/base/test_motrix_backend_options.py | 9 +++++++++ tests/envs/test_multi_entity_consumer.py | 7 ++----- tests/training/test_training_helpers.py | 2 ++ uv.lock | 20 +++++++++---------- 11 files changed, 53 insertions(+), 24 deletions(-) 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_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 94e8f0960..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 @@ -217,11 +218,7 @@ def test_registry_factory_mujoco_multi_entity_reset_isolation(num_envs): def test_registry_factory_mujoco_consumes_portable_profile_operation_fixture(): - scene_compiler = pytest.importorskip( - "unisim.scene_compiler", - reason="UniSim portable MJCF profile is newer than the released 1.6.0 dependency", - ) - assert scene_compiler.PORTABLE_MJCF_PROFILE_ID == "portable-mjcf-v1" + assert PORTABLE_MJCF_PROFILE_ID == "portable-mjcf-v1" factory = pickle.loads(pickle.dumps(registry_env_factory(TASK, "mujoco"))) env = factory( num_envs=5, 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 = [