molmo-spaces 0.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. molmo_spaces/__init__.py +3 -0
  2. molmo_spaces/configs/__init__.py +61 -0
  3. molmo_spaces/configs/abstract_config.py +43 -0
  4. molmo_spaces/configs/abstract_exp_config.py +211 -0
  5. molmo_spaces/configs/base_nav_to_obj_config.py +112 -0
  6. molmo_spaces/configs/base_open_task_configs.py +56 -0
  7. molmo_spaces/configs/base_packing_configs.py +21 -0
  8. molmo_spaces/configs/base_pick_and_place_color_configs.py +31 -0
  9. molmo_spaces/configs/base_pick_and_place_configs.py +27 -0
  10. molmo_spaces/configs/base_pick_and_place_next_to_configs.py +26 -0
  11. molmo_spaces/configs/base_pick_config.py +114 -0
  12. molmo_spaces/configs/camera_configs.py +959 -0
  13. molmo_spaces/configs/dummy_config.py +18 -0
  14. molmo_spaces/configs/policy_configs.py +461 -0
  15. molmo_spaces/configs/policy_configs_baselines.py +138 -0
  16. molmo_spaces/configs/robot_configs.py +427 -0
  17. molmo_spaces/configs/task_configs.py +200 -0
  18. molmo_spaces/configs/task_sampler_configs.py +327 -0
  19. molmo_spaces/controllers/__init__.py +0 -0
  20. molmo_spaces/controllers/abstract.py +83 -0
  21. molmo_spaces/controllers/base_pose.py +263 -0
  22. molmo_spaces/controllers/joint_pos.py +73 -0
  23. molmo_spaces/controllers/joint_rel_pos.py +84 -0
  24. molmo_spaces/controllers/joint_vel.py +78 -0
  25. molmo_spaces/controllers/torso_height.py +75 -0
  26. molmo_spaces/data_generation/__init__.py +0 -0
  27. molmo_spaces/data_generation/config/__init__.py +6 -0
  28. molmo_spaces/data_generation/config/benchmarks_datagen_configs.py +16 -0
  29. molmo_spaces/data_generation/config/door_opening_configs.py +168 -0
  30. molmo_spaces/data_generation/config/nav_to_obj_configs.py +71 -0
  31. molmo_spaces/data_generation/config/object_manipulation_datagen_configs.py +896 -0
  32. molmo_spaces/data_generation/config_registry.py +73 -0
  33. molmo_spaces/data_generation/main.py +149 -0
  34. molmo_spaces/data_generation/pipeline.py +1373 -0
  35. molmo_spaces/env/__init__.py +0 -0
  36. molmo_spaces/env/abstract_sensors.py +125 -0
  37. molmo_spaces/env/arena/__init__.py +0 -0
  38. molmo_spaces/env/arena/arena_utils.py +325 -0
  39. molmo_spaces/env/arena/bathroom.py +31 -0
  40. molmo_spaces/env/arena/cabinet.py +63 -0
  41. molmo_spaces/env/arena/drawer.py +32 -0
  42. molmo_spaces/env/arena/kitchen.py +89 -0
  43. molmo_spaces/env/arena/procthor_types.py +244 -0
  44. molmo_spaces/env/arena/randomization/__init__.py +0 -0
  45. molmo_spaces/env/arena/randomization/dynamics.py +303 -0
  46. molmo_spaces/env/arena/randomization/lighting.py +484 -0
  47. molmo_spaces/env/arena/randomization/test_randomizers.py +411 -0
  48. molmo_spaces/env/arena/randomization/texture.py +1863 -0
  49. molmo_spaces/env/arena/scene_tweaks.py +246 -0
  50. molmo_spaces/env/camera_manager.py +999 -0
  51. molmo_spaces/env/data_views.py +803 -0
  52. molmo_spaces/env/env.py +1079 -0
  53. molmo_spaces/env/mj_extensions.py +116 -0
  54. molmo_spaces/env/object_manager.py +1685 -0
  55. molmo_spaces/env/rby1_sensors.py +280 -0
  56. molmo_spaces/env/sensors.py +1101 -0
  57. molmo_spaces/env/sensors_cameras.py +170 -0
  58. molmo_spaces/evaluation/__init__.py +63 -0
  59. molmo_spaces/evaluation/benchmark_schema.py +600 -0
  60. molmo_spaces/evaluation/configs/__init__.py +0 -0
  61. molmo_spaces/evaluation/configs/evaluation_configs.py +349 -0
  62. molmo_spaces/evaluation/eval_main.py +769 -0
  63. molmo_spaces/evaluation/json_eval_runner.py +335 -0
  64. molmo_spaces/evaluation/policy_server.py +209 -0
  65. molmo_spaces/evaluation/robot_eval_overrides.py +89 -0
  66. molmo_spaces/grasp_generation/__init__.py +0 -0
  67. molmo_spaces/grasp_generation/find_objects.py +108 -0
  68. molmo_spaces/grasp_generation/pipeline/__init__.py +0 -0
  69. molmo_spaces/grasp_generation/pipeline/articulation_test.py +965 -0
  70. molmo_spaces/grasp_generation/pipeline/combine_meshes.py +153 -0
  71. molmo_spaces/grasp_generation/pipeline/extract_leaf_meshes.py +429 -0
  72. molmo_spaces/grasp_generation/pipeline/generate_grasps.py +1042 -0
  73. molmo_spaces/grasp_generation/pipeline/perturbations_test.py +643 -0
  74. molmo_spaces/grasp_generation/robotiq_gripper.py +65 -0
  75. molmo_spaces/grasp_generation/run_articulable.py +495 -0
  76. molmo_spaces/grasp_generation/run_rigid.py +281 -0
  77. molmo_spaces/housegen/__init__.py +0 -0
  78. molmo_spaces/housegen/builder.py +2204 -0
  79. molmo_spaces/housegen/constants.py +230 -0
  80. molmo_spaces/housegen/exporter.py +629 -0
  81. molmo_spaces/housegen/utils.py +1581 -0
  82. molmo_spaces/kinematics/__init__.py +0 -0
  83. molmo_spaces/kinematics/floating_rum_kinematics.py +162 -0
  84. molmo_spaces/kinematics/mujoco_kinematics.py +254 -0
  85. molmo_spaces/kinematics/parallel/__init__.py +0 -0
  86. molmo_spaces/kinematics/parallel/dummy_parallel_kinematics.py +87 -0
  87. molmo_spaces/kinematics/parallel/parallel_kinematics.py +107 -0
  88. molmo_spaces/kinematics/parallel/warp_kinematics.py +652 -0
  89. molmo_spaces/kinematics/test_robot_ik.py +104 -0
  90. molmo_spaces/molmo_spaces_constants.py +768 -0
  91. molmo_spaces/planner/__init__.py +0 -0
  92. molmo_spaces/planner/abstract.py +14 -0
  93. molmo_spaces/planner/astar_planner.py +227 -0
  94. molmo_spaces/planner/curobo_planner.py +606 -0
  95. molmo_spaces/planner/curobo_planner_client.py +307 -0
  96. molmo_spaces/planner/curobo_planner_server.py +608 -0
  97. molmo_spaces/planner/robot_specific/__init__.py +0 -0
  98. molmo_spaces/planner/test_grpc_batch.py +185 -0
  99. molmo_spaces/policy/__init__.py +0 -0
  100. molmo_spaces/policy/base_policy.py +204 -0
  101. molmo_spaces/policy/dummy_policy.py +50 -0
  102. molmo_spaces/policy/learned_policy/__init__.py +0 -0
  103. molmo_spaces/policy/learned_policy/bimanual_yam_pi_policy.py +360 -0
  104. molmo_spaces/policy/learned_policy/cap_policy.py +229 -0
  105. molmo_spaces/policy/learned_policy/dreamzero_policy.py +241 -0
  106. molmo_spaces/policy/learned_policy/keyboard_policy.py +230 -0
  107. molmo_spaces/policy/learned_policy/lerobot_grpc_client.py +209 -0
  108. molmo_spaces/policy/learned_policy/phone_policy.py +199 -0
  109. molmo_spaces/policy/learned_policy/pi_policy.py +217 -0
  110. molmo_spaces/policy/learned_policy/rum_client.py +227 -0
  111. molmo_spaces/policy/learned_policy/spacemouse_policy.py +322 -0
  112. molmo_spaces/policy/learned_policy/utils.py +246 -0
  113. molmo_spaces/policy/learned_policy/websocket_policy.py +137 -0
  114. molmo_spaces/policy/random_policy.py +39 -0
  115. molmo_spaces/policy/solvers/__init__.py +3 -0
  116. molmo_spaces/policy/solvers/curobo_planner_policy.py +707 -0
  117. molmo_spaces/policy/solvers/move_solver.py +0 -0
  118. molmo_spaces/policy/solvers/navigation/__init__.py +0 -0
  119. molmo_spaces/policy/solvers/navigation/astar_planner_policy.py +539 -0
  120. molmo_spaces/policy/solvers/object_manipulation/__init__.py +3 -0
  121. molmo_spaces/policy/solvers/object_manipulation/base_object_manipulation_planner_policy.py +671 -0
  122. molmo_spaces/policy/solvers/object_manipulation/curobo_open_close_planner_policy.py +883 -0
  123. molmo_spaces/policy/solvers/object_manipulation/curobo_pick_and_place_planner_policy.py +681 -0
  124. molmo_spaces/policy/solvers/object_manipulation/open_close_planner_policy.py +234 -0
  125. molmo_spaces/policy/solvers/object_manipulation/pick_and_place_color_planner_policy.py +9 -0
  126. molmo_spaces/policy/solvers/object_manipulation/pick_and_place_next_to_planner_policy.py +200 -0
  127. molmo_spaces/policy/solvers/object_manipulation/pick_and_place_planner_policy.py +293 -0
  128. molmo_spaces/policy/solvers/object_manipulation/pick_planner_policy.py +175 -0
  129. molmo_spaces/policy/solvers/opening_solver.py +703 -0
  130. molmo_spaces/renderer/__init__.py +0 -0
  131. molmo_spaces/renderer/abstract_renderer.py +173 -0
  132. molmo_spaces/renderer/filament_rendering.py +376 -0
  133. molmo_spaces/renderer/offline_renderers/__init__.py +0 -0
  134. molmo_spaces/renderer/offline_renderers/domain_randomization.py +113 -0
  135. molmo_spaces/renderer/offline_renderers/omniverse_renderer.py +299 -0
  136. molmo_spaces/renderer/offline_renderers/opengl_rendrerer.py +190 -0
  137. molmo_spaces/renderer/opengl_context.py +185 -0
  138. molmo_spaces/renderer/opengl_rendering.py +540 -0
  139. molmo_spaces/resources/__init__.py +0 -0
  140. molmo_spaces/resources/asset_id_to_object_type.json +1655 -0
  141. molmo_spaces/resources/base_scene.xml +33 -0
  142. molmo_spaces/resources/generate_user_asset_library_index.py +146 -0
  143. molmo_spaces/resources/generate_user_grasp_library_index.py +108 -0
  144. molmo_spaces/resources/material_to_textures.json +13694 -0
  145. molmo_spaces/robots/__init__.py +0 -0
  146. molmo_spaces/robots/abstract.py +419 -0
  147. molmo_spaces/robots/bimanual_yam.py +151 -0
  148. molmo_spaces/robots/find_gripper_finger_range.py +75 -0
  149. molmo_spaces/robots/floating_robotiq.py +59 -0
  150. molmo_spaces/robots/floating_rum.py +112 -0
  151. molmo_spaces/robots/franka.py +262 -0
  152. molmo_spaces/robots/i2rt_yam.py +131 -0
  153. molmo_spaces/robots/mobile_franka.py +278 -0
  154. molmo_spaces/robots/rby1.py +437 -0
  155. molmo_spaces/robots/robot_views/__init__.py +0 -0
  156. molmo_spaces/robots/robot_views/abstract.py +838 -0
  157. molmo_spaces/robots/robot_views/bimanual_yam_view.py +190 -0
  158. molmo_spaces/robots/robot_views/franka_cap_view.py +76 -0
  159. molmo_spaces/robots/robot_views/franka_droid_view.py +154 -0
  160. molmo_spaces/robots/robot_views/franka_fr3_view.py +115 -0
  161. molmo_spaces/robots/robot_views/i2rt_yam_view.py +153 -0
  162. molmo_spaces/robots/robot_views/mobile_franka_droid_view.py +41 -0
  163. molmo_spaces/robots/robot_views/rby1_view.py +360 -0
  164. molmo_spaces/robots/robot_views/rum_gripper_view.py +162 -0
  165. molmo_spaces/tasks/__init__.py +0 -0
  166. molmo_spaces/tasks/eval_task_sampler.py +325 -0
  167. molmo_spaces/tasks/gym_env.py +246 -0
  168. molmo_spaces/tasks/json_eval_task_sampler.py +893 -0
  169. molmo_spaces/tasks/llm_task_utils.py +203 -0
  170. molmo_spaces/tasks/multi_task.py +121 -0
  171. molmo_spaces/tasks/nav_task.py +318 -0
  172. molmo_spaces/tasks/nav_task_sampler.py +414 -0
  173. molmo_spaces/tasks/opening_task_samplers.py +517 -0
  174. molmo_spaces/tasks/opening_tasks.py +662 -0
  175. molmo_spaces/tasks/packing_task.py +10 -0
  176. molmo_spaces/tasks/packing_task_sampler.py +140 -0
  177. molmo_spaces/tasks/pick_and_place_color_task.py +44 -0
  178. molmo_spaces/tasks/pick_and_place_color_task_sampler.py +146 -0
  179. molmo_spaces/tasks/pick_and_place_next_to_task.py +177 -0
  180. molmo_spaces/tasks/pick_and_place_next_to_task_sampler.py +171 -0
  181. molmo_spaces/tasks/pick_and_place_object_target_task_sampler.py +164 -0
  182. molmo_spaces/tasks/pick_and_place_task.py +251 -0
  183. molmo_spaces/tasks/pick_and_place_task_sampler.py +541 -0
  184. molmo_spaces/tasks/pick_task.py +194 -0
  185. molmo_spaces/tasks/pick_task_sampler.py +1204 -0
  186. molmo_spaces/tasks/task.py +566 -0
  187. molmo_spaces/tasks/task_sampler.py +1147 -0
  188. molmo_spaces/tasks/task_sampler_errors.py +47 -0
  189. molmo_spaces/tasks/task_scene_utils.py +75 -0
  190. molmo_spaces/tasks/util_samplers/__init__.py +0 -0
  191. molmo_spaces/tasks/util_samplers/grasp_sampler.py +204 -0
  192. molmo_spaces/tasks/util_samplers/navgoal_sampler.py +295 -0
  193. molmo_spaces/utils/__init__.py +0 -0
  194. molmo_spaces/utils/articulation_utils.py +554 -0
  195. molmo_spaces/utils/asset_names.py +36 -0
  196. molmo_spaces/utils/benchmark_utils.py +1052 -0
  197. molmo_spaces/utils/camera_utils.py +45 -0
  198. molmo_spaces/utils/constants/__init__.py +0 -0
  199. molmo_spaces/utils/constants/camera_constants.py +29 -0
  200. molmo_spaces/utils/constants/object_constants.py +781 -0
  201. molmo_spaces/utils/constants/simulation_constants.py +1 -0
  202. molmo_spaces/utils/controller_utils.py +39 -0
  203. molmo_spaces/utils/depth_utils.py +716 -0
  204. molmo_spaces/utils/devices/__init__.py +0 -0
  205. molmo_spaces/utils/devices/keyboard.py +52 -0
  206. molmo_spaces/utils/devices/spacemouse.py +343 -0
  207. molmo_spaces/utils/distance_transform_utils.py +131 -0
  208. molmo_spaces/utils/eval_camera_randomization_utils.py +531 -0
  209. molmo_spaces/utils/eval_utils.py +532 -0
  210. molmo_spaces/utils/fisheye_warping.py +454 -0
  211. molmo_spaces/utils/function_utils.py +82 -0
  212. molmo_spaces/utils/grasp_sample.py +239 -0
  213. molmo_spaces/utils/grasps.py +340 -0
  214. molmo_spaces/utils/lazy_loading_utils.py +283 -0
  215. molmo_spaces/utils/lemma_utils.py +52 -0
  216. molmo_spaces/utils/license_utils.py +478 -0
  217. molmo_spaces/utils/linalg_utils.py +231 -0
  218. molmo_spaces/utils/mj_model_and_data_utils.py +200 -0
  219. molmo_spaces/utils/mp_logging.py +422 -0
  220. molmo_spaces/utils/mujoco_scene_utils.py +373 -0
  221. molmo_spaces/utils/object_metadata.py +402 -0
  222. molmo_spaces/utils/object_retriever.py +77 -0
  223. molmo_spaces/utils/patch_renderer_flags.py +16 -0
  224. molmo_spaces/utils/pose.py +69 -0
  225. molmo_spaces/utils/profiler_utils.py +340 -0
  226. molmo_spaces/utils/rendering_utils.py +23 -0
  227. molmo_spaces/utils/sampler_utils.py +256 -0
  228. molmo_spaces/utils/save_utils.py +1070 -0
  229. molmo_spaces/utils/scene_maps.py +1075 -0
  230. molmo_spaces/utils/scene_metadata_utils.py +189 -0
  231. molmo_spaces/utils/spatial_utils.py +116 -0
  232. molmo_spaces/utils/synset_utils.py +1380 -0
  233. molmo_spaces/utils/task_relevant_objects_and_workspace_utils.py +113 -0
  234. molmo_spaces/utils/test_utils.py +1083 -0
  235. molmo_spaces/utils/video_utils.py +113 -0
  236. molmo_spaces-0.2.9.dist-info/METADATA +463 -0
  237. molmo_spaces-0.2.9.dist-info/RECORD +241 -0
  238. molmo_spaces-0.2.9.dist-info/WHEEL +5 -0
  239. molmo_spaces-0.2.9.dist-info/entry_points.txt +2 -0
  240. molmo_spaces-0.2.9.dist-info/licenses/LICENSE +13 -0
  241. molmo_spaces-0.2.9.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ from pathlib import Path
2
+
3
+ MOLMO_SPACES_BASE_DIR = Path(__file__).parent
@@ -0,0 +1,61 @@
1
+ """Configuration module for MolmoSpaces experiments.
2
+
3
+ This module provides configuration classes organized by category:
4
+ - abstract_config: Base Config class
5
+ - abstract_exp_config: Base experiment configuration
6
+ - camera_configs: Camera-related configurations
7
+ - robot_configs: Robot-related configurations
8
+ - task_configs: Task-related configurations
9
+ - task_sampler_configs: Task sampler-related configurations
10
+ - policy_configs: Policy-related configurations
11
+ """
12
+
13
+ from molmo_spaces.configs.abstract_config import Config
14
+ from molmo_spaces.configs.abstract_exp_config import MlSpacesExpConfig
15
+ from molmo_spaces.configs.camera_configs import (
16
+ CameraConfig,
17
+ CameraSystemConfig,
18
+ FixedExocentricCameraConfig,
19
+ FrankaDroidCameraSystem,
20
+ FrankaRandomizedD405D455CameraSystem,
21
+ MjcfCameraConfig,
22
+ RandomizedExocentricCameraConfig,
23
+ RBY1GoProD455CameraSystem,
24
+ RBY1MjcfCameraSystem,
25
+ RobotMountedCameraConfig,
26
+ )
27
+ from molmo_spaces.configs.policy_configs import BasePolicyConfig
28
+ from molmo_spaces.configs.robot_configs import BaseRobotConfig, FrankaRobotConfig
29
+ from molmo_spaces.configs.task_configs import BaseMujocoTaskConfig, PickTaskConfig
30
+ from molmo_spaces.configs.task_sampler_configs import (
31
+ BaseMujocoTaskSamplerConfig,
32
+ PickTaskSamplerConfig,
33
+ )
34
+
35
+ __all__ = [
36
+ "Config",
37
+ "MlSpacesExpConfig",
38
+ # Camera configs - new unified system
39
+ "CameraSystemConfig",
40
+ "CameraConfig",
41
+ "MjcfCameraConfig",
42
+ "RobotMountedCameraConfig",
43
+ "FixedExocentricCameraConfig",
44
+ "RandomizedExocentricCameraConfig",
45
+ "RBY1MjcfCameraSystem",
46
+ "RBY1GoProD455CameraSystem",
47
+ "FrankaRandomizedD405D455CameraSystem",
48
+ "FrankaDroidCameraSystem",
49
+ # Robot configs
50
+ "BaseRobotConfig",
51
+ "FrankaRobotConfig",
52
+ # Task configs
53
+ "BaseMujocoTaskConfig",
54
+ "PickTaskConfig",
55
+ # Task sampler configs
56
+ "BaseMujocoTaskSamplerConfig",
57
+ "PickTaskSamplerConfig",
58
+ # Policy configs
59
+ "BasePolicyConfig",
60
+ "ObjectManipulationPlannerPolicyConfig",
61
+ ]
@@ -0,0 +1,43 @@
1
+ """Simple configuration management using Pydantic.
2
+ This module provides a base configuration class that can be extended to create specific configurations.
3
+ It uses Pydantic for data validation and can return dicts or jsons or save or load jsons from files.
4
+ """
5
+
6
+ from pydantic import BaseModel, ConfigDict
7
+
8
+
9
+ class Config(BaseModel):
10
+ """
11
+ Base configuration class that can be extended for specific configurations.
12
+ Provides methods to convert to dict, json, and to save/load from files.
13
+ """
14
+
15
+ model_config = ConfigDict(
16
+ arbitrary_types_allowed=True, # allow arbitrary types in the config
17
+ # frozen=True, # (Optional) Make the config immutable
18
+ )
19
+
20
+ def to_dict(self) -> dict:
21
+ """Convert the configuration to a dictionary."""
22
+ return self.model_dump()
23
+
24
+ def to_json(self) -> str:
25
+ # TODO(max): this can cause errors, try printing out the config to see missmatches w/ print(self)
26
+ return self.model_dump_json(warnings="error")
27
+
28
+ @classmethod
29
+ def from_dict(cls, data: dict) -> "Config":
30
+ """Create a configuration instance from a dictionary."""
31
+ return cls.model_validate(data)
32
+
33
+ @classmethod
34
+ def load_from_json(cls, file_path: str) -> "Config":
35
+ """Load the configuration from a JSON file."""
36
+ with open(file_path, "r") as f:
37
+ data = f.read()
38
+ return cls.model_validate_json(data)
39
+
40
+ def save_to_json(self, file_path: str) -> None:
41
+ """Save the configuration to a JSON file."""
42
+ with open(file_path, "w") as f:
43
+ f.write(self.to_json())
@@ -0,0 +1,211 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import datetime
5
+ import logging
6
+ import pickle
7
+ from abc import ABC, abstractmethod
8
+ from pathlib import Path
9
+ from typing import Any, ClassVar
10
+
11
+ from molmo_spaces.configs.abstract_config import Config
12
+ from molmo_spaces.configs.camera_configs import (
13
+ AllCameraSystems,
14
+ CameraSystemConfig,
15
+ FixedExocentricCameraConfig,
16
+ MjcfCameraConfig,
17
+ RandomizedExocentricCameraConfig,
18
+ RobotMountedCameraConfig,
19
+ )
20
+ from molmo_spaces.configs.policy_configs import BasePolicyConfig
21
+ from molmo_spaces.configs.robot_configs import BaseRobotConfig
22
+ from molmo_spaces.configs.task_configs import AllTaskConfigs
23
+ from molmo_spaces.configs.task_sampler_configs import BaseMujocoTaskSamplerConfig
24
+ from molmo_spaces.tasks.task import BaseMujocoTask
25
+ from molmo_spaces.utils.pose import pose_mat_to_7d
26
+ from molmo_spaces.utils.profiler_utils import Profiler
27
+
28
+ log = logging.getLogger(__name__)
29
+
30
+
31
+ class MlSpacesExpConfig(Config, ABC):
32
+ """
33
+ Base configuration class for experiments.
34
+ This should be extended to create specific experiment configurations.
35
+ """
36
+
37
+ config_version: str = "0.1"
38
+ num_envs: (
39
+ int # Number of batched environments per worker (for vectorized physics in CPUMujocoEnv)
40
+ )
41
+ num_workers: int = (
42
+ 1 # Number of worker processes for parallel data generation (episode-level parallelism)
43
+ )
44
+
45
+ task_type: str # Task type: e.g. pick, pick_and_place, etc.
46
+ use_passive_viewer: bool # Launch passive viewer for rendering
47
+ viewer_cam_dict: dict # Dictionary containing viewer camera parameters
48
+ policy_dt_ms: float # Default policy time step
49
+ ctrl_dt_ms: float # Default control time step
50
+ sim_dt_ms: float # Default simulation time step
51
+ seed: int | None = None # Random seed for task sampling (if None, generates random seed)
52
+ task_horizon: int | None = None # Maximum number of steps per episode (if None, no time limit)
53
+ end_on_success: bool = (
54
+ False # Whether to end episode immediately upon success (overrides task_horizon if True)
55
+ )
56
+ collision_free_pose_limit: int = 3
57
+
58
+ # Scene configuration
59
+ scene_dataset: str # Scenes to use, e.g. ithor, procthor-10k, procthor-objaverse. If "user", use the scene_xml_paths in task_sampler_config.
60
+ data_split: str = "train" # Data split to use, e.g. train, val, test
61
+
62
+ @property
63
+ def fps(self) -> float:
64
+ return 1000.0 / self.policy_dt_ms
65
+
66
+ # Configuration fields using imported base classes
67
+ camera_config: CameraSystemConfig | None = None # Configuration for cameras and sensors
68
+ robot_config: BaseRobotConfig # Configuration for the robot
69
+ task_sampler_config: BaseMujocoTaskSamplerConfig # Configuration for the task sampler
70
+ task_config: AllTaskConfigs # Configuration for tasks
71
+ task_config_preset_exp: AllTaskConfigs | None = None # Cached config for whole experiment
72
+ task_config_preset_scn: AllTaskConfigs | None = None # Cached config for scene
73
+ policy_config: BasePolicyConfig # Configuration for policies
74
+
75
+ benchmark_path: Path | None = None # Contains a json with a list of fully-specified episodes.
76
+
77
+ # Evaluation runtime parameters (optional, set during evaluation initialization)
78
+ # Using Any to avoid circular import - actual type is EvalRuntimeParams from eval_main
79
+ eval_runtime_params: Any = None
80
+
81
+ # Output and profiling
82
+ output_dir: Path # Output directory for experiment results
83
+ profile: bool = False # Whether to enable profiling
84
+ profiler: Profiler | None = None # Profiler instance (auto-created if profile=True)
85
+ datagen_profiler: bool = True # run the datagen profiler
86
+
87
+ # Logging
88
+ log_level: str = "info" # Global logging level: "debug", "info", "warning", "error", "none"
89
+ use_wandb: bool = False
90
+ wandb_project: str | None = None
91
+ wandb_name: str | None = None # Weights & Biases run name
92
+
93
+ # Backward compatibility aliases for nested class references (ClassVar so Pydantic ignores them)
94
+ CameraConfig: ClassVar[type] = CameraSystemConfig
95
+ RobotConfig: ClassVar[type] = BaseRobotConfig
96
+ PolicyConfig: ClassVar[type] = BasePolicyConfig
97
+
98
+ filter_for_successful_trajectories: bool = True # If True, only save successful trajectories to main output directory (failed episodes may be sampled 1% for debug directory). If False, save all trajectories to main output directory.
99
+
100
+ environment_light_intensity: float = 15000.0
101
+
102
+ no_cached_map: bool = False
103
+
104
+ def model_post_init(self, _context) -> None:
105
+ """This serves as the __init__() called after internal validation of config parameters"""
106
+ assert (self.policy_dt_ms / self.ctrl_dt_ms).is_integer(), (
107
+ "policy_dt_ms must be a multiple of ctrl_dt_ms"
108
+ )
109
+ assert (self.ctrl_dt_ms / self.sim_dt_ms).is_integer(), (
110
+ "ctrl_dt_ms must be a multiple of sim_dt"
111
+ )
112
+
113
+ @property
114
+ @abstractmethod
115
+ def tag(self) -> str:
116
+ """A string describing the experiment."""
117
+
118
+ def save_config(self, output_dir=None) -> None:
119
+ """Saves the current configuration to the output directory"""
120
+ if output_dir is None:
121
+ output_dir = self.output_dir
122
+ output_dir = Path(output_dir)
123
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
124
+ output_dir.mkdir(parents=True, exist_ok=True)
125
+ config_path = output_dir / f"experiment_config_{timestamp}.pkl"
126
+ with open(config_path, "wb") as f:
127
+ pickle.dump(self, f)
128
+ log.info(f"Saved experiment configuration to {output_dir}")
129
+
130
+ @staticmethod
131
+ def load_config(output_dir: Path) -> MlSpacesExpConfig:
132
+ """Loads a configuration from a file"""
133
+ config_path = output_dir / "experiment_config.pkl"
134
+ with open(config_path, "rb") as f:
135
+ config = pickle.load(f)
136
+ log.info(f"Loaded experiment configuration from {output_dir}")
137
+ return config
138
+
139
+ # The code below this is used for saving episode state so that it can be re-loaded w/o sampling
140
+ class SavedEpisode(Config):
141
+ """Config informationd describing a sinlge episode"""
142
+
143
+ camera_config: AllCameraSystems | None = None # Configuration for cameras and sensors
144
+ robot_config: BaseRobotConfig | None = None # Configuration for the robot
145
+ task_config: AllTaskConfigs | None = None # Configuration for tasks
146
+ task_cls_str: str | None = None
147
+
148
+ def freeze_task_config(self, observation, task: BaseMujocoTask = None) -> None:
149
+ """Saves the state of a sampled task i.e. an episode"""
150
+ sc = self.SavedEpisode()
151
+
152
+ # RMH: deep argument VERY IMPORTANT. Mutates config for future episodes otherwise
153
+ sc.robot_config = self.robot_config.model_copy(deep=True)
154
+ # remove un-serializable
155
+ sc.robot_config.robot_cls = None
156
+ sc.robot_config.robot_factory = None
157
+ sc.robot_config.robot_view_factory = None
158
+ # save state
159
+ sc.robot_config.init_qpos_noise_range = None # remove ranges
160
+ sc.robot_config.init_qpos = observation[0]["qpos"]
161
+ sc.camera_config = self.camera_config.model_copy(deep=True)
162
+ for i, camera in enumerate(sc.camera_config.cameras):
163
+ # Some cameras can contain random sampling, e.g. of positions
164
+ # Read the camera's positions and convert them to fixed cameras
165
+ if isinstance(camera, MjcfCameraConfig | RobotMountedCameraConfig):
166
+ cam = task.env.camera_manager.registry[camera.name]
167
+ new_camera = RobotMountedCameraConfig(
168
+ name=cam.name,
169
+ reference_body_names=list(cam.reference_body_names),
170
+ camera_offset=list(cam.camera_offset),
171
+ lookat_offset=list(cam.lookat_offset),
172
+ camera_quaternion=list(cam.camera_quaternion),
173
+ fov=cam.fov,
174
+ )
175
+ sc.camera_config.cameras[i] = new_camera
176
+
177
+ elif isinstance(camera, RandomizedExocentricCameraConfig | FixedExocentricCameraConfig):
178
+ cam = task.env.camera_manager.registry[camera.name]
179
+ new_camera = FixedExocentricCameraConfig(
180
+ name=cam.name,
181
+ fov=cam.fov,
182
+ pos=list(cam.pos),
183
+ up=list(cam.up),
184
+ forward=list(cam.forward),
185
+ )
186
+ sc.camera_config.cameras[i] = new_camera
187
+ else:
188
+ raise NotImplementedError(f"Cannot freeze camera of type {type(camera).__name__}")
189
+
190
+ # for all task relevant objects, save the poses
191
+ # assert task.config.task_config.object_poses is None
192
+ obj_poses = {}
193
+ om = task.env.object_managers[task.env.current_batch_index]
194
+ task_objects = om.get_mobile_objects()
195
+ for task_object in task_objects:
196
+ obj_poses[task_object.name] = pose_mat_to_7d(task_object.pose).tolist()
197
+ task.config.task_config.object_poses = obj_poses
198
+
199
+ sc.task_config = self.task_config.model_copy(deep=True)
200
+ # remove un-serializable
201
+ sc.task_config.task_cls = None
202
+ # save the name of the task class
203
+ sc.task_cls_str = (
204
+ self.task_config.task_cls.__module__ + "." + self.task_config.task_cls.__name__
205
+ )
206
+
207
+ assert sc.task_config.robot_base_pose is not None
208
+
209
+ sc_bytes = pickle.dumps(sc)
210
+ sc_b64 = base64.b64encode(sc_bytes).decode("utf-8")
211
+ return sc_b64
@@ -0,0 +1,112 @@
1
+ """
2
+ Example configuration for RBY1 navigation to object data generation using the extracted task sampler.
3
+ This shows how the scene randomization functionality from the reference script has been
4
+ properly integrated into the modular task sampler architecture.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import numpy as np
10
+
11
+ from molmo_spaces.configs.abstract_config import Config
12
+ from molmo_spaces.configs.abstract_exp_config import MlSpacesExpConfig
13
+ from molmo_spaces.configs.camera_configs import RBY1MjcfCameraSystem
14
+ from molmo_spaces.configs.policy_configs import AStarNavToObjPolicyConfig, BasePolicyConfig
15
+ from molmo_spaces.configs.robot_configs import BaseRobotConfig, RBY1Config
16
+ from molmo_spaces.configs.task_configs import NavToObjTaskConfig
17
+ from molmo_spaces.configs.task_sampler_configs import NavToObjTaskSamplerConfig
18
+ from molmo_spaces.tasks.nav_task import NavToObjTask
19
+ from molmo_spaces.tasks.nav_task_sampler import NavToObjTaskSampler
20
+ from molmo_spaces.utils.profiler_utils import Profiler
21
+
22
+
23
+ class NavToObjBaseConfig(MlSpacesExpConfig):
24
+ """Base configuration for navigation to object data generation tasks."""
25
+
26
+ # NOTE: will not work if used directly. Subclass examples in data_generation/configs.py
27
+
28
+ # --- Experiment-level config parameters ---
29
+ num_envs: int = 1 # Number of environments to run in each thread
30
+ use_passive_viewer: bool = False # Launch passive viewer for rendering
31
+ viewer_camera: None = None
32
+ viewer_cam_dict: dict = {
33
+ "distance": 5.0,
34
+ "azimuth": 45.0,
35
+ "elevation": -30.0,
36
+ "lookat": np.array([0.0, 0.0, 0.5]),
37
+ }
38
+ policy_dt_ms: float = 200.0 # policy time step
39
+ ctrl_dt_ms: float = 2.0 # control time step
40
+ sim_dt_ms: float = 2.0 # simulation time step
41
+ task_horizon: int = 500 # Maximum steps per episode to prevent infinite runs
42
+ record_videos: bool = False # Whether to record videos of episodes
43
+
44
+ # --- Data generation settings ---
45
+ num_threads: int = 1 # parallel data generation threads
46
+ profile: bool = True # Whether to profile the data generation pipeline
47
+ profiler: Profiler | None = None
48
+ output_dir: str | None = None # Directory to save generated data
49
+ use_wandb: bool = False # Whether to use Weights & Biases logging
50
+ wandb_name: str | None = None # Weights & Biases run name
51
+ wandb_project: str | None = None # Weights & Biases project name
52
+
53
+ # --- Task type configuration ---
54
+ task_type: str = "nav_to_obj" # Task type: nav_to_obj
55
+
56
+ # --- ProcTHOR dataset configuration ---
57
+ scene_dataset: str = "procthor-10k" # Name of the scene dataset to load
58
+ data_split: str = "train" # Data split to use
59
+
60
+ robot_config: BaseRobotConfig | None = None
61
+
62
+ # Camera configuration - using new unified camera system
63
+ camera_config: RBY1MjcfCameraSystem = RBY1MjcfCameraSystem()
64
+
65
+ # Task sampler configuration (imported from task_sampler_configs.py)
66
+ task_sampler_config: NavToObjTaskSamplerConfig = NavToObjTaskSamplerConfig(
67
+ task_sampler_class=NavToObjTaskSampler
68
+ )
69
+
70
+ # Task configuration (imported from task_configs.py)
71
+ task_config: NavToObjTaskConfig = NavToObjTaskConfig(task_cls=NavToObjTask)
72
+ task_config_preset: NavToObjTaskConfig | None = None
73
+
74
+ # Policy configuration (imported from policy_configs.py)
75
+ policy_config: BasePolicyConfig = AStarNavToObjPolicyConfig()
76
+
77
+ def _init_policy_config(self) -> BasePolicyConfig:
78
+ """Initialize policy config. Override in subclasses for dynamic initialization."""
79
+ return self.policy_config
80
+
81
+ def model_post_init(self, __context) -> None:
82
+ """Initialize and validate configuration after Pydantic model initialization"""
83
+ super().model_post_init(__context)
84
+
85
+ try:
86
+ self.policy_config = self._init_policy_config()
87
+ except RuntimeError as e:
88
+ # Check if this is a CUDA/GPU-related error
89
+ error_msg = str(e)
90
+ if "NVIDIA" in error_msg or "CUDA" in error_msg or "GPU" in error_msg:
91
+ # No GPU available - this is expected on manager nodes that just coordinate jobs
92
+ # Policy config will be initialized later on worker nodes that have GPUs
93
+ print(
94
+ f"Warning: Skipping policy config initialization due to missing GPU: {error_msg}"
95
+ )
96
+ self.policy_config = None
97
+ else:
98
+ raise
99
+
100
+ # Auto-create profiler instance if profiling is enabled
101
+ if self.profile and self.profiler is None:
102
+ self.profiler = Profiler()
103
+
104
+ @property
105
+ def tag(self) -> str:
106
+ return "nav_to_obj_datagen"
107
+
108
+ class SavedEpisode(Config):
109
+ camera_config: RBY1MjcfCameraSystem | None = None # Configuration for cameras and sensors
110
+ robot_config: RBY1Config | None = None # Configuration for the robot
111
+ task_config: NavToObjTaskConfig | None = None # Configuration for tasks
112
+ task_cls_str: str | None = None
@@ -0,0 +1,56 @@
1
+ from molmo_spaces.configs.base_pick_config import PickBaseConfig
2
+ from molmo_spaces.configs.policy_configs import BasePolicyConfig, OpenClosePlannerPolicyConfig
3
+ from molmo_spaces.configs.task_configs import OpeningTaskConfig
4
+ from molmo_spaces.configs.task_sampler_configs import (
5
+ OpenTaskSamplerConfig,
6
+ )
7
+ from molmo_spaces.tasks.opening_task_samplers import OpenTaskSampler
8
+ from molmo_spaces.tasks.opening_tasks import OpeningTask
9
+
10
+
11
+ class OpeningBaseConfig(PickBaseConfig):
12
+ """Base configuration for opening task data generation."""
13
+
14
+ task_type: str = "open"
15
+
16
+ # Task sampler configuration (imported from task_sampler_configs.py)
17
+ task_sampler_config: OpenTaskSamplerConfig = OpenTaskSamplerConfig(
18
+ task_sampler_class=OpenTaskSampler,
19
+ target_initial_state_open_percentage=0, # 0 for open task
20
+ )
21
+
22
+ # Task configuration (imported from task_configs.py)
23
+ task_config: OpeningTaskConfig = OpeningTaskConfig(
24
+ task_cls=OpeningTask,
25
+ task_success_threshold=0.15, # low for now, due to placement/IK constraints, should be ~0.66
26
+ joint_index=0,
27
+ any_inst_of_category=True, # open any instance of category
28
+ )
29
+ task_config_preset: OpeningTaskConfig | None = None
30
+
31
+ # Policy configuration (imported from policy_configs.py)
32
+ policy_config: BasePolicyConfig = OpenClosePlannerPolicyConfig()
33
+
34
+
35
+ class ClosingBaseConfig(PickBaseConfig):
36
+ """Base configuration for closing task data generation."""
37
+
38
+ task_type: str = "close"
39
+
40
+ # Task sampler configuration (imported from task_sampler_configs.py)
41
+ task_sampler_config: OpenTaskSamplerConfig = OpenTaskSamplerConfig(
42
+ task_sampler_class=OpenTaskSampler,
43
+ target_initial_state_open_percentage=0.5, # 0.67 for close task
44
+ )
45
+
46
+ # Task configuration (imported from task_configs.py)
47
+ task_config: OpeningTaskConfig = OpeningTaskConfig(
48
+ task_cls=OpeningTask,
49
+ task_success_threshold=0.85, # For closing Task, 0.33
50
+ joint_index=0,
51
+ any_inst_of_category=False, # open any instance of category
52
+ )
53
+ task_config_preset: OpeningTaskConfig | None = None
54
+
55
+ # Policy configuration (imported from policy_configs.py)
56
+ policy_config: BasePolicyConfig = OpenClosePlannerPolicyConfig()
@@ -0,0 +1,21 @@
1
+ from molmo_spaces.configs.base_pick_config import PickBaseConfig
2
+ from molmo_spaces.configs.policy_configs import PickAndPlacePlannerPolicyConfig
3
+ from molmo_spaces.configs.task_configs import PackingTaskConfig
4
+ from molmo_spaces.configs.task_sampler_configs import PackingTaskSamplerConfig
5
+ from molmo_spaces.data_generation.config_registry import register_config
6
+ from molmo_spaces.tasks.packing_task import PackingTask
7
+ from molmo_spaces.tasks.packing_task_sampler import PackingTaskSampler
8
+ from molmo_spaces.utils.constants.object_constants import PICK_AND_PLACE_OBJECTS
9
+
10
+
11
+ @register_config("PackingDataGenConfig")
12
+ class PackingDataGenConfig(PickBaseConfig):
13
+ task_type: str = "packing"
14
+ num_workers: int = 1
15
+ task_sampler_config: PackingTaskSamplerConfig = PackingTaskSamplerConfig(
16
+ task_sampler_class=PackingTaskSampler,
17
+ pickup_types=PICK_AND_PLACE_OBJECTS,
18
+ samples_per_house=20,
19
+ )
20
+ task_config: PackingTaskConfig = PackingTaskConfig(task_cls=PackingTask)
21
+ policy_config: PickAndPlacePlannerPolicyConfig = PickAndPlacePlannerPolicyConfig()
@@ -0,0 +1,31 @@
1
+ from pathlib import Path
2
+
3
+ from molmo_spaces.configs.base_pick_config import PickBaseConfig
4
+ from molmo_spaces.configs.policy_configs import PickAndPlaceColorPlannerPolicyConfig
5
+ from molmo_spaces.configs.task_configs import PickAndPlaceColorTaskConfig
6
+ from molmo_spaces.configs.task_sampler_configs import PickAndPlaceColorTaskSamplerConfig
7
+ from molmo_spaces.data_generation.config_registry import register_config
8
+ from molmo_spaces.molmo_spaces_constants import ASSETS_DIR
9
+ from molmo_spaces.tasks.pick_and_place_color_task import PickAndPlaceColorTask
10
+ from molmo_spaces.tasks.pick_and_place_color_task_sampler import PickAndPlaceColorTaskSampler
11
+
12
+
13
+ @register_config("PickAndPlaceColorDataGenConfig")
14
+ class PickAndPlaceColorDataGenConfig(PickBaseConfig):
15
+ task_type: str = "pick_and_place_color"
16
+ num_workers: int = 1
17
+ output_dir: Path = ASSETS_DIR / "experiment_output" / "datagen" / "pick_and_place_color_base_v1"
18
+ wandb_project: str = "molmo-spaces-data-generation"
19
+ task_sampler_config: PickAndPlaceColorTaskSamplerConfig = PickAndPlaceColorTaskSamplerConfig(
20
+ task_sampler_class=PickAndPlaceColorTaskSampler,
21
+ samples_per_house=20,
22
+ )
23
+ task_config: PickAndPlaceColorTaskConfig = PickAndPlaceColorTaskConfig(
24
+ task_cls=PickAndPlaceColorTask
25
+ )
26
+ policy_config: PickAndPlaceColorPlannerPolicyConfig = PickAndPlaceColorPlannerPolicyConfig()
27
+ use_passive_viewer: bool = False
28
+
29
+ @property
30
+ def tag(self) -> str:
31
+ return "pick_and_place_color_base_datagen"
@@ -0,0 +1,27 @@
1
+ from molmo_spaces.configs.abstract_config import Config
2
+ from molmo_spaces.configs.base_pick_config import PickBaseConfig
3
+ from molmo_spaces.configs.camera_configs import AllCameraSystems
4
+ from molmo_spaces.configs.policy_configs import PickAndPlacePlannerPolicyConfig
5
+ from molmo_spaces.configs.robot_configs import FrankaRobotConfig
6
+ from molmo_spaces.configs.task_configs import PickAndPlaceTaskConfig
7
+ from molmo_spaces.configs.task_sampler_configs import PickAndPlaceTaskSamplerConfig
8
+ from molmo_spaces.tasks.pick_and_place_task import PickAndPlaceTask
9
+ from molmo_spaces.tasks.pick_and_place_task_sampler import PickAndPlaceTaskSampler
10
+
11
+
12
+ class PickAndPlaceDataGenConfig(PickBaseConfig):
13
+ task_type: str = "pick_and_place"
14
+ num_workers: int = 1
15
+ task_sampler_config: PickAndPlaceTaskSamplerConfig = PickAndPlaceTaskSamplerConfig(
16
+ task_sampler_class=PickAndPlaceTaskSampler,
17
+ pickup_types=[],
18
+ samples_per_house=20,
19
+ )
20
+ task_config: PickAndPlaceTaskConfig = PickAndPlaceTaskConfig(task_cls=PickAndPlaceTask)
21
+ policy_config: PickAndPlacePlannerPolicyConfig = PickAndPlacePlannerPolicyConfig()
22
+
23
+ class SavedEpisode(Config):
24
+ camera_config: AllCameraSystems | None = None # Configuration for cameras and sensors
25
+ robot_config: FrankaRobotConfig | None = None # Configuration for the robot
26
+ task_config: PickAndPlaceTaskConfig | None = None # Configuration for tasks
27
+ task_cls_str: str | None = None
@@ -0,0 +1,26 @@
1
+ from molmo_spaces.configs.base_pick_config import PickBaseConfig
2
+ from molmo_spaces.configs.policy_configs import PickAndPlaceNextToPlannerPolicyConfig
3
+ from molmo_spaces.configs.robot_configs import BaseRobotConfig, FrankaRobotConfig
4
+ from molmo_spaces.configs.task_configs import PickAndPlaceNextToTaskConfig
5
+ from molmo_spaces.configs.task_sampler_configs import PickAndPlaceNextToTaskSamplerConfig
6
+ from molmo_spaces.data_generation.config_registry import register_config
7
+ from molmo_spaces.tasks.pick_and_place_next_to_task import PickAndPlaceNextToTask
8
+ from molmo_spaces.tasks.pick_and_place_next_to_task_sampler import PickAndPlaceNextToTaskSampler
9
+ from molmo_spaces.utils.constants.object_constants import PICK_AND_PLACE_OBJECTS
10
+
11
+
12
+ @register_config("PickAndPlaceNextToDataGenConfig")
13
+ class PickAndPlaceNextToDataGenConfig(PickBaseConfig):
14
+ task_type: str = "pick_and_place_next_to"
15
+ num_workers: int = 1
16
+ task_sampler_config: PickAndPlaceNextToTaskSamplerConfig = PickAndPlaceNextToTaskSamplerConfig(
17
+ task_sampler_class=PickAndPlaceNextToTaskSampler,
18
+ pickup_types=PICK_AND_PLACE_OBJECTS,
19
+ samples_per_house=20,
20
+ )
21
+ task_config: PickAndPlaceNextToTaskConfig = PickAndPlaceNextToTaskConfig(
22
+ task_cls=PickAndPlaceNextToTask
23
+ )
24
+ policy_config: PickAndPlaceNextToPlannerPolicyConfig = PickAndPlaceNextToPlannerPolicyConfig()
25
+ robot_config: BaseRobotConfig = FrankaRobotConfig()
26
+ use_passive_viewer: bool = False