路径:include/ctrl/power_manager.h、src/ctrl/power_manager.cpp、src/ctrl/power_feedback.cpp。
成熟度:功率模型、按轮分配、能量反馈、可选 RLS 和最终电流限制已接入软件调用链;模型参数、实测功率、动态响应和实车规则边界尚未标定或上机验证。
运行时 power 直接使用 ctrl::power_manager::info_type,经语义预检后在 Robot 初始化之后、事件循环启动之前 init()。不配置 power 或设置 enabled: false 时不做模型限功率,NoForce 和输入无效时的零输出仍保留。
motion_control::task() 每轮在整机状态和失联门后调用功率策略;它读取底盘抽象的 wheel_motors(),顺序固定为左前、右前、左后、右后。底盘设备只提供实际绑定的电机和运动学,不依赖控制层,也不读取裁判或超容。算法没有额外线程、阻塞等待或私有全局机器人状态;每次为固定四轮做有界计算,继承运动控制协程的周期。
完整输出链为:
底盘轮速目标 → 电机速度 PID → requested_current()
→ power_manager 按轮分配 → motor_base::set_current_limit()
→ DJI current() 的绝对限幅、使能/在线门 → DJI 电机组编码发送
输出限制写入电机最终电流通道,不会重新写速度目标冒充限功率。分配后、组发送前即使 PID 又改变原始电流,绝对上限仍然有效;单独使用比例因子不能保证这一点。NoForce、无效 dt、任一轮离线、缺失电机或不支持电流控制时,四轮上限均为零。驱动本身的禁用和离线门仍优先于上限。电机实际速度在两次策略更新之间变化时,模型功率也会变化;此软件边界不构成连续时间物理功率保证。
旧工程 src/chassis/power_controller.cc 使用原始反馈 RPM 转出的转子角速度,模型为:
P = tau * omega + k1 * abs(omega) + k2 * tau^2 + k3
其 M3508 减速比 g = 3591 / 187,转子力矩每原始电流单位为 0.3 / g * 20 / 16384。新驱动的 angle_speed() 为减速后输出轴 rad/s,因此默认参数做代数换算:
| 新参数 | 默认来源 | 单位语义 |
|---|---|---|
torque_per_current |
0.3 * 20 / 16384 |
输出轴 Nm / 原始电流指令单位 |
speed_loss |
0.22 * g |
W / (输出轴 rad/s) |
torque_loss |
1.2 / g² |
W / (输出轴 Nm)² |
constant_loss |
2.78 |
四轮总固定损耗 W |
测试验证换算前后同一物理状态的模型值一致。这些数值是源码可追溯的初值,不是新的功率计标定结果;尤其旧速度损耗项换算后较大,可能在不高的轮速下就耗尽默认预算。不能为使机器人运动而无依据地减小系数。实际不同电机或减速器必须配置相应模型。
旧分配误差把轮速目标 m/s 与转子角速度 rad/s 相减,量纲不一致;新误差为输出轴目标和反馈 rad/s 之差。error_weight_low/high 明确配置为 rad/s,默认 1/2 是新软件策略阈值,不能声称继承了旧 15/20 的物理含义。
按轮分配保留“速度误差权重与需求功率权重混合”的业务意图。先扣除四轮速度损耗和固定损耗,再以最多五轮有界分配重新分配未用预算,最后求电流绝对值的二次方程。每轮电流只缩小,不反向、不放大,也不超过驱动上限。
分配使用 abs(tau * omega) 的保守包络,不以某轮制动再生抵扣另一轮耗电;因此当前符号改变也不能借用虚构的再生预算。该包络是对当前配置模型的约束,不能消除传感延迟或错误模型造成的物理误差。
当零电流时的速度损耗和固定损耗已经超过预算,算法令全部电流为零,设置 budget_unachievable,并保留非零的模型损耗供遥测读取。不会把电机滑行或固定损耗宣称为零功率。
控制层每轮独立检查裁判机器人状态、功率缓冲字段和超容反馈的新鲜度。新鲜裁判功率上限优先于超容回显;两者都失联使用显式 offline_power_limit,该值不得超过 configured_power_limit。默认配置与离线上限均为 35 W,只是保守软件初值,不是当前赛事规则推导。max_cap_boost 默认 0,显式增加放电预算也不会抬高发给超容的充电输入上限。
有健康超容时使用旧协议的能量索引 0..255,默认基础/满能量目标为 100/250;该索引不是焦耳。无超容但有新鲜裁判缓冲时使用缓冲能量 J,默认 50/60。能量环继续比较能量平方根,目标值、增益均为配置。旧 kd=0.2 按 1 ms 调用步换算为秒制 0.0002;周期抖动通过实际 dt_seconds 处理,来源切换清除导数历史。能量不足时允许预算降至零,不复制旧最低功率强制下限。
每轮 co_await super_cap::set() 刷新控制命令;超容自身定时重发并独立检查命令超时、反馈超时和错误位。NoForce 时关闭超容。发往超容的输入上限取新鲜裁判值或离线配置值,由超容驱动再次执行设备上限。
旧裁判功率热量结构前八个字节明确命名为保留字段;本迁移不把它们猜测成实测功率。RLS 只接受健康超容提供的底盘实测功率。
rls_enabled 默认 false。开启后,周期策略使用四轮反馈原始电流和输出轴角速度构造 sum(abs(omega))、sum(tau²),实测功率扣除带符号机械功率和固定损耗后估计两个非负损耗系数。参数增量和协方差先在临时状态中计算,只有全部有限、协方差有效且处于配置范围时才提交。
RLS 仅消耗新的超容有效反馈序号;运动控制多次读到同一报文不会重复学习。实测功率不大于 5 W、负损耗、无激励、离线、NoForce 或无效电机样本不会更新。rls_period 是最短更新间隔;这不是一个阻塞守护线程。它尚未验证实物测量同步或闭环收敛,应在台架完成电流/速度/功率采样对齐后启用。
chassis_base::info_type::wheel_directions 顺序为 LF/RF/LR/RR,取值只能为 ±1;utils::kinematics::mecanum_motor_targets() 在统一比例限速后施加这些符号。未填字段时默认 {1,-1,1,-1} 保留迁移前目标仓库行为;迁移配置显式填写 {-1,1,-1,1},恢复旧工程同坐标输入的四轮最终目标。
旧工程轮数组顺序为 id1 左前、id2 右前、id3 右后、id4 左后。按新 LF/RF/LR/RR 顺序,旧最终目标为 {-x+y+w, x+y+w, -x-y+w, x-y+w}。不能只按数组索引比较后轮。测试覆盖三个基轴、混合输入、限速比例和 NaN 清零;符号的源码等价性不代表接线方向已验证。
tests/power_control_tests.cpp 覆盖模型单位转换、对称与随机四轮限功率、能量环切换、RLS 新鲜序号、NaN/无效周期/失联/NoForce,以及绑定假电机上的实际发送电流门。假电机调用与 DJI/M9025 相同的 motor_protocol::gated_current();在分配后将 PID 请求从 1000 放大到 ±20000,编码电流仍受原分配上限限制。该测试不构造 CAN。
本次按用户要求没有执行 xmake,也没有运行机器人或 start.sh。使用直接 clang++ 构建并运行纯测试;另对功率遥测协程与底盘设备做语法编译检查。没有 Linux 主目标链接、总线、超容硬件、功率计或实车验证。