cmvr-es/example/solve_ik.cpp

131 lines
4.1 KiB
C++
Raw Normal View History

//
// Created by xtkuang on 2025/7/31.
//
#include "utils/dynamics/robot.h"
#include "utils/controller/cartesian_controller.h"
#include <Eigen/Dense>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <cmath>
#include <glog/logging.h>
constexpr int DOF = 14;
using RobotT = cmvr::dyn::Robot<DOF>;
using ControllerT = cmvr::ctrl::CartesianController<DOF>;
// 将欧拉角(rx, ry, rz)转为旋转矩阵,旋转顺序 Z→Y→X
Eigen::Matrix3d eulerToRotationMatrix(double rx, double ry, double rz)
{
Eigen::Matrix3d R_x;
R_x << 1, 0, 0,
0, cos(rx), -sin(rx),
0, sin(rx), cos(rx);
Eigen::Matrix3d R_y;
R_y << cos(ry), 0, sin(ry),
0, 1, 0,
-sin(ry), 0, cos(ry);
Eigen::Matrix3d R_z;
R_z << cos(rz), -sin(rz), 0,
sin(rz), cos(rz), 0,
0, 0, 1;
// ✅ 按照输入顺序 X → Y → Z 旋转
return R_x * R_y * R_z;
}
int main(int argc, char **argv)
{
if (argc != 9)
{
std::cerr << "用法: " << argv[0] << " <base link> <target link> <x> <y> <z> <rx> <ry> <rz>\n";
return -1;
}
std::vector<std::string> link_names = {
"PELVIS_S",
"L_SHOULDER_P_S", "L_SHOULDER_R_S", "L_SHOULDER_Y_S", "L_ELBOW_R_S", "L_WRIST_P_S", "L_WRIST_Y_S", "L_WRIST_R_S",
2025-08-23 15:51:07 +08:00
"R_SHOULDER_P_S", "R_SHOULDER_R_S", "R_SHOULDER_Y_S", "R_ELBOW_R_S", "R_WRIST_P_S", "R_WRIST_Y_S", "R_WRIST_R_S", "R_CAM", "R_FINGER_TIP"
};
std::vector<std::string> joint_names = {
"L_SHOULDER_P", "L_SHOULDER_R", "L_SHOULDER_Y", "L_ELBOW_R", "L_WRIST_P", "L_WRIST_Y", "L_WRIST_R",
"R_SHOULDER_P", "R_SHOULDER_R", "R_SHOULDER_Y", "R_ELBOW_R", "R_WRIST_P", "R_WRIST_Y", "R_WRIST_R",
};
std::string BASE_LINK = argv[1];
std::string target_link = argv[2];
bool find_base_link = false;
bool find_target_link = false;
for (auto link_name : link_names) {
if (BASE_LINK == link_name) {
find_base_link = true;
}
if (target_link == link_name) {
find_target_link = true;
}
}
if (!find_base_link) {
std::cerr << "base link 无效" << std::endl;
return -1;
}
if (!find_target_link) {
std::cerr << "target link 无效" << std::endl;
return -1;
}
double x = std::stod(argv[3]);
double y = std::stod(argv[4]);
double z = std::stod(argv[5]);
double rx = std::stod(argv[6]) * M_PI / 180.0;
double ry = std::stod(argv[7]) * M_PI / 180.0;
double rz = std::stod(argv[8]) * M_PI / 180.0;
// 1. 加载机器人模型
auto rcfg = LoadRobotFromURDF(
"/home/xtkuang/projects/cmvr-es/config/robot_description/hc_description/dual_arm.urdf",
/*root*/ "PELVIS_S");
auto robot = std::make_shared<RobotT>(rcfg);
auto state = robot->MakeState(link_names, joint_names);
// 初始关节角度
Eigen::Vector<double, DOF> q_init;
q_init << -0.3647738137, -1.4556045962, 1.6057029118, -1.8483036779, 2.9024825461, 0.1850049007, -0.5602506899,
-0.3448998226801712, 0.9351815151808957, 2.2703399775931388, 1.6895896595300133, -2.3279553847104077, 0.46019613485676647, 0.3009592467697589;
state->SetQ(q_init);
robot->ComputeForwardKinematics(state);
// 2. 构造目标位姿矩阵
Eigen::Matrix4d T_target = Eigen::Matrix4d::Identity();
T_target.block<3,3>(0,0) = eulerToRotationMatrix(rx, ry, rz); // 输入为弧度
T_target(0,3) = x;
T_target(1,3) = y;
T_target(2,3) = z;
// 3. 创建控制器
ControllerT ctrl(robot);
constexpr double DT = 0.002; // 2ms
std::vector<cmvr::ctrl::PoseTarget> targets = {
{target_link, T_target, 0.5, 1.0}
};
Eigen::Vector<double, DOF> q_cmd;
bool ok = ctrl.compute(state, BASE_LINK, targets, DT, ControllerT::Mode::Position, q_cmd, 10000, 1e-6);
// ✅ 格式化输出
std::cout << "[IK Solve] success=" << std::boolalpha << ok << "\n";
std::cout << "left: ";
for(int i=0; i<7; ++i) std::cout << q_cmd[i] << (i<6?" ":"");
std::cout << "\nright: ";
for(int i=7; i<14; ++i) std::cout << q_cmd[i] << (i<13?" ":"");
std::cout << std::endl;
return 0;
}