4. 控制周期与实时性:控制频率的选择,RTOS任务优先级配置,通信延迟对抖动的影响
聊到人形机器人的抖动,很多人第一反应是PID参数没调好。但说实话,我见过太多案例——PID参数已经调到极限了,机器人还是抖。这时候你该怀疑什么?
我建议你先看看控制周期和实时性。这两个东西,才是决定控制质量的地基。地基不稳,上面盖多漂亮的PID算法都没用。
4.1 控制频率怎么选?不是越快越好
很多人有个误区:控制频率越高,控制效果越好。其实不是这样。你想想看,频率太高,系统反而会出问题。
核心原则:控制频率至少要高于系统机械谐振频率的2倍,但不要超过传感器更新率的1/2。
我在项目中遇到过一台双足机器人,走路时髋关节一直抖。一开始我以为是电机齿槽转矩的问题,折腾了两天。后来一查,控制频率设了2kHz,但IMU的更新率只有500Hz。说白了,控制器在拿过时的数据做决策,不抖才怪。
具体怎么选?我一般按这个流程来:
- 摸清机械谐振频率——用手推一下关节,或者扫频测试,找到第一个谐振峰
- 确定传感器更新率——编码器、IMU、力矩传感器,取最慢的那个
- 选控制频率——在谐振频率×2 和 传感器更新率÷2 之间取一个值
- 留余量——实际用的时候,再降20%左右,给系统留点喘气的空间
| 关节类型 | 典型谐振频率 | 推荐控制频率 | 传感器限制 |
|---|---|---|---|
| 髋关节(大惯量) | 15-25 Hz | 500-800 Hz | 编码器 1kHz |
| 膝关节(中惯量) | 25-40 Hz | 800-1000 Hz | 编码器 1kHz |
| 踝关节(小惯量) | 40-60 Hz | 1000-1500 Hz | IMU 500Hz |
| 手臂末端 | 10-20 Hz | 400-600 Hz | 力矩传感器 500Hz |
我的小技巧:如果你不确定谐振频率,可以先设一个保守值(比如500Hz),然后边跑边往上提。当抖动突然变大的那一刻,你就知道临界点在哪了。
4.2 RTOS任务优先级配置——别让控制任务饿死
控制频率选好了,接下来就是怎么在RTOS里把它跑稳。我见过太多人,代码写得挺好,但任务优先级配得一塌糊涂。
举个例子。有一次我帮朋友调试一个机器人,控制周期总是忽长忽短。查了半天,发现他把通信任务优先级设得比控制任务还高。结果每次收发数据时,控制任务就被抢占了。嗯,这能不抖吗?
我个人习惯这样配优先级:
- 最高优先级:电流环/力矩环(1kHz以上,必须实时响应)
- 次高优先级:位置环/速度环(控制任务本体)
- 中等优先级:状态估计(IMU融合、关节状态更新)
- 低优先级:通信任务(CAN、EtherCAT、串口)
- 最低优先级:日志、调试、人机交互
注意:千万不要把控制任务和通信任务放在同一个优先级。我曾经吃过这个亏——两个任务同优先级,RTOS轮转调度,控制周期直接翻倍。
这里给一个FreeRTOS的配置示例,我常用的:
// 任务优先级定义
#define PRIO_CURRENT_LOOP 5 // 电流环,最高
#define PRIO_POSITION_LOOP 4 // 位置环
#define PRIO_STATE_ESTIMATE 3 // 状态估计
#define PRIO_CAN_COMM 2 // CAN通信
#define PRIO_LOGGING 1 // 日志
// 任务创建
xTaskCreate(currentLoopTask, "CurrentLoop", 256, NULL, PRIO_CURRENT_LOOP, NULL);
xTaskCreate(positionLoopTask, "PosLoop", 512, NULL, PRIO_POSITION_LOOP, NULL);
xTaskCreate(stateEstimateTask, "StateEst", 512, NULL, PRIO_STATE_ESTIMATE, NULL);
xTaskCreate(canCommTask, "CANComm", 256, NULL, PRIO_CAN_COMM, NULL);
xTaskCreate(loggingTask, "Logging", 128, NULL, PRIO_LOGGING, NULL);
还有一个容易被忽略的点——中断优先级。控制任务用的定时器中断,优先级一定要高于其他外设中断。不然定时器一响,结果被CAN中断抢了,控制周期就歪了。
4.3 通信延迟——看不见的抖动源
这个坑我踩过好几次。通信延迟,说白了就是数据从传感器到控制器、再从控制器到执行器,路上花了多少时间。这个时间如果不稳定,抖动就来了。
我举个例子。你用的是CAN总线,理论速率1Mbps。但实际跑起来,总线负载一高,帧的发送延迟就会波动。这个波动反映到控制上,就是周期抖动。
常见的通信方式及其延迟特性:
| 通信方式 | 典型延迟 | 抖动 | 适用场景 |
|---|---|---|---|
| EtherCAT | < 100 μs | < 1 μs | 高端人形机器人 |
| CAN FD | 100-500 μs | 10-50 μs | 中端机器人 |
| 普通CAN | 200-1000 μs | 50-200 μs | 低端/教育机器人 |
| RS485/Modbus | 1-5 ms | 0.5-2 ms | 不推荐用于实时控制 |
| WiFi/UDP | 1-10 ms | 1-5 ms | 仅用于远程监控 |
关键指标:通信延迟的值不是最可怕的,可怕的是抖动。一个稳定的500μs延迟,比一个波动在100-500μs之间的延迟好得多。
怎么降低通信延迟的影响?我总结了几条经验:
- 用同步模式——EtherCAT的DC模式、CAN的同步帧,都能让所有节点在同一时刻采样
- 减少总线负载——能合并的数据帧就合并,别一帧只传一个字节
- 数据预处理——在传感器端做滤波,别把原始噪声全扔到总线上
- 时间戳补偿——每个数据包带上时间戳,控制器可以根据延迟做插值
避坑指南:我曾经在CAN总线上同时跑了电机控制和传感器数据,结果总线负载到了80%。控制周期从1ms抖到了1.8ms。后来我把传感器数据改成每5ms发一次,问题就解决了。说白了,别让非实时数据挤占实时数据的带宽。
4.4 知识体系总览
下面这张图,把控制周期、RTOS优先级、通信延迟这三者的关系串起来了。你可以把它当作调试时的检查清单。
你看,这三件事其实是环环相扣的。控制频率选得再好,RTOS优先级配乱了也没用;RTOS配得再合理,通信延迟一抖,全白搭。我每次调试新机器人,都会按这个流程走一遍,基本能解决80%的抖动问题。
最后提醒一句:别一上来就调PID。先拿示波器或者逻辑分析仪,看看你的控制周期到底稳不稳。如果周期本身就在抖,调PID就是白费力气。我见过太多人在这上面浪费了一两周时间。