跳转至

动力学

LAV2 面向陆空两栖与飞行平台提供统一的动力学参数与接口框架。其实现将动力学组织为一个共享参数对象,以及若干与执行形式相关的模型实现,使得本地 MuJoCo 运行器与 GPU/任务端后端能够在相同的物理常数和接口约定上保持一致。

已知建模限制

这里的模块拆分主要服务于实现组织与数值计算,并不意味着旋翼与接触动力学在物理上已经被完全解耦。例如升力对接触力的影响等耦合关系,尚未进一步建模。

机体参数

VehicleParams 是平台最核心的参数接口。它将机体描述划分为:

  • 环境参数
  • 机身参数
  • 螺旋桨参数
  • 地面驱动参数
  • 与 PX4 对齐的参数

其中一部分值来自直接配置,另一部分则会在 __post_init__ 中派生出来,例如推力与反扭矩系数、默认初始 RPM,以及悬停油门相关量。因此在实际使用中,VehicleParams 不仅定义平台的原始常数,也定义了下游动力学与控制器真正消费的量。

需要质量、惯量、仿真步长、旋翼系数或驱动几何参数时,应优先从 VehicleParams 出发,而不是把相关字面量散落在各个模块中。

在模块结构层面,显式动力学实现统一组织在 DynamicsBase 这一公共接口之下。地面接触由轮组几何与仿真器接触约束表示,不再使用独立的解析履带外力模块。

时间尺度:sim_dtstep_dt

一旦同一套动力学被放到本地单速率模拟器之外使用,这两个时间参数就会变得非常重要。sim_dt 表示执行器与物理积分步长,而 step_dt 表示控制器更新步长。

在带 decimation 的框架中,例如 Isaac Lab,这两者往往并不相同,因为物理引擎的步进频率通常高于控制策略或命令更新频率。当后续引入高层与低层策略异步运行时,这种区分也同样重要。把这两个字段统一保存在 VehicleParams 中,可以避免将频率假设隐含在单个模块内部。

旋翼动力学

RotorDynamics 将每个旋翼的 RPM 命令转换为一个批量 (N, 8) 输出数组:

  • 每个环境的前 4 个量:推力
  • 每个环境的后 4 个量:反扭矩

它的更新规则遵循标准的旋翼模型结构。命令转速不会被瞬时施加,而是先经过滤波与速率限制;随后根据旋翼速度与电机角加速度计算推力与反扭矩:

\[ f_i = c_T \omega_i^2 \]
\[ \tau_i = c_M \omega_i^2 d_i \]

其中,\(\omega_i\) 表示旋翼转速,\(f_i\) 表示推力,\(\tau_i\) 表示反扭矩,\(c_T\)\(c_M\) 分别是推力与扭矩系数,\(d_i \in \{+1, -1\}\) 通过 VehicleParams.spin_dir 编码旋翼旋向;约定 +1 为顺时针,-1 为逆时针。实际滤波更新中,还会使用独立的上升/下降时间常数,并对 RPM 变化率做显式裁剪。

要让这个模型真正有意义,它必须和真实平台参数保持一致,尤其包括:

  • 初始旋翼转速
  • 电机惯量与时间常数
  • 推力与扭矩系数
  • 最大 RPM
  • 旋翼旋向

地面驱动执行器

地面平台使用关节化轮组与仿真器接触模型。在 MuJoCo 中,LAV2 将左右输出轴速度目标分别发送给每侧唯一的主动关节,再通过 equality 约束同步主动轮与承重轮组;ATMO 同样每侧只使用一个闭环速度伺服器,并用 equality 约束表示前后轮壳之间的同步带传动。

Isaac Lab 沿用相同的二维侧速度目标和“每侧一个主动关节”契约。当前 LAV2 与 ATMO USD 仍需后续补齐与 MJCF 一致的关节拓扑和机械耦合;不能通过向从动关节重复下发 ActionTerm 目标来替代资产级耦合。

这样可以明确分离控制器、actuator 与接触职责:DifferentialDriveController 负责底盘级命令分配,平台适配层把每侧目标映射到物理关节,速度伺服器按配置的增益与力矩上限输出,物理引擎负责求解轮地作用力。当命令是轮速时,速度伺服增益是闭环跟踪增益,不能用开环 DC 电机的转矩—转速斜率代替。

状态与命令约定

所有控制器与轨迹接口使用字典形式的状态与目标对象。所有状态数组均为批量形式,带有一个前导环境维度 N(num_envs)。整个控制栈使用的字典键如下:

形状 单位 描述
pos (N, 3) m 世界坐标系位置
vel (N, 3) m/s 世界坐标系速度
vel_b (N, 3) m/s 机体系速度
att_euler (N, 3) rad 横滚、俯仰、偏航(XYZ 内旋)
att_quat (N, 4) 四元数(xyzw)
att_rotmat (N, 9) 旋转矩阵(行主序展平)
ang_vel (N, 3) rad/s 机体系角速度
thrust (N, 1) N 总推力目标

飞行状态字典包含 posvelatt_euleratt_quatatt_rotmatang_vel。地面控制器状态字典包含 posatt_eulervel_bang_vel(注意此处使用 vel_b 而非 vel)。

飞行与地面控制器都遵循 ControllerBase 的更新签名:update(target: dict, state: dict) -> ArrayLikecontrol_mask 字典控制哪些目标通道由外部提供、哪些由级联内部生成。

N = 1(单环境)时,批量形状退化为 (1, 3)(1, 4) 等。lav2/dynamics/numpy/ 下的遗留 NumPy 实现使用非批量形状(如 (3,)(4,)),且不与 Array API 兼容。

明确上述字典约定之后,再去阅读本地模拟器、控制器栈和各类任务封装会容易很多。

并行后端一致性

lav2/dynamics/ 下的顶层模块是后端无关的 Array API 实现——通过 self._xp 分发,单一代码库即可服务于 NumPy、Torch、JAX 和 CuPy。numpy/torch/ 子包是保留用于基准测试的遗留参考实现;新增动力学模块应以 Array API 顶层为目标。

API 交叉引用