Wheels (bt.Wheels)¶
How a robot mounted on a vehicle rolls it: which joints are the wheels, how
big they are, which frame stands on the floor. Hand one to
scene.mount_robot(..., wheels=...) and the wheel joints turn by exactly
what the vehicle drives. See
The robot is the vehicle.
wheels = bt.Wheels({"left_wheel_joint": 0.085, "right_wheel_joint": 0.085},
base_frame="base_footprint")
scene.add_vehicle("base", body=[], path=..., stations=..., drive=wheels.vehicle_drive)
scene.mount_robot("base", robot="g1d", wheels=wheels)
wheels = bt.Wheels.from_catalog("unitree/g1/g1-d") # a vehicle.mobile_manipulator package
# A wheel-legged quadruped: a gait as well; `mode="auto"` (the default) rolls
# or walks each leg of a route as the floor decides, "roll" / "walk" force it.
scene.mount_robot("dog", robot="go2w", gait=gait, wheels=bt.Wheels({...}))
tl.locomotion("go2w") # what it rolled and walked
bt.Wheels.rolls("unitree/go2/go2-w") # True: a legged package with `wheels`
wheels = bt.Wheels.from_catalog("unitree/go2/go2-w") # to mount beside bt.Gait.from_catalog
See also Wheels for feet.
wheels
¶
Wheels — how a robot mounted on a vehicle rolls it.
A humanoid upper body on a wheeled base — a semi-humanoid — is one machine:
one purchase, one URDF, arms and torso and wheels in one joint tree. To a
cell it is what a legged machine is, a vehicle whose running gear is the
robot itself: it is sent with bt.seq.goto, arrives with
bt.seq.device_done, and has to fit the aisle like any AGV. Wheels is
what the vehicle vocabulary lacks for it — which joints are the wheels, how
big they are, and which frame stands on the floor. Hand it to
scene.mount_robot(..., wheels=...) and the wheels turn whenever the
vehicle drives; there is no "spin the wheels" action to author.
Nothing is simulated physically. The vehicle's checked motion is the only input: each wheel turns by exactly the distance its hub travelled — forward on a straight, opposite ways through a pivot, not at all on a lift ride — and the turning is baked into the joint track alongside whatever the arms do on the way. What the declaration changes beyond the picture:
- the machine is one row of the BOM (the vehicle is not a second purchase),
- a
walkablesurface under it — a floor slab, a lift car's floor — is where it rolls, not a collision, -
the wheel joints are the mount's: no motion or ramp may drive them.
wheels = bt.Wheels( {"left_wheel_joint": 0.085, "right_wheel_joint": 0.085}, base_frame="base_footprint", ) scene.add_vehicle("base", body=[], path=..., stations=..., speed=0.8) scene.mount_robot("base", robot="g1d", wheels=wheels) # stands it on the floor
A catalog package of category vehicle.mobile_manipulator carries all of
this in its manifest (the locomotion block the catalog builder validated
the package to drive with), and so does a vehicle.legged one whose block
has wheels (Wheels.rolls(package) says which):
robot = bt.Robot.from_catalog("unitree/g1/g1-d")
wheels = bt.Wheels.from_catalog("unitree/g1/g1-d")
scene.add_vehicle("base", body=[], path=..., drive=wheels.vehicle_drive, ...)
scene.mount_robot("base", robot="g1d", wheels=wheels)
A mecanum wheel adds its rollers' handedness, a swerve module its steering joint:
bt.Wheels({"fl_wheel": (0.076, -1), "fr_wheel": (0.076, +1),
"rl_wheel": (0.076, +1), "rr_wheel": (0.076, -1)}, drive="mecanum")
bt.Wheels({"wheel_1": 0.06, "wheel_2": 0.06, "wheel_3": 0.06},
steer={"wheel_1": "steer_1", "wheel_2": "steer_2", "wheel_3": "steer_3"},
drive="swerve")
A wheel-legged quadruped — a Go2-W, a B2-W: wheels for feet — is mounted
with a Gait and Wheels. The gait's feet are the axle frames the
wheels turn on (a frame fixed to each calf at the wheel joint's origin), its
foot_radius is the wheel radius, and mode says which gear takes the
route. "auto" (the default) decides leg by leg of every route from the
floor under it: rolled where the floor is continuous, walked where it
steps — a stair flight, a kerb taller than max_step — from a wheel's
leading edge before the first step to a hind foot's last landing past the
last one, a turn walked when either straight beside it is, a roll too short
to be worth the change walked with its neighbours; the walked legs go at the
gait's speed, the rest at the vehicle's. "roll" holds the legs in
the posture the machine was mounted in and turns every wheel by its hub's
travel, refusing a step by name; "walk" locks the wheels and walks on
them as on feet everywhere, wheel radius for foot radius.
gait = bt.Gait(legs={"FL": "FL_axle", ...}, foot_radius=0.086, speed=0.4, ...)
wheels = bt.Wheels({"FL_foot_joint": 0.086, ...})
scene.mount_robot("dog", robot="go2w", gait=gait, wheels=wheels)
tl.locomotion("go2w") # [(t0, t1, "roll" | "walk", metres), ...]
Wheels
¶
How a mounted robot rolls. Every name is checked against the model when the robot is mounted.
Attributes:
| Name | Type | Description |
|---|---|---|
wheels |
Wheel joint -> rolling radius in metres, or |
|
steer |
Wheel joint -> the joint that steers it about the vertical (a swerve module). It is aimed along the wheel's travel, by the shorter turn. |
|
base_frame |
The link whose origin is the machine's point on the
floor, under its turn centre — a URDF's |
|
posture |
Joint -> value the machine is put in as it is mounted — how it travels (torso down, arms tucked). Other joints keep the value they had. |
|
drive |
What the base is — |
|
mode |
For a machine mounted with a gait as well (a wheel-legged
quadruped): |
|
max_step |
The tallest break in the floor the wheels roll over, metres — a kerb, a threshold. Zero, the default, walks (or refuses) every step; state a figure the wheels are rated for. |
drive
class-attribute
¶
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'.
max_step
class-attribute
¶
Convert a string or number to a floating-point number, if possible.
mode
class-attribute
¶
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'.
vehicle_drive
property
¶
The add_vehicle(drive=...) this base wants: holonomic for
mecanum / omni / swerve (it translates any way holding its
heading), differential otherwise (it turns on the spot and
drives where it faces).
from_catalog
classmethod
¶
from_catalog(
package: str | Path,
*,
revision: str | None = None,
posture: str | None = "travel",
**overrides: Any,
) -> Wheels
The wheels a catalog package declares.
package is a catalog id ("unitree/g1/g1-d" — resolved and
fetched like Robot.from_catalog, pinned with revision) or a
package directory on disk. The manifest's locomotion block of
kind: wheeled and its frames.base_frame become the Wheels;
keyword overrides replace any field. A legged package whose
block carries wheels — a wheel-legged machine, a Go2-W — gives
its wheels too, to be mounted beside bt.Gait.from_catalog of the
same package (mode "auto", and the wheels' max_step_mm).
A package that only walks, or carries no block, is refused by name.
posture names one of the package's locomotion.postures;
the default takes travel when the package states it. Pass
None to mount the machine as it stands. A wheel-legged package
has one posture, wheels.posture, laid over the stance.
postures
staticmethod
¶
The postures a package states (locomotion.postures) — the
names :meth:from_catalog takes as posture=.
rolls
staticmethod
¶
Whether a package carries wheels at all: a kind: wheeled block,
or a legged block with wheels (a wheel-legged machine) — what to
ask before :meth:from_catalog rather than catch its refusal.