Skip to content

Gaits (bt.Gait)

How a robot mounted on a vehicle walks it: the feet, the stance, the rhythm. Hand one to scene.mount_robot(..., gait=...) and the legs walk whenever the vehicle drives. See Legged robots.

gait = bt.Gait(
    legs={"FL": "FL_foot", "FR": "FR_foot", "RL": "RL_foot", "RR": "RR_foot"},
    stance={...}, pattern="trot", period=0.45, lift=0.07, max_stride=0.45,
    foot_radius=0.022,
)
scene.mount_robot("walker", robot="go2", gait=gait)
timeline.footfalls("go2")        # every step: (leg, lift, land, (x, y, z))

gait

Gaits — how a robot mounted on a vehicle walks it.

To a cell, a quadruped or a humanoid is a vehicle with legs: it is sent with bt.seq.goto, arrives with bt.seq.device_done, carries what sits on its back, and has to fit the aisle like any AGV. What the vehicle vocabulary lacks is the legs, and that is all a Gait adds — which links are the feet, how the machine stands, and the rhythm it walks to. Hand it to scene.mount_robot(..., gait=...) and the legs walk whenever the vehicle drives; there is no walk action to author, any more than there is a "spin the wheels" action for an AMR.

Nothing is simulated physically. The body rides the vehicle's closed-form motion, the footfalls are planned from it the moment the vehicle is dispatched (a foot lands where its stance will be centred under the body), a planted foot never moves in the world, and each leg is solved by IK every scan tick. What the bake answers is what it answers for any vehicle — does it fit, does it clash, how long does the cycle take — with legs that move like legs instead of a body that hovers.

gait = bt.Gait(
    legs={"FL": "FL_foot", "FR": "FR_foot", "RL": "RL_foot", "RR": "RR_foot"},
    stance={"FL_hip_joint": 0.0, "FL_thigh_joint": 0.8, "FL_calf_joint": -1.5, ...},
    pattern="trot", period=0.5, lift=0.06, max_stride=0.4, foot_radius=0.022,
)
scene.add_vehicle("dog", body=[], path=..., stations=..., speed=0.6)
scene.mount_robot("dog", robot="go2", gait=gait)   # stands it on the floor

A catalog package of category vehicle.legged carries all of this in its manifest (the locomotion block the catalog builder validated the package to walk with), so the cell does not copy joint names out of a URDF:

dog = bt.Robot.from_catalog("unitree/go2/go2")
gait = bt.Gait.from_catalog("unitree/go2/go2")   # or a package directory
scene.mount_robot("dog", robot="go2", gait=gait)

A biped is the same thing with two legs, soles instead of balls, arms that swing, and a body that bobs:

gait = bt.Gait(
    legs={"L": "left_ankle_roll_link", "R": "right_ankle_roll_link"}, contact="sole",
    stance={...}, pattern="biped", period=0.9, lift=0.05, max_stride=0.5,
    foot_radius=0.035, arm_swing={"left_shoulder_pitch_joint": -0.25,
                                  "right_shoulder_pitch_joint": 0.25},
    bob=0.02, lateral=0.02,
)

Gait

How a mounted robot walks. Every name is checked against the model when the robot is mounted.

Attributes:

Name Type Description
legs

Leg name -> foot link, in the order the pattern's phase table is read: FL, FR, RL, RR for the quadruped patterns, L, R for biped. A value may also be (foot_link, contact) to give one leg its own contact.

stance

Joint -> value of the standing pose. Must name every leg joint; other joints keep the value they had when mounted.

pattern

walk (duty 0.75, lateral sequence), trot (duty 0.5, diagonal pairs), biped (duty 0.6), or custom with duty and phases.

period

Cycle period in seconds.

lift

Swing apex above the floor, metres.

max_stride

The longest step a leg may take between two landings: speed * period (and the pivot's outer-foot arc) must stay under it, or the bake refuses the vehicle's rates by name.

foot_radius

How far the foot link's origin stands above the floor: a ball foot's radius, or an ankle frame's height over its sole. Zero for a frame on the sole itself.

contact

point (a ball: position only), sole (flat on the floor, pointing where it landed) or sole_yaw_free, for every leg not given its own. A sole's foot link must point +Z up in the stance; a 6-DOF leg keeps it flat and pointed, a 5-DOF leg keeps it flat.

bob

Vertical sway of the body while walking, metres — up over each planted leg, down through double support, twice a cycle.

lateral

Lean of the body over the planted leg, metres, once a cycle. Both are zero by default (a trotting quadruped's body rides nearly rigid); a biped wants a couple of centimetres.

max_step

Tallest step (rise between two consecutive footholds of one leg, metres) the machine may take — a catalog package fills it from max_step_height_mm. Also how far above or below the vehicle plane a walkable surface (a stair tread) is searched for a foothold. None skips the declared check and searches 0.3 m; unreachable steps then fall to the IK.

duty

Stance fraction of the cycle, custom pattern only.

phases

Per-leg cycle phase in [0, 1), custom pattern only.

body_link

The link the legs hang from; the root link by default.

arm_swing

Joint -> amplitude (rad) swung in time with the first leg — a biped's arms. Left alone while the robot holds something or a ramp is driving them (a carried part rides still).

bob class-attribute

bob = 0.0

Convert a string or number to a floating-point number, if possible.

contact class-attribute

contact = 'point'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

foot_radius class-attribute

foot_radius = 0.0

Convert a string or number to a floating-point number, if possible.

lateral class-attribute

lateral = 0.0

Convert a string or number to a floating-point number, if possible.

lift class-attribute

lift = 0.06

Convert a string or number to a floating-point number, if possible.

max_stride class-attribute

max_stride = 0.4

Convert a string or number to a floating-point number, if possible.

pattern class-attribute

pattern = 'trot'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

period class-attribute

period = 0.5

Convert a string or number to a floating-point number, if possible.

from_catalog classmethod

from_catalog(
    package: str | Path,
    *,
    revision: str | None = None,
    posture: str | None = None,
    **overrides: Any,
) -> Gait

The gait a catalog package declares.

package is a catalog id ("unitree/go2/go2" — resolved and fetched like Robot.from_catalog, pinned with revision) or a package directory on disk, one holding manifest.yaml (a local build of the catalog builder, say). The manifest's locomotion block — the feet, the stance, the rhythm the package was validated to walk with — becomes the Gait; keyword overrides replace any field (period=0.5). A package without the block (anything but vehicle.legged) is refused by name.

posture="stairs" asks for the package's stair posture instead of its standing one: lower, and with a shorter swing, which is how a legged machine actually takes a flight (a body held at its walking height asks the downhill legs for reach they do not have). A package that does not carry one is refused by name rather than walked up a flight in the wrong posture — state the stance yourself, or pass posture=None to take the standing one knowingly.

postures staticmethod

postures(
    package: str | Path, *, revision: str | None = None
) -> tuple[str, ...]

The postures a package carries beside its standing stance.

("stairs",) for a package that states how the machine stands on a flight, () for one that does not — a cell that can do either asks first, rather than requiring the posture and handling the refusal. The names are what :meth:from_catalog takes as posture=.