/** * @file m20_policy_runner.hpp * @brief m20_policy_runner * @author Bo (Percy) Peng * @version 1.0 * @date 2025-11-07 * * @copyright Copyright (c) 2025 DeepRobotics * */ #pragma once #define PI 3.14159265358979323846 #include "policy_runner_base.hpp" #include #include #include #include #include class M20PolicyRunner : public PolicyRunnerBase { private: VecXf kp_, kd_; VecXf dof_default_eigen_policy, dof_default_eigen_robot; Vec3f max_cmd_vel_, gravity_direction = Vec3f(0., 0., -1.); VecXf dof_pos_default_; timespec system_time; const int motor_num = 16; const int observation_dim = 57; const int action_dim = 16; float agent_timestep = 0.02; float current_time; bool is_fallen = true; VecXf joint_pos_rl = VecXf(action_dim);// in rl squenece VecXf joint_vel_rl = VecXf(action_dim); const std::string policy_path_; float omega_scale_ = 0.25; float dof_vel_scale_ = 0.05; VecXf imu_w_eigen, base_acc_eigen, motor_p_eigen, motor_v_eigen, current_action_eigen, last_action_eigen, current_observation_, projected_gravity, tmp_action_eigen; RobotAction robot_action; std::vector robot_order = { "fl_hipx_joint", "fl_hipy_joint", "fl_knee_joint", "fl_wheel_joint", "fr_hipx_joint", "fr_hipy_joint", "fr_knee_joint", "fr_wheel_joint", "hl_hipx_joint", "hl_hipy_joint", "hl_knee_joint", "hl_wheel_joint", "hr_hipx_joint", "hr_hipy_joint", "hr_knee_joint", "hr_wheel_joint"}; std::vector policy_order = { "fl_hipx_joint", "fl_hipy_joint", "fl_knee_joint", "fr_hipx_joint", "fr_hipy_joint", "fr_knee_joint", "hl_hipx_joint", "hl_hipy_joint", "hl_knee_joint", "hr_hipx_joint", "hr_hipy_joint", "hr_knee_joint", "fl_wheel_joint", "fr_wheel_joint", "hl_wheel_joint", "hr_wheel_joint", }; std::vector action_scale_robot = {0.125, 0.25, 0.25, 5, 0.125, 0.25, 0.25, 5, 0.125, 0.25, 0.25, 5, 0.125, 0.25, 0.25, 5}; Ort::SessionOptions session_options_; Ort::Session session_{nullptr}; Ort::Env env_; std::vector robot2policy_idx, policy2robot_idx; const char* input_names_[1] = {"obs"}; // must keep the same as model export const char* output_names_[1] = {"actions"}; VecXf command; Ort::MemoryInfo memory_info{nullptr}; const std::array input_observationShape = {1, observation_dim}; float time_step = 0.; int stop_count = 1000; public: M20PolicyRunner(const std::string &policy_name, const std::string &policy_path) : PolicyRunnerBase(policy_name), policy_path_(policy_path),env_(ORT_LOGGING_LEVEL_WARNING, "M20PolicyRunner"), session_options_{}, session_{nullptr}, memory_info(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)) { dof_default_eigen_policy.setZero(action_dim); dof_default_eigen_robot.setZero(action_dim); dof_default_eigen_policy << 0.0, -0.6, 1.0, 0.0, -0.6, 1.0, 0.0, 0.6, -1.0, 0.0, 0.6, -1.0, 0.0, 0.0, 0.0, 0.0; dof_default_eigen_robot << 0.0, -0.6, 1.0, 0.0, 0.0, -0.6, 1.0, 0.0, 0.0, 0.6, -1.0, 0.0, 0.0, 0.6, -1.0, 0.0; SetDecimation(4); session_options_.SetIntraOpNumThreads(4); session_options_.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED); if (access(policy_path_.c_str(), F_OK) != 0) { std::cerr << "Model file not found: " << policy_path_ << std::endl; throw std::runtime_error("Model file missing"); } // 加载模型 session_ = Ort::Session(env_, policy_path_.c_str(), session_options_); kp_ = Vec4f(80, 80, 80, 0.).replicate(4, 1); kd_ = Vec4f(2, 2, 2, 0.6).replicate(4, 1); robot2policy_idx = generate_permutation(robot_order, policy_order); policy2robot_idx = generate_permutation(policy_order, robot_order); // for (int i = 0; i < action_dim; ++i){ // std::cout << "robot2policy_idx[" << i << "]: " << robot2policy_idx[i] << std::endl; // std::cout << "policy2robot_idx[" << i << "]: " << policy2robot_idx[i] << std::endl; // } robot_action.kp = kp_; robot_action.kd = kd_; robot_action.tau_ff = VecXf::Zero(motor_num); robot_action.goal_joint_pos = VecXf::Zero(motor_num); robot_action.goal_joint_vel = VecXf::Zero(motor_num); current_observation_.setZero(observation_dim); last_action_eigen.setZero(action_dim); tmp_action_eigen.setZero(action_dim); current_action_eigen.setZero(action_dim); memory_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); } ~M20PolicyRunner() override = default; std::vector generate_permutation( const std::vector& from, const std::vector& to, int default_index = 0) { std::unordered_map idx_map; for (int i = 0; i < from.size(); ++i) { idx_map[from[i]] = i; } std::vector perm; for (const auto& name : to) { auto it = idx_map.find(name); if (it != idx_map.end()) { perm.push_back(it->second); } else { perm.push_back(default_index); // 如果找不到,就填默认值 } } return perm; } void DisplayPolicyInfo(){} void OnEnter() { run_cnt_ = 0; cmd_vel_input_.setZero(); last_action_eigen.setZero(action_dim); tmp_action_eigen.setZero(action_dim); motor_p_eigen.setZero(12); motor_v_eigen.setZero(motor_num); } VecXf Onnx_infer(VecXf current_observation){ Ort::Value input_tensor = Ort::Value::CreateTensor( memory_info, current_observation.data(), current_observation.size(), input_observationShape.data(), input_observationShape.size() ); std::vector inputs; inputs.emplace_back(std::move(input_tensor)); // 避免拷贝构造 auto outputs = session_.Run( Ort::RunOptions{nullptr}, input_names_, inputs.data(), 1, output_names_, 1 ); float* action_data = outputs[0].GetTensorMutableData(); Eigen::Map action_map(action_data, action_dim); return VecXf(action_map); // 返回一个Eigen向量的副本 } RobotAction getRobotAction(const RobotBasicState &ro, const UserCommand &uc) { Vec3f base_omgea = ro.base_omega * omega_scale_; Vec3f projected_gravity = ro.base_rot_mat.inverse() * gravity_direction; Vec3f command = Vec3f(uc.forward_vel_scale, uc.side_vel_scale, uc.turnning_vel_scale); for (int i = 0; i < action_dim; ++i){ joint_pos_rl(i) = ro.joint_pos(robot2policy_idx[i]); joint_vel_rl(i) = ro.joint_vel(robot2policy_idx[i]) * dof_vel_scale_; } joint_pos_rl.segment(12, 4).setZero(); joint_pos_rl -= dof_default_eigen_policy; current_observation_<