一、qmini 网络输出内容分析

1.1 固定配置

1.1.1 网络输出维度(12维)

  • 前2维:步态相位频率 (0.5~3.5 Hz)
  • 后10维:关节位置增量速度 (-13.5~13.5 rad/s)

1.1.2 控制流程

  1. 网络推理:输出12维数据,范围 [-1, 1]

  2. 输出转换 (rl_controller.cpp 第211-224行):

    • 将 [-1,1] 映射到实际物理量
    • 后10维映射为位置增量速度 [-13.5, 13.5] rad/s
  3. 增量累加 (rl_controller.cpp 第75-82行):

    1
    joint_act.segment(0, NUM_ACTUAT_JOINTS) += increment.segment(NUM_LEGS, NUM_ACTUAT_JOINTS) * _rl_time_step;

    增量乘以时间步长后累加到 joint_act(关节目标位置)

  4. 发送电机命令 (rl_controller.cpp 第162-181行):

    1
    2
    motor_command_tmp.q_target[i] = joint_act[...];  // 目标位置
    motor_command_tmp.dq_target[i] = 0.; // 目标速度为0

1.1.3 结论

网络输出的是位置增量速度,经过积分后变成位置,最终以位置控制方式发送给电机。电机工作在 FOC 模式下,通过 PD 控制器(kp, kd)跟踪目标位置。

二、输入电机信息

根据 rl_controller.cpp 第162-181行的 set_rl_joint_act2dds_motor_command 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// source/user/rl_controller.cpp
void RLController::set_rl_joint_act2dds_motor_command(char mode) {
MotorCommand motor_command_tmp;
for (int i = 0; i < NUM_JOINTS; ++i) {
motor_command_tmp.q_target[i] = joint_act[jointIndex2Sim[i]];
if (mode=='q') {
motor_command_tmp.kp[i] = 0.;
motor_command_tmp.kd[i] = 0.;
} else if (mode=='1') {
motor_command_tmp.kp[i] = _kp_soft[jointIndex2Sim[i]];
motor_command_tmp.kd[i] = _kd_soft[jointIndex2Sim[i]];
}
else {
motor_command_tmp.kp[i] = _kp[jointIndex2Sim[i]];
motor_command_tmp.kd[i] = _kd[jointIndex2Sim[i]];
}
motor_command_tmp.tau_ff[i] = 0.;
motor_command_tmp.dq_target[i] = 0.;
}
dds_motor_command->SetData(motor_command_tmp);
}

电机命令包含 5 个值(每个关节):

参数 含义 代码中的值
q_target 目标位置 (rad) joint_act[i] 即网络输出累积的关节位置
dq_target 目标速度 (rad/s) 0. - 固定为0
kp 位置刚度 根据模式选择 _kp_kp_soft
kd 速度阻尼 根据模式选择 _kd_kd_soft
tau_ff 前馈力矩 (Nm) 0. - 固定为0

电机控制公式(PD控制):

$$\tau = k_p \cdot (q_{target} - q) + k_d \cdot (dq_{target} - dq) + \tau_{ff}$$

由于 dq_target=0tau_ff=0,实际简化为:

$$\tau = k_p \cdot (q_{target} - q) - k_d \cdot dq$$