2024-04-28 19:22:24 +08:00
|
|
|
|
/**
|
|
|
|
|
******************************************************************************
|
|
|
|
|
* @file robotics.cpp/h
|
|
|
|
|
* @brief Robotic toolbox on STM32. STM32机器人学库
|
|
|
|
|
* @author Spoon Guan
|
|
|
|
|
* @ref [1] SJTU ME385-2, Robotics, Y.Ding
|
|
|
|
|
* [2] Bruno Siciliano, et al., Robotics: Modelling, Planning and
|
|
|
|
|
* Control, Springer, 2010.
|
|
|
|
|
* [3] R.Murry, Z.X.Li, and S.Sastry, A Mathematical Introduction
|
|
|
|
|
* to Robotic Manipulation, CRC Press, 1994.
|
|
|
|
|
******************************************************************************
|
|
|
|
|
* Copyright (c) 2023 Team JiaoLong-SJTU
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "robotics.h"
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 1> robotics::r2rpy(Matrixf<3, 3> R) {
|
|
|
|
|
float rpy[3] = {
|
|
|
|
|
atan2f(R[1][0], R[0][0]), // yaw
|
|
|
|
|
atan2f(-R[2][0], sqrtf(R[2][1] * R[2][1] + R[2][2] * R[2][2])), // pitch
|
|
|
|
|
atan2f(R[2][1], R[2][2]) // roll
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<3, 1>(rpy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 3> robotics::rpy2r(Matrixf<3, 1> rpy) {
|
|
|
|
|
float c[3] = {cosf(rpy[0][0]), cosf(rpy[1][0]), cosf(rpy[2][0])};
|
|
|
|
|
float s[3] = {sinf(rpy[0][0]), sinf(rpy[1][0]), sinf(rpy[2][0])};
|
|
|
|
|
float R[9] = {
|
|
|
|
|
c[0] * c[1], // R11
|
|
|
|
|
c[0] * s[1] * s[2] - s[0] * c[2], // R12
|
|
|
|
|
c[0] * s[1] * c[2] + s[0] * s[2], // R13
|
|
|
|
|
s[0] * c[1], // R21
|
|
|
|
|
s[0] * s[1] * s[2] + c[0] * c[2], // R22
|
|
|
|
|
s[0] * s[1] * c[2] - c[0] * s[2], // R23
|
|
|
|
|
-s[1], // R31
|
|
|
|
|
c[1] * s[2], // R32
|
|
|
|
|
c[1] * c[2] // R33
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<3, 3>(R);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::r2angvec(Matrixf<3, 3> R) {
|
|
|
|
|
float theta = acosf(math::limit(0.5f * (R.trace() - 1), -1, 1));
|
|
|
|
|
if (theta == 0 || theta == PI) {
|
|
|
|
|
float angvec[4] = {
|
|
|
|
|
(1 + R[0][0] - R[1][1] - R[2][2]) / 4.0f, // rx=(1+R11-R22-R33)/4
|
|
|
|
|
(1 - R[0][0] + R[1][1] - R[2][2]) / 4.0f, // ry=(1-R11+R22-R33)/4
|
|
|
|
|
(1 - R[0][0] - R[1][1] + R[2][2]) / 4.0f, // rz=(1-R11-R22+R33)/4
|
|
|
|
|
theta // theta
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<4, 1>(angvec);
|
|
|
|
|
}
|
|
|
|
|
float angvec[4] = {
|
|
|
|
|
(R[2][1] - R[1][2]) / (2.0f * sinf(theta)), // rx=(R32-R23)/2sinθ
|
|
|
|
|
(R[0][2] - R[2][0]) / (2.0f * sinf(theta)), // ry=(R13-R31)/2sinθ
|
|
|
|
|
(R[1][0] - R[0][1]) / (2.0f * sinf(theta)), // rz=(R21-R12)/2sinθ
|
|
|
|
|
theta // theta
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<4, 1>(angvec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 3> robotics::angvec2r(Matrixf<4, 1> angvec) {
|
|
|
|
|
float theta = angvec[3][0];
|
|
|
|
|
Matrixf<3, 1> r = angvec.block<3, 1>(0, 0);
|
|
|
|
|
Matrixf<3, 3> R;
|
|
|
|
|
// Rodrigues formula: R=I+ω^sinθ+ω^^2(1-cosθ)
|
|
|
|
|
R = matrixf::eye<3, 3>() + vector3f::hat(r) * sinf(theta) +
|
|
|
|
|
vector3f::hat(r) * vector3f::hat(r) * (1 - cosf(theta));
|
|
|
|
|
return R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::r2quat(Matrixf<3, 3> R) {
|
|
|
|
|
float q[4] = {
|
|
|
|
|
0.5f * sqrtf(math::limit(R.trace(), -1, 1) + 1), // q0=cos(θ/2)
|
|
|
|
|
math::sign(R[2][1] - R[1][2]) * 0.5f *
|
|
|
|
|
sqrtf(math::limit(R[0][0] - R[1][1] - R[2][2], -1, 1) +
|
|
|
|
|
1), // q1=rx*sin(θ/2)
|
|
|
|
|
math::sign(R[0][2] - R[2][0]) * 0.5f *
|
|
|
|
|
sqrtf(math::limit(-R[0][0] + R[1][1] - R[2][2], -1, 1) +
|
|
|
|
|
1), // q2=ry*sin(θ/2)
|
|
|
|
|
math::sign(R[1][0] - R[0][1]) * 0.5f *
|
|
|
|
|
sqrtf(math::limit(-R[0][0] - R[1][1] + R[2][2], -1, 1) +
|
|
|
|
|
1), // q3=rz*sin(θ/2)
|
|
|
|
|
};
|
|
|
|
|
return (Matrixf<4, 1>(q) / Matrixf<4, 1>(q).norm());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 3> robotics::quat2r(Matrixf<4, 1> q) {
|
|
|
|
|
float R[9] = {
|
|
|
|
|
1 - 2.0f * (q[2][0] * q[2][0] + q[3][0] * q[3][0]), // R11
|
|
|
|
|
2.0f * (q[1][0] * q[2][0] - q[0][0] * q[3][0]), // R12
|
|
|
|
|
2.0f * (q[1][0] * q[3][0] + q[0][0] * q[2][0]), // R13
|
|
|
|
|
2.0f * (q[1][0] * q[2][0] + q[0][0] * q[3][0]), // R21
|
|
|
|
|
1 - 2.0f * (q[1][0] * q[1][0] + q[3][0] * q[3][0]), // R22
|
|
|
|
|
2.0f * (q[2][0] * q[3][0] - q[0][0] * q[1][0]), // R23
|
|
|
|
|
2.0f * (q[1][0] * q[3][0] - q[0][0] * q[2][0]), // R31
|
|
|
|
|
2.0f * (q[2][0] * q[3][0] + q[0][0] * q[1][0]), // R32
|
|
|
|
|
1 - 2.0f * (q[1][0] * q[1][0] + q[2][0] * q[2][0]) // R33
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<3, 3>(R);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 1> robotics::quat2rpy(Matrixf<4, 1> q) {
|
|
|
|
|
float rpy[3] = {
|
|
|
|
|
atan2f(2.0f * (q[1][0] * q[2][0] + q[0][0] * q[3][0]),
|
|
|
|
|
1 - 2.0f * (q[2][0] * q[2][0] + q[3][0] * q[3][0])), // yaw
|
|
|
|
|
asinf(2.0f * (q[0][0] * q[2][0] - q[1][0] * q[3][0])), // pitch
|
|
|
|
|
atan2f(2.0f * (q[2][0] * q[3][0] + q[0][0] * q[1][0]),
|
|
|
|
|
1 - 2.0f * (q[1][0] * q[1][0] + q[2][0] * q[2][0])) // rol
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<3, 1>(rpy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::rpy2quat(Matrixf<3, 1> rpy) {
|
|
|
|
|
float c[3] = {cosf(0.5f * rpy[0][0]), cosf(0.5f * rpy[1][0]),
|
|
|
|
|
cosf(0.5f * rpy[2][0])}; // cos(*/2)
|
|
|
|
|
float s[3] = {sinf(0.5f * rpy[0][0]), sinf(0.5f * rpy[1][0]),
|
|
|
|
|
sinf(0.5f * rpy[2][0])}; // sin(*/2)
|
|
|
|
|
float q[4] = {
|
|
|
|
|
c[0] * c[1] * c[2] + s[0] * s[1] * s[2], // q0=cos(θ/2)
|
|
|
|
|
c[0] * c[1] * s[2] - s[0] * s[1] * c[2], // q1=rx*sin(θ/2)
|
|
|
|
|
c[0] * s[1] * c[2] + s[0] * c[1] * s[2], // q2=ry*sin(θ/2)
|
|
|
|
|
s[0] * c[1] * c[2] - c[0] * s[1] * s[2] // q3=rz*sin(θ/2)
|
|
|
|
|
};
|
|
|
|
|
return (Matrixf<4, 1>(q) / Matrixf<4, 1>(q).norm());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::quat2angvec(Matrixf<4, 1> q) {
|
|
|
|
|
float cosq0;
|
|
|
|
|
float theta = 2.0f * acosf(math::limit(q[0][0], -1, 1));
|
|
|
|
|
if (theta == 0 || theta == PI) {
|
|
|
|
|
float angvec[4] = {0, 0, 0, theta}; // θ=0||PI, return[0;θ]
|
|
|
|
|
return Matrixf<4, 1>(angvec);
|
|
|
|
|
}
|
|
|
|
|
Matrixf<3, 1> vec = q.block<3, 1>(1, 0);
|
|
|
|
|
float angvec[4] = {
|
|
|
|
|
vec[0][0] / vec.norm(), // rx
|
|
|
|
|
vec[1][0] / vec.norm(), // ry
|
|
|
|
|
vec[2][0] / vec.norm(), // rz
|
|
|
|
|
theta // theta
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<4, 1>(angvec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::angvec2quat(Matrixf<4, 1> angvec) {
|
|
|
|
|
float c = cosf(0.5f * angvec[3][0]), s = sinf(0.5f * angvec[3][0]);
|
|
|
|
|
float q[4] = {
|
|
|
|
|
c, // q0=cos(θ/2)
|
|
|
|
|
s * angvec[0][0], // q1=rx*sin(θ/2)
|
|
|
|
|
s * angvec[1][0], // q2=ry*sin(θ/2)
|
|
|
|
|
s * angvec[2][0] // q3=rz*sin(θ/2)
|
|
|
|
|
};
|
|
|
|
|
return Matrixf<4, 1>(q) / Matrixf<4, 1>(q).norm();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 3> robotics::t2r(Matrixf<4, 4> T) {
|
|
|
|
|
return T.block<3, 3>(0, 0); // R=T(1:3,1:3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::r2t(Matrixf<3, 3> R) {
|
|
|
|
|
// T=[R,0;0,1]
|
|
|
|
|
float T[16] = {R[0][0], R[0][1], R[0][2], 0, R[1][0], R[1][1], R[1][2], 0,
|
|
|
|
|
R[2][0], R[2][1], R[2][2], 0, 0, 0, 0, 1};
|
|
|
|
|
return Matrixf<4, 4>(T);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 1> robotics::t2p(Matrixf<4, 4> T) {
|
|
|
|
|
return T.block<3, 1>(0, 3); // p=T(1:3,4)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::p2t(Matrixf<3, 1> p) {
|
|
|
|
|
// T=[I,P;0,1]
|
|
|
|
|
float T[16] = {1, 0, 0, p[0][0], 0, 1, 0, p[1][0],
|
|
|
|
|
0, 0, 1, p[2][0], 0, 0, 0, 1};
|
|
|
|
|
return Matrixf<4, 4>(T);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::rp2t(Matrixf<3, 3> R, Matrixf<3, 1> p) {
|
|
|
|
|
// T=[R,P;0,1]
|
|
|
|
|
float T[16] = {R[0][0], R[0][1], R[0][2], p[0][0], R[1][0], R[1][1],
|
|
|
|
|
R[1][2], p[1][0], R[2][0], R[2][1], R[2][2], p[2][0],
|
|
|
|
|
0, 0, 0, 1};
|
|
|
|
|
return Matrixf<4, 4>(T);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::invT(Matrixf<4, 4> T) {
|
|
|
|
|
Matrixf<3, 3> RT = t2r(T).trans();
|
|
|
|
|
Matrixf<3, 1> p_ = -1.0f * RT * t2p(T);
|
|
|
|
|
float invT[16] = {RT[0][0], RT[0][1], RT[0][2], p_[0][0], RT[1][0], RT[1][1],
|
|
|
|
|
RT[1][2], p_[1][0], RT[2][0], RT[2][1], RT[2][2], p_[2][0],
|
|
|
|
|
0, 0, 0, 1};
|
|
|
|
|
return Matrixf<4, 4>(invT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<3, 1> robotics::t2rpy(Matrixf<4, 4> T) {
|
|
|
|
|
return r2rpy(t2r(T));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::rpy2t(Matrixf<3, 1> rpy) {
|
|
|
|
|
return r2t(rpy2r(rpy));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::t2angvec(Matrixf<4, 4> T) {
|
|
|
|
|
return r2angvec(t2r(T));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::angvec2t(Matrixf<4, 1> angvec) {
|
|
|
|
|
return r2t(angvec2r(angvec));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 1> robotics::t2quat(Matrixf<4, 4> T) {
|
|
|
|
|
return r2quat(t2r(T));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::quat2t(Matrixf<4, 1> quat) {
|
|
|
|
|
return r2t(quat2r(quat));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<6, 1> robotics::t2twist(Matrixf<4, 4> T) {
|
|
|
|
|
Matrixf<3, 1> p = t2p(T);
|
|
|
|
|
Matrixf<4, 1> angvec = t2angvec(T);
|
|
|
|
|
Matrixf<3, 1> phi = angvec.block<3, 1>(0, 0) * angvec[3][0];
|
|
|
|
|
float twist[6] = {p[0][0], p[1][0], p[2][0], phi[0][0], phi[1][0], phi[2][0]};
|
|
|
|
|
return Matrixf<6, 1>(twist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::twist2t(Matrixf<6, 1> twist) {
|
|
|
|
|
Matrixf<3, 1> p = twist.block<3, 1>(0, 0);
|
|
|
|
|
float theta = twist.block<3, 1>(3, 0).norm();
|
|
|
|
|
float angvec[4] = {0, 0, 0, theta};
|
|
|
|
|
if (theta != 0) {
|
|
|
|
|
angvec[0] = twist[3][0] / theta;
|
|
|
|
|
angvec[1] = twist[4][0] / theta;
|
|
|
|
|
angvec[2] = twist[5][0] / theta;
|
|
|
|
|
}
|
|
|
|
|
return rp2t(angvec2r(angvec), p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::DH_t::fkine() {
|
|
|
|
|
float ct = cosf(theta), st = sinf(theta); // cosθ, sinθ
|
|
|
|
|
float ca = cosf(alpha), sa = sinf(alpha); // cosα, sinα
|
|
|
|
|
|
|
|
|
|
// T =
|
|
|
|
|
// | cθ -sθcα sθsα acθ |
|
|
|
|
|
// | sθ cθcα -cθsα asθ |
|
|
|
|
|
// | 0 sα cα d |
|
|
|
|
|
// | 0 0 0 1 |
|
|
|
|
|
T[0][0] = ct;
|
|
|
|
|
T[0][1] = -st * ca;
|
|
|
|
|
T[0][2] = st * sa;
|
|
|
|
|
T[0][3] = a * ct;
|
|
|
|
|
|
|
|
|
|
T[1][0] = st;
|
|
|
|
|
T[1][1] = ct * ca;
|
|
|
|
|
T[1][2] = -ct * sa;
|
|
|
|
|
T[1][3] = a * st;
|
|
|
|
|
|
|
|
|
|
T[2][0] = 0;
|
|
|
|
|
T[2][1] = sa;
|
|
|
|
|
T[2][2] = ca;
|
|
|
|
|
T[2][3] = d;
|
|
|
|
|
|
|
|
|
|
T[3][0] = 0;
|
|
|
|
|
T[3][1] = 0;
|
|
|
|
|
T[3][2] = 0;
|
|
|
|
|
T[3][3] = 1;
|
|
|
|
|
|
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
robotics::Link::Link(float theta,
|
|
|
|
|
float d,
|
|
|
|
|
float a,
|
|
|
|
|
float alpha,
|
|
|
|
|
robotics::Joint_Type_e type,
|
|
|
|
|
float offset,
|
|
|
|
|
float qmin,
|
|
|
|
|
float qmax,
|
|
|
|
|
float m,
|
|
|
|
|
Matrixf<3, 1> rc,
|
|
|
|
|
Matrixf<3, 3> I) {
|
|
|
|
|
dh_.theta = theta;
|
|
|
|
|
dh_.d = d;
|
|
|
|
|
dh_.alpha = alpha;
|
|
|
|
|
dh_.a = a;
|
|
|
|
|
type_ = type;
|
|
|
|
|
offset_ = offset;
|
|
|
|
|
qmin_ = qmin;
|
|
|
|
|
qmax_ = qmax;
|
|
|
|
|
m_ = m;
|
|
|
|
|
rc_ = rc;
|
|
|
|
|
I_ = I;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
robotics::Link::Link(const Link& link) {
|
|
|
|
|
dh_.theta = link.dh_.theta;
|
|
|
|
|
dh_.d = link.dh_.d;
|
|
|
|
|
dh_.alpha = link.dh_.alpha;
|
|
|
|
|
dh_.a = link.dh_.a;
|
|
|
|
|
type_ = link.type_;
|
|
|
|
|
offset_ = link.offset_;
|
|
|
|
|
qmin_ = link.qmin_;
|
|
|
|
|
qmax_ = link.qmax_;
|
|
|
|
|
m_ = link.m_;
|
|
|
|
|
rc_ = link.rc_;
|
|
|
|
|
I_ = link.I_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
robotics::Link& robotics::Link::operator=(Link link) {
|
|
|
|
|
dh_.theta = link.dh_.theta;
|
|
|
|
|
dh_.d = link.dh_.d;
|
|
|
|
|
dh_.alpha = link.dh_.alpha;
|
|
|
|
|
dh_.a = link.dh_.a;
|
|
|
|
|
type_ = link.type_;
|
|
|
|
|
offset_ = link.offset_;
|
|
|
|
|
qmin_ = link.qmin_;
|
|
|
|
|
qmax_ = link.qmax_;
|
|
|
|
|
m_ = link.m_;
|
|
|
|
|
rc_ = link.rc_;
|
|
|
|
|
I_ = link.I_;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Matrixf<4, 4> robotics::Link::T(float q) {
|
|
|
|
|
if (type_ == R) {
|
|
|
|
|
if (qmin_ >= qmax_)
|
|
|
|
|
dh_.theta = q + offset_;
|
|
|
|
|
else
|
|
|
|
|
dh_.theta = math::limit(q + offset_, qmin_, qmax_);
|
|
|
|
|
} else {
|
|
|
|
|
if (qmin_ >= qmax_)
|
|
|
|
|
dh_.d = q + offset_;
|
|
|
|
|
else
|
|
|
|
|
dh_.d = math::limit(q + offset_, qmin_, qmax_);
|
|
|
|
|
}
|
|
|
|
|
return dh_.fkine();
|
|
|
|
|
}
|
2024-05-10 14:36:27 +08:00
|
|
|
|
|
2024-05-11 06:06:43 +08:00
|
|
|
|
bool robotics::check_ikine(Matrixf<4, 4> T)
|
|
|
|
|
{
|
|
|
|
|
const float L1=0.151,L3=0.350,L4=0.139;
|
|
|
|
|
Matrixf<3,1> Pe = T.block<3, 1>(0, 3); // p=T(1:3,4)
|
|
|
|
|
Matrixf<3,1> Ze = T.block<3, 1>(0, 2); // z=T(1:3,3)
|
|
|
|
|
|
|
|
|
|
//求解W点(球形腕)
|
|
|
|
|
Matrixf<3,1> Pw = Pe-L4*Ze;
|
|
|
|
|
float length = Pw.norm();
|
|
|
|
|
//满足构成三角形条件,theta2才有解
|
|
|
|
|
if(length <= (L1+L3) && length >= (L3-L1))
|
|
|
|
|
return true;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 14:36:27 +08:00
|
|
|
|
Matrixf<5,2> robotics::my_analytic_ikine(Matrixf<4, 4> T)
|
|
|
|
|
{
|
|
|
|
|
const float L1=0.151,L3=0.350,L4=0.139;
|
|
|
|
|
Matrixf<3,1> Pe = T.block<3, 1>(0, 3); // p=T(1:3,4)
|
|
|
|
|
Matrixf<3,1> Ze = T.block<3, 1>(0, 2); // z=T(1:3,3)
|
|
|
|
|
//求解W点(球形腕)
|
|
|
|
|
Matrixf<3,1> Pw = Pe-L4*Ze;
|
|
|
|
|
//求解theta1
|
|
|
|
|
float theta_1 = atan2(Pw[1][0],Pw[0][0]);
|
|
|
|
|
//求解theta2
|
|
|
|
|
//L1^2 + L3^2 - 2*L1*L3*cos_th2 = norm(Pw)^2
|
|
|
|
|
float cos_th2 = (L1*L1 + L3*L3 - Pw.norm()*Pw.norm())/(2*L1*L3);
|
|
|
|
|
float theta_2 = acosf(cos_th2) ; //关节2 有PI/2的offset
|
|
|
|
|
//计算T02
|
|
|
|
|
DH_t l1_dh = {
|
|
|
|
|
.theta = theta_1,
|
|
|
|
|
.d = L1,
|
|
|
|
|
.a = 0,
|
|
|
|
|
.alpha = PI/2,
|
|
|
|
|
};
|
|
|
|
|
DH_t l2_dh = {
|
|
|
|
|
.theta = theta_2,
|
|
|
|
|
.d = 0,
|
|
|
|
|
.a = 0,
|
|
|
|
|
.alpha = PI/2,
|
|
|
|
|
};
|
|
|
|
|
Matrixf<4,4> T02 = l1_dh.fkine() * l2_dh.fkine();
|
|
|
|
|
|
|
|
|
|
Matrixf<4,4> T25 = invT(T02) * T;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//腕关节(theta_5)朝上 >0
|
|
|
|
|
float theta_30 = atan2(T25[1][2],T25[0][2]);
|
|
|
|
|
float theta_40 = atan2(sqrtf(T25[0][2]*T25[0][2] + T25[1][2]*T25[1][2]),T25[2][2]);
|
|
|
|
|
float theta_50 = atan2(T25[2][1],-T25[2][0]);
|
|
|
|
|
//腕关节(theta_5)朝下 <0
|
|
|
|
|
float theta_31 = atan2(-T25[1][2],-T25[0][2]);
|
|
|
|
|
float theta_41 = atan2(-sqrtf(T25[0][2]*T25[0][2] + T25[1][2]*T25[1][2]),T25[2][2]);
|
|
|
|
|
float theta_51 = atan2(-T25[2][1],T25[2][0]);
|
2024-05-11 06:06:43 +08:00
|
|
|
|
//
|
|
|
|
|
// float q_data[10] = {theta_1,theta_2 - PI/2,theta_30,theta_40,theta_50,
|
|
|
|
|
// theta_1,theta_2 - PI/2,theta_31,theta_41,theta_51};//关节2 有PI/2的offset
|
|
|
|
|
//
|
|
|
|
|
float q_data[10]={ theta_1,theta_1 ,
|
|
|
|
|
theta_2 - PI/2 , theta_2 - PI/2,
|
|
|
|
|
theta_30,theta_31 ,
|
|
|
|
|
theta_40 , theta_41 ,
|
|
|
|
|
theta_50,theta_51 };
|
2024-05-10 14:36:27 +08:00
|
|
|
|
|
|
|
|
|
Matrixf<5,2> ik_q(q_data);
|
|
|
|
|
return ik_q;
|
|
|
|
|
}
|