DFX_inspire_service/example/hand_example.cpp
2025-08-18 10:56:30 +08:00

163 lines
4.7 KiB
C++

/**
* @file inspire_hand.cpp
* @brief This is an example of how to control the Unitree H1 (Inspire) Hand using unitree_sdk2.
*/
// Inspire Hand Topic IDL Types
#include <unitree/idl/go2/MotorCmds_.hpp>
#include <unitree/idl/go2/MotorStates_.hpp>
// DDS Channel
#include <unitree/robot/channel/channel_publisher.hpp>
#include <unitree/robot/channel/channel_subscriber.hpp>
#include <unitree/common/thread/thread.hpp>
#include <eigen3/Eigen/Dense>
#include <unordered_map>
/**
* @brief Unitree H1 Hand Controller
* The user can subscribe to "rt/inspire/state" to get the current state of the hand and publish to "rt/inspire/cmd" to control the hand.
*
* IDL Types
* user ---(unitree_go::msg::dds_::MotorCmds_)---> "rt/inspire/cmd"
* user <--(unitree_go::msg::dds_::MotorStates_)-- "rt/inspire/state"
*
* @attention Currently the hand only supports position control, which means only the `q` field in idl is used.
*/
class H1HandController
{
public:
H1HandController()
{
this->InitDDS_();
}
/**
* @brief Control the hand to a specific label
*/
void ctrl(std::string label)
{
if(labels.find(label) != labels.end())
{
this->ctrl(labels[label], labels[label]);
}
else
{
std::cout << "Invalid label: " << label << std::endl;
}
}
/**
* @brief Move the fingers to the specified angles
*
* @note The angles should be in the range [0, 1]
* 0: close 1: open
*/
void ctrl(
const Eigen::Matrix<float, 6, 1>& right_angles,
const Eigen::Matrix<float, 6, 1>& left_angles)
{
for(size_t i(0); i<6; i++)
{
cmd.cmds()[i].q() = right_angles(i);
cmd.cmds()[i+6].q() = left_angles(i);
}
handcmd->Write(cmd);
}
/**
* @brief Get the right hand angles
*
* Joint order: [pinky, ring, middle, index, thumb_bend, thumb_rotation]
*/
Eigen::Matrix<float, 6, 1> getRightQ()
{
std::lock_guard<std::mutex> lock(mtx);
Eigen::Matrix<float, 6, 1> q;
for(size_t i(0); i<6; i++)
{
q(i) = state.states()[i].q();
}
return q;
}
/**
* @brief Get the left hand angles
*
* Joint order: [pinky, ring, middle, index, thumb_bend, thumb_rotation]
*/
Eigen::Matrix<float, 6, 1> getLeftQ()
{
std::lock_guard<std::mutex> lock(mtx);
Eigen::Matrix<float, 6, 1> q;
for(size_t i(0); i<6; i++)
{
q(i) = state.states()[i+6].q();
}
return q;
}
unitree_go::msg::dds_::MotorCmds_ cmd;
unitree_go::msg::dds_::MotorStates_ state;
private:
void InitDDS_()
{
handcmd = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>(
"rt/inspire/cmd");
handcmd->InitChannel();
cmd.cmds().resize(12);
handstate = std::make_shared<unitree::robot::ChannelSubscriber<unitree_go::msg::dds_::MotorStates_>>(
"rt/inspire/state");
handstate->InitChannel([this](const void *message){
std::lock_guard<std::mutex> lock(mtx);
state = *(unitree_go::msg::dds_::MotorStates_*)message;
});
state.states().resize(12);
}
// DDS parameters
std::mutex mtx;
unitree::robot::ChannelPublisherPtr<unitree_go::msg::dds_::MotorCmds_> handcmd;
unitree::robot::ChannelSubscriberPtr<unitree_go::msg::dds_::MotorStates_> handstate;
// Saved labels
std::unordered_map<std::string, Eigen::Matrix<float, 6, 1>> labels = {
{"open", Eigen::Matrix<float, 6, 1>::Ones()},
{"close", Eigen::Matrix<float, 6, 1>::Zero()},
{"half", Eigen::Matrix<float, 6, 1>::Constant(0.5)},
};
};
/**
* Main Function
*/
int main(int argc, char** argv)
{
std::cout << " --- Unitree Robotics --- \n";
std::cout << " H1 Hand Example \n\n";
// Target label
std::string label = "close"; // You change this value to other labels
// Initialize the DDS Channel
std::string networkInterface = argc > 1 ? argv[1] : "";
unitree::robot::ChannelFactory::Instance()->Init(0, networkInterface);
// Create the H1 Hand Controller
auto h1hand = std::make_shared<H1HandController>();
int cnt = 0;
while (true)
{
usleep(100000);
if(cnt++ % 10 == 0)
label = label == "close" ? "open" : "close";
h1hand->ctrl(label); // Control the hand
std::cout << "-- Hand State --\n";
std::cout << " R: " << h1hand->getRightQ().transpose() << std::endl;
std::cout << " L: " << h1hand->getLeftQ().transpose() << std::endl;
std::cout << "\033[3A"; // Move cursor up 3 lines
}
return 0;
}