IDMath.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. #include "IDMath.hpp"
  2. #include <cmath>
  3. #include <limits>
  4. namespace btInverseDynamics {
  5. static const idScalar kIsZero = 5 * std::numeric_limits<idScalar>::epsilon();
  6. // requirements for axis length deviation from 1.0
  7. // experimentally set from random euler angle rotation matrices
  8. static const idScalar kAxisLengthEpsilon = 10 * kIsZero;
  9. void setZero(vec3 &v) {
  10. v(0) = 0;
  11. v(1) = 0;
  12. v(2) = 0;
  13. }
  14. void setZero(vecx &v) {
  15. for (int i = 0; i < v.size(); i++) {
  16. v(i) = 0;
  17. }
  18. }
  19. void setZero(mat33 &m) {
  20. m(0, 0) = 0;
  21. m(0, 1) = 0;
  22. m(0, 2) = 0;
  23. m(1, 0) = 0;
  24. m(1, 1) = 0;
  25. m(1, 2) = 0;
  26. m(2, 0) = 0;
  27. m(2, 1) = 0;
  28. m(2, 2) = 0;
  29. }
  30. void skew(vec3& v, mat33* result) {
  31. (*result)(0, 0) = 0.0;
  32. (*result)(0, 1) = -v(2);
  33. (*result)(0, 2) = v(1);
  34. (*result)(1, 0) = v(2);
  35. (*result)(1, 1) = 0.0;
  36. (*result)(1, 2) = -v(0);
  37. (*result)(2, 0) = -v(1);
  38. (*result)(2, 1) = v(0);
  39. (*result)(2, 2) = 0.0;
  40. }
  41. idScalar maxAbs(const vecx &v) {
  42. idScalar result = 0.0;
  43. for (int i = 0; i < v.size(); i++) {
  44. const idScalar tmp = BT_ID_FABS(v(i));
  45. if (tmp > result) {
  46. result = tmp;
  47. }
  48. }
  49. return result;
  50. }
  51. idScalar maxAbs(const vec3 &v) {
  52. idScalar result = 0.0;
  53. for (int i = 0; i < 3; i++) {
  54. const idScalar tmp = BT_ID_FABS(v(i));
  55. if (tmp > result) {
  56. result = tmp;
  57. }
  58. }
  59. return result;
  60. }
  61. #if (defined BT_ID_HAVE_MAT3X)
  62. idScalar maxAbsMat3x(const mat3x &m) {
  63. // only used for tests -- so just loop here for portability
  64. idScalar result = 0.0;
  65. for (idArrayIdx col = 0; col < m.cols(); col++) {
  66. for (idArrayIdx row = 0; row < 3; row++) {
  67. result = BT_ID_MAX(result, std::fabs(m(row, col)));
  68. }
  69. }
  70. return result;
  71. }
  72. void mul(const mat33 &a, const mat3x &b, mat3x *result) {
  73. if (b.cols() != result->cols()) {
  74. error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
  75. static_cast<int>(b.cols()), static_cast<int>(result->cols()));
  76. abort();
  77. }
  78. for (idArrayIdx col = 0; col < b.cols(); col++) {
  79. const idScalar x = a(0,0)*b(0,col)+a(0,1)*b(1,col)+a(0,2)*b(2,col);
  80. const idScalar y = a(1,0)*b(0,col)+a(1,1)*b(1,col)+a(1,2)*b(2,col);
  81. const idScalar z = a(2,0)*b(0,col)+a(2,1)*b(1,col)+a(2,2)*b(2,col);
  82. setMat3xElem(0, col, x, result);
  83. setMat3xElem(1, col, y, result);
  84. setMat3xElem(2, col, z, result);
  85. }
  86. }
  87. void add(const mat3x &a, const mat3x &b, mat3x *result) {
  88. if (a.cols() != b.cols()) {
  89. error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
  90. static_cast<int>(a.cols()), static_cast<int>(b.cols()));
  91. abort();
  92. }
  93. for (idArrayIdx col = 0; col < b.cols(); col++) {
  94. for (idArrayIdx row = 0; row < 3; row++) {
  95. setMat3xElem(row, col, a(row, col) + b(row, col), result);
  96. }
  97. }
  98. }
  99. void sub(const mat3x &a, const mat3x &b, mat3x *result) {
  100. if (a.cols() != b.cols()) {
  101. error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
  102. static_cast<int>(a.cols()), static_cast<int>(b.cols()));
  103. abort();
  104. }
  105. for (idArrayIdx col = 0; col < b.cols(); col++) {
  106. for (idArrayIdx row = 0; row < 3; row++) {
  107. setMat3xElem(row, col, a(row, col) - b(row, col), result);
  108. }
  109. }
  110. }
  111. #endif
  112. mat33 transformX(const idScalar &alpha) {
  113. mat33 T;
  114. const idScalar cos_alpha = BT_ID_COS(alpha);
  115. const idScalar sin_alpha = BT_ID_SIN(alpha);
  116. // [1 0 0]
  117. // [0 c s]
  118. // [0 -s c]
  119. T(0, 0) = 1.0;
  120. T(0, 1) = 0.0;
  121. T(0, 2) = 0.0;
  122. T(1, 0) = 0.0;
  123. T(1, 1) = cos_alpha;
  124. T(1, 2) = sin_alpha;
  125. T(2, 0) = 0.0;
  126. T(2, 1) = -sin_alpha;
  127. T(2, 2) = cos_alpha;
  128. return T;
  129. }
  130. mat33 transformY(const idScalar &beta) {
  131. mat33 T;
  132. const idScalar cos_beta = BT_ID_COS(beta);
  133. const idScalar sin_beta = BT_ID_SIN(beta);
  134. // [c 0 -s]
  135. // [0 1 0]
  136. // [s 0 c]
  137. T(0, 0) = cos_beta;
  138. T(0, 1) = 0.0;
  139. T(0, 2) = -sin_beta;
  140. T(1, 0) = 0.0;
  141. T(1, 1) = 1.0;
  142. T(1, 2) = 0.0;
  143. T(2, 0) = sin_beta;
  144. T(2, 1) = 0.0;
  145. T(2, 2) = cos_beta;
  146. return T;
  147. }
  148. mat33 transformZ(const idScalar &gamma) {
  149. mat33 T;
  150. const idScalar cos_gamma = BT_ID_COS(gamma);
  151. const idScalar sin_gamma = BT_ID_SIN(gamma);
  152. // [ c s 0]
  153. // [-s c 0]
  154. // [ 0 0 1]
  155. T(0, 0) = cos_gamma;
  156. T(0, 1) = sin_gamma;
  157. T(0, 2) = 0.0;
  158. T(1, 0) = -sin_gamma;
  159. T(1, 1) = cos_gamma;
  160. T(1, 2) = 0.0;
  161. T(2, 0) = 0.0;
  162. T(2, 1) = 0.0;
  163. T(2, 2) = 1.0;
  164. return T;
  165. }
  166. mat33 tildeOperator(const vec3 &v) {
  167. mat33 m;
  168. m(0, 0) = 0.0;
  169. m(0, 1) = -v(2);
  170. m(0, 2) = v(1);
  171. m(1, 0) = v(2);
  172. m(1, 1) = 0.0;
  173. m(1, 2) = -v(0);
  174. m(2, 0) = -v(1);
  175. m(2, 1) = v(0);
  176. m(2, 2) = 0.0;
  177. return m;
  178. }
  179. void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T) {
  180. const idScalar sa = BT_ID_SIN(alpha);
  181. const idScalar ca = BT_ID_COS(alpha);
  182. const idScalar st = BT_ID_SIN(theta);
  183. const idScalar ct = BT_ID_COS(theta);
  184. (*r)(0) = a;
  185. (*r)(1) = -sa * d;
  186. (*r)(2) = ca * d;
  187. (*T)(0, 0) = ct;
  188. (*T)(0, 1) = -st;
  189. (*T)(0, 2) = 0.0;
  190. (*T)(1, 0) = st * ca;
  191. (*T)(1, 1) = ct * ca;
  192. (*T)(1, 2) = -sa;
  193. (*T)(2, 0) = st * sa;
  194. (*T)(2, 1) = ct * sa;
  195. (*T)(2, 2) = ca;
  196. }
  197. void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T) {
  198. const idScalar c = BT_ID_COS(angle);
  199. const idScalar s = -BT_ID_SIN(angle);
  200. const idScalar one_m_c = 1.0 - c;
  201. const idScalar &x = axis(0);
  202. const idScalar &y = axis(1);
  203. const idScalar &z = axis(2);
  204. (*T)(0, 0) = x * x * one_m_c + c;
  205. (*T)(0, 1) = x * y * one_m_c - z * s;
  206. (*T)(0, 2) = x * z * one_m_c + y * s;
  207. (*T)(1, 0) = x * y * one_m_c + z * s;
  208. (*T)(1, 1) = y * y * one_m_c + c;
  209. (*T)(1, 2) = y * z * one_m_c - x * s;
  210. (*T)(2, 0) = x * z * one_m_c - y * s;
  211. (*T)(2, 1) = y * z * one_m_c + x * s;
  212. (*T)(2, 2) = z * z * one_m_c + c;
  213. }
  214. bool isPositiveDefinite(const mat33 &m) {
  215. // test if all upper left determinants are positive
  216. if (m(0, 0) <= 0) { // upper 1x1
  217. return false;
  218. }
  219. if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0) { // upper 2x2
  220. return false;
  221. }
  222. if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
  223. m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
  224. m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
  225. return false;
  226. }
  227. return true;
  228. }
  229. bool isPositiveSemiDefinite(const mat33 &m) {
  230. // test if all upper left determinants are positive
  231. if (m(0, 0) < 0) { // upper 1x1
  232. return false;
  233. }
  234. if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0) { // upper 2x2
  235. return false;
  236. }
  237. if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
  238. m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
  239. m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0) {
  240. return false;
  241. }
  242. return true;
  243. }
  244. bool isPositiveSemiDefiniteFuzzy(const mat33 &m) {
  245. // test if all upper left determinants are positive
  246. if (m(0, 0) < -kIsZero) { // upper 1x1
  247. return false;
  248. }
  249. if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero) { // upper 2x2
  250. return false;
  251. }
  252. if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
  253. m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
  254. m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero) {
  255. return false;
  256. }
  257. return true;
  258. }
  259. idScalar determinant(const mat33 &m) {
  260. return m(0, 0) * m(1, 1) * m(2, 2) + m(0, 1) * m(1, 2) * m(2, 0) + m(0, 2) * m(1, 0) * m(2, 1) -
  261. m(0, 2) * m(1, 1) * m(2, 0) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2);
  262. }
  263. bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint) {
  264. // TODO(Thomas) do we really want this?
  265. // in cases where the inertia tensor about the center of mass is zero,
  266. // the determinant of the inertia tensor about the joint axis is almost
  267. // zero and can have a very small negative value.
  268. if (!isPositiveSemiDefiniteFuzzy(I)) {
  269. error_message("invalid inertia matrix for body %d, not positive definite "
  270. "(fixed joint)\n",
  271. index);
  272. error_message("matrix is:\n"
  273. "[%.20e %.20e %.20e;\n"
  274. "%.20e %.20e %.20e;\n"
  275. "%.20e %.20e %.20e]\n",
  276. I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
  277. I(2, 2));
  278. return false;
  279. }
  280. // check triangle inequality, must have I(i,i)+I(j,j)>=I(k,k)
  281. if (!has_fixed_joint) {
  282. if (I(0, 0) + I(1, 1) < I(2, 2)) {
  283. error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
  284. error_message("matrix is:\n"
  285. "[%.20e %.20e %.20e;\n"
  286. "%.20e %.20e %.20e;\n"
  287. "%.20e %.20e %.20e]\n",
  288. I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
  289. I(2, 2));
  290. return false;
  291. }
  292. if (I(0, 0) + I(1, 1) < I(2, 2)) {
  293. error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
  294. error_message("matrix is:\n"
  295. "[%.20e %.20e %.20e;\n"
  296. "%.20e %.20e %.20e;\n"
  297. "%.20e %.20e %.20e]\n",
  298. I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
  299. I(2, 2));
  300. return false;
  301. }
  302. if (I(1, 1) + I(2, 2) < I(0, 0)) {
  303. error_message("invalid inertia tensor for body %d, I(1,1) + I(2,2) < I(0,0)\n", index);
  304. error_message("matrix is:\n"
  305. "[%.20e %.20e %.20e;\n"
  306. "%.20e %.20e %.20e;\n"
  307. "%.20e %.20e %.20e]\n",
  308. I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
  309. I(2, 2));
  310. return false;
  311. }
  312. }
  313. // check positive/zero diagonal elements
  314. for (int i = 0; i < 3; i++) {
  315. if (I(i, i) < 0) { // accept zero
  316. error_message("invalid inertia tensor, I(%d,%d)= %e <0\n", i, i, I(i, i));
  317. return false;
  318. }
  319. }
  320. // check symmetry
  321. if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero) {
  322. error_message("invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
  323. "%e\n",
  324. index, I(1, 0) - I(0, 1));
  325. return false;
  326. }
  327. if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero) {
  328. error_message("invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
  329. "%e\n",
  330. index, I(2, 0) - I(0, 2));
  331. return false;
  332. }
  333. if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero) {
  334. error_message("invalid inertia tensor body %d I(1,2)!=I(2,1). I(1,2)-I(2,1)= %e\n", index,
  335. I(1, 2) - I(2, 1));
  336. return false;
  337. }
  338. return true;
  339. }
  340. bool isValidTransformMatrix(const mat33 &m) {
  341. #define print_mat(x) \
  342. error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
  343. x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
  344. // check for unit length column vectors
  345. for (int i = 0; i < 3; i++) {
  346. const idScalar length_minus_1 =
  347. BT_ID_FABS(m(0, i) * m(0, i) + m(1, i) * m(1, i) + m(2, i) * m(2, i) - 1.0);
  348. if (length_minus_1 > kAxisLengthEpsilon) {
  349. error_message("Not a valid rotation matrix (column %d not unit length)\n"
  350. "column = [%.18e %.18e %.18e]\n"
  351. "length-1.0= %.18e\n",
  352. i, m(0, i), m(1, i), m(2, i), length_minus_1);
  353. print_mat(m);
  354. return false;
  355. }
  356. }
  357. // check for orthogonal column vectors
  358. if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon) {
  359. error_message("Not a valid rotation matrix (columns 0 and 1 not orthogonal)\n");
  360. print_mat(m);
  361. return false;
  362. }
  363. if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon) {
  364. error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
  365. print_mat(m);
  366. return false;
  367. }
  368. if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon) {
  369. error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
  370. print_mat(m);
  371. return false;
  372. }
  373. // check determinant (rotation not reflection)
  374. if (determinant(m) <= 0) {
  375. error_message("Not a valid rotation matrix (determinant <=0)\n");
  376. print_mat(m);
  377. return false;
  378. }
  379. return true;
  380. }
  381. bool isUnitVector(const vec3 &vector) {
  382. return BT_ID_FABS(vector(0) * vector(0) + vector(1) * vector(1) + vector(2) * vector(2) - 1.0) <
  383. kIsZero;
  384. }
  385. vec3 rpyFromMatrix(const mat33 &rot) {
  386. vec3 rpy;
  387. rpy(2) = BT_ID_ATAN2(-rot(1, 0), rot(0, 0));
  388. rpy(1) = BT_ID_ATAN2(rot(2, 0), BT_ID_COS(rpy(2)) * rot(0, 0) - BT_ID_SIN(rpy(0)) * rot(1, 0));
  389. rpy(0) = BT_ID_ATAN2(-rot(2, 0), rot(2, 2));
  390. return rpy;
  391. }
  392. }