第四节:状态空间与动作空间设计

好,我们直接进入正题。状态空间和动作空间的设计,说白了就是定义「机器人能看到什么」和「机器人能做什么」。这两个东西没定好,后面的强化学习算法再牛也白搭。我在项目中见过太多人一上来就堆高维状态,结果训练了三天三夜,机器人还在原地打转。

4.1 本体感知状态:机器人的「身体感觉」

人形机器人要站稳、要走路,首先得知道自己身体啥姿势。这就像你闭着眼睛也能摸到鼻子——这叫本体感知。

关节角度与角速度:这是最基础的状态。每个关节的当前角度和角速度,直接反映了机器人的运动姿态。我个人习惯把关节角度归一化到[-1, 1]之间,这样神经网络收敛会快很多。

# 关节角度归一化示例
def normalize_joint_angle(angle, joint_range):
    # joint_range: [min, max]
    normalized = 2.0 * (angle - joint_range[0]) / (joint_range[1] - joint_range[0]) - 1.0
    return np.clip(normalized, -1.0, 1.0)

IMU数据:IMU提供的是躯干的姿态信息。包括三轴加速度、三轴角速度,以及通过滤波得到的欧拉角(横滚、俯仰、偏航)。

嗯,这里要注意:IMU数据噪声很大。我曾经在仿真里跑得好好的模型,一上真机就摔。后来发现是IMU的原始数据没做低通滤波。你想想看,电机振动带来的高频噪声,直接喂给策略网络,它不懵才怪。

我的经验:IMU数据建议用二阶巴特沃斯低通滤波器,截止频率设在20Hz左右。既能滤掉电机振动,又不丢失运动特征。

4.2 外部感知状态:机器人的「眼睛」

光知道自己啥姿势还不够。机器人得知道地面长啥样,不然一脚踩空就摔了。

地形高度扫描:这是我最常用的外部感知方式。用一个2D或3D的高度图,表示机器人周围的地形起伏。

举个例子:在机器人前方扫描一个5×5的网格,每个格子代表该位置的地面高度。这样策略网络就能「看到」前面有个台阶,或者有个坑。

扫描参数 典型值 说明
扫描范围 1.5m × 1.0m 前方1.5米,左右各0.5米
网格分辨率 0.1m 太密了计算量大,太稀了看不清细节
网格数量 15 × 10 = 150 这个维度对策略网络来说刚刚好

为什么会用网格而不是直接用点云?说白了,网格是结构化数据,CNN或者MLP处理起来更顺手。点云虽然信息更丰富,但处理起来麻烦得多。

避坑指南:我曾经把地形扫描范围设得太大(3米),结果机器人总想「看」太远的地方,反而忽略了脚下。后来我把范围缩小到1.5米,训练效率直接翻倍。记住:机器人不需要知道十米外的地形,它只需要知道下一步踩哪里。

4.3 动作空间设计:机器人如何「行动」

动作空间决定了机器人能做什么动作。在人形机器人领域,最常用的动作空间是PD目标位置。

什么叫PD目标位置?就是每个关节的PD控制器(比例-微分控制器)的目标角度。策略网络输出的是「我希望这个关节转到什么角度」,然后底层的PD控制器去执行。

# 动作空间定义示例
class ActionSpace:
    def __init__(self, num_joints=12):
        # 每个关节的目标位置范围(弧度)
        self.joint_limits = {
            'hip_roll': [-0.5, 0.5],
            'hip_pitch': [-1.2, 1.2],
            'knee_pitch': [0.0, 2.5],
            'ankle_pitch': [-0.8, 0.8]
        }
        self.action_dim = num_joints
        
    def clip_action(self, action):
        # 将动作限制在安全范围内
        return np.clip(action, -1.0, 1.0)

我个人习惯把动作空间归一化到[-1, 1]之间。这样策略网络输出的动作值天然就在这个范围,再映射到实际的关节角度范围。好处是网络更容易学习,不会因为关节范围差异大而导致梯度爆炸。

4.4 状态与动作的「组合拳」

把上面这些拼起来,就构成了完整的观测空间。我一般这样组织:

  • 本体状态:关节角度(12维) + 关节角速度(12维) + IMU数据(6维) = 30维
  • 外部状态:地形高度扫描(150维)
  • 历史状态:前3步的本体状态(90维) —— 这个很重要,单帧状态信息不够

总状态维度:30 + 150 + 90 = 270维。动作空间:12维(12个关节的目标位置)。

核心原则:状态空间要「够用但不过剩」。270维是我在多个项目中验证过的平衡点。维度太少,机器人学不会复杂地形;维度太多,训练时间成倍增加。

4.5 知识体系总览

下面这张图总结了状态空间与动作空间的核心逻辑。我画这张图的时候,脑子里想的就是「机器人怎么感知世界,怎么做出反应」。

状态空间与动作空间设计 状态空间 (Observation) 本体感知状态 关节角度(12) + 角速度(12) + IMU(6) 外部感知状态 地形高度扫描(150维网格) 策略网络 输入: 270维状态 动作空间 (Action) PD目标位置 12个关节目标角度 动作归一化 输出范围 [-1, 1] 关键设计原则 1. 状态维度要「够用但不过剩」:270维是经验平衡点 2. 归一化是必须的:关节角度、IMU数据都要归一化到[-1,1] 3. 历史状态很重要:单帧信息不够,至少保留前3步 4. 动作空间要安全:用PD控制器做底层保护,防止输出危险角度 5. 地形扫描范围要合理:1.5米足够,太远反而干扰决策

你看这张图,从左到右就是机器人的「感知-决策-行动」闭环。状态空间是输入,动作空间是输出,中间的策略网络负责把感知映射成行动。

一个小技巧:刚开始训练时,可以先用简单的状态空间(比如只保留本体感知),等机器人学会基本站立和行走后,再逐步加入地形扫描。这样训练过程更可控,也更容易定位问题。

好了,状态空间和动作空间的设计就讲到这里。记住:好的设计能让训练事半功倍,坏的设计能让你的GPU烧到冒烟也学不会。下次我们聊聊奖励函数的设计——那才是真正考验功力的地方。

可可精品资料库