Files
2026-10-22 09:23:54 +08:00

160 lines
6.2 KiB
C++

/**
* @file rl_control_state.hpp
* @brief rl policy runnning state for quadruped-wheel robot
* @author DeepRobotics
* @version 1.0
* @date 2025-11-07
*
* @copyright Copyright (c) 2025 DeepRobotics
*
*/
#pragma once
#include "state_base.h"
#include "policy_runner_base.hpp"
#include "m20_policy_runner.hpp"
#include "fire_ant_policy_runner.hpp"
#include "robot_interface.h"
#include "user_command_interface.h"
#include "json.hpp"
#include "basic_function.hpp"
namespace qw {
class RLControlState : public StateBase {
private:
RobotBasicState rbs_[2];
std::atomic<int> rbs_write_index_{0};
int getrbsReadIndex() const { return 1 - rbs_write_index_.load(std::memory_order_acquire); }
std::atomic<int> state_run_cnt_{0};
std::shared_ptr<PolicyRunnerBase> policy_ptr_;
std::shared_ptr<M20PolicyRunner> m20_policy_;
std::shared_ptr<FireAntPolicyRunner> fire_ant_policy_;
std::thread run_policy_thread_;
std::atomic<bool> start_flag_{true};
float policy_cost_time_ = 1;
Eigen::MatrixXf acc_rot = Eigen::MatrixXf::Zero(20, 3);
int acc_rot_count = 0;
void UpdateRobotObservation() {
int write_idx = rbs_write_index_.load(std::memory_order_relaxed);
RobotBasicState& buffer = rbs_[write_idx];
buffer.base_rpy = ri_ptr_->GetImuRpy();
buffer.base_rot_mat = RpyToRm(buffer.base_rpy);
buffer.base_omega = ri_ptr_->GetImuOmega();
buffer.base_acc = ri_ptr_->GetImuAcc();
buffer.base_lin_vel = ri_ptr_->GetBaseLinearVelocity();
buffer.joint_pos = ri_ptr_->GetJointPosition();
buffer.joint_vel = ri_ptr_->GetJointVelocity();
buffer.joint_tau = ri_ptr_->GetJointTorque();
buffer.contact_force = ri_ptr_->GetContactForce();
// 储存
buffer.flt_base_acc_mat.row(acc_rot_count) = buffer.base_acc.transpose();
acc_rot_count += 1;
acc_rot_count = acc_rot_count % 20;
rbs_write_index_.store(1 - write_idx, std::memory_order_release);
}
void PolicyRunner() {
int run_cnt_record = -1;
while (start_flag_) {
const int state_run_cnt = state_run_cnt_.load(std::memory_order_acquire);
if (state_run_cnt % policy_ptr_->decimation_ == 0 && state_run_cnt != run_cnt_record) {
timespec start_timestamp, end_timestamp;
clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
auto ra = policy_ptr_->getRobotAction(rbs_[getrbsReadIndex()], *(uc_ptr_->GetUserCommand()));
MatXf res = ra.ConvertToMat();
ri_ptr_->SetJointCommand(res);
run_cnt_record = state_run_cnt;
clock_gettime(CLOCK_MONOTONIC, &end_timestamp);
policy_cost_time_ = (end_timestamp.tv_sec - start_timestamp.tv_sec) * 1e3
+ (end_timestamp.tv_nsec - start_timestamp.tv_nsec) / 1e6;
}
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
}
public:
RLControlState(const RobotName &robot_name, const std::string &state_name,
std::shared_ptr<ControllerData> data_ptr) : StateBase(robot_name, state_name, data_ptr) {
rbs_[0] = RobotBasicState(ri_ptr_->dof_num_);
rbs_[1] = RobotBasicState(ri_ptr_->dof_num_);
if (robot_name_ == RobotName::M20) {
namespace fs = std::filesystem;
fs::path base = fs::path(__FILE__).parent_path();
auto model_path = fs::canonical(base / ".." / ".." / "policy" / "policy.onnx");
m20_policy_ = std::make_shared<M20PolicyRunner>("m20_policy", model_path.string());
policy_ptr_ = m20_policy_;
} else if (robot_name_ == RobotName::FireAnt) {
namespace fs = std::filesystem;
fs::path base = fs::path(__FILE__).parent_path();
auto model_path = fs::canonical(base / ".." / ".." / "policy" / "fire_ant_policy.onnx");
fire_ant_policy_ = std::make_shared<FireAntPolicyRunner>("fire_ant_stage2", model_path.string());
policy_ptr_ = fire_ant_policy_;
}
if (!policy_ptr_) {
std::cerr << "error policy" << std::endl;
exit(0);
}
policy_ptr_->DisplayPolicyInfo();
}
~RLControlState() {
start_flag_ = false;
if (run_policy_thread_.joinable()) run_policy_thread_.join();
}
virtual void OnEnter() {
state_run_cnt_.store(-1, std::memory_order_release);
start_flag_ = true;
policy_ptr_->OnEnter();
run_policy_thread_ = std::thread(std::bind(&RLControlState::PolicyRunner, this));
StateBase::msfb_.UpdateCurrentState(RobotMotionState::RLControlMode);
};
virtual void OnExit() {
start_flag_ = false;
if (run_policy_thread_.joinable()) run_policy_thread_.join();
state_run_cnt_.store(-1, std::memory_order_release);
}
virtual void Run() {
UpdateRobotObservation();
state_run_cnt_.fetch_add(1, std::memory_order_release);
}
virtual bool LoseControlJudge() {
if (uc_ptr_->GetUserCommand()->target_mode == uint8_t(RobotMotionState::JointDamping)) return true;
return PostureUnsafeCheck();
}
bool PostureUnsafeCheck() {
// Vec3f rpy = ri_ptr_->GetImuRpy();
// if(rpy(0) > 30./180*M_PI || rpy(1) > 45./180*M_PI){
// std::cout << "posture value: " << 180./M_PI*rpy.transpose() << std::endl;
// return true;
// }
return false;
}
virtual StateName GetNextStateName() {
if (uc_ptr_->GetUserCommand()->safe_control_mode != 0)
return StateName::kJointDamping;
if (uc_ptr_->GetUserCommand()->target_mode == uint8_t(RobotMotionState::LieDown))
return StateName::kLieDown;
return StateName::kRLControl;
}
};
};