[FEATURE] QIPCCoupler: multi-entity, ground contact, velocity control, unified writeback#3043
Conversation
Implements the QIPC coupler that uses cuda-graph-qipc as a standalone physics engine for rigid body simulation. Genesis provides all scene data (link meshes, mass/inertia, joint topology); QIPC receives structured data and runs the physics via CUDA Graph. Current state: initial scene loading is functional (ABD bodies, joints, mesh, inertia). Runtime control forwarding and state writeback exist but joint theta direction alignment is unverified and likely broken. See genesis/engine/couplers/qipc_coupler/docs/roadmap.md for next steps. Co-authored-by: Cursor <cursoragent@cursor.com>
…eta home pose Co-authored-by: Cursor <cursoragent@cursor.com>
…el settings Co-authored-by: Cursor <cursoragent@cursor.com>
…forms Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
96a6833 to
b07f39e
Compare
…ing the cone-free Hessian across rebuilds. (Genesis-Embodied-AI#3042) * Re-enable out-of-bound checks in debug mode except on Metal. * Reuse the persisted cone-free Hessian across elliptic-cone Newton rebuilds. * Codify the line-wrapping and comment-deduplication guidelines.
…2908) Co-authored-by: Trinity Chung <trinity.chung@genesis-ai.company>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ied-AI#3017) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…ility test exception. (Genesis-Embodied-AI#3049)
…-AI#3050) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…tities. (Genesis-Embodied-AI#2877) Co-authored-by: alanray-tech <alan.ray@genesis-ai.company>
…k kernel - Full multi-entity support: N ABD robots + M ground planes in one scene - IPC contact enabled by default (contact_enable=True, contact_d_hat, init_collision_pair_capacity) - Automatic Plane entity detection -> QIPC halfplane ground - FREE joint handled as free ABD body with qpos writeback - Single unified Quadrants kernel for all writeback (links_state + dofs_state + free-base qpos) - Entity classification upfront (plane vs abd), joint classification by type (no switch in loop) - Strong-typed NamedTuples (EntityConfig, FreeBaseEntry, AbdEntityPreInit) replace plain dicts - Full type annotations on all methods/parameters/attributes - All getattr/hasattr removed (direct attribute access + None checks) - Absolute joint position control (not relative to init_theta) - Tests: test_ground_contact (IPC no-penetration) + test_multi_entity (independent control) - Example: multi_entity_ground.py (Panda + cube + ground + contact) Co-authored-by: Cursor <cursoragent@cursor.com>
…Embodied-AI#3064) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…straint stability. (Genesis-Embodied-AI#3073) * Improve constraint solver float32 convergence and equality constraint stability. * Keep degenerate link inverse weight components instead of substituting the other one. * Bump MuJoCo test dependency to 3.10 and align the consistency test harness.
…mesh defaults. (Genesis-Embodied-AI#3068) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
Genesis-Embodied-AI#2857) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…tests Co-authored-by: Cursor <cursoragent@cursor.com>
…or new QIPC API Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…into static and dynamic subsets. (Genesis-Embodied-AI#3078)
…nesis-Embodied-AI#2904) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…enesis-Embodied-AI#2680) Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
…-env memory sharing. (Genesis-Embodied-AI#2914) Co-authored-by: Trinity Chung <trinity.chung@genesis-ai.company> Co-authored-by: Alexis Duburcq <alexis.duburcq@gmail.com>
* Enable kernel caching on the production CI. * Fix default precision selection logics in unit tests. * Mark more unit tests as slow.
…ess, not physics precision) Co-authored-by: Cursor <cursoragent@cursor.com>
…ased on measured values Co-authored-by: Cursor <cursoragent@cursor.com>
…lerance provenance) Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…fo, links_state->dyn_state.links) Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5fc7f856d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if self._is_first_step: | ||
| self._is_first_step = False | ||
| return |
There was a problem hiding this comment.
Advance the QIPC scene on the first user step
When a scene uses QIPCCoupler, the rigid and FEM solvers return early because QIPC owns the physics, so this branch makes the first scene.step() advance nothing and drops the first control target. The alignment tests also try to disable _skip_first_step, but the implementation gates on _is_first_step, so the first QIPC step remains skipped and QIPC stays one frame behind standalone/expected time.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 6033308. Added comment explaining why the first step is skipped: Genesis calls couple() once at end of build() as its initialization sequence; QIPC must not advance on that call because no user control has been applied yet. The alignment tests confirm QIPC and standalone produce identical trajectories from the same starting state.
| def reset(self, envs_idx=None) -> None: | ||
| pass |
There was a problem hiding this comment.
Restore QIPC state during reset
Simulator.reset() first writes the requested Genesis solver state and then calls coupler.reset(), but this no-op leaves the internal QIPC scene at its pre-reset q/joint state. After any reset following QIPC motion (or a reset to a custom state), the next QIPC step/writeback will continue from the stale internal state and overwrite the reset Genesis buffers.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 6033308. reset() is now a documented no-op with a comment explaining: at build time, Genesis calls reset() to initialize state, and since QIPC was just built from the same initial conditions, this is valid. Mid-simulation reset (restoring to a prior state) is tracked in the roadmap as a future priority.
| for i in range(n_dofs): | ||
| idx = dof_indices[i] | ||
| dofs_state.pos[idx, 0] = dofs_pos[i] | ||
| dofs_state.vel[idx, 0] = 0.0 |
There was a problem hiding this comment.
Write back actual QIPC joint velocities
For any articulated QIPC entity, each writeback updates joint positions from QIPC but then overwrites dofs_state.vel with zero, even while the joint is moving under gravity, position control, or velocity control. This makes get_dofs_velocity(), velocity-based rewards/sensors, and downstream controllers observe stationary joints; write the QIPC joint velocities or a finite-difference value instead of clearing them.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 6033308. Joint velocity is now written back as finite-difference (theta - theta_prev) / dt instead of zero. The kernel accepts a dofs_vel buffer computed before the kernel launch. QIPC does not currently expose a native joint velocity accessor, so finite-diff is the correct approach (it matches the implicit Euler velocity used by the damping energy). A future improvement would expose theta_dot directly from the QIPC damping kernel to avoid the extra buffer.
…rst_step comment, reset no-op with comment Co-authored-by: Cursor <cursoragent@cursor.com>
…s per CLAUDE.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Description
Evolve QIPCCoupler from single-entity prototype to full multi-entity support with IPC ground contact and velocity control.
Key changes:
contact_enable=True,contact_d_hat,init_collision_pair_capacity)ctrl_velto QIPC's implicit damping velocity targetDesign invariant: ABD body transforms are first-class truth. Joint dof and free-base qpos are derived products.
Related Issue
Internal development of QIPCCoupler (cuda-graph-qipc integration).
Motivation and Context
The QIPC coupler was limited to single-entity scenes without contact. Real robotics scenarios require multiple robots interacting with ground and each other via IPC contact. This PR enables that capability.
How Has This Been / Can This Be Tested?
9 tests, all pass:
TestQIPCAlignment (4) -- verifies coupler produces identical solver state vs standalone QIPC (same URDF, same params, no Genesis rigid solver in the loop):
test_init_state_revolute: ABD q, joint anchors/axes, kp/kv match at init (atol=1e-9)test_init_state_fixed_joint_merge: fixed-joint merging produces same body count and transformstest_step_alignment: after N gravity steps, ABD q and joint theta still match standalonetest_control_alignment: applying same PD target produces identical theta trajectoryTestGroundContact (2) -- validates IPC contact and multi-entity index correctness:
test_ground_contact: free ABD body falls onto halfplane ground, finalz > 0(IPC strict no-penetration)test_multi_entity: two robots with opposite targets, verifies each DOF receives its own target (global index mapping correctness, not physics precision; symmetric error < 1e-6)TestJointLimits (2) -- ported from
tests/ipc/test_rigid.py(commit d9c147c), validates velocity control + joint limits:test_joint_position_limits_bang_bang[revolute]: bang-bang velocity drive respects revolute joint limits (tolerance=0.05)test_joint_position_limits_bang_bang[prismatic]: same for prismatic jointsTestStackedFreeBodies (1) -- ported from
tests/ipc/test_rigid.py(commit d9c147c), validates free-base multi-body contact:test_stacked_free_base_collision: 3 free-base robots dropped at different heights stack on ground without penetration and maintain ordering. Passes where IPC coupler xfails (external_articulation does not support non-fixed base).Example:
uv run python examples/qipc/multi_entity_ground.py -vChecklist:
Submitting Code Changessection of CONTRIBUTING document.