膝关节肌肉骨骼仿真与轨迹跟踪控制 (mujoco_musculoskeletal_knee_tracking)

模块归属:肌肉骨骼人 / 下肢 · 功能:控制 运行环境:Ubuntu 22.04 + ROS 2 Humble + Python 3.10 + MuJoCo 3.16.0

本模块使用 MuJoCo 建立单关节膝关节肌肉骨骼模型,以屈肌(腘绳肌近似)/ 伸肌(股四头肌近似) 两条拮抗肌肉驱动胫骨,通过 PD 控制器实现正弦 / 阶跃轨迹跟踪,并发布关节角、肌肉激活与实际力矩。适合用于理解"肌肉如何通过肌腱驱动机器人关节、PD 控制器如何跟踪轨迹"。

1. 原理 (Theory)

1.1 肌肉骨骼模型

  • 股骨(femur):固定于髋端,向下延伸;胫骨(tibia) 通过 knee 铰链关节(绕 x 轴)连接,可屈伸。
  • 两条拮抗肌肉通过肌腱(tendon) 驱动关节:
  • 屈肌(flexor):激活时产生屈曲(关节角增大);
  • 伸肌(extensor):激活时产生伸展(关节角减小)。
  • 肌腱绕过关节处的 wrap 圆柱(knee_wrap),提供恒定正力矩臂,避免肌腱在屈曲大角度时长度趋零引发的非物理被动力。

1.2 坐标约定

  • 0° = 完全伸展(小腿竖直下垂,自然平衡);
  • 正角 = 屈曲;关节限位 -15° ~ 90°,建议控制轨迹 10° ~ 70°。

1.3 PD 控制器 → 拮抗肌肉激活

记误差 e = θ_desired − θ_actual,关节角速度 q̇:

τ = kp·e − kd·q̇

所需力矩 τ 归一化到肌肉激活(max_torque 为肌肉等效最大力矩):

若 τ ≥ 0 (需屈曲):  flexor = clamp(τ / max_torque),  extensor = 0
若 τ < 0 (需伸展):  extensor = clamp(−τ / max_torque), flexor = 0

另含两类安全保护:数值检查(非法输入 → 激活归零)与双向限位保护(到 90° 上限仍要屈曲 → 停屈肌;到 −15° 下限仍要伸展 → 停伸肌)。

2. 接口 (Interfaces)

话题 类型 方向 说明
knee/reference std_msgs/Float64 订阅 目标角度 [deg],外部下发可覆盖内置轨迹
knee/angle std_msgs/Float64 发布 当前关节角 [deg]
knee/activation std_msgs/Float64MultiArray 发布 [flexor, extensor] 激活
knee/torque std_msgs/Float64 发布 执行器广义力 [N·m]

3. 配置 (Configuration)

见 config/params.yaml:

参数 默认 说明
sim.dt 0.005 仿真步长 [s],会写入 model.opt.timestep
sim.duration 30.0 内置轨迹时长 [s]
trajectory.type sine sine | step
trajectory.amplitude_deg 40.0 轨迹幅值 [deg]
trajectory.frequency_hz 0.4 正弦频率 [Hz]
trajectory.bias_deg 30.0 轨迹偏置 [deg]
ctrl.kp 30.0 比例增益 [N·m/rad]
ctrl.kd 3.0 微分增益 [N·m·s/rad]
ctrl.max_torque 17.5 肌肉等效最大力矩 [N·m],= 单肌 500 N × wrap 半径 0.035 m
ctrl.limit_deg 90.0 屈曲上限 [deg]
ctrl.limit_low_deg -15.0 伸展下限 [deg]
sim.exit_after_duration false true:内置轨迹跑完后节点自动退出

关于 sim.duration:内置轨迹跑满 duration 后节点执行安全停止(激活归零,关节回落到下垂位)。 一旦收到 /knee/reference 外部目标,就切换到外部跟踪模式,不再受 duration 限制。

4. 依赖与构建 (Dependencies & Build)

# Python 依赖(MuJoCo 通过 pip 安装,不是 rosdep key)
python3 -m pip install -r requirements.txt

cd ~/ros2_ws/src
git clone <模块仓库> mujoco_musculoskeletal_knee_tracking
cd ~/ros2_ws
colcon build --packages-select mujoco_musculoskeletal_knee_tracking
source install/setup.bash

5. 运行 (Run)

# 推荐: launch
ros2 launch mujoco_musculoskeletal_knee_tracking main.launch.py

# 或: 直接运行
ros2 run mujoco_musculoskeletal_knee_tracking mujoco_musculoskeletal_knee_tracking_node

查看输出:

ros2 topic echo /knee/angle
ros2 topic echo /knee/activation
ros2 topic echo /knee/torque

外部下发目标角度(覆盖内置正弦轨迹):

ros2 topic pub /knee/reference std_msgs/Float64 "{data: 50.0}" --once

6. 离线演示 (Offline demo)

不依赖 ROS 2,直接生成运行效果 GIF / 评价图 / 指标:

python3 simulate_tracking.py               # 带图形环境:生成 GIF + 曲线 + 指标
python3 simulate_tracking.py --no-render   # 无图形/远程环境:只出曲线与指标

输出(默认写到 results/):tracking.gif(< 5 MB)、tracking_eval.png(正弦段)、tracking_step.png(阶跃段)、tracking_metrics.txt。

simulate_tracking.py 与 validate_model.py 的参数统一从 config/params.yaml 读取,改一处即同时生效。

7. 运行效果 (Results)

正弦轨迹跟踪(bias=30°、幅值 40°、0.4 Hz、PD kp=30 kd=3):

轨迹跟踪评价

轨迹跟踪动图

阶跃响应(20° → 50°,用于给出超调与调节时间):

阶跃响应

8. 数据与评价 (Data & Metrics)

指标分两段,口径不同:

正弦段(bias=30°、amp=40°、0.4 Hz)——参考持续变化,不存在超调/调节时间,只报告:

  • RMSE:角度误差均方根;
  • 最大绝对误差。

阶跃段(20° → 50°)——用于给出超调、调节时间与稳态误差:

  • 超调:相对阶跃幅值的百分比;
  • 调节时间:进入并保持在 ±2% 带宽内的时间;
  • 稳态误差:末段平均值与目标之差。

默认参数(PD kp=30 kd=3,max_torque=17.5 N·m)结果:

指标 数值
正弦 RMSE 8.65°
正弦最大绝对误差 13.96°
阶跃超调 0.0 %
阶跃调节时间 未进入 ±2% 带(进入 ±5° 需 0.22 s)
阶跃稳态误差 −6.62°(低于目标)

稳态下垂的主因是重力矩未做前馈补偿:PD 在误差为 0 时输出为 0,维持屈曲姿态所需的重力矩只能靠残余误差换取。正弦段的 RMSE 同样以重力矩偏差为主,PD 的相位滞后作为叠加因素。

9. 故障处理 (Troubleshooting)

现象 可能原因 处理
关节不运动 mujoco 未安装 python3 -m pip install -r requirements.txt
跟踪幅值明显不足 kp 过小或 max_torque 过大 增大 kp,确认 max_torque 约等于肌肉实际最大力矩(本模型 = 500 N × 0.035 m = 17.5 N·m)
高频振荡 kd 不足 增大 kd
触到限位剧烈冲击 轨迹幅值过大 控制轨迹保持在 10°~70° 内
模型无法加载(中文路径) 文件路径含特殊字符 用 from_xml_string 读取(本模块已内置),或使用纯英文路径
远程/无图形环境报 OpenGL 错误 无渲染后端 加 --no-render,或设置 MUJOCO_GL=egl

10. 附:本地验证 (Local validation)

python3 validate_model.py               # 含渲染
python3 validate_model.py --no-render   # 无图形环境

验证:模型可加载、单独激活屈肌→屈曲、单独激活伸肌→伸展、无控制→0° 平衡、双向限位生效,并(可选)输出 results/model_render.png。

单元测试覆盖控制器纯逻辑与模型集成(模型加载、屈肌/伸肌方向、关节限位、max_torque 与模型参数一致性):

python3 -m pytest test -q

本模块开发过程中使用了大模型辅助(代码生成与调试),并对提交内容负责。