FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

R1_A5: `mode_pr` outside `{0,1}` triggers a hard, unrecoverable FSM 811→816 lockout — locomotion and arm_sdk override appear mutually exclusive · Issue #182 · unitreerobotics/unitree_sdk2_python · GitHub

R1_A5: mode_pr outside {0,1} triggers a hard, unrecoverable FSM 811→816 lockout — locomotion and arm_sdk override appear mutually exclusive #182

Description

Summary

On an R1 EDU (arm config R1_A5), using rt/arm_sdk for direct arm control while ai_sport is in locomotion mode (FSM state 811) causes an immediate, one-way transition to FSM state 816, after which the robot cannot walk — not via LocoClient.SetVelocity, and not via the physical R3 remote. This appears to be enforced deliberately and continuously by ai_sport itself, not a client-side bug, an SDK gap, or a race condition. I can't find any combination of documented fields that achieves simultaneous locomotion + arm override on this platform, and I'd like to know whether that's currently intended, and if not, what the correct mechanism is.

This surfaced while using xr_teleoperate with --arm=R1_A5, but every finding below is at the unitree_sdk2py/ai_sport level and reproduces independently of that repo.

Environment

  • Robot: R1 EDU, arm config R1_A5
  • LocoClient version: R1, 1.0.0.0
  • unitree_sdk2py version/commit: 65691c8

Reproduction

  1. Boot the robot, enter locomotion mode via the R3 remote (R2+A, walk mode). Confirm via LocoClient._Call(7001, "{}") that FSM is in state 811 and the robot walks normally from the remote.
  2. Start publishing rt/arm_sdk LowCmd_ messages with valid arm joint targets (R1_A5 joint indices, mode_pr=100).
  3. Observe FSM transitions from 811 to 816 within a few milliseconds of the first arm_sdk publish.
  4. While in 816:
  • The physical R3 remote no longer commands walking.
  • LocoClient.SetVelocity(vx, vy, omega, duration) returns without moving the robot. (Separately, this call returns error code 127 in our testing even when it does work correctly in FSM 811 — we believe that's an unrelated, cosmetic issue previously filed separately; not the basis for this report.)
  • Calling LocoClient.SetFsmId(811) repeatedly (tested at 20 Hz for 5+ seconds) is rejected on every single call with return code 1001. This is not one of unitree_sdk2py's own RPC_ERR_* framework codes (rpc/internal.py defines all of those in the 3000s — RPC_ERR_UNKNOWN=3001 through RPC_ERR_SERVER_LEASE_EXIST=3207), so 1001 appears to be a genuine, deliberate application-level refusal from ai_sport, not a client/transport artifact. The uniform, repeated rejection (no calls slipped through to 811) argues against this being a timing race that a faster or more sustained retry loop could win.

What we tried to find a middle ground

  • mode_pr as a graduated blend weight: R1_A5_ArmController in xr_teleoperate sets LowCmd_.mode_pr to an integer 0–100, with a comment describing it as an arm_sdk blend weight ("R1/R1-A5 arm_sdk uses mode_pr as a percentage weight"). Empirically, this field behaves as a binary trigger, not a percentage: held values of 0 and 1 never leave FSM 811 (and never affect arm response); any value >=2 (tested at 2, 5, 50, 100) transitions to 816 within ms, regardless of magnitude. 0 and 1 are exactly mode_pr's two documented, legitimate values elsewhere in the SDK (the PR/AB ankle-mode selector used identically by G1/H1_2/R1 low-level examples), which strongly suggests this "percentage weight" framing is a mistaken assumption in the driver code rather than a real R1 firmware feature, and that any out-of-range value is simply being treated as invalid/unexpected by ai_sport.
  • kNotUsedJoint0.q as the blend weight, mirroring G1/H1_2/H2's actual convention (in those platforms, motor_cmd[kNotUsedJoint0].q is ramped 0.0→1.0 as a float, and mode_pr is never touched for this purpose — see g1_loco_client.py/G1 arm_sdk examples). We reimplemented this exactly for R1_A5 (leaving mode_pr fixed at 0, and a similar test at 1). Result (both times): locomotion is preserved (FSM stays 811, R3 remote and SetVelocity both work), but the arms no longer respond to any value of this field — it appears to be unread by ai_sport on R1.
  • We could not find an intermediate FSM id, mode, or API call bridging these two states. r1_loco_api.py's error-code section is an empty stub (compare to G1's, which has real definitions filled in), and there is also no r1_arm_sdk_dds_example.py in unitree_sdk2_python's examples, unlike G1 (arm5/arm7) and H2, which both ship one.

Related issues

  • xr_teleoperate #319 reports the same 811→816 transition and asks essentially the same question ("is arm overlay together with locomotion intended to be possible on R1 at all?"), without a response as of this writing. That report also saw SetVelocity return 127 unconditionally in every FSM state on their unit, which we believe is the separate, cosmetic issue rather than the cause of the lockout itself.

Questions

  • Is simultaneous locomotion and rt/arm_sdk-style direct arm control intended to be supported on R1_A5 at all in the current firmware?
  • If so, what is the correct signaling mechanism? kNotUsedJoint0.q (the G1/H1_2 convention) does not appear to be read by ai_sport on R1.
  • If not, is FSM 816's total loss of locomotion (including from the physical remote) an intentional safety interlock, or a currently-incomplete implementation that's expected to change?

Happy to provide packet captures, exact firmware/SDK version info, or run further diagnostics.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL