YouDuck.ai

Backlash, and which side the encoder sits on

Last updated

Backlash is the free play in a geared transmission: on reversal the input turns a little before the output starts moving.

Every main microduck_rl task has a Backlash twin with ±1° (2° total) of play on each of the 14 servo joints:

Mjlab-Velocity-Flat-Backlash-MicroDuck

Insert -Backlash before MicroDuck in the task id.

The encoder’s position is the point

This is the part that is easy to get wrong and the most worth learning.

On the real robot, the encoder sits on the output side of the play.

So the simulation has to match that structure. The official implementation does two things:

  1. Each servo gets an unactuated passive_<joint>_backlash hinge.
  2. Both the firmware PD emulation (BacklashEncoderBamActuator) and the joint_pos / joint_vel observations read through the backlash — qpos[servo] + qpos[backlash].

Modelling it on the wrong side

Put the encoder on the input side and the policy believes it knows the joint position exactly, while on hardware it reads the value after the play.

That difference has an unfriendly property: it is invisible while the joint holds still and arrives all at once on reversal. The robot stands fine and starts misbehaving the moment it walks — and you go looking at the gait policy rather than at the observation.

One engineering benefit

Observation and action dimensions are unchanged, so ONNX export and the runtime need no changes at all. A policy trained with backlash and one trained without are directly interchangeable.

See src/mjlab_microduck/tasks/backlash.py.