frames.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /** \file itasc/kdl/frames.cpp
  2. * \ingroup itasc
  3. */
  4. /***************************************************************************
  5. frames.cxx - description
  6. -------------------------
  7. begin : June 2006
  8. copyright : (C) 2006 Erwin Aertbelien
  9. email : firstname.lastname@mech.kuleuven.ac.be
  10. History (only major changes)( AUTHOR-Description ) :
  11. ***************************************************************************
  12. * This library is free software; you can redistribute it and/or *
  13. * modify it under the terms of the GNU Lesser General Public *
  14. * License as published by the Free Software Foundation; either *
  15. * version 2.1 of the License, or (at your option) any later version. *
  16. * *
  17. * This library is distributed in the hope that it will be useful, *
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  20. * Lesser General Public License for more details. *
  21. * *
  22. * You should have received a copy of the GNU Lesser General Public *
  23. * License along with this library; if not, write to the Free Software *
  24. * Foundation, Inc., 51 Franklin Street, *
  25. * Fifth Floor, Boston, MA 02110-1301, USA. *
  26. * *
  27. ***************************************************************************/
  28. #include "frames.hpp"
  29. namespace KDL {
  30. #ifndef KDL_INLINE
  31. #include "frames.inl"
  32. #endif
  33. void Frame::Make4x4(double * d)
  34. {
  35. int i;
  36. int j;
  37. for (i=0;i<3;i++) {
  38. for (j=0;j<3;j++)
  39. d[i*4+j]=M(i,j);
  40. d[i*4+3] = p(i)/1000;
  41. }
  42. for (j=0;j<3;j++)
  43. d[12+j] = 0.;
  44. d[15] = 1;
  45. }
  46. Frame Frame::DH_Craig1989(double a,double alpha,double d,double theta)
  47. // returns Modified Denavit-Hartenberg parameters (According to Craig)
  48. {
  49. double ct,st,ca,sa;
  50. ct = cos(theta);
  51. st = sin(theta);
  52. sa = sin(alpha);
  53. ca = cos(alpha);
  54. return Frame(Rotation(
  55. ct, -st, 0,
  56. st*ca, ct*ca, -sa,
  57. st*sa, ct*sa, ca ),
  58. Vector(
  59. a, -sa*d, ca*d )
  60. );
  61. }
  62. Frame Frame::DH(double a,double alpha,double d,double theta)
  63. // returns Denavit-Hartenberg parameters (Non-Modified DH)
  64. {
  65. double ct,st,ca,sa;
  66. ct = cos(theta);
  67. st = sin(theta);
  68. sa = sin(alpha);
  69. ca = cos(alpha);
  70. return Frame(Rotation(
  71. ct, -st*ca, st*sa,
  72. st, ct*ca, -ct*sa,
  73. 0, sa, ca ),
  74. Vector(
  75. a*ct, a*st, d )
  76. );
  77. }
  78. double Vector2::Norm() const
  79. {
  80. double tmp0 = fabs(data[0]);
  81. double tmp1 = fabs(data[1]);
  82. if (tmp0 >= tmp1) {
  83. if (tmp1 == 0)
  84. return 0;
  85. return tmp0*sqrt(1+sqr(tmp1/tmp0));
  86. } else {
  87. return tmp1*sqrt(1+sqr(tmp0/tmp1));
  88. }
  89. }
  90. // makes v a unitvector and returns the norm of v.
  91. // if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
  92. // if this is not good, check the return value of this method.
  93. double Vector2::Normalize(double eps) {
  94. double v = this->Norm();
  95. if (v < eps) {
  96. *this = Vector2(1,0);
  97. return v;
  98. } else {
  99. *this = (*this)/v;
  100. return v;
  101. }
  102. }
  103. // do some effort not to lose precision
  104. double Vector::Norm() const
  105. {
  106. double tmp1;
  107. double tmp2;
  108. tmp1 = fabs(data[0]);
  109. tmp2 = fabs(data[1]);
  110. if (tmp1 >= tmp2) {
  111. tmp2=fabs(data[2]);
  112. if (tmp1 >= tmp2) {
  113. if (tmp1 == 0) {
  114. // only to everything exactly zero case, all other are handled correctly
  115. return 0;
  116. }
  117. return tmp1*sqrt(1+sqr(data[1]/data[0])+sqr(data[2]/data[0]));
  118. } else {
  119. return tmp2*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
  120. }
  121. } else {
  122. tmp1=fabs(data[2]);
  123. if (tmp2 > tmp1) {
  124. return tmp2*sqrt(1+sqr(data[0]/data[1])+sqr(data[2]/data[1]));
  125. } else {
  126. return tmp1*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
  127. }
  128. }
  129. }
  130. // makes v a unitvector and returns the norm of v.
  131. // if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
  132. // if this is not good, check the return value of this method.
  133. double Vector::Normalize(double eps) {
  134. double v = this->Norm();
  135. if (v < eps) {
  136. *this = Vector(1,0,0);
  137. return v;
  138. } else {
  139. *this = (*this)/v;
  140. return v;
  141. }
  142. }
  143. bool Equal(const Rotation& a,const Rotation& b,double eps) {
  144. return (Equal(a.data[0],b.data[0],eps) &&
  145. Equal(a.data[1],b.data[1],eps) &&
  146. Equal(a.data[2],b.data[2],eps) &&
  147. Equal(a.data[3],b.data[3],eps) &&
  148. Equal(a.data[4],b.data[4],eps) &&
  149. Equal(a.data[5],b.data[5],eps) &&
  150. Equal(a.data[6],b.data[6],eps) &&
  151. Equal(a.data[7],b.data[7],eps) &&
  152. Equal(a.data[8],b.data[8],eps) );
  153. }
  154. void Rotation::Ortho()
  155. {
  156. double n;
  157. n=sqrt(sqr(data[0])+sqr(data[3])+sqr(data[6]));n=(n>1e-10)?1.0/n:0.0;data[0]*=n;data[3]*=n;data[6]*=n;
  158. n=sqrt(sqr(data[1])+sqr(data[4])+sqr(data[7]));n=(n>1e-10)?1.0/n:0.0;data[1]*=n;data[4]*=n;data[7]*=n;
  159. n=sqrt(sqr(data[2])+sqr(data[5])+sqr(data[8]));n=(n>1e-10)?1.0/n:0.0;data[2]*=n;data[5]*=n;data[8]*=n;
  160. }
  161. Rotation operator *(const Rotation& lhs,const Rotation& rhs)
  162. // Complexity : 27M+27A
  163. {
  164. return Rotation(
  165. lhs.data[0]*rhs.data[0]+lhs.data[1]*rhs.data[3]+lhs.data[2]*rhs.data[6],
  166. lhs.data[0]*rhs.data[1]+lhs.data[1]*rhs.data[4]+lhs.data[2]*rhs.data[7],
  167. lhs.data[0]*rhs.data[2]+lhs.data[1]*rhs.data[5]+lhs.data[2]*rhs.data[8],
  168. lhs.data[3]*rhs.data[0]+lhs.data[4]*rhs.data[3]+lhs.data[5]*rhs.data[6],
  169. lhs.data[3]*rhs.data[1]+lhs.data[4]*rhs.data[4]+lhs.data[5]*rhs.data[7],
  170. lhs.data[3]*rhs.data[2]+lhs.data[4]*rhs.data[5]+lhs.data[5]*rhs.data[8],
  171. lhs.data[6]*rhs.data[0]+lhs.data[7]*rhs.data[3]+lhs.data[8]*rhs.data[6],
  172. lhs.data[6]*rhs.data[1]+lhs.data[7]*rhs.data[4]+lhs.data[8]*rhs.data[7],
  173. lhs.data[6]*rhs.data[2]+lhs.data[7]*rhs.data[5]+lhs.data[8]*rhs.data[8]
  174. );
  175. }
  176. Rotation Rotation::RPY(double roll,double pitch,double yaw)
  177. {
  178. double ca1,cb1,cc1,sa1,sb1,sc1;
  179. ca1 = cos(yaw); sa1 = sin(yaw);
  180. cb1 = cos(pitch);sb1 = sin(pitch);
  181. cc1 = cos(roll);sc1 = sin(roll);
  182. return Rotation(ca1*cb1,ca1*sb1*sc1 - sa1*cc1,ca1*sb1*cc1 + sa1*sc1,
  183. sa1*cb1,sa1*sb1*sc1 + ca1*cc1,sa1*sb1*cc1 - ca1*sc1,
  184. -sb1,cb1*sc1,cb1*cc1);
  185. }
  186. // Gives back a rotation matrix specified with RPY convention
  187. void Rotation::GetRPY(double& roll,double& pitch,double& yaw) const
  188. {
  189. if (fabs(data[6]) > 1.0 - epsilon ) {
  190. roll = -sign(data[6]) * atan2(data[1], data[4]);
  191. pitch= -sign(data[6]) * PI / 2;
  192. yaw = 0.0 ;
  193. } else {
  194. roll = atan2(data[7], data[8]);
  195. pitch = atan2(-data[6], sqrt( sqr(data[0]) +sqr(data[3]) ) );
  196. yaw = atan2(data[3], data[0]);
  197. }
  198. }
  199. Rotation Rotation::EulerZYZ(double Alfa,double Beta,double Gamma) {
  200. double sa,ca,sb,cb,sg,cg;
  201. sa = sin(Alfa);ca = cos(Alfa);
  202. sb = sin(Beta);cb = cos(Beta);
  203. sg = sin(Gamma);cg = cos(Gamma);
  204. return Rotation( ca*cb*cg-sa*sg, -ca*cb*sg-sa*cg, ca*sb,
  205. sa*cb*cg+ca*sg, -sa*cb*sg+ca*cg, sa*sb,
  206. -sb*cg , sb*sg, cb
  207. );
  208. }
  209. void Rotation::GetEulerZYZ(double& alfa,double& beta,double& gamma) const {
  210. if (fabs(data[6]) < epsilon ) {
  211. alfa=0.0;
  212. if (data[8]>0) {
  213. beta = 0.0;
  214. gamma= atan2(-data[1],data[0]);
  215. } else {
  216. beta = PI;
  217. gamma= atan2(data[1],-data[0]);
  218. }
  219. } else {
  220. alfa=atan2(data[5], data[2]);
  221. beta=atan2(sqrt( sqr(data[6]) +sqr(data[7]) ),data[8]);
  222. gamma=atan2(data[7], -data[6]);
  223. }
  224. }
  225. Rotation Rotation::Rot(const Vector& rotaxis,double angle) {
  226. // The formula is
  227. // V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
  228. // can be found by multiplying it with an arbitrary vector p
  229. // and noting that this vector is rotated.
  230. double ct = cos(angle);
  231. double st = sin(angle);
  232. double vt = 1-ct;
  233. Vector rotvec = rotaxis;
  234. rotvec.Normalize();
  235. return Rotation(
  236. ct + vt*rotvec(0)*rotvec(0),
  237. -rotvec(2)*st + vt*rotvec(0)*rotvec(1),
  238. rotvec(1)*st + vt*rotvec(0)*rotvec(2),
  239. rotvec(2)*st + vt*rotvec(1)*rotvec(0),
  240. ct + vt*rotvec(1)*rotvec(1),
  241. -rotvec(0)*st + vt*rotvec(1)*rotvec(2),
  242. -rotvec(1)*st + vt*rotvec(2)*rotvec(0),
  243. rotvec(0)*st + vt*rotvec(2)*rotvec(1),
  244. ct + vt*rotvec(2)*rotvec(2)
  245. );
  246. }
  247. Rotation Rotation::Rot2(const Vector& rotvec,double angle) {
  248. // rotvec should be normalized !
  249. // The formula is
  250. // V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
  251. // can be found by multiplying it with an arbitrary vector p
  252. // and noting that this vector is rotated.
  253. double ct = cos(angle);
  254. double st = sin(angle);
  255. double vt = 1-ct;
  256. return Rotation(
  257. ct + vt*rotvec(0)*rotvec(0),
  258. -rotvec(2)*st + vt*rotvec(0)*rotvec(1),
  259. rotvec(1)*st + vt*rotvec(0)*rotvec(2),
  260. rotvec(2)*st + vt*rotvec(1)*rotvec(0),
  261. ct + vt*rotvec(1)*rotvec(1),
  262. -rotvec(0)*st + vt*rotvec(1)*rotvec(2),
  263. -rotvec(1)*st + vt*rotvec(2)*rotvec(0),
  264. rotvec(0)*st + vt*rotvec(2)*rotvec(1),
  265. ct + vt*rotvec(2)*rotvec(2)
  266. );
  267. }
  268. Vector Rotation::GetRot() const
  269. // Returns a vector with the direction of the equiv. axis
  270. // and its norm is angle
  271. {
  272. Vector axis = Vector((data[7]-data[5]),
  273. (data[2]-data[6]),
  274. (data[3]-data[1]) )/2;
  275. double sa = axis.Norm();
  276. double ca = (data[0]+data[4]+data[8]-1)/2.0;
  277. double alfa;
  278. if (sa > epsilon)
  279. alfa = ::atan2(sa,ca)/sa;
  280. else {
  281. if (ca < 0.0) {
  282. alfa = KDL::PI;
  283. axis.data[0] = 0.0;
  284. axis.data[1] = 0.0;
  285. axis.data[2] = 0.0;
  286. if (data[0] > 0.0) {
  287. axis.data[0] = 1.0;
  288. } else if (data[4] > 0.0) {
  289. axis.data[1] = 1.0;
  290. } else {
  291. axis.data[2] = 1.0;
  292. }
  293. } else {
  294. alfa = 0.0;
  295. }
  296. }
  297. return axis * alfa;
  298. }
  299. Vector2 Rotation::GetXZRot() const
  300. {
  301. // [0,1,0] x Y
  302. Vector2 axis(data[7], -data[1]);
  303. double norm = axis.Normalize();
  304. if (norm < epsilon) {
  305. norm = (data[4] < 0.0) ? PI : 0.0;
  306. } else {
  307. norm = acos(data[4]);
  308. }
  309. return axis*norm;
  310. }
  311. /** Returns the rotation angle around the equiv. axis
  312. * @param axis the rotation axis is returned in this variable
  313. * @param eps : in the case of angle == 0 : rot axis is undefined and choosen
  314. * to be +/- Z-axis
  315. * in the case of angle == PI : 2 solutions, positive Z-component
  316. * of the axis is choosen.
  317. * @result returns the rotation angle (between [0..PI] )
  318. * /todo :
  319. * Check corresponding routines in rframes and rrframes
  320. */
  321. double Rotation::GetRotAngle(Vector& axis,double eps) const {
  322. double ca = (data[0]+data[4]+data[8]-1)/2.0;
  323. if (ca>1-eps) {
  324. // undefined choose the Z-axis, and angle 0
  325. axis = Vector(0,0,1);
  326. return 0;
  327. }
  328. if (ca < -1+eps) {
  329. // two solutions, choose a positive Z-component of the axis
  330. double z = sqrt( (data[8]+1)/2 );
  331. double x = (data[2])/2/z;
  332. double y = (data[5])/2/z;
  333. axis = Vector( x,y,z );
  334. return PI;
  335. }
  336. double angle = acos(ca);
  337. double sa = sin(angle);
  338. axis = Vector((data[7]-data[5])/2/sa,
  339. (data[2]-data[6])/2/sa,
  340. (data[3]-data[1])/2/sa );
  341. return angle;
  342. }
  343. bool operator==(const Rotation& a,const Rotation& b) {
  344. #ifdef KDL_USE_EQUAL
  345. return Equal(a,b);
  346. #else
  347. return ( a.data[0]==b.data[0] &&
  348. a.data[1]==b.data[1] &&
  349. a.data[2]==b.data[2] &&
  350. a.data[3]==b.data[3] &&
  351. a.data[4]==b.data[4] &&
  352. a.data[5]==b.data[5] &&
  353. a.data[6]==b.data[6] &&
  354. a.data[7]==b.data[7] &&
  355. a.data[8]==b.data[8] );
  356. #endif
  357. }
  358. }