turtlebot3-burger_150.png
turtlebot3-waffle-pi_150.png
turtlebot3-arm_150.png
walking-y2_150.png
turbot3-multi_150.png
turbot3-dl-ros1_150.png
turbot3-ai.png
turbot3-dl-ros2_150.png
turbot3-slam_150.png
turbot3-arm_150.png
turtlebot4-lite_150.png
turtlebot4-pro_150.png
turbot4-dl_150.png
turbot4-ai_150.png
aidriving-racebot_150.png
aidriving-autodrive_150.png
turtlebot-arm_150.png
openmanipulator-x_150.png
Home » OpenDuckMini强化学习框架入门教程 » OpenDuckMini强化学习框架入门教程-工具类

OpenDuckMini强化学习框架入门教程-工具类

纠错,疑问,交流: 请进入讨论区请点击进入页面,扫码加入微信群或Q群进行交流

获取最新文章: 扫一扫加入“创客智造”公众号

欢迎加入我们的openduckmini交流群,微信扫描右侧二维码立即进群交流

群二维码

工具类

  • 理解和使用相关便利工具

概述

工具类模块(playground/common/utils.py)提供了一些辅助功能,主要用于动作后处理和信号滤波。目前主要包含一个 LowPassActionFilter 类,用于平滑策略输出的动作。

LowPassActionFilter

作用

对策略输出的动作信号进行低通滤波,消除高频抖动,使动作更平滑、更自然。

原理

使用一阶低通滤波器(也称为指数平滑):

动作_filtered(t) = alpha * 动作_filtered(t-1) + (1 - alpha) * 动作_raw(t)

其中:
alpha = cutoff_freq / (cutoff_freq + control_freq)

类定义

class LowPassActionFilter:
    def __init__(self, control_freq, cutoff_frequency=30.0):
        self.last_action = 0
        self.current_action = 0
        self.control_freq = float(control_freq)
        self.cutoff_frequency = float(cutoff_frequency)
        self.alpha = self.compute_alpha()

参数

参数 默认值 说明
control_freq (构造时传入) 控制频率 (Hz)
cutoff_frequency 30.0 Hz 截止频率,高于此的频率分量被衰减

方法

def compute_alpha(self):
    """计算滤波系数 alpha"""
    return (1.0 / self.cutoff_frequency) / (
        1.0 / self.control_freq + 1.0 / self.cutoff_frequency
    )

def push(self, action):
    """推送新的原始动作"""
    self.current_action = action

def get_filtered_action(self):
    """获取滤波后的动作"""
    self.last_action = (
        self.alpha * self.last_action + 
        (1 - self.alpha) * self.current_action
    )
    return self.last_action

使用示例

from playground.common.utils import LowPassActionFilter

# 创建滤波器 (50 Hz 控制频率, 37.5 Hz 截止频率)
action_filter = LowPassActionFilter(50, cutoff_frequency=37.5)

# 在控制循环中使用
action_filter.push(raw_action)
smoothed_action = action_filter.get_filtered_action()

频率响应

控制频率 截止频率 alpha 效果
50 Hz 37.5 Hz 0.429 中度平滑
50 Hz 25 Hz 0.333 较强平滑
50 Hz 10 Hz 0.167 强力平滑

其他辅助功能

plot_saved_obs.py

用于分析推理过程中保存的观测数据:

# 推理后保存观测 (由 mujoco_infer.py 自动完成)
pickle.dump(self.saved_obs, open("mujoco_saved_obs.pkl", "wb"))

# 使用 plot_saved_obs.py 分析

动作处理策略

Open Duck Playground 提供了三种动作处理方式:

1. 低通滤波

使用 LowPassActionFilter 平滑动作:

# 在 joystick.py 中 (已注释)
self.action_filter = LowPassActionFilter(1/0.02, cutoff_frequency=37.5)
action_filter.push(action_w_delay)
action = action_filter.get_filtered_action()

2. 电机速度限制

限制每步关节位置的最大变化量(当前默认方式):

motor_targets = clip(
    motor_targets,
    prev_motor_targets - max_motor_velocity * dt,
    prev_motor_targets + max_motor_velocity * dt,
)

3. 动作变化率代价

通过奖励函数 cost_action_rate 间接鼓励平滑动作:

cost_action_rate = sum(square(action - last_action))

三种方式的对比

方式 训练中 推理中 效果
低通滤波 已注释 已注释 直接平滑,可能引入延迟
速度限制 启用 (USE_MOTOR_SPEED_LIMITS=True) 启用 限制最大变化率,无延迟
动作代价 始终启用 N/A 间接鼓励,但不强制

常量定义

playground/open_duck_mini_v2/constants.py 提供机器人特定的常量和辅助函数:

# 路径
ROOT_PATH = epath.Path(__file__).parent
FLAT_TERRAIN_XML = ROOT_PATH / "xmls" / "scene_flat_terrain.xml"
# ...

# 任务到 XML 的映射
def task_to_xml(task_name):
    return {"flat_terrain": ..., "rough_terrain": ...}[task_name]

# 关节信息
JOINTS_ORDER_NO_HEAD = [
    "left_hip_yaw", "left_hip_roll", "left_hip_pitch",
    "left_knee", "left_ankle",
    "right_hip_yaw", "right_hip_roll", "right_hip_pitch",
    "right_knee", "right_ankle",
]

# 传感器名称
GRAVITY_SENSOR = "upvector"
GYRO_SENSOR = "gyro"
# ...

JAX 编译缓存

BaseRunner 初始化时配置了 JAX 编译缓存:

os.makedirs(".tmp", exist_ok=True)
jax.config.update("jax_compilation_cache_dir", ".tmp/jax_cache")
jax.config.update("jax_persistent_cache_min_entry_size_bytes", -1)
jax.config.update("jax_persistent_cache_min_compile_time_secs", 0)

这显著加速了重复训练,因为 JAX 的 XLA 编译结果会被缓存到磁盘。

纠错,疑问,交流: 请进入讨论区请点击进入页面,扫码加入微信群或Q群进行交流

获取最新文章: 扫一扫加入“创客智造”公众号

欢迎加入我们的openduckmini交流群,微信扫描右侧二维码立即进群交流

群二维码

标签: OpenDuckMini强化学习框架