11.5 运动控制算法
OpenLoong-Dyn-Control 项目提供了一套基于 MPC(模型预测控制)和 WBC(全身体控制)的仿人机器人运动控制框架,可部署在 MuJoCo 仿真平台上。该框架基于上海人形机器人创新中心的青龙机器人模型,支持行走、跳跃及盲踩障碍物等运动示例,实物样机已验证了相关功能。其设计特点包括易部署(依赖简化)、可扩展(分层模块化)以及易理解(代码逻辑清晰),非常适合二次开发。
11.5.1 机器人的站立与行走
核心文件 walk_wbc.cpp 位于 demo 目录下,负责实现从站立到行走的完整仿真流程。程序加载模型并初始化 UI 控制器、动力学求解器、WBC 优先级控制器及步态调度器等模块,通过仿真循环推进时间步。在循环中,系统更新传感器数据与机器人状态,经状态估计、运动学动力学计算后,由 WBC 求解关节控制量,结合 PVT 控制生成力矩指令。此外,还包含足端放置规划、期望速度生成及仿真数据记录等功能,支持可视化交互以监控行走过程。
模型加载与初始化
首先,我们需要创建错误信息缓冲区并初始化默认提示文本,随后调用 MuJoCo 的 mj_loadXML 函数加载指定路径的仿真场景 XML 模型文件。这里传入错误缓冲区是为了捕获加载异常。基于加载完成的 mjModel 实例,调用 mj_makeData 创建对应的 mjData 仿真数据结构,用于存储仿真过程中的关节位置、力等动态数据,为后续行走仿真搭建基础的模型和数据载体。
// 错误信息缓冲区,初始值为"无法加载二进制模型"
char error[1000] = "无法加载二进制模型";
// 加载 MuJoCo 仿真场景的 XML 模型文件,参数:模型路径、虚拟文件系统、错误缓冲区、缓冲区长度
mjModel* mj_model = mj_loadXML("../models/scene_board.xml", 0, error, 1000);
// 创建与模型对应的仿真数据结构,存储仿真过程中的动态数据(如关节位置、力等)
mjData* mj_data = mj_makeData(mj_model);
主函数入口与模块实例化
接下来是程序入口 main 函数,这里实例化了机器人行走仿真所需的核心控制模块,包括 UI 控制器、数据接口、运动学动力学求解器、WBC 控制器和步态调度器等。同时初始化机器人站立腿长、期望前进速度等物理参数与步态规划参数,定义足端/手部期望位姿变量并求解腿部逆运动学,最后初始化 WBC 控制器初始关节位置。为数据日志记录器注册仿真时间、电机状态、基链接位姿等需记录的变量及维度,完成仿真前的全量参数与模块初始化工作。
//************************
// 主函数:程序入口
int main(int argc, const char** argv) {
// 初始化各类核心控制类实例
UIctr uiController(mj_model, mj_data); // MuJoCo 的 UI 控制器(负责仿真可视化、交互)
MJ_Interface ;
;
;
;
;
;
FootPlacement footPlacement;
;
;
;
stand_legLength = ;
foot_height = ;
xv_des = ;
RobotState.width_hips = ;
footPlacement.kp_vx = ;
footPlacement.kp_vy = ;
footPlacement.kp_wz = ;
footPlacement.stepHeight = ;
footPlacement.legLength = stand_legLength;
model_nv = kinDynSolver.model_nv;
;
;
;
;
;
;
Eigen::Vector3d fe_l_pos_L_des = {, , -stand_legLength};
Eigen::Vector3d fe_r_pos_L_des = {, , -stand_legLength};
Eigen::Vector3d fe_l_eul_L_des = {, , };
Eigen::Vector3d fe_r_eul_L_des = {, , };
Eigen::Matrix3d fe_l_rot_des = ((), (), ());
Eigen::Matrix3d fe_r_rot_des = ((), (), ());
Eigen::Vector<, > hd_l_des = {, , , , , , };
Eigen::Vector<, > hd_r_des = {, , , , , , };
resLeg = kinDynSolver.(fe_l_rot_des, fe_l_pos_L_des, fe_r_rot_des, fe_r_pos_L_des);
Eigen::VectorXd qIniDes = Eigen::VectorXd::(mj_model->nq, );
qIniDes.(, , mj_model->nq - , ) = resLeg.jointPosRes;
qIniDes.(, , , ) = hd_l_des;
qIniDes.(, , , ) = hd_r_des;
WBC_solv.(qIniDes, RobotState.q);
logger.(, );
logger.(, model_nv - );
logger.(, model_nv - );
logger.(, );
logger.(, );
logger.(, );
logger.(, );
logger.(, );
logger.(, );
logger.(, );
logger.();
}



