Add Open Drawer task and passive articulation defaults - #473
Conversation
Add the official OpenDrawer task, passive articulation tutorial, entity-specific drive defaults, and backend drive-type regression coverage.
Greptile SummaryThe PR adds the
Confidence Score: 4/5The PR is not yet safe to merge because partial runtime updates can still silently disable explicitly driven generic articulations. The configuration deserialization path now preserves entity-specific drive defaults and failed expert plans are rejected, but Files Needing Attention: embodichain/lab/sim/objects/articulation.py
|
| Filename | Overview |
|---|---|
| embodichain/lab/sim/cfg.py | Partial drive_pros dictionaries now inherit the current articulation or robot defaults instead of resetting unspecified fields. |
| embodichain/lab/sim/objects/articulation.py | Adds backend drive-type inspection, but the public partial runtime setter still implicitly changes driven articulations to passive mode. |
| embodichain_tasks/embodichain_tasks/tableware/open_drawer.py | Adds the expert drawer-opening task and now validates every planner result before consuming its trajectory. |
| embodichain_tasks/configs/gym/open_drawer/cobot_magic_3cam.json | Defines the CobotMagic drawer environment, cameras, passive drawer configuration, and task runtime settings. |
| scripts/tutorials/sim/create_articulation.py | Demonstrates constructing a passive drawer, verifying backend drive types, and actuating it using external joint forces. |
| tests/sim/test_cfg.py | Covers passive articulation defaults, force-driven robot defaults, and preservation under partial dictionary overrides. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Load partial drive_pros] --> B{Entity configuration}
B -->|ArticulationCfg| C[Preserve drive_type none]
B -->|RobotCfg| D[Preserve drive_type force]
C --> E[Construct passive articulation]
D --> F[Construct force-driven robot]
G[OpenDrawer expert generation] --> H[Plan move to start]
H --> I{Plan successful?}
I -->|No| J[Raise RuntimeError]
I -->|Yes| K[Plan approach and pull]
K --> L[Assemble expert actions]
Prompt To Fix All With AI
### Issue 1
embodichain/lab/sim/objects/articulation.py:1678
**Partial updates disable joint drives**
When a driven generic `Articulation` receives a runtime stiffness, damping, effort, velocity, friction, or armature update without an explicit `drive_type`, this method forwards its default `"none"` to the backend, making the selected joints passive and preventing subsequent position or velocity targets from applying drive force.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (4): Last reviewed commit: "test(task): remove OpenDrawer integratio..." | Re-trigger Greptile
There was a problem hiding this comment.
Pull request overview
This PR adds an official OpenDrawer-v1 task under embodichain_tasks, introduces a passive-articulation tutorial, and adjusts config parsing so partial drive_pros overrides preserve entity-specific joint drive defaults (passive articulations vs force-driven robots). It also exposes backend joint drive types for validation and extends regression tests/docs around these behaviors.
Changes:
- Add
OpenDrawer-v1environment, JSON config, and a simulation-backed test validating demo generation and backend drive types. - Add a new articulation tutorial script + documentation that verifies passive drive defaults via backend
DriveType. - Update config parsing to preserve existing
JointDrivePropertiesCfgdefaults when loading partial overrides from dicts, and add unit tests for this behavior.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/sim/test_cfg.py | Adds unit tests ensuring ArticulationCfg/RobotCfg preserve default drive_type under partial drive_pros overrides. |
| tests/sim/objects/test_articulation.py | Adds a regression test validating default backend joint drive type is DriveType.NONE after construction. |
| tests/gym/envs/tasks/test_open_drawer.py | Adds registration/config/sim tests for OpenDrawer-v1, including backend drive-type checks and demo action validation. |
| scripts/tutorials/sim/create_articulation.py | New tutorial script demonstrating passive articulations and verifying backend drive types while force-opening/closing a drawer. |
| embodichain/lab/sim/objects/articulation.py | Changes set_joint_drive default to "none" and adds get_joint_drive_type() for backend verification. |
| embodichain/lab/sim/cfg.py | Extends JointDrivePropertiesCfg.from_dict to support “defaults-preserving” partial overrides; integrates into ArticulationCfg/RobotCfg parsing. |
| embodichain_tasks/embodichain_tasks/tableware/open_drawer.py | New OpenDrawerEnv task environment registered as OpenDrawer-v1 with expert demo generation. |
| embodichain_tasks/embodichain_tasks/tableware/init.py | Exposes the new tableware task module exports. |
| embodichain_tasks/configs/gym/open_drawer/cobot_magic_3cam.json | Adds the CobotMagic 3-camera Open Drawer task configuration. |
| docs/source/tutorial/index.rst | Adds the new articulation tutorial to the learning path and toctree. |
| docs/source/tutorial/articulation.rst | New tutorial documentation for loading articulations and inspecting passive drive defaults. |
| docs/source/overview/sim/sim_articulation.md | Updates articulation docs to reflect drive_pros defaults (drive_type="none") and documents get_joint_drive_type(). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (1)
embodichain/lab/sim/cfg.py:767
JointDrivePropertiesCfg.from_dictaccepts values like per-joint mappings (e.g.,stiffness: {"joint.*": 1000.0}) and other non-scalar types, but theinit_dictannotation only allowsstr | float | int. This makes the signature misleading for type checkers and IDEs.
init_dict: Dict[str, str | float | int],
Reject failed or empty planner results, respect the tutorial headless flag, and widen joint-drive override type hints.
| friction (torch.Tensor): The joint friction coefficient with shape (len(env_ids), len(joint_ids)). | ||
| armature (torch.Tensor): The joint armature with shape (len(env_ids), len(joint_ids)). | ||
| drive_type (str, optional): The type of drive to apply. Defaults to "force". | ||
| drive_type (str, optional): The type of drive to apply. Defaults to "none". |
There was a problem hiding this comment.
Partial updates disable joint drives
When a driven generic Articulation receives a runtime stiffness, damping, effort, velocity, friction, or armature update without an explicit drive_type, this method forwards its default "none" to the backend, making the selected joints passive and preventing subsequent position or velocity targets from applying drive force.
Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/sim/objects/articulation.py
Line: 1678
Comment:
**Partial updates disable joint drives**
When a driven generic `Articulation` receives a runtime stiffness, damping, effort, velocity, friction, or armature update without an explicit `drive_type`, this method forwards its default `"none"` to the backend, making the selected joints passive and preventing subsequent position or velocity targets from applying drive force.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (2)
embodichain/lab/sim/objects/articulation.py:1679
Articulation.set_joint_drive()usesdrive_type="none"by default, so calling it withoutdrive_typewill disable drives even when the caller is only trying to tweak parameters likemax_effort/max_velocity(there are existing call sites that omitdrive_type, e.g.tests/sim/objects/test_articulation.py). If the intent is “do not change drive mode unless explicitly requested”, consider keeping the default as "force" (and relying onArticulationCfg.drive_pros.drive_type="none"to keep articulations passive), or otherwise updating the API so omittingdrive_typedoesn’t flip the mode.
max_velocity (torch.Tensor): The maximum velocity of the joint drive with shape (len(env_ids), len(joint_ids)).
friction (torch.Tensor): The joint friction coefficient with shape (len(env_ids), len(joint_ids)).
armature (torch.Tensor): The joint armature with shape (len(env_ids), len(joint_ids)).
drive_type (str, optional): The type of drive to apply. Defaults to "none".
joint_ids (Sequence[int] | None, optional): The joint indices to apply the drive to. If None, applies to all joints. Defaults to None.
docs/source/overview/sim/sim_articulation.md:164
- In the USD override example,
JointDrivePropertiesCfg(stiffness=..., damping=...)does not setdrive_type. Since generic articulations default todrive_type="none", this example won’t actually enable a drive whenuse_usd_properties=False. If the intent is to demonstrate driving joints via config, setdrive_type="force"(or another mode) explicitly.
usd_art_cfg_override = ArticulationCfg(
fpath=get_data_path("path/to/robot.usd"),
init_pos=(0, 0, 0.5),
use_usd_properties=False, # Use config instead
drive_pros=JointDrivePropertiesCfg(stiffness=5000, damping=500)
)
Description
This PR adds an official
OpenDrawer-v1expert task and a passive-articulation tutorial, while preserving entity-specific joint-drive defaults when partialdrive_prosoverrides are loaded from environment configuration.The change:
embodichain_tasks;drive_type="none") and robots force-driven when only stiffness/damping are overridden;Dependencies: None.
Issue: N/A (requested directly).
Type of change
Screenshots
Not applicable.
Validation
black --check --diff --color ./ --extend-exclude 'embodichain/gen_sim/gradio_ui/'— 633 files unchangedblack . --extend-exclude 'embodichain/gen_sim/gradio_ui/'— 633 files unchangedpytest -q tests/sim/test_cfg.py tests/gym/envs/tasks/test_open_drawer.py tests/sim/objects/test_articulation.py::TestArticulationCPU::test_default_drive_type_is_none_after_construction— 16 passedpython scripts/tutorials/sim/create_articulation.py --headless --max-steps 5— passedsphinx-build -M html docs/source <temporary-build-dir>— succeeded (repository baseline warnings remain)Checklist
black .command to format the code base.