quadruped_ros2_control/controllers/rl_quadruped_controller/src/RlQuadrupedController.cpp

276 lines
10 KiB
C++
Raw Normal View History

2024-10-04 20:14:34 +08:00
//
// Created by tlab-uav on 24-10-4.
//
2024-10-15 20:17:03 +08:00
#include "RlQuadrupedController.h"
2024-10-04 20:14:34 +08:00
2025-03-30 11:04:48 +08:00
namespace rl_quadruped_controller
{
2024-10-04 20:14:34 +08:00
using config_type = controller_interface::interface_configuration_type;
2025-03-30 11:04:48 +08:00
controller_interface::InterfaceConfiguration LeggedGymController::command_interface_configuration() const
{
2024-10-04 20:14:34 +08:00
controller_interface::InterfaceConfiguration conf = {config_type::INDIVIDUAL, {}};
conf.names.reserve(joint_names_.size() * command_interface_types_.size());
2025-03-30 11:04:48 +08:00
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);
2025-03-30 11:04:48 +08:00
}
else
{
conf.names.push_back(joint_name + "/" += interface_type);
}
2024-10-04 20:14:34 +08:00
}
}
return conf;
}
2025-03-30 11:04:48 +08:00
controller_interface::InterfaceConfiguration LeggedGymController::state_interface_configuration() const
{
2024-10-04 20:14:34 +08:00
controller_interface::InterfaceConfiguration conf = {config_type::INDIVIDUAL, {}};
conf.names.reserve(joint_names_.size() * state_interface_types_.size());
2025-03-30 11:04:48 +08:00
for (const auto& joint_name : joint_names_)
{
for (const auto& interface_type : state_interface_types_)
{
2024-10-04 20:14:34 +08:00
conf.names.push_back(joint_name + "/" += interface_type);
}
}
2025-03-30 11:04:48 +08:00
for (const auto& interface_type : imu_interface_types_)
{
2024-10-04 20:14:34 +08:00
conf.names.push_back(imu_name_ + "/" += interface_type);
}
2025-03-30 11:04:48 +08:00
for (const auto& interface_type : foot_force_interface_types_)
{
2024-10-04 20:14:34 +08:00
conf.names.push_back(foot_force_name_ + "/" += interface_type);
}
return conf;
}
controller_interface::return_type LeggedGymController::
2025-03-30 11:04:48 +08:00
update(const rclcpp::Time& time, const rclcpp::Duration& period)
{
if (ctrl_component_.enable_estimator_)
{
if (ctrl_component_.robot_model_ == nullptr)
{
2024-10-21 21:47:25 +08:00
return controller_interface::return_type::OK;
}
2024-10-15 20:17:03 +08:00
2025-03-03 23:37:42 +08:00
ctrl_component_.robot_model_->update();
ctrl_component_.estimator_->update();
2024-10-21 21:47:25 +08:00
}
2024-10-15 20:17:03 +08:00
2025-03-30 11:04:48 +08:00
if (mode_ == FSMMode::NORMAL)
{
2025-03-03 23:37:42 +08:00
current_state_->run(time, period);
2024-10-04 20:14:34 +08:00
next_state_name_ = current_state_->checkChange();
2025-03-30 11:04:48 +08:00
if (next_state_name_ != current_state_->state_name)
{
2024-10-04 20:14:34 +08:00
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());
}
2025-03-30 11:04:48 +08:00
}
else if (mode_ == FSMMode::CHANGE)
{
2024-10-04 20:14:34 +08:00
current_state_->exit();
current_state_ = next_state_;
current_state_->enter();
mode_ = FSMMode::NORMAL;
}
return controller_interface::return_type::OK;
}
2025-03-30 11:04:48 +08:00
controller_interface::CallbackReturn LeggedGymController::on_init()
{
try
{
joint_names_ = auto_declare<std::vector<std::string>>("joints", joint_names_);
feet_names_ = auto_declare<std::vector<std::string>>("feet_names", feet_names_);
2024-10-04 20:14:34 +08:00
command_interface_types_ =
2025-03-30 11:04:48 +08:00
auto_declare<std::vector<std::string>>("command_interfaces", command_interface_types_);
2024-10-04 20:14:34 +08:00
state_interface_types_ =
2025-03-30 11:04:48 +08:00
auto_declare<std::vector<std::string>>("state_interfaces", state_interface_types_);
2024-10-04 20:14:34 +08:00
command_prefix_ = auto_declare<std::string>("command_prefix", command_prefix_);
2024-10-15 20:17:03 +08:00
base_name_ = auto_declare<std::string>("base_name", base_name_);
2024-10-04 20:14:34 +08:00
// imu sensor
imu_name_ = auto_declare<std::string>("imu_name", imu_name_);
2025-03-30 11:04:48 +08:00
imu_interface_types_ = auto_declare<std::vector<std::string>>("imu_interfaces", state_interface_types_);
2024-10-07 11:57:32 +08:00
2024-10-15 20:17:03 +08:00
// foot_force_sensor
foot_force_name_ = auto_declare<std::string>("foot_force_name", foot_force_name_);
foot_force_interface_types_ =
2025-03-30 11:04:48 +08:00
auto_declare<std::vector<std::string>>("foot_force_interfaces", foot_force_interface_types_);
feet_force_threshold_ = auto_declare<double>("feet_force_threshold", feet_force_threshold_);
2024-10-07 11:57:32 +08:00
2024-10-21 17:40:42 +08:00
// pose parameters
2025-03-30 11:04:48 +08:00
down_pos_ = auto_declare<std::vector<double>>("down_pos", down_pos_);
stand_pos_ = auto_declare<std::vector<double>>("stand_pos", stand_pos_);
2024-10-21 17:40:42 +08:00
stand_kp_ = auto_declare<double>("stand_kp", stand_kp_);
stand_kd_ = auto_declare<double>("stand_kd", stand_kd_);
2025-03-03 23:37:42 +08:00
get_node()->get_parameter("update_rate", ctrl_interfaces_.frequency_);
RCLCPP_INFO(get_node()->get_logger(), "Controller Update Rate: %d Hz", ctrl_interfaces_.frequency_);
2024-10-15 20:17:03 +08:00
2025-03-30 11:04:48 +08:00
if (foot_force_interface_types_.size() == 4)
{
2025-03-04 00:07:24 +08:00
RCLCPP_INFO(get_node()->get_logger(), "Enable Estimator");
2025-03-03 23:37:42 +08:00
ctrl_component_.enable_estimator_ = true;
ctrl_component_.estimator_ = std::make_shared<Estimator>(ctrl_interfaces_, ctrl_component_);
2024-10-21 21:47:25 +08:00
}
2025-03-30 11:04:48 +08:00
ctrl_component_.node_ = get_node();
}
catch (const std::exception& e)
{
2024-10-04 20:14:34 +08:00
fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what());
return controller_interface::CallbackReturn::ERROR;
}
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn LeggedGymController::on_configure(
2025-03-30 11:04:48 +08:00
const rclcpp_lifecycle::State& /*previous_state*/)
{
2024-10-15 20:17:03 +08:00
robot_description_subscription_ = get_node()->create_subscription<std_msgs::msg::String>(
"/robot_description", rclcpp::QoS(rclcpp::KeepLast(1)).transient_local(),
2025-03-30 11:04:48 +08:00
[this](const std_msgs::msg::String::SharedPtr msg)
{
if (ctrl_component_.enable_estimator_)
{
2025-03-03 23:37:42 +08:00
ctrl_component_.robot_model_ = std::make_shared<QuadrupedRobot>(
ctrl_interfaces_, msg->data, feet_names_, base_name_);
2024-10-21 21:47:25 +08:00
}
2024-10-15 20:17:03 +08:00
});
2024-10-04 20:14:34 +08:00
control_input_subscription_ = get_node()->create_subscription<control_input_msgs::msg::Inputs>(
2025-03-30 11:04:48 +08:00
"/control_input", 10, [this](const control_input_msgs::msg::Inputs::SharedPtr msg)
{
2024-10-04 20:14:34 +08:00
// Handle message
2025-03-03 23:37:42 +08:00
ctrl_interfaces_.control_inputs_.command = msg->command;
ctrl_interfaces_.control_inputs_.lx = msg->lx;
ctrl_interfaces_.control_inputs_.ly = msg->ly;
ctrl_interfaces_.control_inputs_.rx = msg->rx;
ctrl_interfaces_.control_inputs_.ry = msg->ry;
2024-10-04 20:14:34 +08:00
});
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn LeggedGymController::on_activate(
2025-03-30 11:04:48 +08:00
const rclcpp_lifecycle::State& /*previous_state*/)
{
2024-10-04 20:14:34 +08:00
// clear out vectors in case of restart
2025-03-03 23:37:42 +08:00
ctrl_interfaces_.clear();
2024-10-04 20:14:34 +08:00
// assign command interfaces
2025-03-30 11:04:48 +08:00
for (auto& interface : command_interfaces_)
{
2024-10-04 20:14:34 +08:00
std::string interface_name = interface.get_interface_name();
2025-03-30 11:04:48 +08:00
if (const size_t pos = interface_name.find('/'); pos != std::string::npos)
{
2024-10-04 20:14:34 +08:00
command_interface_map_[interface_name.substr(pos + 1)]->push_back(interface);
2025-03-30 11:04:48 +08:00
}
else
{
2024-10-04 20:14:34 +08:00
command_interface_map_[interface_name]->push_back(interface);
}
}
// assign state interfaces
2025-03-30 11:04:48 +08:00
for (auto& interface : state_interfaces_)
{
if (interface.get_prefix_name() == imu_name_)
{
2025-03-03 23:37:42 +08:00
ctrl_interfaces_.imu_state_interface_.emplace_back(interface);
2025-03-30 11:04:48 +08:00
}
else if (interface.get_prefix_name() == foot_force_name_)
{
2025-03-03 23:37:42 +08:00
ctrl_interfaces_.foot_force_state_interface_.emplace_back(interface);
2025-03-30 11:04:48 +08:00
}
else
{
2024-10-04 20:14:34 +08:00
state_interface_map_[interface.get_interface_name()]->push_back(interface);
}
}
// Create FSM List
2025-03-03 23:37:42 +08:00
state_list_.passive = std::make_shared<StatePassive>(ctrl_interfaces_);
state_list_.fixedDown = std::make_shared<StateFixedDown>(ctrl_interfaces_, down_pos_, stand_kp_, stand_kd_);
state_list_.fixedStand = std::make_shared<StateFixedStand>(ctrl_interfaces_, stand_pos_, stand_kp_, stand_kd_);
2025-03-30 11:04:48 +08:00
state_list_.rl = std::make_shared<StateRL>(ctrl_interfaces_, ctrl_component_, stand_pos_);
2024-10-04 20:14:34 +08:00
// Initialize FSM
current_state_ = state_list_.passive;
current_state_->enter();
next_state_ = current_state_;
next_state_name_ = current_state_->state_name;
mode_ = FSMMode::NORMAL;
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn LeggedGymController::on_deactivate(
2025-03-30 11:04:48 +08:00
const rclcpp_lifecycle::State& /*previous_state*/)
{
2024-10-04 20:14:34 +08:00
release_interfaces();
return CallbackReturn::SUCCESS;
}
controller_interface::CallbackReturn
2025-03-30 11:04:48 +08:00
LeggedGymController::on_cleanup(const rclcpp_lifecycle::State& previous_state)
{
2024-10-04 20:14:34 +08:00
return ControllerInterface::on_cleanup(previous_state);
}
controller_interface::CallbackReturn
2025-03-30 11:04:48 +08:00
LeggedGymController::on_shutdown(const rclcpp_lifecycle::State& previous_state)
{
2024-10-04 20:14:34 +08:00
return ControllerInterface::on_shutdown(previous_state);
}
2025-03-30 11:04:48 +08:00
controller_interface::CallbackReturn LeggedGymController::on_error(const rclcpp_lifecycle::State& previous_state)
{
2024-10-04 20:14:34 +08:00
return ControllerInterface::on_error(previous_state);
}
2025-03-30 11:04:48 +08:00
std::shared_ptr<FSMState> LeggedGymController::getNextState(const FSMStateName stateName) const
{
switch (stateName)
{
case FSMStateName::INVALID:
return state_list_.invalid;
case FSMStateName::PASSIVE:
return state_list_.passive;
case FSMStateName::FIXEDDOWN:
return state_list_.fixedDown;
case FSMStateName::FIXEDSTAND:
return state_list_.fixedStand;
case FSMStateName::RL:
return state_list_.rl;
default:
return state_list_.invalid;
2024-10-04 20:14:34 +08:00
}
}
}
#include "pluginlib/class_list_macros.hpp"
2024-10-10 21:22:58 +08:00
PLUGINLIB_EXPORT_CLASS(rl_quadruped_controller::LeggedGymController, controller_interface::ControllerInterface);