168 lines
4.9 KiB
C++
168 lines
4.9 KiB
C++
/**
|
|
* @file state_machine_base.h
|
|
* @brief state machine base class for different robot state machine control
|
|
* @author DeepRobotics
|
|
* @version 1.0
|
|
* @date 2025-11-07
|
|
*
|
|
* @copyright Copyright (c) 2025 DeepRobotics
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "state_base.h"
|
|
#include "safe_controller.hpp"
|
|
|
|
class TimeTool {
|
|
private:
|
|
int tfd; /**< Timer descriptor.*/
|
|
int efd; /**< Epoll descriptor.*/
|
|
int fds, ret; /**< Variables used to initialize the timer.*/
|
|
uint64_t value; /**< Variables used to initialize the timer.*/
|
|
struct epoll_event ev, *evptr; /**< Variables used to initialize the timer.*/
|
|
struct itimerspec time_intv; /**< Variables used to initialize the timer.*/
|
|
public:
|
|
timespec system_time; /**< A class for accurately obtaining time.*/
|
|
/**
|
|
* @brief Initialize timer, input cycle(ms).
|
|
* @param Cycle time unit: ms
|
|
*/
|
|
void time_init(int ms) {
|
|
tfd = timerfd_create(CLOCK_MONOTONIC, 0); //创建定时器
|
|
if (tfd == -1) {
|
|
printf("create timer fd fail \r\n");
|
|
}
|
|
time_intv.it_value.tv_sec = 0; //设定2s超时
|
|
time_intv.it_value.tv_nsec = 1000 * 1000 * ms;
|
|
time_intv.it_interval.tv_sec = time_intv.it_value.tv_sec; //每隔2s超时
|
|
time_intv.it_interval.tv_nsec = time_intv.it_value.tv_nsec;
|
|
|
|
printf("timer start ...\n");
|
|
timerfd_settime(tfd, 0, &time_intv, NULL); //启动定时器
|
|
|
|
efd = epoll_create1(0); //创建epoll实例
|
|
if (efd == -1) {
|
|
printf("create epoll fail \r\n");
|
|
close(tfd);
|
|
}
|
|
|
|
evptr = (struct epoll_event *) calloc(1, sizeof(struct epoll_event));
|
|
if (evptr == NULL) {
|
|
printf("epoll event calloc fail \r\n");
|
|
close(tfd);
|
|
close(efd);
|
|
}
|
|
|
|
ev.data.fd = tfd;
|
|
ev.events = EPOLLIN; //监听定时器读事件,当定时器超时时,定时器描述符可读。
|
|
epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev); //添加到epoll监听队列中
|
|
}
|
|
|
|
/**
|
|
* @brief Acquire interrupt signal
|
|
* @return 1:Enter interrupt 0:no
|
|
*/
|
|
int time_interrupt() {
|
|
fds = epoll_wait(efd, evptr, 1, 10);
|
|
if (evptr[0].events & EPOLLIN) {
|
|
ret = read(evptr->data.fd, &value, sizeof(uint64_t));
|
|
if (ret == -1) {
|
|
printf("read return 1 -1, errno :%d \r\n", errno);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
} /**< Acquire interrupt signal.*/
|
|
|
|
/**
|
|
* @brief How long has it been
|
|
* @param Initial time
|
|
*/
|
|
double getCurrentTime(double start_time) {
|
|
clock_gettime(1, &system_time);
|
|
return system_time.tv_sec + system_time.tv_nsec / 1e9 - start_time;
|
|
}
|
|
|
|
/**
|
|
* @brief Get current time
|
|
*/
|
|
double get_start_time() {
|
|
clock_gettime(1, &system_time);
|
|
return system_time.tv_sec + system_time.tv_nsec / 1e9;
|
|
} /**< Get start time.*/
|
|
};
|
|
|
|
|
|
class StateMachineBase {
|
|
private:
|
|
/* data */
|
|
public:
|
|
StateMachineBase(const RobotType &robot_type) : robot_type_(robot_type) {
|
|
|
|
}
|
|
|
|
virtual ~StateMachineBase() {}
|
|
|
|
virtual void Start() = 0;
|
|
|
|
virtual void Run() {
|
|
run_thread_ = std::thread(&StateMachineBase::RunThread, this);
|
|
rclcpp::spin(ri_ptr_->get_node());
|
|
|
|
if (run_thread_.joinable())
|
|
run_thread_.join();
|
|
}
|
|
|
|
virtual void RunThread() {
|
|
set_timer.time_init(5);
|
|
startTime = set_timer.get_start_time();
|
|
|
|
while (rclcpp::ok()) {
|
|
if (set_timer.time_interrupt()) {
|
|
ri_ptr_->RefreshRobotData();
|
|
|
|
current_controller_->Run();
|
|
|
|
if (current_controller_->LoseControlJudge()){
|
|
next_state_name_ = StateName::kJointDamping;
|
|
}
|
|
else {
|
|
next_state_name_ = current_controller_->GetNextStateName();
|
|
}
|
|
|
|
if (next_state_name_ != current_state_name_) {
|
|
current_controller_->OnExit();
|
|
std::cout << current_controller_->state_name_ << " ------------> ";
|
|
current_controller_ = GetStateControllerPtr(next_state_name_);
|
|
std::cout << current_controller_->state_name_ << std::endl;
|
|
current_controller_->OnEnter();
|
|
current_state_name_ = next_state_name_;
|
|
}
|
|
++run_cnt_;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void Stop() = 0;
|
|
|
|
virtual std::shared_ptr<StateBase> GetStateControllerPtr(StateName state_name) = 0;
|
|
|
|
const RobotType robot_type_;
|
|
|
|
int run_cnt_ = 0;
|
|
double _dt = 0.001, startTime;
|
|
TimeTool set_timer{};
|
|
|
|
std::shared_ptr<UserCommandInterface> uc_ptr_;
|
|
std::shared_ptr<RobotInterface> ri_ptr_;
|
|
std::shared_ptr<ControlParameters> cp_ptr_;
|
|
std::shared_ptr<SafeController> sc_ptr_;
|
|
|
|
std::shared_ptr<StateBase> current_controller_;
|
|
StateName current_state_name_, next_state_name_;
|
|
|
|
std::thread run_thread_;
|
|
};
|
|
|