Skip to content

Feat/a2 joystick flat#671

Merged
TATP-233 merged 4 commits into
mainfrom
feat/a2-joystick-flat
Jul 8, 2026
Merged

Feat/a2 joystick flat#671
TATP-233 merged 4 commits into
mainfrom
feat/a2-joystick-flat

Conversation

@lemon-star608

Copy link
Copy Markdown
Collaborator

Summary

加入A2_joystick/mujoco任务

Linked Work

  • Issue:
  • Milestone:

Validation

  • make check
  • uv run pytest -m "not slow"
  • Additional task-specific validation listed below

Commands actually run:

# paste exact commands here

Impact

  • Backend impact: mujoco / motrix / both / none
  • Platform impact: macOS / Linux / both / unknown
  • Training effect expected: yes / no / unknown

Artifacts

  • W&B:
  • benchmark result:
  • video / screenshot:
  • ONNX / checkpoint:

Checklist

  • Added or updated tests where needed
  • Updated docs if behavior or workflow changed
  • Linked the driving issue
  • Noted any follow-up work explicitly

@lemon-star608 lemon-star608 requested a review from TATP-233 as a code owner July 2, 2026 10:06
Comment thread src/unilab/envs/locomotion/common/commands.py

@TATP-233 TATP-233 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

检查stand 指令其他地方已经实现过了

lemon-star608 added a commit that referenced this pull request Jul 2, 2026
…ding_fraction

Review on #671 flagged that the standing-command logic our A2 PR added to
common/commands.py already existed elsewhere. It did: the block "zero a random
rel_standing_envs fraction of rows to zero" was copy-pasted inline in six DR
provider sites (go1/rough, go2/rough, go2w/rough, go2w/joystick reset+resample,
g1/joystick) with no shared helper.

Extract the block into common.commands.apply_standing_fraction() (in-place, same
RNG guard) and route all six sites plus sample_commands_with_standing through it.
Per-site zero_small_xy thresholds (0.08 for rough, 0.2 default for g1/go2w) and
heading handling are preserved, and the rough.py resample paths that only do
zero_small_xy (no standing fraction) are left untouched. Behaviour-preserving:
make test-all still 1431 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lemon-star608 lemon-star608 force-pushed the feat/a2-joystick-flat branch from 7b7bf25 to 17ce0bd Compare July 7, 2026 15:52
Self-contained robots/a2/ (meshes copied from the A2+Airbot composite),
12 position-style leg actuators with A2-strength gain classes, Go2-
compatible IMU/foot sensors. No arm, no keyframe (keyframe lives in the
task scene, per the asset/XML structure contract).
The A2 leg-only MJCF mirrors the Go2 joystick sensor/geom/leg-ordering
contract and uses <position> actuators, so the task reuses Go2WalkTask
unchanged. Only the A2 identity differs: scene path, standing pose, and
per-joint PD gains.

- A2 flat scene (scene_flat.xml) with four foot-contact sensors and a home
  keyframe aligned to unitree_rl_mjlab INIT_STATE (height 0.4, thigh 0.9,
  calf -1.8, hips +-0.1); default_angles derive from it automatically.
- A2JoystickCfg / A2JoystickFlatEnv registered and wired into the
  locomotion registry bootstrap.
- Per-joint PD gains via PdControlConfig.position_gains() (hip/thigh
  kp=100/kd=4, calf kp=150/kd=6) forwarded to the backend; the scalar
  default keeps Go2 behaviour byte-for-byte unchanged.
- a2_joystick_flat/mujoco owner YAML carrying training + reward.
- End-to-end contract tests (XML compiles, 12-DOF, obs layout, per-joint
  model gains, finite step) and support-matrix refresh.
Enable the sim2real DR suite on A2JoystickFlat (budget 500 iters; A2 is
~2.8x Go2 mass) and let the policy stand still at zero command instead of
marching in place.

Domain randomization:
- A2JoystickDomainRandomizationProvider supplies per-joint base gains so
  randomize_kp/kd scales each actuator off its true baseline (calf off
  150, not the shared scalar), and caches the pristine dof-armature +
  geom-friction tables via the public backend getters (cold path, no
  feature leak) so randomize_dof_armature and randomize_ground_friction
  are effective; the floor geom is the priority geom for friction.
- com_offset_y/z declared so the base COM randomizes in all three axes.
- DR ranges reference unitree_rl_mjlab A2 events (joint_armature scale
  0.9-1.1, foot friction 0.3-1.6); body_mass and gravity stay off.

Zero-command standing (gated so Go2's default behaviour is unchanged):
- RewardConfig.command_threshold gates the phase-driven gait rewards
  (swing_feet_z / contact) and the gait phase clock: while standing
  (||command|| <= threshold) the phase freezes per-env and a planted
  robot earns full contact reward. Default 0.0 keeps Go2's reward vector
  and phase advance byte-for-byte unchanged.
- New rewards stand_still / hip_deviation / stand_feet_air penalize
  residual micro-stepping and stance drift at zero command, all gated by
  command_threshold so they cost locomotion nothing.
- sample_commands_with_standing is the single source of truth for the
  standing-aware command distribution, shared by the reset path (DR
  provider) and mid-episode resampling (resampling_time > 0).

Tests: DR-on env constructs and steps finite, friction/armature baselines
cached once, floor geom dominates friction; Go2 stand-still contract
(phase freeze, gated rewards, command sampling).
@lemon-star608 lemon-star608 force-pushed the feat/a2-joystick-flat branch from 17ce0bd to dd781a0 Compare July 8, 2026 13:57
Relocate the A2-specific standstill logic out of Go2WalkTask (= Go2JoystickFlat)
and into the A2JoystickFlatEnv subclass, so Go2 flat's reward vector and gait
clock revert to the main baseline byte-for-byte.

Go2WalkTask keeps only default-preserving override seams: _advance_phase(phase)
(unconditional advance), a no-op _update_commands(info) hook, and the existing
_make_dr_provider / position_gains seams. RewardConfig, swing_feet_z and contact
are restored to main (no command_threshold, no gating).

A2 owns the standstill: A2RewardConfig(RewardConfig) carries command_threshold
and A2JoystickCfg narrows the reward_config annotation so the owner YAML builds
A2RewardConfig. A2JoystickFlatEnv overrides _advance_phase (freeze standing
envs), _update_commands (standing-aware mid-episode resample) and
_init_reward_functions (stand_still / hip_deviation / stand_feet_air plus
command-gated swing_feet_z / contact). The gated swing reward wraps the base
Go2 method; contact is re-implemented because its standing branch is interleaved
per-foot. sample_commands_with_standing stays a shared helper.

The standstill unit tests move to the A2 test file; the Go2 test file keeps the
shared-helper tests plus regressions asserting Go2 phase advance is unconditional
and RewardConfig has no command_threshold.
@lemon-star608 lemon-star608 force-pushed the feat/a2-joystick-flat branch from dd781a0 to 1f971e4 Compare July 8, 2026 14:18
Comment thread src/unilab/envs/locomotion/go2/joystick.py
@TATP-233 TATP-233 merged commit 408d581 into main Jul 8, 2026
6 checks passed
@TATP-233 TATP-233 deleted the feat/a2-joystick-flat branch July 8, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants