LeRobot documentation
Escribir docstrings
Escribir docstrings
La referencia de la API de LeRobot se genera directamente desde las docstrings en src/lerobot/. Una docstring no es un comentario, sino la documentación publicada para ese objeto, y el formato siguiente es lo que analizan el renderizador y las comprobaciones de CI.
Esta página es el contrato. Si vas a añadir o editar algo público en src/lerobot/, síguelo.
Un método público sin documentar es invisible.
[[autodoc]]omite silenciosamente los miembros que no tienen docstring: no emite ninguna advertencia ni error, simplemente no aparece en la página renderizada. La cobertura y la completitud de la referencia de la API son el mismo problema.
El formato en un ejemplo
Encabezados de sección de Google, formato de tipo de Hugging Face. Ambos, no uno u otro.
def send_action(self, action: RobotAction, rate_hz: float = 30.0) -> RobotAction:
"""Command the robot to move to a target joint configuration.
Values are clipped by the configured maximum relative target before reaching the motors, so the
returned action may differ from the requested one.
Args:
action (`dict[str, float]`):
Target values keyed by motor name, e.g. `{"shoulder_pan.pos": 0.0}`. Keys must match the
robot's action features.
rate_hz (`float`, *optional*, defaults to `30.0`):
Control loop frequency.
Returns:
`dict[str, float]`: The action actually written to the motors after safety clipping.
Raises:
DeviceNotConnectedError: If the robot has not been connected.
Example:
```python
>>> from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
>>> robot = SO101Follower(SO101FollowerConfig(port="/dev/ttyACM0")) # doctest: +SKIP
>>> robot.connect() # doctest: +SKIP
>>> robot.send_action({"shoulder_pan.pos": 0.0}) # doctest: +SKIP
```
"""Las referencias cruzadas se omiten en los ejemplos de esta página; consulte Referencias cruzadas para conocer su sintaxis y por qué no se pueden mostrar dentro de un bloque de código.
Reglas
Secciones
Args: · Returns: · Raises: · Yields: · Example: · Note:
En ese orden. Ningún otro encabezado de sección. Primero va un resumen de una línea, luego una descripción libre opcional y, después, las secciones.
La línea Args: se analiza mediante máquina
name (`type`, *optional*, defaults to `X`):
Description, indented on its own line.La cláusula *optional*, defaults to se compara con el valor predeterminado real de la firma mediante make check-docstrings. No es decorativa: si escribes un valor predeterminado que ha divergido del código, CI
falla. Omitir la cláusula por completo para los parámetros obligatorios:
Args:
port (`str`):
Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
max_relative_target (`float | dict[str, float]`, *optional*):
Caps the magnitude of the relative positional target vector. `None` disables clipping.
use_degrees (`bool`, *optional*, defaults to `True`):
Keep `True` for backward compatibility with existing policies and datasets.Los tipos van entre comillas invertidas. Use *optional* sin defaults to cuando el valor predeterminado sea None o no merezca la pena repetirlo.
Devuelve: es de tipo primero
Una línea con sangría, primero el tipo, luego dos puntos y después la descripción:
Returns:
`dict[str, float]`: The action actually written to the motors after safety clipping.Yields: tiene la misma forma.
**Atributos**: , nunca Atributos:
doc-builder interpreta un Attributes: sin más como un sinónimo de Parameters:, por lo que tus atributos se renderizan como argumentos del constructor. Esto es silencioso e incorrecto. Siempre que los atributos difieran de los parámetros del constructor, usa la forma en negrita con un separador --:
class Robot(abc.ABC):
"""The base abstract class for all LeRobot-compatible robots.
**Attributes**:
- **config_class** (`type[RobotConfig]`) -- The expected configuration class for this robot.
- **name** (`str`) -- The unique robot name used to identify this robot type.
"""Nota --, no :.
Referencias cruzadas
Use the bracket syntax of doc-builder: a path enclosed in square brackets and backticks. Los roles de Sphinx (:pymeth:, :pyattr:) no son compatibles y se renderizan como texto literal en la página.
| Desea | Escribir |
|---|---|
| Clase en el paquete principal | [Robot] |
| Método, mostrar la ruta completa | [Robot.connect] |
| Método, mostrar el nombre sin adornos | [~Robot.connect] |
| Ruta anidada | [~robots.Robot.connect] |
| Objeto en otra biblioteca de HF | [~accelerate.Accelerator] |
El ~ elimina la ruta solo del texto del enlace; el enlace sigue resolviéndose a la ruta completa.
doc-builder resuelve esta sintaxis en todas partes de una página, incluso dentro de bloques de código delimitados. Por eso, los ejemplos de docstring de esta página usan prosa simple en lugar de referencias cruzadas: un bloque de código que contenga una de estas referencias mostraría el enlace resuelto en lugar de la sintaxis que necesitas escribir. En tus propios docstrings, usa referencias cruzadas libremente; esta restricción solo afecta a la documentación sobre la sintaxis.
Avisos
Usa citas de bloque estilo GitHub:
> [!TIP]
> Call this once at startup — it takes about two seconds.
> [!WARNING]
> Torque is disabled on disconnect. The arm will drop if it is holding a load.El componente <Tip> es obsoleto según doc-builder; no agregues nuevos.
Los ejemplos deben estar delimitados
Un ejemplo se encuentra dentro de un bloque ```python que contiene >>>. La valla es lo que hace que se renderice como un bloque de código, y es lo que la expresión regular del preprocesador de doctest busca:
Example:
```python
>>> from lerobot.robots.so_follower import SO101FollowerConfig
>>> cfg = SO101FollowerConfig(port="/dev/ttyACM0")
>>> cfg.use_degrees
True
```Un
>>>sin valla se recopila igualmente: doctest encuentra los prompts en cualquier parte de una docstring. Lo que se pierde es el renderizado, por lo que aparece como un bloque de texto en la página. Cada ejemplo necesita la valla.
Cada ejemplo se ejecuta en CI o lleva # doctest: +SKIP. Todo lo que implique hardware, una GPU o descargas del Hub lleva +SKIP:
Example:
```python
>>> robot.connect() # doctest: +SKIP
>>> policy = ACTPolicy.from_pretrained("lerobot/act_aloha_sim_transfer_cube_human") # doctest: +SKIP
```Agregue archivos que contengan ejemplos ejecutables a utils/documentation_tests.txt.
Coloca ejemplos en los tres a cinco puntos de entrada genuinos de un módulo. Los ejemplos en accesores triviales son ruido.
Tres patrones que encontrarás constantemente
Dataclasses de configuración
Los campos de configuración se documentan históricamente con comentarios # sobre cada campo. doc-builder no puede ver los comentarios en línea: una clase así se renderiza con todos los campos listados y sin una sola descripción. Muévelos a un bloque Args: en la docstring de la clase:
@dataclass
class SOFollowerConfig:
"""Configuration for SO-family follower arms.
Args:
port (`str`):
Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
max_relative_target (`float | dict[str, float]`, *optional*):
Caps the magnitude of the relative positional target vector. A scalar applies to all motors;
a dict maps motor name to a per-motor cap. `None` disables clipping.
use_degrees (`bool`, *optional*, defaults to `True`):
Keep `True` for backward compatibility with existing policies and datasets.
"""
port: str
max_relative_target: float | dict[str, float] | None = None
use_degrees: bool = Truedoc-builder no hereda las docstrings de las clases base. Las clases de configuración registradas de LeRobot suelen ser shims de herencia múltiple delgados:
@RobotConfig.register_subclass("so101_follower") @dataclass class SOFollowerRobotConfig(RobotConfig, SOFollowerConfig): passEsa clase renderiza cada campo, incluidos los que hereda, sin descripciones, sin importar lo bien documentadas que estén las clases base. El bloque
Args:debe estar en la clase concreta que[[autodoc]]nombra, y debe cubrir también los campos heredados.
Clase base y luego subclase concreta
La base abstracta contiene el contrato canónico. Las subclases documentan solo lo que se desvía: semántica del puerto, peculiaridades de calibración, disposición de los motores y claves de funciones admitidas. No copies el contrato de la base en cada subclase.
Robot, Teleoperator, Camera, MotorsBusBase, ProcessorStep y PreTrainedPolicy siguen todos esta forma.
Alias a nivel de módulo
Varios nombres públicos son alias en lugar de clases distintas:
SO100FollowerConfig = SOFollowerRobotConfig SO101FollowerConfig = SOFollowerRobotConfig
[[autodoc]] resuelve el alias y muestra el nombre de clase canónico, por lo que un encabezado ## SO101FollowerConfig mostrará class lerobot.robots.so_follower.SOFollowerRobotConfig en el cuerpo. Documenta la clase canónica una sola vez y menciona los alias en el texto de la página, en lugar de asignar a cada alias su propio bloque de autodoc.
Qué no documentar
- Miembros privados. Todo lo que comience con
_no forma parte de la API pública. - La anotación de tipo reescrita en prosa.
port (str): A string.no aporta nada. Indique para qué sirve. - Código de upstream incluido.
src/lerobot/policies/molmoact2/molmoact2_hf_model/se incluye desdetransformersy ya tiene docstrings al estilo de upstream. Déjalo como está: restilizarlo solo crea conflictos en la próxima sincronización. Está excluido de la referencia de la API y de las comprobaciones de docstrings.
Cómo se aplica esto
| Comprobar | Lo que detecta |
|---|---|
make check-docstrings | Una entrada Args: que no coincide con la firma; un valor predeterminado documentado que ha divergido del real |
make doctest | Ejemplos que ya no se ejecutan |
make check-doctest-list | Entradas obsoletas o no ordenadas en utils/documentation_tests.txt |
ruff (reglas D) | Violaciones del estilo de convención de Google |
interrogate | Cobertura de docstrings por debajo del umbral actual |
| doc-builder | Una ruta de [[autodoc]] que apunta a algo que no existe: esto rompe la compilación de la documentación |
Ejecútelos juntos antes de abrir una PR:
make check-docstrings && make doctest && pre-commit run --all-files
Luego, renderiza la página y mírala en realidad:
doc-builder build lerobot docs/source/ --build_dir /tmp/doc-build
Lista de verificación
- Cada miembro público que modificaste tiene una docstring.
- Cada entrada de
Args:coincide con la firma, incluida la cláusula*optional*, defaults to. -
Returns:es de tipo primero en una línea con sangría. - No atributos sin formato
Attributes:— usa**Attributes**:con separadores--. - No hay roles de Sphinx: las referencias cruzadas usan [
~module.Class.method]. - Los ejemplos están dentro de un bloque
```pythony se ejecutan en CI o llevan# doctest: +SKIP. - Los campos del dataclass de configuración están en un bloque
Args:de la clase concreta, no en comentarios#. - La página renderizada ha sido revisada a simple vista.