LeRobot Feature Schema
SUMMARY
Define stable feature keys and compatible data types, shapes, and dimension names for every frame in a LeRobot dataset.
What Is a Feature Schema?
A feature schema defines the structure of the data recorded in each frame of a LeRobot dataset.
features = {
"<feature_a>": {
"dtype": "<data_type>",
"shape": [...],
"names": [...],
},
"<feature_b>": {
"dtype": "<data_type>",
"shape": [...],
"names": [...],
},
}Each feature is identified by a feature key, such as <feature_a>, <feature_b> and so on.
Feature Definition
Each feature has the following structure:
"<feature_key>": {
"dtype": "<data_type>",
"shape": [...],
"names": [...],
}dtype
Defines how the feature is represented and stored.
Supported dtypes
dtype | Meaning |
|---|---|
"video" | Visual frames that LeRobot stores and encodes as video. |
"image" | Visual frames stored as individual images. |
"float32" | Numeric tensor or array values stored as 32-bit floats. |
"bool" | Boolean values. |
"string" | Text or string values. |
shape
Defines the expected shape of the value recorded for that feature.
"shape": [7]This represents a seven-element vector.
"shape": [3, 480, 640]This represents a three-channel image with a height of 480 and width of 640.
names
Describes the dimensions or individual elements of the feature.
For a vector:
"shape": [3],
"names": ["x", "y", "z"],For an image:
"shape": [3, 480, 640],
"names": ["channel", "height", "width"],The names must match the meaning and ordering of the corresponding dimensions or elements.
Example Feature Schema
The following example describes a robot with two cameras, robot state, force/torque sensing, and a seven-dimensional action.
CUSTOMIZE THE SCHEMA
The feature schema is application-specific.
You can add or remove observations, change camera names and resolutions, change robot-state dimensions, add sensors, and define the action representation required by your robot.
Every feature must still provide a compatible dtype, shape, and names definition.
features = {
"observation.images.front": {
"dtype": "video",
"shape": [3, 480, 640],
"names": ["channel", "height", "width"],
},
"observation.images.wrist": {
"dtype": "video",
"shape": [3, 480, 640],
"names": ["channel", "height", "width"],
},
"observation.state": {
"dtype": "float32",
"shape": [7],
"names": [
"shoulder_pan",
"shoulder_lift",
"elbow",
"wrist_1",
"wrist_2",
"wrist_3",
"gripper",
],
},
"observation.force": {
"dtype": "float32",
"shape": [6],
"names": [
"force_x",
"force_y",
"force_z",
"torque_x",
"torque_y",
"torque_z",
],
},
"action": {
"dtype": "float32",
"shape": [7],
"names": [
"shoulder_pan",
"shoulder_lift",
"elbow",
"wrist_1",
"wrist_2",
"wrist_3",
"gripper",
],
},
}Feature Naming Best Practices
- Use stable, descriptive, dot-separated feature names.
- Keep sensor and state inputs under the
observation.namespace. - Use the canonical top-level
actionkey for robot commands. - Avoid encoding episode numbers, timestamps, or changing runtime values in feature names.
- Use the schema's
nameslist to label dimensions within a vector feature; it does not replace the feature key. - LeRobot standardizes common policy-facing keys such as
observation.image,observation.images.<camera_name>,observation.state, andaction, but does not define a universal grammar for every custom feature.
| Data | Recommended feature name | Examples |
|---|---|---|
| Single camera | observation.image | observation.image |
| Multiple cameras | observation.images.<camera_name> | observation.images.front, observation.images.wrist |
| Primary robot state | observation.state | Joint positions and gripper state packed into one vector |
| Additional observation | observation.<name> | observation.force, observation.end_effector_pose |
| Action | action | Joint targets, Cartesian commands, or gripper commands |
| Task description | task | "Pick up the blue cube" |
- Custom keys may require a feature mapping or processor when a policy expects standard keys. See LeRobot's observation conventions and dataset format examples.