quadruped_ros2_control/controllers/unitree_guide_controller/src/UnitreeGuideController.cpp

219 lines
9.2 KiB
C++
Raw Normal View History

2024-09-09 22:18:19 +08:00
//
// Created by tlab-uav on 24-9-6.
//
2024-09-14 17:54:39 +08:00
#include "unitree_guide_controller/UnitreeGuideController.h"
#include "unitree_guide_controller/FSM/StatePassive.h"
#include "unitree_guide_controller/robot/QuadrupedRobot.h"
2024-09-09 22:18:19 +08:00
namespace unitree_guide_controller {
2024-09-09 22:18:19 +08:00
using config_type = controller_interface::interface_configuration_type;
controller_interface::InterfaceConfiguration UnitreeGuideController::command_interface_configuration() const {
2024-09-09 22:18:19 +08:00
controller_interface::InterfaceConfiguration conf = {config_type::INDIVIDUAL, {}};
conf.names.reserve(joint_names_.size() * command_interface_types_.size());
for (const auto &joint_name: joint_names_) {
for (const auto &interface_type: command_interface_types_) {
if (!command_prefix_.empty()) {
conf.names.push_back(command_prefix_ + "/" + joint_name + "/" += interface_type);
} else {
conf.names.push_back(joint_name + "/" += interface_type);
}
2024-09-09 22:18:19 +08:00
}
}
return conf;
}
controller_interface::InterfaceConfiguration UnitreeGuideController::state_interface_configuration() const {
2024-09-09 22:18:19 +08:00
controller_interface::InterfaceConfiguration conf = {config_type::INDIVIDUAL, {}};
conf.names.reserve(joint_names_.size() * state_interface_types_.size());
for (const auto &joint_name: joint_names_) {
for (const auto &interface_type: state_interface_types_) {
conf.names.push_back(joint_name + "/" += interface_type);
}
}
2024-09-16 13:44:08 +08:00
for (const auto &interface_type: imu_interface_types_) {
conf.names.push_back(imu_name_ + "/" += interface_type);
}
2024-09-09 22:18:19 +08:00
return conf;
}
controller_interface::return_type UnitreeGuideController::
2024-09-09 22:18:19 +08:00
update(const rclcpp::Time &time, const rclcpp::Duration &period) {
2024-09-16 21:15:34 +08:00
// auto now = std::chrono::steady_clock::now();
// std::chrono::duration<double> time_diff = now - last_update_time_;
// last_update_time_ = now;
//
// // Calculate the frequency
// update_frequency_ = 1.0 / time_diff.count();
// RCLCPP_INFO(get_node()->get_logger(), "Update frequency: %f Hz", update_frequency_);
2024-09-18 13:52:37 +08:00
ctrl_comp_.robot_model_.update();
2024-09-18 19:37:01 +08:00
ctrl_comp_.wave_generator_.update();
2024-09-18 13:52:37 +08:00
ctrl_comp_.estimator_.update();
2024-09-16 21:15:34 +08:00
if (mode_ == FSMMode::NORMAL) {
current_state_->run();
2024-09-11 14:01:07 +08:00
next_state_name_ = current_state_->checkChange();
if (next_state_name_ != current_state_->state_name) {
mode_ = FSMMode::CHANGE;
next_state_ = getNextState(next_state_name_);
RCLCPP_INFO(get_node()->get_logger(), "Switched from %s to %s",
current_state_->state_name_string.c_str(), next_state_->state_name_string.c_str());
}
} else if (mode_ == FSMMode::CHANGE) {
current_state_->exit();
current_state_ = next_state_;
current_state_->enter();
mode_ = FSMMode::NORMAL;
2024-09-09 22:18:19 +08:00
}
2024-09-09 22:18:19 +08:00
return controller_interface::return_type::OK;
}
controller_interface::CallbackReturn UnitreeGuideController::on_init() {
2024-09-09 22:18:19 +08:00
try {
joint_names_ = auto_declare<std::vector<std::string> >("joints", joint_names_);
command_interface_types_ =
auto_declare<std::vector<std::string> >("command_interfaces", command_interface_types_);
state_interface_types_ =
auto_declare<std::vector<std::string> >("state_interfaces", state_interface_types_);
2024-09-16 13:44:08 +08:00
// imu sensor
imu_name_ = auto_declare<std::string>("imu_name", imu_name_);
imu_interface_types_ = auto_declare<std::vector<std::string> >("imu_interfaces", state_interface_types_);
command_prefix_ = auto_declare<std::string>("command_prefix", command_prefix_);
feet_names_ =
auto_declare<std::vector<std::string> >("feet_names", feet_names_);
2024-09-09 22:18:19 +08:00
} catch (const std::exception &e) {
fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what());
return controller_interface::CallbackReturn::ERROR;
}
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn UnitreeGuideController::on_configure(
2024-09-09 22:18:19 +08:00
const rclcpp_lifecycle::State &previous_state) {
2024-09-11 14:01:07 +08:00
control_input_subscription_ = get_node()->create_subscription<control_input_msgs::msg::Inputs>(
"/control_input", 10, [this](const control_input_msgs::msg::Inputs::SharedPtr msg) {
2024-09-09 22:18:19 +08:00
// Handle message
2024-09-11 14:01:07 +08:00
ctrl_comp_.control_inputs_.get().command = msg->command;
ctrl_comp_.control_inputs_.get().lx = msg->lx;
ctrl_comp_.control_inputs_.get().ly = msg->ly;
ctrl_comp_.control_inputs_.get().rx = msg->rx;
ctrl_comp_.control_inputs_.get().ry = msg->ry;
2024-09-09 22:18:19 +08:00
});
2024-09-11 20:41:12 +08:00
2024-09-12 13:56:51 +08:00
robot_description_subscription_ = get_node()->create_subscription<std_msgs::msg::String>(
"/robot_description", rclcpp::QoS(rclcpp::KeepLast(1)).transient_local(),
2024-09-12 13:56:51 +08:00
[this](const std_msgs::msg::String::SharedPtr msg) {
ctrl_comp_.robot_model_.init(msg->data, feet_names_);
2024-09-18 13:52:37 +08:00
ctrl_comp_.balance_ctrl_.init(ctrl_comp_.robot_model_);
2024-09-12 13:56:51 +08:00
});
2024-09-11 20:41:12 +08:00
get_node()->get_parameter("update_rate", ctrl_comp_.frequency_);
RCLCPP_INFO(get_node()->get_logger(), "Controller Manager Update Rate: %d Hz", ctrl_comp_.frequency_);
2024-09-18 19:37:01 +08:00
ctrl_comp_.wave_generator_.init(0.45, 0.5, Vec4(0, 0.5, 0.5, 0));
2024-09-09 22:18:19 +08:00
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn
UnitreeGuideController::on_activate(const rclcpp_lifecycle::State &previous_state) {
2024-09-09 22:18:19 +08:00
// clear out vectors in case of restart
ctrl_comp_.clear();
2024-09-09 22:18:19 +08:00
// assign command interfaces
for (auto &interface: command_interfaces_) {
std::string interface_name = interface.get_interface_name();
if (const size_t pos = interface_name.find('/'); pos != std::string::npos) {
command_interface_map_[interface_name.substr(pos + 1)]->push_back(interface);
} else {
command_interface_map_[interface_name]->push_back(interface);
}
2024-09-09 22:18:19 +08:00
}
// assign state interfaces
for (auto &interface: state_interfaces_) {
2024-09-16 13:44:08 +08:00
if (interface.get_prefix_name() == imu_name_) {
ctrl_comp_.imu_state_interface_.emplace_back(interface);
} else {
state_interface_map_[interface.get_interface_name()]->push_back(interface);
}
2024-09-09 22:18:19 +08:00
}
2024-09-19 22:45:08 +08:00
// Create FSM List
state_list_.passive = std::make_shared<StatePassive>(ctrl_comp_);
2024-09-11 20:41:12 +08:00
state_list_.fixedDown = std::make_shared<StateFixedDown>(ctrl_comp_);
state_list_.fixedStand = std::make_shared<StateFixedStand>(ctrl_comp_);
2024-09-12 13:56:51 +08:00
state_list_.swingTest = std::make_shared<StateSwingTest>(ctrl_comp_);
2024-09-13 15:00:20 +08:00
state_list_.freeStand = std::make_shared<StateFreeStand>(ctrl_comp_);
2024-09-16 21:15:34 +08:00
state_list_.balanceTest = std::make_shared<StateBalanceTest>(ctrl_comp_);
2024-09-18 19:37:01 +08:00
state_list_.trotting = std::make_shared<StateTrotting>(ctrl_comp_);
// Initialize FSM
current_state_ = state_list_.passive;
current_state_->enter();
next_state_ = current_state_;
next_state_name_ = current_state_->state_name;
mode_ = FSMMode::NORMAL;
2024-09-09 22:18:19 +08:00
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn UnitreeGuideController::on_deactivate(
2024-09-09 22:18:19 +08:00
const rclcpp_lifecycle::State &previous_state) {
release_interfaces();
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn
UnitreeGuideController::on_cleanup(const rclcpp_lifecycle::State &previous_state) {
2024-09-09 22:18:19 +08:00
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn
UnitreeGuideController::on_error(const rclcpp_lifecycle::State &previous_state) {
2024-09-09 22:18:19 +08:00
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn
UnitreeGuideController::on_shutdown(const rclcpp_lifecycle::State &previous_state) {
2024-09-09 22:18:19 +08:00
return CallbackReturn::SUCCESS;
}
2024-09-11 14:01:07 +08:00
std::shared_ptr<FSMState> UnitreeGuideController::getNextState(FSMStateName stateName) const {
switch (stateName) {
case FSMStateName::INVALID:
return state_list_.invalid;
case FSMStateName::PASSIVE:
return state_list_.passive;
2024-09-11 20:41:12 +08:00
case FSMStateName::FIXEDDOWN:
return state_list_.fixedDown;
2024-09-11 14:01:07 +08:00
case FSMStateName::FIXEDSTAND:
return state_list_.fixedStand;
2024-09-13 15:00:20 +08:00
case FSMStateName::FREESTAND:
return state_list_.freeStand;
2024-09-18 19:37:01 +08:00
case FSMStateName::TROTTING:
return state_list_.trotting;
2024-09-12 13:56:51 +08:00
case FSMStateName::SWINGTEST:
return state_list_.swingTest;
2024-09-16 21:15:34 +08:00
case FSMStateName::BALANCETEST:
return state_list_.balanceTest;
2024-09-11 14:01:07 +08:00
default:
return state_list_.invalid;
}
}
2024-09-09 22:18:19 +08:00
}
#include "pluginlib/class_list_macros.hpp"
PLUGINLIB_EXPORT_CLASS(unitree_guide_controller::UnitreeGuideController, controller_interface::ControllerInterface);