fix(entity): write root velocity via free-joint DoFs, not set_vel/set_ang - #244
Merged
Conversation
…_ang Genesis's RigidEntity exposes get_vel/get_ang but no set_vel/set_ang (those setters exist only on FEM/tool entities), so every root-velocity write built on getattr(handle, "set_vel", ...) silently no-opped on rigid articulations: push_by_setting_velocity, the velocity half of reset_root_state_uniform, Articulation.write_root_state, and the cube kick/reset paths in the wuji and franka examples. Push-based domain randomization never reached the simulator. Root velocity now routes through genelab.entity.write_root_velocity, which drives set_dofs_velocity on the base free joint's 6 DoFs (0-2 world-frame linear, 3-5 angular) and falls back to the direct setters for entity types that genuinely have them (FEM/tool entities, test fakes). A genesis_runtime-gated test round-trips the write through a real free box and reads it back via get_vel/get_ang. Fixes #242
Auditing every getattr-guarded Genesis call after #242 found one more live silent no-op of the same class: Genesis 1.2's outer Viewer forwards register_keybinds but not set_message_text, so the keyboard bridge's HUD line never displayed. Fall back to viewer._pyrender_viewer (the same wrapper gap the viewer.plugins / _viewer_plugins scene fallback covers). Everything else checks out against Genesis 1.2: all DR setters, sensor getters, and solver set_gravity exist; set_dofs_friction and set_dofs_position_target are dead-but-harmless second arms of or-chains. tests/test_genesis_api_contract.py now pins every getattr-guarded name against the installed Genesis so upstream renames fail loudly at the next version bump instead of silently disabling physics or UI.
Owner
Author
|
Follow-up: same-class audit (pushed as 10dad32) The root cause of #242 isn't
Also added |
3 tasks
KraHsu
added a commit
that referenced
this pull request
Jul 10, 2026
fix(entity): write root velocity via free-joint DoFs, not set_vel/set_ang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #242 — and the same dead idiom everywhere else it was copied.
Genesis's
RigidEntityAPI is asymmetric:get_vel/get_angexist, butset_vel/set_angexist only on FEM / tool entities. Every write site built ongetattr(handle, "set_vel", None)therefore silently no-opped on rigid articulations:mdp.push_by_setting_velocity— the entire event (the bug: push_by_setting_velocity 对 RigidEntity 静默失效(set_vel/set_ang 不存在) #242 report)mdp.reset_root_state_uniform— the velocity halfArticulationWriter.write_root_state— velocity halves (pose worked)examples/wujireorient — cube reset velocity zeroing, the interval velocity kick (its docstring calls it "the important robustness lever"; it read current velocity via the existing getters, then wrote through the missing setters), and the goal-marker velocity zeroingexamples/franka— cube reset velocity zeroingFix: new
genelab.entity.write_root_velocity(handle, lin_vel_w, ang_vel_w, env_ids)routes the write throughset_dofs_velocityon the base free joint's 6 DoFs (0–2 world-frame linear, 3–5 angular; free-joint discovery mirrors the binder'sn_dofs >= 6idiom), with a fallback to the direct setters for entity types that genuinely have them (FEM / tool entities, existing test fakes). All seven sites now call it. Fixed-base entities correctly write nothing (Falsereturn).Impact note (in CHANGELOG): policies previously trained with push events effectively had those disturbances disabled; retraining may be needed where push robustness matters.
Test plan
tests/test_root_velocity.py: fakes mirror the Genesis 1.2 surface (deliberately withoutset_vel/set_ang) so a regression to the old idiom fails instead of no-opping — covers the helper, both event terms, the writer seam, fixed-base and fallback pathsgenesis_runtime-gated integration test: builds a real free box (RigidObjectCfg(fixed=False)), writes velocity, reads it back viaget_vel/get_angtest_articulation_stateroot-state round-trip still passes (its fake has 1-DoF joints only → takes the fallback path)ruff check+ruff format --checkclean; pyright adds no new errors over main; full suite 925 passed / 4 skipped (one pre-existing, environment-only Qt/plotter abort in full-process runs reproduces identically on clean main and is unrelated)🤖 Generated with Claude Code