控制器
控制器栈负责将高层目标转换为 MuJoCo 演示所需的执行器级命令。就实际阅读体验而言,本地 runner 是理解这条数据流最好的入口,因为它把目标状态、控制器、mixer、动力学以及 MuJoCo actuators 全部串在了同一个文件里。
在包结构层面,具体控制器统一组织在公共接口 ControllerBase 之下。它定义了 PID、几何控制、以及学习式或自适应控制器共用的生命周期与目标管理模式。
flowchart LR
Target[目标或策略输出] --> Mapping[映射]
Mapping --> Controller[控制器]
Controller --> Mixer[Mixer]
Mixer --> Rotor[旋翼动力学]
Rotor --> MuJoCo[MuJoCo 执行器]
Mapping --> TrackController[履带控制器]
TrackController --> TrackDynamics[履带动力学]
TrackDynamics --> MuJoCo
端到端控制流程
lav2.controller.run 中的飞行控制循环按如下顺序执行:
- 读取 MuJoCo 传感器,获取位姿、速度、姿态和机体系角速度。
- 构造 FlightController 所期望的控制器状态向量。
- 将目标与状态转换为总推力和机体系力矩。
- 通过 Mixer 将该 wrench 分配为旋翼 RPM 命令。
- 将旋翼 RPM 命令输入 RotorDynamics。
- 将得到的推力与扭矩写入 MuJoCo actuators。
履带控制路径与之类似,但会用 TrackController 与 TrackDynamics 替代 mixer 加旋翼动力学这一支路。
PID 控制器
lav2.controller.pid 中包含可复用的 PID 基础块,以及两个组合控制器:
飞行控制器
飞行控制器采用级联 PID 结构:
- 位置环生成速度目标
- 速度环生成横滚 / 俯仰命令与总推力
- 姿态环生成角速度目标
- 角速度环生成机体系力矩
flowchart LR
TPos[位置目标]
TVel[速度目标]
TAtt[姿态目标]
TRate[角速度目标]
TThr[总推力目标]
subgraph Cascade[飞行控制级联]
direction LR
Pos[位置环] --> Vel[速度环] --> Att[姿态环] --> Rate[角速度环] --> Mixer[Mixer] --> Rotor[旋翼动力学] --> Act[MuJoCo 执行器]
end
TPos --> Pos
TVel --> Vel
TAtt --> Att
TRate --> Rate
TThr --> Mixer
control_mask 决定了哪些目标通道由外部直接提供,哪些通道则在级联内部生成。这正是同一个控制器能够同时支持位置式与低层控制模式的关键。
在 lav2.controller.run 中,较低层的飞行模式还会覆盖总推力进入控制栈的方式。对于 cmd_ctatt 与 cmd_ctbr,推力相关目标会先通过 apply_thrust_curve(...),再经由 Mixer 直接注入 mixer 输入,而不是由外层的位置环和速度环生成。这也是为什么这些模式表现为“嵌套的姿态 / 角速度控制 + 油门直通”,而不是完整的外环位置控制。
履带控制器
履带控制器工作在平面状态布局 [x, y, yaw, u, v, r] 上,输出左右履带的加速度式命令。由于这一路径当前主要针对平面地面约束建模,而不是完整 6-DoF 飞行约束,因此它的结构会比飞行级联简单得多。
其它控制器家族
包内还提供了建立在 ControllerBase 之上的其它控制器结构:
lav2.controller.geo:飞行几何控制器家族lav2.controller.xadap:用于更专门控制实验的自适应或学习式控制路径
即使它们内部的控制律不同于 PID 级联,在包级组织方式上仍遵循同一模式。
Mixer 与控制分配
Mixer 仅用于旋翼飞行器路径。它通过求逆一个基于 VehicleParams 派生出的几何分配矩阵,把总推力与横滚 / 俯仰 / 偏航力矩分配到四个旋翼命令上。
Mixer 还承担了与 PX4 对齐的归一化推力转换功能。之所以重要,是因为 PX4 本质上工作在归一化推力 / 力矩风格的输入语义上,而不是直接消费物理量形式的 wrench 命令;因此,LAV2 正是在 mixer 这一层完成“内部物理推力表示”与“PX4 风格归一化命令”之间的转换。
这里有两个需要特别注意的实现细节。
首先,NumPy 与 Torch 版 mixer 目前有意保持了不完全一致的行为。NumPy 版本额外实现了一种分配策略:在发生饱和时优先保留横滚与俯仰控制裕度,再分配偏航。而 Torch 版本则保留了更基础的分配路径,以兼顾计算效率与更通用的 batched 场景。
其次,虽然两个实现都承担“把期望推力与力矩映射为旋翼命令”这一高层职责,但如果你在不同后端之间比较精确的分配行为,应当预期存在这一当前差异。
输出会先在平方 RPM 空间中裁剪,再取平方根。
辅助模块
当你处理的不只是控制律本身时,还有两个辅助模块很值得了解:
lav2.controller.utils:提供控制器响应、执行器行为的日志、可视化与数据导出能力。lav2.controller.mapping:负责将策略输出对齐到对应控制环期望的输入形式,这对分层 RL 控制尤其重要,因为不同 RL agent 可能驱动级联中的不同层。
运行时入口
lav2.controller.run.main是uv run lav2背后的 CLI 入口。control_callback负责在运行时切换飞行模式与履带模式。- 飞行与履带两条执行路径都实现于
lav2.controller.run中,紧接在control_callback之后,是理解本地完整数据流的最佳阅读位置。
接下来读什么
当你需要理解本地模拟器或调节控制器增益时,请使用本页。若下一步工作是强化学习训练,或需要大规模 batched 环境,则转到 Isaac Lab 任务。
API 交叉引用
- 基础接口:ControllerBase
- PID 模块:lav2.controller.pid
- 飞行控制器:FlightController
- 履带控制器:TrackController
- 几何控制器:lav2.controller.geo
- 自适应控制路径:lav2.controller.xadap
- Mixer:Mixer
- Mapping 辅助:lav2.controller.mapping
- 日志与绘图辅助:lav2.controller.utils
- 本地 runner:lav2.controller.run