DFX_inspire_service/example/greet_common.hpp
2026-08-04 16:09:17 +04:00

103 lines
3.9 KiB
C++

/**
* @file greet_common.hpp
* @brief Shared arm-action + Inspire-hand greeting routines (handshake / thumbup).
*
* Arm uses Unitree's built-in actions (G1ArmActionClient, balance-aware).
* Hand uses the Inspire DDS bridge -> REQUIRES ./inspire_g1 running for fingers.
*/
#pragma once
#include "unitree/robot/g1/arm/g1_arm_action_client.hpp"
#include "unitree/robot/g1/arm/g1_arm_action_error.hpp"
#include <unitree/idl/go2/MotorCmds_.hpp>
#include <unitree/robot/channel/channel_publisher.hpp>
#include <eigen3/Eigen/Dense>
#include <iostream>
#include <memory>
#include <string>
#include <unistd.h>
using Vec6 = Eigen::Matrix<float, 6, 1>;
// Inspire hand command publisher (open-loop; needs inspire_g1 running).
class Hand
{
public:
Hand()
{
pub_ = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
pub_->InitChannel();
cmd_.cmds().resize(12);
}
void set(const Vec6 &right, const Vec6 &left)
{
for (size_t i = 0; i < 6; i++) { cmd_.cmds()[i].q() = right(i); cmd_.cmds()[i + 6].q() = left(i); }
pub_->Write(cmd_);
}
private:
unitree_go::msg::dds_::MotorCmds_ cmd_;
unitree::robot::ChannelPublisherPtr<unitree_go::msg::dds_::MotorCmds_> pub_;
};
inline Vec6 gv(float p, float r, float m, float i, float tb, float tr) { Vec6 v; v << p, r, m, i, tb, tr; return v; }
inline void ghold(int ms) { usleep(ms * 1000); }
// q in [0,1], 0=closed 1=open; order pinky,ring,middle,index,thumb_bend,thumb_rot
static const Vec6 G_OPEN = gv(1, 1, 1, 1, 1, 1);
static const Vec6 G_THUMBUP = gv(0, 0, 0, 0, 1, 1);
static const Vec6 G_SHAKE_READY = gv(0.85, 0.85, 0.85, 0.85, 0.85, 0.6);
static const Vec6 G_SHAKE_GRIP = gv(0.2, 0.2, 0.2, 0.2, 0.25, 0.1);
// Execute a built-in arm action; print a helpful message on failure.
inline bool arm_do(unitree::robot::g1::G1ArmActionClient &arm, int id, const char *name)
{
using namespace unitree::robot::g1;
std::cout << "arm: " << name << " (" << id << ") ..." << std::endl;
int32_t ret = arm.ExecuteAction(id);
if (ret != 0) {
std::cerr << " arm action '" << name << "' failed, code " << ret;
if (ret == UT_ROBOT_ARM_ACTION_ERR_ARMSDK) std::cerr << " (rt/arm_sdk occupied)";
else if (ret == UT_ROBOT_ARM_ACTION_ERR_INVALID_FSM_ID) std::cerr << " (need fsm {500,501,801})";
else if (ret == UT_ROBOT_ARM_ACTION_ERR_HOLDING) std::cerr << " (arm holding; send release 99)";
std::cerr << std::endl;
return false;
}
return true;
}
// arm reaches out -> hand grips -> thumbs-up -> arm releases
inline void runHandshake(unitree::robot::g1::G1ArmActionClient &arm, Hand &hand)
{
hand.set(G_SHAKE_READY, G_OPEN); // present an open hand
if (!arm_do(arm, 27, "shake hand")) { hand.set(G_OPEN, G_OPEN); return; }
ghold(300);
std::cout << "hand: grip" << std::endl;
hand.set(G_SHAKE_GRIP, G_OPEN); ghold(1500);
std::cout << "hand: thumbs-up" << std::endl;
hand.set(G_THUMBUP, G_OPEN); ghold(1200);
hand.set(G_OPEN, G_OPEN); ghold(400);
arm_do(arm, 99, "release arm");
}
// raise right hand -> hand thumbs-up -> arm releases
inline void runThumbup(unitree::robot::g1::G1ArmActionClient &arm, Hand &hand)
{
if (!arm_do(arm, 23, "right hand up")) { hand.set(G_OPEN, G_OPEN); return; }
ghold(300);
std::cout << "hand: thumbs-up" << std::endl;
hand.set(G_THUMBUP, G_OPEN); ghold(2500);
hand.set(G_OPEN, G_OPEN); ghold(400);
arm_do(arm, 99, "release arm");
}
// Shared setup: init DDS + arm client + hand, then return the arm client.
inline std::shared_ptr<unitree::robot::g1::G1ArmActionClient> greet_init(const std::string &iface)
{
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
auto arm = std::make_shared<unitree::robot::g1::G1ArmActionClient>();
arm->Init();
arm->SetTimeout(10.f);
return arm;
}