Delta Robot example
Dependencies: BufferedSerial Eigen
Fork of TCPSocket_Example by
DeltaKinematics.cpp
- Committer:
- je310
- Date:
- 2018-10-07
- Revision:
- 4:778bc352c47f
File content as of revision 4:778bc352c47f:
// DeltaKinematics - kinematics computation for delta parallel robot arm // Copyright(C) 2018 Szymon Szantula // // This program is free software : you can redistribute it and / or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program.If not, see <http://www.gnu.org/licenses/.> #include "DeltaKinematics.h" template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_SQRT3 = std::sqrt(3.0); template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_HSQRT3 = std::sqrt(3.0)/ 2.0; template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_DEG2RAD_FACTOR = M_PI / 180.0; template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_RAD2DEG_FACTOR = 180.0 / M_PI; template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_MROTZ120[3][3] = {{-0.5, 0.866025403784439, 0.0}, {-0.866025403784439, -0.5, 0.0}, {0.0, 0.0, 1.0}}; template <typename RealDataType> const RealDataType DeltaKinematics<RealDataType>::_ROTZ120[3][3] = {{-0.5, -0.866025403784439, 0.0}, {0.866025403784439, -0.5, 0.0}, {0.0, 0.0, 1.0}}; template <typename RealDataType> DeltaKinematics<RealDataType>::DeltaKinematics(DeltaGeometricDim dim) { _sb = dim.sb; _sp = dim.sp; _Ll = dim.L; _l = dim.l; _h = dim.h; _max_neg_angle = dim.max_neg_angle; _min_parallelogram_angle = dim.min_parallelogram_angle; Initialise(); } template <typename RealDataType> void DeltaKinematics<RealDataType>::Initialise() { _wb = _SQRT3 / 6 * _sb; _ub = _SQRT3 / 3 * _sb; _wp = _SQRT3 / 6 * _sp; _up = _SQRT3 / 3 * _sp; _B1[0] = 0; _B1[1] = -_wb; _B1[2] = 0; _B2[0] = _HSQRT3 * _wb; _B2[1] = _wb / 2; _B2[2] = 0; _B3[0] = -_HSQRT3 * _wb; _B3[1] = _wb / 2; _B3[2] = 0; _Pp1[0] = 0; _Pp1[1] = -_up; _Pp1[2] = 0; _Pp2[0] = _sp / 2; _Pp2[1] = -_wp; _Pp2[2] = 0; _Pp3[0] = -_sp / 2; _Pp3[1] = -_wp; _Pp3[2] = 0; _b1[0] = _sb / 2; _b1[1] = -_wb; _b1[2] = 0; _b2[0] = 0; _b2[1] = -_ub; _b2[2] = 0; _b3[0] = -_sb / 2; _b3[1] = -_wb; _b3[2] = 0; } template <typename RealDataType> void DeltaKinematics<RealDataType>::RotateByMatrix(RealDataType *point, const RealDataType (*matrix)[3]) { RealDataType temp[3]; for (int i = 0; i < 3; ++i) { temp[i] = matrix[i][0] * point[0] + matrix[i][1] * point[1] + matrix[i][2] * point[2]; } point[0] = temp[0]; point[1] = temp[1]; point[2] = temp[2]; } template <typename RealDataType> int DeltaKinematics<RealDataType>::CalculateIpk(DeltaVector *v, int num) { RealDataType temp_p[3]; RealDataType temp_phi; int flag; for (int i = 0; i < num; ++i) { /* compute p1*/ temp_p[0] = _Pp1[0] + v[i].x; temp_p[1] = _Pp1[1] + v[i].y; temp_p[2] = _Pp1[2] + v[i].z; /* calculate angle */ flag = CalculateAngle(_b1, temp_p, &temp_phi); if (flag) { return 1; } else { v[i].phi1 = temp_phi; } /* compute p2 and change reference system */ temp_p[0] = v[i].x; temp_p[1] = v[i].y; temp_p[2] = v[i].z; RotateByMatrix(temp_p, _MROTZ120); temp_p[0] += _Pp1[0]; temp_p[1] += _Pp1[1]; temp_p[2] += _Pp1[2]; /* check all conditions */ flag = CalculateAngle(_b1, temp_p, &temp_phi); if (flag) { return 1; } else { v[i].phi2 = temp_phi; } /* compute p3 change reference system */ temp_p[0] = v[i].x; temp_p[1] = v[i].y; temp_p[2] = v[i].z; RotateByMatrix(temp_p, _ROTZ120); temp_p[0] += _Pp1[0]; temp_p[1] += _Pp1[1]; temp_p[2] += _Pp1[2]; /* check all conditions */ flag = CalculateAngle(_b1, temp_p, &temp_phi); if (flag) { return 1; } else { v[i].phi3 = temp_phi; } } return 0; } template <typename RealDataType> int DeltaKinematics<RealDataType>::CalculateFpk(DeltaVector *v, int num) { _A1[0] = 0.0; RealDataType hsp = _sp / 2.0; int flag; for (int i = 0; i < num; ++i) { _A1[1] = -_wb - _Ll * std::cos(_DEG2RAD_FACTOR * v[i].phi1) + _up; _A1[2] = -_Ll * std::sin(_DEG2RAD_FACTOR * v[i].phi1); _A2[0] = _HSQRT3 * (_wb + _Ll * std::cos(_DEG2RAD_FACTOR * v[i].phi2)) - hsp; _A2[1] = 0.5 * (_wb + _Ll * std::cos(_DEG2RAD_FACTOR * v[i].phi2)) - _wp; _A2[2] = -_Ll * std::sin(_DEG2RAD_FACTOR * v[i].phi2); _A3[0] = -_HSQRT3 * (_wb + _Ll * std::cos(_DEG2RAD_FACTOR * v[i].phi3)) + hsp; _A3[1] = 0.5 * (_wb + _Ll * std::cos(_DEG2RAD_FACTOR * v[i].phi3)) - _wp; _A3[2] = -_Ll * std::sin(_DEG2RAD_FACTOR * v[i].phi3); if (_A1[2] == _A2[2] && _A2[2] == _A3[2]) { flag = ThreeSpheresIntersectionB(&v[i]); } else { flag = ThreeSpheresIntersectionA(&v[i]); } if (flag) { return flag; } } return 0; } template <typename RealDataType> int DeltaKinematics<RealDataType>::ThreeSpheresIntersectionA(DeltaVector *v) { RealDataType a11, a12, a13, a21, a22, a23, b1, b2, a1, a2, a3, a4, a5, a6, a7, a, b, c, delta; a11 = 2 * (_A3[0] - _A1[0]); a12 = 2 * (_A3[1] - _A1[1]); a13 = 2 * (_A3[2] - _A1[2]); if (a13 == 0.0) return 1; a21 = 2 * (_A3[0] - _A2[0]); a22 = 2 * (_A3[1] - _A2[1]); a23 = 2 * (_A3[2] - _A2[2]); if (a23 == 0.0) return 1; RealDataType A3_pow2 = _A3[0] * _A3[0] + _A3[1] * _A3[1] + _A3[2] * _A3[2]; b1 = -_A1[0] * _A1[0] - _A1[1] * _A1[1] - _A1[2] * _A1[2] + A3_pow2; b2 = -_A2[0] * _A2[0] - _A2[1] * _A2[1] - _A2[2] * _A2[2] + A3_pow2; a1 = a11 / a13 - a21 / a23; a2 = a12 / a13 - a22 / a23; a3 = b2 / a23 - b1 / a13; if (a1 == 0.0) return 1; a4 = -a2 / a1; a5 = -a3 / a1; a6 = (-a21 * a4 - a22) / a23; a7 = (b2 - a21 * a5) / a23; a = a4 * a4 + 1 + a6 * a6; if (a == 0.0) return 1; b = 2 * a4 * (a5 - _A1[0]) - 2 * _A1[1] + 2 * a6 * (a7 - _A1[2]); c = a5 * (a5 - 2 * _A1[0]) + a7 * (a7 - 2 * _A1[2]) + _A1[0] * _A1[0] + _A1[1] * _A1[1] + _A1[2] * _A1[2] - _l * _l; if ((delta = b * b - 4 * a * c) < 0.0) return 1; DeltaVector pp1, pp2; pp1.y = (-b + std::sqrt(delta)) / (2 * a); pp1.x = a4 * pp1.y + a5; pp1.z = a6 * pp1.y + a7; pp2.y = (-b - std::sqrt(delta)) / (2 * a); pp2.x = a4 * pp2.y + a5; pp2.z = a6 * pp2.y + a7; if (pp1.z < 0.0 && CalculateIpk(&pp1, 1) == 0) { v->x = pp1.x; v->y = pp1.y; v->z = pp1.z; return 0; } else if (pp2.z < 0.0 && CalculateIpk(&pp2, 1) == 0) { v->x = pp2.x; v->y = pp2.y; v->z = pp2.z; return 0; } else { return 1; } } template <typename RealDataType> int DeltaKinematics<RealDataType>::ThreeSpheresIntersectionB(DeltaVector *v) { RealDataType a, b, c, d, e, f, zn, B, C, delta; zn = _A1[2]; a = 2 * (_A3[0] - _A1[0]); b = 2 * (_A3[1] - _A1[1]); d = 2 * (_A3[0] - _A2[0]); e = 2 * (_A3[1] - _A2[1]); RealDataType A3_pow2 = _A3[0] * _A3[0] + _A3[1] * _A3[1]; c = -_A1[0] * _A1[0] - _A1[1] * _A1[1] + A3_pow2; f = -_A2[0] * _A2[0] - _A2[1] * _A2[1] + A3_pow2; DeltaVector pp; RealDataType denom = a * e - b * d; if (denom == 0.0) return 1; pp.x = (c * e - b * f) / denom; pp.y = (a * f - c * d) / denom; B = -2*zn; C = zn * zn - _l * _l + (pp.x - _A1[0]) * (pp.x - _A1[0]) + (pp.y - _A1[1]) * (pp.y - _A1[1]); delta = B * B - 4 * C; if (delta < 0.0) return 1; RealDataType z1, z2; z1 = (-B + std::sqrt(delta)) / 2; z2 = (-B - std::sqrt(delta)) / 2; pp.z = z1; if (pp.z < 0.0 && CalculateIpk(&pp, 1) == 0) { v->x = pp.x; v->y = pp.y; v->z = pp.z; return 0; } pp.z = z2; if (pp.z < 0.0 && CalculateIpk(&pp, 1) == 0) { v->x = pp.x; v->y = pp.y; v->z = pp.z; return 0; } return 1; } template <typename RealDataType> int DeltaKinematics<RealDataType>::CalculateAngle(const RealDataType *B, const RealDataType *P, RealDataType *phi) { /* length of projection of vector AP on yz plane */ RealDataType lyz = _l * _l - P[0] * P[0]; if (lyz <= 0.0) return 1; lyz = std::sqrt(lyz); /* check if gamma angle is correct */ if (P[0] != 0.0) { if (_RAD2DEG_FACTOR * std::atan(lyz / std::abs(P[0])) < _min_parallelogram_angle) return 1; } /* compute vector BP -> both points B and P should be reduced to 2D points (yz) */ RealDataType vector_bp[2]; vector_bp[0] = P[1] - B[1]; vector_bp[1] = P[2] - B[2]; /* check if vector points in right direction */ if (vector_bp[1] >= 0) return 1; /* check if the vector have right size */ RealDataType d = std::sqrt(vector_bp[1] * vector_bp[1] + vector_bp[0] * vector_bp[0]); if (d >= lyz + _Ll || d <= std::abs(lyz - _Ll)) return 1; /* calculate alpha angle */ RealDataType alpha = 180.0 + std::atan2(vector_bp[1], vector_bp[0]) * _RAD2DEG_FACTOR; /* calculate beta angle - cosine theorem */ RealDataType beta = _RAD2DEG_FACTOR * std::acos((_Ll * _Ll + d * d - lyz * lyz) / (2 * _Ll * d)); /* calculate phi angle and check max_neg_angle condition */ *phi = alpha - beta; if (*phi < _max_neg_angle) { return 1; } /* if everything is OK */ return 0; } template <typename RealDataType> void DeltaKinematics<RealDataType>::DeltaVector::Print() { #ifdef LIB_TEST_MODE std::cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << "\n" << "phi1 = " << phi1 << " " << "phi2 = " << phi2 << " " << "phi3 = " << phi3 << "\n"; #endif } template <typename RealDataType> void DeltaKinematics<RealDataType>::DeltaVector::Clear() { x = y = z = phi1 = phi2 = phi3 = 0.0; } /* Explicit instantations */ template class DeltaKinematics<float>; template class DeltaKinematics<double>;