LeRobot documentation

电机

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

电机

SerialMotorsBus 是串行总线上 Feetech 或 Dynamixel 舵机链的底层接口。机器人使用它来读取位置并写入目标位置;除非您正在添加硬件,否则很少会直接操作它。每个舵机的型号会在 rustypot 中查找,该库保存了控制表以及不同系列之间的差异事实,并且也负责管理串行端口。FeetechMotorsBus 和 DynamixelMotorsBus 是它的已弃用别名,仅保留一个版本。

从基于 SDK 的总线迁移

这些别名保留了类名,而非旧版 SDK 属性和模型表:

  • bus.model_resolution_table[model] 变为 bus.resolution(model);其他模型表(model_ctrl_table、model_number_table、……)现在是 rustypot 的伺服定义。
  • 操作模式通过名称进行选择,bus.set_operating_mode("position"),而不是将 OperatingMode 值写入 Operating_Mode 寄存器。
  • SDK 端口和包处理程序不再对外暴露:rustypot 拥有串口。
  • protocol_version 会被忽略:每个 motor 的模型会提供其协议。

有关添加新总线,请参阅 自带硬件;有关特定设备的说明,请参阅 更新 Feetech 固件 和 Damiao 电机与 CAN 总线。

SerialMotorsBus

类 lerobot.motors.SerialMotorsBus

< >

( port: strmotors: dict[str, Motor]calibration: dict[str, MotorCalibration] | None = None )

读取和写入通过一个串行端口菊花链连接的 Feetech 或 Dynamixel 舵机链。

rustypot 负责处理每个模型的元数据(控制表、分辨率、波特率、工作模式)以及串行 I/O;LeRobot 负责归一化、校准以及推荐设置。多个模型的电机(例如 STS 和 SCS,或 XL430 和 XL330)共享同一端口。

要查找端口,请运行:

lerobot-find-port
>>> Finding all available ports for the MotorsBus.
>>> ["/dev/tty.usbmodem575E0032081", "/dev/tty.usbmodem575E0031751"]
>>> Remove the usb cable from your MotorsBus and press Enter when done.
>>> The port of this MotorsBus is /dev/tty.usbmodem575E0031751.
>>> Reconnect the usb cable.

单个 Feetech sts3215 在总线上的示例:

from lerobot.motors import Motor, MotorNormMode, SerialMotorsBus

bus = SerialMotorsBus(
    port="/dev/tty.usbmodem575E0031751",
    motors={"my_motor": Motor(1, "sts3215", MotorNormMode.RANGE_M100_100)},
)
bus.connect()

position = bus.read("Present_Position", "my_motor", normalize=False)

# Move a few motor steps as an example
bus.write("Goal_Position", "my_motor", position + 30, normalize=False)

bus.disconnect()

configure_motors

< >

( return_delay_time: int = 0maximum_acceleration: int = 254acceleration: int = 254 )

参数

  • return_delay_time (int,可选,默认为 0) — 电机响应前的延迟时间,单位为 2 µs;电机出厂时设置为 250(即 500 µs)。
  • maximum_acceleration (int,可选,默认为 254) — 加速度上限,适用于具备该功能的舵机(Feetech STS),数值越高,加速和减速越快。
  • acceleration (int,可选,默认为 254) — 加速度,适用于支持该功能的舵机(Feetech)。

将 LeRobot 的推荐设置写入每个电机。

连接

< >

( handshake: bool = True )

参数

  • handshake (bool,可选,默认为 True) — 是否检查每个电机是否以其模型的型号进行响应,以及同一配置中的 Feetech 电机是否运行同一固件。

引发

DeviceAlreadyConnectedError 或 ConnectionError 或 RuntimeError

  • DeviceAlreadyConnectedError — 如果端口已经打开。
  • ConnectionError — 如果无法打开端口。
  • RuntimeError — 如果握手失败,端口将再次关闭。

打开串口并检查电机。

disable_torque

< >

( motors: NameOrID | Sequence[NameOrID] | None = Nonenum_retry: int = 0 )

参数

  • motors (str | int | Sequence[str | int],可选) — 要释放的电机,按名称或 id 指定。None 表示选择所有电机。
  • num_retry (int,可选,默认为 0) — 在发生通信故障后,对每个电机进行的额外重试次数。

引发

ConnectionError

  • ConnectionError — 如果某些电机无法连接;错误消息中会列出它们的名称。

禁用所选电机的扭矩。

在关闭扭矩后,可以写入电机的 EEPROM,并且 Feetech 电机的锁会打开。系统会尝试操作每个选定的电机;失败情况会被报告,且无响应的电机可能仍处于扭矩启用状态。

断开连接

< >

( disable_torque: bool = True )

参数

  • disable_torque (bool,可选,默认为 True) — 是否在关闭端口前禁用所有电机的扭矩,以确保没有电机处于阻力状态。

关闭串行端口,默认情况下关闭所有电机的扭矩。

在已断开的总线上调用是安全的,即使禁用扭矩失败,端口也会被释放。

enable_torque

< >

( motors: NameOrID | Sequence[NameOrID] | None = Nonenum_retry: int = 0 )

参数

  • motors (str | int | Sequence[str | int],可选) — 要锁定的电机,按名称或 id 指定。None 表示选择所有电机。
  • num_retry (int,可选,默认为 0) — 在发生通信故障后,对每个电机进行的额外重试次数。

引发

ConnectionError

  • ConnectionError — 如果某些电机无法连接;错误消息中会列出它们的名称。

启用所选电机的扭矩,并关闭 Feetech 电机的锁定。

ping

< >

( motor: NameOrIDnum_retry: int = 0 ) → int | None

参数

  • motor (str | int) — 电机,按名称或 id 指定,为总线的电机之一。
  • num_retry (int,可选,默认为 0) — 通信失败后的额外重试次数。

返回值

int | None

当电机未响应或拒绝读取时,模型编号为 None。

电机响应的型号编号。

读取 Model_Number 而非发送 ping:存在性和身份验证只需一次往返,而非两次。

读取

< >

( data_name: strmotor: strnormalize: bool = Truenum_retry: int = 0 ) → int | float

参数

  • data_name (str) — 注册名称,例如 "Present_Position";不区分大小写。
  • motor (str) — 电机名称。
  • normalize (bool,可选,默认为 True) — 是否将位置缩放到其校准和范数模式所定义的范围。
  • num_retry (int,可选,默认为 0) — 通信失败后的额外重试次数。

返回值

int | float

原始值,或归一化后的值。

引发

ConnectionError 或 RuntimeError

  • ConnectionError — 如果电机没有响应。
  • RuntimeError — 如果电机拒绝读取。其状态中的警报(例如过载)不会引发此错误。

读取一个电机的寄存器。

read_calibration

< >

( ) → dict[str, MotorCalibration]

返回值

dict[str, MotorCalibration]

每个电机的校准,按名称列出。

读取每个电机的校准值。

没有回零偏移寄存器(Feetech SCS)的电机报告值为 0,而没有 Drive_Mode 寄存器(Feetech)的电机报告驱动模式为 0。

record_calibration

< >

( mode: strfull_turn_motors: Sequence[str]inverted_motors: Sequence[str] = ()motors: Sequence[str] | None = None ) → dict[str, MotorCalibration]

参数

  • mode (str) — 电机的运行模式,例如 "position"。
  • full_turn_motors (Sequence[str]) — 指定使用整个编码器范围,而非电机实际移动范围。
  • inverted_motors (Sequence[str],可选,默认为 ()) — 反向旋转的电机。
  • motors (Sequence[str],可选) — 要校准的电机。None 表示校准所有电机。

返回值

dict[str, MotorCalibration]

按总线顺序对每个电机进行校准。

引发

ValueError

  • ValueError — 如果某个电机不在总线上,或者整圈电机或反转电机不属于要校准的电机之一;此时不会触碰任何电机。

手动移动电机以进行校准。

选定的电机被释放,进入运行模式并设定方向:对于具有 Drive_Mode 寄存器的电机,会写入其方向(无论是否反转);而对于其他电机(如 Feetech 舵机),则在归一化过程中通过软件应用反转。随后,用户将各关节保持在运动范围的中点,这相当于每个电机旋转半圈,并让每个关节遍历其整个运动范围,持续记录直至按下 ENTER。整圈电机不会被记录:它覆盖其型号编码器的整个范围。

电机需要工作模式和回零偏移量,而 Feetech SCS0009 两者都不具备。它们的回零偏移量和位置限制会被重写,缓存的 calibration 会被清除,并且其扭矩保持关闭状态。返回的校准值既不会写入位置限制,也不会被保存:~SerialMotorsBus.write_calibration 负责写入,而设备负责保存。

record_ranges_of_motion

< >

( motors: NameOrID | Sequence[NameOrID] | None = Nonedisplay_values: bool = True ) → tuple[dict[str, int | float], dict[str, int | float]]

参数

  • motors (str | int | Sequence[str | int], 可选) — 要记录的电机,按名称或 id 指定。None 表示选择所有电机。
  • display_values (bool,可选,默认为 True) — 是否打印实时表格。

返回值

tuple[dict[str, int | float], dict[str, int | float]]

每个电机按名称划分的最低和最高原始位置。

引发

ValueError

  • ValueError — 如果某个电机未移动:其最低位置和最高位置相等。

手动记录每个选定电机移动的范围,直到按 ENTER。

在关闭扭矩的情况下,手动移动关节,同时实时表格显示其位置。

reset_calibration

< >

( motors: NameOrID | Sequence[NameOrID] | None = None )

参数

  • motors (str | int | Sequence[str | int],可选) — 要重置的电机,按名称或 id 指定。None 表示选择所有电机。

恢复所选电机的出厂校准。

对于配备回零偏移的电机,其回零偏移被设置为 0,位置限制范围覆盖整个编码器。缓存的 calibration 会被清除。

分辨率

< >

( model: str ) → int

参数

  • model (str) — 总线其中一个电机的型号,例如 "sts3215"。

返回值

int

每轮步数,例如在 12 位编码器上为 4096。

引发

ValueError

  • ValueError — 如果模型未计算编码器步骤。

电机模型每转的编码器步数。

set_baudrate

< >

( baudrate: int )

参数

  • baudrate (int) — 波特率,单位为比特每秒。

更改已打开端口的波特率。

每次连接时,端口都会以 default_baudrate 打开。

set_half_turn_homings

< >

( motors: NameOrID | Sequence[NameOrID] | None = None ) → dict[str, int]

参数

  • motors (str | int | Sequence[str | int],可选) — 要回零的电机,按名称或 id 指定。None 表示选择所有电机。

返回值

dict[str, int]

按名称写入每个电机的回零偏移量。

引发

ValueError

  • ValueError — 如果所选电机没有归零偏移量,例如 Feetech SCS。

将每个选定电机的当前位置设置为半圈。

电机的校准会被重置,随后每个电机都会获得一个归零偏移量,使其当前位置移动到编码器量程的一半,例如 12 位编码器的 2047。每个选定的电机都必须具有归零偏移量,在写入任何寄存器之前都会对此进行检查。

set_operating_mode

< >

( mode: strmotors: NameOrID | Sequence[NameOrID] | None = None )

参数

  • mode (str) — 运行模式的名称,例如 "position"。
  • motors (str | int | Sequence[str | int],可选) — 要设置的电机,按名称或 id 指定。None 表示选择所有电机。

引发

ValueError

  • ValueError — 如果所选电机没有该模式;此时没有电机更改模式。

将选定的电机置于由名称指定的运行模式。

这些模式源自每个电机的定义,因此它们取决于具体的模型,而不仅仅是系列:例如 Feetech SCS0009 就没有任何模式。所选的每个电机都必须支持该模式,系统会在任何电机切换模式之前对此进行检查。请在关闭扭矩的情况下写入该模式。

  • position:保存单回合内的目标位置以及位置限制。
  • velocity:以恒定速度持续旋转,如同车轮。
  • pwm:直接驱动电机电压,开环控制。
  • step(Feetech):按照写入目标位置的步数进行移动。
  • current(Dynamixel):保持目标电流,即无论位置如何,都施加一个扭矩。
  • extended_position(Dynamixel):在多个周期内保持目标位置。在此模式下,Min_Position_Limit 和 Max_Position_Limit 寄存器将被忽略。
  • current_based_position(Dynamixel):在多个周期内保持目标位置,同时电流受目标电流限制,类似于夹持器在夹持物体时不能将其压碎。

setup_motor

< >

( motor: strinitial_baudrate: int | None = Noneinitial_id: int | None = None )

参数

  • motor (str) — 电机的名称。
  • initial_baudrate (int, 可选) — 电机当前响应的波特率。
  • initial_id (int, 可选) — 电机当前响应的 Id,与 initial_baudrate 配合使用。

引发

RuntimeError 或 ConnectionError

  • RuntimeError — 如果未找到电机、电机型号不匹配,或者在配置完成后未按预期响应。
  • ConnectionError — 如果与电机的通信失败。

为单个电机指定其 id 以及总线的默认波特率。

电机必须是总线上唯一的设备。除非同时提供了 initial_baudrate 和 initial_id,否则需要先找到它:如果只提供了 initial_baudrate,则在该波特率下查找;否则在其型号的波特率范围内查找;如果单独提供了 initial_id,则会被找到的 id 替换。随后 rustypot 会关闭其扭矩,打开其 EEPROM,并写入 id 和波特率。

setup_motors

< >

( motors: Sequence[str] | None = None )

参数

  • motors (Sequence[str],可选) — 按设置顺序排列的电机。None 表示从最后一个电机到第一个电机,对于机械臂而言,即从夹爪向下。

逐个设置电机,要求每次只有一个电机连接到总线上。

sync_read

< >

( data_name: strmotors: NameOrID | Sequence[NameOrID] | None = Nonenormalize: bool = Truenum_retry: int = 0 ) → dict[str, int | float]

参数

  • data_name (str) — 注册名称,例如 "Present_Position";不区分大小写。
  • motors (str | int | Sequence[str | int], 可选) — 要读取的电机,按名称或 id 指定。None 表示读取所有电机。
  • normalize (bool,可选,默认为 True) — 是否将位置缩放到其校准和范数模式所定义的范围。
  • num_retry (int,可选,默认为 0) — 通信失败后的额外重试次数。重试会重新发送所有组,包括之前已成功发送的组;未知的电机或寄存器永远不会被重试。

返回值

dict[str, int | float]

每个电机的值,按名称列出。

引发

ConnectionError 或 RuntimeError

  • ConnectionError — 如果电机没有响应。
  • RuntimeError — 如果电机拒绝读取,则会抛出此错误。状态中的警报(例如过载)不会引发此错误。

读取多个电机的寄存器。

rustypot 会为共享同一协议以及寄存器地址和大小的一组电机发送一次 Sync Read,而对于像 Feetech SCS 这类伺服电机,则不使用 Sync Read,而是依次读取。因此,这些值并非同一时刻的快照。

sync_write

< >

( data_name: strvalues: Value | dict[str, Value]normalize: bool = Truenum_retry: int = 0 )

参数

  • data_name (str) — 注册名称,例如 "Goal_Position";不区分大小写。
  • values (int | float | dict[str, int | float]) — 每个电机的一个值,或按电机名称指定的值。
  • normalize (bool,可选,默认为 True) — 位置是否以校准和归一化模式所定义的范围内给出。
  • num_retry (int,可选,默认为 0) — 端口失败后的额外重试次数。每次重试都会重新发送所有组。

引发

ConnectionError

  • ConnectionError — 如果端口失败。

写入多个电机的寄存器,无需等待响应。

与 ~SerialMotorsBus.write 不同,同步写入不会收到任何电机的应答:速度更快,适用于控制循环,但丢失的数据包不会被察觉。rustypot 会为每组共享相同协议以及寄存器地址和大小的电机发送一个同步写入。

torque_disabled

< >

( motors: NameOrID | Sequence[NameOrID] | None = None )

参数

  • motors (str | int | Sequence[str | int],可选) — 要释放的电机,按名称或 id 指定。None 表示选择所有电机。

在 with 代码块执行期间,禁用所选电机的扭矩。

退出时扭矩会重新启用,即使代码块抛出异常也是如此,这适用于配置电机。

示例:

>>> with bus.torque_disabled():
...     bus.set_operating_mode("position")

写入

< >

( data_name: strmotor: strvalue: Valuenormalize: bool = Truenum_retry: int = 0 )

参数

  • data_name (str) — 注册名称,例如 "Goal_Position";不区分大小写。
  • motor (str) — 电机名称。
  • value (int | float) — 要写入的值,根据 normalize 的说明,为归一化值或原始值。
  • normalize (bool,可选,默认为 True) — 位置是否在其校准和归一化模式所定义的范围内给出。
  • num_retry (int,可选,默认为 0) — 通信失败后的额外重试次数。

引发

ConnectionError 或 RuntimeError

  • ConnectionError — 如果电机没有响应。
  • RuntimeError — 如果电机拒绝写入。其状态中的警报(例如过载)不会引发异常。

写入一个电机的寄存器,并等待其响应。

与 ~SerialMotorsBus.sync_write 不同,电机会对写入操作进行确认,因此会报告失败:速度较慢,但适用于配置电机。

write_calibration

< >

( calibration_dict: dict[str, MotorCalibration]cache: bool = True )

参数

  • calibration_dict (dict[str, MotorCalibration]) — 按名称划分的每个电机的校准数据,格式与 ~SerialMotorsBus.read_calibration 的返回值一致。
  • cache (bool,可选,默认为 True) — 是否将校准保留为总线的 calibration,该参数用于归一化位置。

将校准数据写入电机,并默认将其缓存。

位置限制会写入每个电机,而归零偏移量则写入具有该功能的电机。ID 和驱动模式均不会被写入:Feetech 的驱动模式在归一化时通过软件应用,而 Dynamixel 的 Drive_Mode 寄存器则单独设置。

Motor

类 lerobot.motors.Motor

< >

( id: intmodel: strnorm_mode: MotorNormModemotor_type_str: str | None = Nonerecv_id: int | None = None )

MotorCalibration

类 lerobot.motors.MotorCalibration

< >

( id: intdrive_mode: inthoming_offset: intrange_min: intrange_max: int )

MotorNormMode

class lerobot.motors.MotorNormMode

< >

( *values )

DriveMode

DriveMode 有两个成员:NON_INVERTED = 0 和 INVERTED = 1。在需要整数的地方,例如 Drive_Mode 寄存器或 MotorCalibration.drive_mode 中,请使用 .value:

bus.write("Drive_Mode", "elbow_flex", DriveMode.INVERTED.value)

类 lerobot.motors.DriveMode

< >

( *values )

Dynamixel 的 Drive_Mode 寄存器值,以及 MotorCalibration.drive_mode 的值。

Update on GitHub