lerobot_env_so101
A standalone SO-101 (SO-ARM101) pick-cube MuJoCo environment, packaged as a
lerobot_env_* plugin (auto-detected by lerobot v0.6.0+ via
@EnvConfig.register_subclass, see
lerobot#3823) and usable
standalone as a plain gymnasium environment.
Installation
pip install lerobot-env-so101
Or from a checkout of the parent repo, for development:
pip install -e packages/lerobot_env_so101
import gymnasium as gym
import lerobot_env_so101 # registers the env
env = gym.make("lerobot_env_so101/SO101PickCube-v0")
Action space
The native action space is 4-dim: [dx, dy, dz, grasp].
SO-101's arm has 5 DOF (6 joints, one of which is the gripper), and the IK
controller in this package only solves for end-effector position. A 6-dim
Cartesian pose target (position + orientation) is not something this
robot/controller pair can track, so orientation deltas are not part of the
action space at all — there is no dead dimension to silently ignore. This was
verified with sim/check_dead_action_dims.py in the parent repo: all 4
dims move the state (0/4 dead).
Contrast with the upstream gym-hil design this was ported from, which kept
the Panda-derived 7-dim [dx,dy,dz,drx,dry,drz,grasp] action space and
silently dropped drx,dry,drz inside the IK solver — 3 of 7 dimensions were
dead, meaning a policy could learn to depend on inputs that had zero effect
on the simulation.
7-dim adapter
Teleop devices and HIL tooling written against the 7-dim Panda convention can
still be used via lerobot_env_so101.wrappers.SevenDofToFourDofAdapter,
which wraps a native env and accepts 7-dim actions, explicitly discarding
drx, dry, drz (see the class docstring — the discard is documented, not
silent).
What changed vs. the upstream port
Ported from
lohpaul9/gym-hil SO-101 branch
(Apache-2.0), submitted upstream as
huggingface/gym-hil#36 /
#37 and self-closed by the
author without review. Authored by Paul Loh (github.com/lohpaul9). See
the parent repo's README.md and docs/references.md for the full context
on why this became a standalone package instead of an upstream PR.
- Action space narrowed from 7-dim to native 4-dim (see above). The
7→4 adapter (
wrappers.py) is new. FrankaGymEnvand theRobotGymEnvabstract base were dropped.RobotGymEnvonly ever had one concrete subclass (SO101GymEnv), so it added an abstraction layer without abstracting anything;SO101GymEnvnow inherits directly fromMujocoGymEnv. No Panda/Franka code is present in this package.- Fixed: dead mocap body. Upstream's
SO101GymEnv.reset_robot()wrotemocap_pos/mocap_quat, butapply_action()never read them — the IK controller tracks its target in a plain Python attribute (self._target_ee_pos), not a MuJoCo mocap body. This package removes the mocap writes fromreset_robot()and removes the corresponding unusedmocap="true"targetbody frompick_scene.xml. - Not fixed, inherited as-is: gripper unit mismatch. LeRobot represents
the gripper as a linear joint (
0= closed,100= open). The MJCF/URDF gripper joint here still uses its native radian range (ctrlrange="-0.17453 1.74533") with no mapping layer. This was already an open issue in the upstream assets (documented in the originalassets/SO101/README.md); it is reproduced inlerobot_env_so101/assets/README.mdhere rather than silently dropped. - Not fixed, inherited as-is: unverified motor parameters.
damping/frictionloss/armaturefor the STS3215 servos are carried over unchanged from the upstream MJCF, which itself adapted them from the Open Duck Mini project rather than measuring the actual SO-101. See the parent repo'sdocs/references.mdfor the cross-check againstmujoco_menagerie/robotstudio_so101(same values, same unverified lineage). System identification is out of scope for this package (see the parent repo's Phase 2 notes). - Dropped: teleop/gamepad/keyboard wrappers,
PassiveViewerWrapper,GripperPenaltyWrapper,ResetDelayWrapper,EEActionWrapper,InputsControlWrapper, and thewrap_env/make_envfactory. These are HIL-teleop infrastructure orthogonal to the environment itself and out of scope for this package; only the base env, the pick-cube task, and the 7→4 action adapter were ported. - Dropped:
joints_properties.xml. Its contents are already inlined intoso101_new_calib.xmlupstream (see the comment there) and no MJCF file<include>s it separately — it was dead weight in the source repo. mujoco>=3.0.0,<4.0.0(same major-version bump the upstream fork made from vanillagym-hil's<3.0.0). Verified working against MuJoCo 3.10.0.- Fixed: sparse-mode success no longer ignores the gripper. Upstream gym-hil (both its Panda environments and the SO-101 port) computes a strict success check and then discards it in sparse mode, replacing it with a lift-only test — so a block knocked upward without ever being grasped terminates the episode as a success. Measured on this environment before the fix: gripper 0.092 m from the block (threshold 0.05 m) with the block lifted 0.20 m still reported success. Sparse mode now also requires the gripper to be near the block.
Known limitations
- Action deltas are unscaled. An action component of magnitude 1.0 is added directly to the end-effector target as 1.0 metres, while the reachable workspace spans at most 0.6 m. Actions beyond roughly +/-0.2 saturate against the workspace bounds within a single 0.1 s control step, so over most of the declared [-1, 1] range the action behaves closer to bang-bang than to a proportional delta. This is inherited from gym-hil, where actions come from human teleoperation and are naturally small; it is a poor fit for an RL policy sampling uniformly from the action space. Callers training policies should scale their outputs down. A configurable action scale is under consideration for a future version.
SO101GymEnvis a base class, not a usable environment. It implements robot control but notstep()/reset(); instantiateSO101PickCubeGymEnv(orgym.make("lerobot_env_so101/SO101PickCube-v0")) instead.
Attribution
- SO-101 MJCF/URDF and control code: ported from lohpaul9/gym-hil (Apache-2.0), authored by Paul Loh (github.com/lohpaul9).
- Base
gym-hilproject structure and license headers: Copyright 2024 The HuggingFace Inc. team (Apache-2.0). - Asset provenance (CAD source, motor parameters): see
lerobot_env_so101/assets/README.md.
Licensed under Apache-2.0 — see LICENSE.
Testing
pip install -e "packages/lerobot_env_so101[test]"
pytest packages/lerobot_env_so101/tests -q
Metadata
Release files for lerobot-env-so101 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lerobot_env_so101-0.1.0.tar.gz | 6.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lerobot_env_so101-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.0 MB
Release files / lerobot_env_so101-0.1.0.tar.gz
| Download URL | lerobot_env_so101-0.1.0.tar.gz |
|---|---|
| Size | 6.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
46f51fc59709bf8feefc5c6a741697f5f1622b79529ba5f45300b4b95e5c52eb
|
|
BLAKE2b-256 checksum How to use checksums |
732cbc3f8015bc767fbb11afbf12288718e2ea956822a4095a077d7b57fd0498
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|
Release files / lerobot_env_so101-0.1.0-py3-none-any.whl
| Download URL | lerobot_env_so101-0.1.0-py3-none-any.whl |
|---|---|
| Size | 6.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
771894f2a141a320e4202a30767f2f903cda6bc1c37aa19ff8b8443b98b86453
|
|
BLAKE2b-256 checksum How to use checksums |
7ba210853c24d907e94fb09f4d2299e71ff1b4e3ef7b42192dc46ff780ce497f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|