MultiBodyTreeImpl.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286
  1. #include "MultiBodyTreeImpl.hpp"
  2. namespace btInverseDynamics
  3. {
  4. MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
  5. : m_num_bodies(num_bodies_), m_num_dofs(num_dofs_)
  6. #if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
  7. ,
  8. m_m3x(3, m_num_dofs)
  9. #endif
  10. {
  11. #if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
  12. resize(m_m3x, m_num_dofs);
  13. #endif
  14. m_body_list.resize(num_bodies_);
  15. m_parent_index.resize(num_bodies_);
  16. m_child_indices.resize(num_bodies_);
  17. m_user_int.resize(num_bodies_);
  18. m_user_ptr.resize(num_bodies_);
  19. m_world_gravity(0) = 0.0;
  20. m_world_gravity(1) = 0.0;
  21. m_world_gravity(2) = -9.8;
  22. }
  23. const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const
  24. {
  25. switch (type)
  26. {
  27. case FIXED:
  28. return "fixed";
  29. case REVOLUTE:
  30. return "revolute";
  31. case PRISMATIC:
  32. return "prismatic";
  33. case FLOATING:
  34. return "floating";
  35. case SPHERICAL:
  36. return "spherical";
  37. }
  38. return "error: invalid";
  39. }
  40. inline void indent(const int &level)
  41. {
  42. for (int j = 0; j < level; j++)
  43. id_printf(" "); // indent
  44. }
  45. void MultiBodyTree::MultiBodyImpl::printTree()
  46. {
  47. id_printf("body %.2d[%s]: root\n", 0, jointTypeToString(m_body_list[0].m_joint_type));
  48. printTree(0, 0);
  49. }
  50. void MultiBodyTree::MultiBodyImpl::printTreeData()
  51. {
  52. for (idArrayIdx i = 0; i < m_body_list.size(); i++)
  53. {
  54. RigidBody &body = m_body_list[i];
  55. id_printf("body: %d\n", static_cast<int>(i));
  56. id_printf("type: %s\n", jointTypeToString(body.m_joint_type));
  57. id_printf("q_index= %d\n", body.m_q_index);
  58. id_printf("Jac_JR= [%f;%f;%f]\n", body.m_Jac_JR(0), body.m_Jac_JR(1), body.m_Jac_JR(2));
  59. id_printf("Jac_JT= [%f;%f;%f]\n", body.m_Jac_JT(0), body.m_Jac_JT(1), body.m_Jac_JT(2));
  60. id_printf("mass = %f\n", body.m_mass);
  61. id_printf("mass * com = [%f %f %f]\n", body.m_body_mass_com(0), body.m_body_mass_com(1),
  62. body.m_body_mass_com(2));
  63. id_printf(
  64. "I_o= [%f %f %f;\n"
  65. " %f %f %f;\n"
  66. " %f %f %f]\n",
  67. body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
  68. body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
  69. body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
  70. id_printf("parent_pos_parent_body_ref= [%f %f %f]\n", body.m_parent_pos_parent_body_ref(0),
  71. body.m_parent_pos_parent_body_ref(1), body.m_parent_pos_parent_body_ref(2));
  72. }
  73. }
  74. int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const
  75. {
  76. switch (type)
  77. {
  78. case FIXED:
  79. return 0;
  80. case REVOLUTE:
  81. case PRISMATIC:
  82. return 1;
  83. case FLOATING:
  84. return 6;
  85. case SPHERICAL:
  86. return 3;
  87. }
  88. bt_id_error_message("unknown joint type %d\n", type);
  89. return 0;
  90. }
  91. void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation)
  92. {
  93. // this is adapted from URDF2Bullet.
  94. // TODO: fix this and print proper graph (similar to git --log --graph)
  95. int num_children = m_child_indices[index].size();
  96. indentation += 2;
  97. int count = 0;
  98. for (int i = 0; i < num_children; i++)
  99. {
  100. int child_index = m_child_indices[index][i];
  101. indent(indentation);
  102. id_printf("body %.2d[%s]: %.2d is child no. %d (qi= %d .. %d) \n", index,
  103. jointTypeToString(m_body_list[index].m_joint_type), child_index, (count++) + 1,
  104. m_body_list[index].m_q_index,
  105. m_body_list[index].m_q_index + bodyNumDoFs(m_body_list[index].m_joint_type));
  106. // first grandchild
  107. printTree(child_index, indentation);
  108. }
  109. }
  110. int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity)
  111. {
  112. m_world_gravity = gravity;
  113. return 0;
  114. }
  115. int MultiBodyTree::MultiBodyImpl::generateIndexSets()
  116. {
  117. m_body_revolute_list.resize(0);
  118. m_body_prismatic_list.resize(0);
  119. int q_index = 0;
  120. for (idArrayIdx i = 0; i < m_body_list.size(); i++)
  121. {
  122. RigidBody &body = m_body_list[i];
  123. body.m_q_index = -1;
  124. switch (body.m_joint_type)
  125. {
  126. case REVOLUTE:
  127. m_body_revolute_list.push_back(i);
  128. body.m_q_index = q_index;
  129. q_index++;
  130. break;
  131. case PRISMATIC:
  132. m_body_prismatic_list.push_back(i);
  133. body.m_q_index = q_index;
  134. q_index++;
  135. break;
  136. case FIXED:
  137. // do nothing
  138. break;
  139. case FLOATING:
  140. m_body_floating_list.push_back(i);
  141. body.m_q_index = q_index;
  142. q_index += 6;
  143. break;
  144. case SPHERICAL:
  145. m_body_spherical_list.push_back(i);
  146. body.m_q_index = q_index;
  147. q_index += 3;
  148. break;
  149. default:
  150. bt_id_error_message("unsupported joint type %d\n", body.m_joint_type);
  151. return -1;
  152. }
  153. }
  154. // sanity check
  155. if (q_index != m_num_dofs)
  156. {
  157. bt_id_error_message("internal error, q_index= %d but num_dofs %d\n", q_index, m_num_dofs);
  158. return -1;
  159. }
  160. m_child_indices.resize(m_body_list.size());
  161. for (idArrayIdx child = 1; child < m_parent_index.size(); child++)
  162. {
  163. const int &parent = m_parent_index[child];
  164. if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1))
  165. {
  166. m_child_indices[parent].push_back(child);
  167. }
  168. else
  169. {
  170. if (-1 == parent)
  171. {
  172. // multiple bodies are directly linked to the environment, ie, not a single root
  173. bt_id_error_message("building index sets parent(%zu)= -1 (multiple roots)\n", child);
  174. }
  175. else
  176. {
  177. // should never happen
  178. bt_id_error_message(
  179. "building index sets. parent_index[%zu]= %d, but m_parent_index.size()= %d\n",
  180. child, parent, static_cast<int>(m_parent_index.size()));
  181. }
  182. return -1;
  183. }
  184. }
  185. return 0;
  186. }
  187. void MultiBodyTree::MultiBodyImpl::calculateStaticData()
  188. {
  189. // relative kinematics that are not a function of q, u, dot_u
  190. for (idArrayIdx i = 0; i < m_body_list.size(); i++)
  191. {
  192. RigidBody &body = m_body_list[i];
  193. switch (body.m_joint_type)
  194. {
  195. case REVOLUTE:
  196. body.m_parent_vel_rel(0) = 0;
  197. body.m_parent_vel_rel(1) = 0;
  198. body.m_parent_vel_rel(2) = 0;
  199. body.m_parent_acc_rel(0) = 0;
  200. body.m_parent_acc_rel(1) = 0;
  201. body.m_parent_acc_rel(2) = 0;
  202. body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
  203. break;
  204. case PRISMATIC:
  205. body.m_body_T_parent = body.m_body_T_parent_ref;
  206. body.m_parent_Jac_JT = body.m_body_T_parent_ref.transpose() * body.m_Jac_JT;
  207. body.m_body_ang_vel_rel(0) = 0;
  208. body.m_body_ang_vel_rel(1) = 0;
  209. body.m_body_ang_vel_rel(2) = 0;
  210. body.m_body_ang_acc_rel(0) = 0;
  211. body.m_body_ang_acc_rel(1) = 0;
  212. body.m_body_ang_acc_rel(2) = 0;
  213. break;
  214. case FIXED:
  215. body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
  216. body.m_body_T_parent = body.m_body_T_parent_ref;
  217. body.m_body_ang_vel_rel(0) = 0;
  218. body.m_body_ang_vel_rel(1) = 0;
  219. body.m_body_ang_vel_rel(2) = 0;
  220. body.m_parent_vel_rel(0) = 0;
  221. body.m_parent_vel_rel(1) = 0;
  222. body.m_parent_vel_rel(2) = 0;
  223. body.m_body_ang_acc_rel(0) = 0;
  224. body.m_body_ang_acc_rel(1) = 0;
  225. body.m_body_ang_acc_rel(2) = 0;
  226. body.m_parent_acc_rel(0) = 0;
  227. body.m_parent_acc_rel(1) = 0;
  228. body.m_parent_acc_rel(2) = 0;
  229. break;
  230. case FLOATING:
  231. // no static data
  232. break;
  233. case SPHERICAL:
  234. //todo: review
  235. body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
  236. body.m_parent_vel_rel(0) = 0;
  237. body.m_parent_vel_rel(1) = 0;
  238. body.m_parent_vel_rel(2) = 0;
  239. body.m_parent_acc_rel(0) = 0;
  240. body.m_parent_acc_rel(1) = 0;
  241. body.m_parent_acc_rel(2) = 0;
  242. break;
  243. }
  244. // resize & initialize jacobians to zero.
  245. #if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
  246. body.m_body_dot_Jac_T_u(0) = 0.0;
  247. body.m_body_dot_Jac_T_u(1) = 0.0;
  248. body.m_body_dot_Jac_T_u(2) = 0.0;
  249. body.m_body_dot_Jac_R_u(0) = 0.0;
  250. body.m_body_dot_Jac_R_u(1) = 0.0;
  251. body.m_body_dot_Jac_R_u(2) = 0.0;
  252. resize(body.m_body_Jac_T, m_num_dofs);
  253. resize(body.m_body_Jac_R, m_num_dofs);
  254. body.m_body_Jac_T.setZero();
  255. body.m_body_Jac_R.setZero();
  256. #endif //
  257. }
  258. }
  259. int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const vecx &u,
  260. const vecx &dot_u, vecx *joint_forces)
  261. {
  262. if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ||
  263. joint_forces->size() != m_num_dofs)
  264. {
  265. bt_id_error_message(
  266. "wrong vector dimension. system has %d DOFs,\n"
  267. "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
  268. m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
  269. static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
  270. return -1;
  271. }
  272. // 1. relative kinematics
  273. if (-1 == calculateKinematics(q, u, dot_u, POSITION_VELOCITY_ACCELERATION))
  274. {
  275. bt_id_error_message("error in calculateKinematics\n");
  276. return -1;
  277. }
  278. // 2. update contributions to equations of motion for every body.
  279. for (idArrayIdx i = 0; i < m_body_list.size(); i++)
  280. {
  281. RigidBody &body = m_body_list[i];
  282. // 3.4 update dynamic terms (rate of change of angular & linear momentum)
  283. body.m_eom_lhs_rotational =
  284. body.m_body_I_body * body.m_body_ang_acc + body.m_body_mass_com.cross(body.m_body_acc) +
  285. body.m_body_ang_vel.cross(body.m_body_I_body * body.m_body_ang_vel) -
  286. body.m_body_moment_user;
  287. body.m_eom_lhs_translational =
  288. body.m_body_ang_acc.cross(body.m_body_mass_com) + body.m_mass * body.m_body_acc +
  289. body.m_body_ang_vel.cross(body.m_body_ang_vel.cross(body.m_body_mass_com)) -
  290. body.m_body_force_user;
  291. }
  292. // 3. calculate full set of forces at parent joint
  293. // (not directly calculating the joint force along the free direction
  294. // simplifies inclusion of fixed joints.
  295. // An alternative would be to fuse bodies in a pre-processing step,
  296. // but that would make changing masses online harder (eg, payload masses
  297. // added with fixed joints to a gripper)
  298. // Also, this enables adding zero weight bodies as a way to calculate frame poses
  299. // for force elements, etc.
  300. for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--)
  301. {
  302. // sum of forces and moments acting on this body from its children
  303. vec3 sum_f_children;
  304. vec3 sum_m_children;
  305. setZero(sum_f_children);
  306. setZero(sum_m_children);
  307. for (idArrayIdx child_list_idx = 0; child_list_idx < m_child_indices[body_idx].size();
  308. child_list_idx++)
  309. {
  310. const RigidBody &child = m_body_list[m_child_indices[body_idx][child_list_idx]];
  311. vec3 child_joint_force_in_this_frame =
  312. child.m_body_T_parent.transpose() * child.m_force_at_joint;
  313. sum_f_children -= child_joint_force_in_this_frame;
  314. sum_m_children -= child.m_body_T_parent.transpose() * child.m_moment_at_joint +
  315. child.m_parent_pos_parent_body.cross(child_joint_force_in_this_frame);
  316. }
  317. RigidBody &body = m_body_list[body_idx];
  318. body.m_force_at_joint = body.m_eom_lhs_translational - sum_f_children;
  319. body.m_moment_at_joint = body.m_eom_lhs_rotational - sum_m_children;
  320. }
  321. // 4. Calculate Joint forces.
  322. // These are the components of force_at_joint/moment_at_joint
  323. // in the free directions given by Jac_JT/Jac_JR
  324. // 4.1 revolute joints
  325. for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
  326. {
  327. RigidBody &body = m_body_list[m_body_revolute_list[i]];
  328. // (*joint_forces)(body.m_q_index) = body.m_Jac_JR.transpose() * body.m_moment_at_joint;
  329. (*joint_forces)(body.m_q_index) = body.m_Jac_JR.dot(body.m_moment_at_joint);
  330. }
  331. // 4.2 for prismatic joints
  332. for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
  333. {
  334. RigidBody &body = m_body_list[m_body_prismatic_list[i]];
  335. // (*joint_forces)(body.m_q_index) = body.m_Jac_JT.transpose() * body.m_force_at_joint;
  336. (*joint_forces)(body.m_q_index) = body.m_Jac_JT.dot(body.m_force_at_joint);
  337. }
  338. // 4.3 floating bodies (6-DoF joints)
  339. for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
  340. {
  341. RigidBody &body = m_body_list[m_body_floating_list[i]];
  342. (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
  343. (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
  344. (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
  345. (*joint_forces)(body.m_q_index + 3) = body.m_force_at_joint(0);
  346. (*joint_forces)(body.m_q_index + 4) = body.m_force_at_joint(1);
  347. (*joint_forces)(body.m_q_index + 5) = body.m_force_at_joint(2);
  348. }
  349. // 4.4 spherical bodies (3-DoF joints)
  350. for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
  351. {
  352. //todo: review
  353. RigidBody &body = m_body_list[m_body_spherical_list[i]];
  354. (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
  355. (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
  356. (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
  357. }
  358. return 0;
  359. }
  360. int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u,
  361. const KinUpdateType type)
  362. {
  363. if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs)
  364. {
  365. bt_id_error_message(
  366. "wrong vector dimension. system has %d DOFs,\n"
  367. "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
  368. m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
  369. static_cast<int>(dot_u.size()));
  370. return -1;
  371. }
  372. if (type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION)
  373. {
  374. bt_id_error_message("invalid type %d\n", type);
  375. return -1;
  376. }
  377. // 1. update relative kinematics
  378. // 1.1 for revolute
  379. for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
  380. {
  381. RigidBody &body = m_body_list[m_body_revolute_list[i]];
  382. mat33 T;
  383. bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &T);
  384. body.m_body_T_parent = T * body.m_body_T_parent_ref;
  385. if (type >= POSITION_VELOCITY)
  386. {
  387. body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
  388. }
  389. if (type >= POSITION_VELOCITY_ACCELERATION)
  390. {
  391. body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
  392. }
  393. }
  394. // 1.2 for prismatic
  395. for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
  396. {
  397. RigidBody &body = m_body_list[m_body_prismatic_list[i]];
  398. body.m_parent_pos_parent_body =
  399. body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
  400. if (type >= POSITION_VELOCITY)
  401. {
  402. body.m_parent_vel_rel =
  403. body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
  404. }
  405. if (type >= POSITION_VELOCITY_ACCELERATION)
  406. {
  407. body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
  408. }
  409. }
  410. // 1.3 fixed joints: nothing to do
  411. // 1.4 6dof joints:
  412. for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
  413. {
  414. RigidBody &body = m_body_list[m_body_floating_list[i]];
  415. body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
  416. transformY(q(body.m_q_index + 1)) *
  417. transformX(q(body.m_q_index));
  418. body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
  419. body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
  420. body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
  421. body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
  422. if (type >= POSITION_VELOCITY)
  423. {
  424. body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
  425. body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
  426. body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
  427. body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
  428. body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
  429. body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
  430. body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
  431. }
  432. if (type >= POSITION_VELOCITY_ACCELERATION)
  433. {
  434. body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
  435. body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
  436. body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
  437. body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
  438. body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
  439. body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
  440. body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
  441. }
  442. }
  443. for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
  444. {
  445. //todo: review
  446. RigidBody &body = m_body_list[m_body_spherical_list[i]];
  447. mat33 T;
  448. T = transformX(q(body.m_q_index)) *
  449. transformY(q(body.m_q_index + 1)) *
  450. transformZ(q(body.m_q_index + 2));
  451. body.m_body_T_parent = T * body.m_body_T_parent_ref;
  452. body.m_parent_pos_parent_body(0)=0;
  453. body.m_parent_pos_parent_body(1)=0;
  454. body.m_parent_pos_parent_body(2)=0;
  455. body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
  456. if (type >= POSITION_VELOCITY)
  457. {
  458. body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
  459. body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
  460. body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
  461. body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
  462. }
  463. if (type >= POSITION_VELOCITY_ACCELERATION)
  464. {
  465. body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
  466. body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
  467. body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
  468. body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
  469. }
  470. }
  471. // 2. absolute kinematic quantities (vector valued)
  472. // NOTE: this should be optimized by specializing for different body types
  473. // (e.g., relative rotation is always zero for prismatic joints, etc.)
  474. // calculations for root body
  475. {
  476. RigidBody &body = m_body_list[0];
  477. // 3.1 update absolute positions and orientations:
  478. // will be required if we add force elements (eg springs between bodies,
  479. // or contacts)
  480. // not required right now, added here for debugging purposes
  481. body.m_body_pos = body.m_body_T_parent * body.m_parent_pos_parent_body;
  482. body.m_body_T_world = body.m_body_T_parent;
  483. if (type >= POSITION_VELOCITY)
  484. {
  485. // 3.2 update absolute velocities
  486. body.m_body_ang_vel = body.m_body_ang_vel_rel;
  487. body.m_body_vel = body.m_parent_vel_rel;
  488. }
  489. if (type >= POSITION_VELOCITY_ACCELERATION)
  490. {
  491. // 3.3 update absolute accelerations
  492. // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
  493. body.m_body_ang_acc = body.m_body_ang_acc_rel;
  494. body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
  495. // add gravitational acceleration to root body
  496. // this is an efficient way to add gravitational terms,
  497. // but it does mean that the kinematics are no longer
  498. // correct at the acceleration level
  499. // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
  500. body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
  501. }
  502. }
  503. for (idArrayIdx i = 1; i < m_body_list.size(); i++)
  504. {
  505. RigidBody &body = m_body_list[i];
  506. RigidBody &parent = m_body_list[m_parent_index[i]];
  507. // 2.1 update absolute positions and orientations:
  508. // will be required if we add force elements (eg springs between bodies,
  509. // or contacts) not required right now added here for debugging purposes
  510. body.m_body_pos =
  511. body.m_body_T_parent * (parent.m_body_pos + body.m_parent_pos_parent_body);
  512. body.m_body_T_world = body.m_body_T_parent * parent.m_body_T_world;
  513. if (type >= POSITION_VELOCITY)
  514. {
  515. // 2.2 update absolute velocities
  516. body.m_body_ang_vel =
  517. body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
  518. body.m_body_vel =
  519. body.m_body_T_parent *
  520. (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
  521. body.m_parent_vel_rel);
  522. }
  523. if (type >= POSITION_VELOCITY_ACCELERATION)
  524. {
  525. // 2.3 update absolute accelerations
  526. // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
  527. body.m_body_ang_acc =
  528. body.m_body_T_parent * parent.m_body_ang_acc -
  529. body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
  530. body.m_body_ang_acc_rel;
  531. body.m_body_acc =
  532. body.m_body_T_parent *
  533. (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
  534. parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
  535. 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
  536. }
  537. }
  538. return 0;
  539. }
  540. #if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
  541. void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody &body)
  542. {
  543. const int &idx = body.m_q_index;
  544. switch (body.m_joint_type)
  545. {
  546. case FIXED:
  547. break;
  548. case REVOLUTE:
  549. setMat3xElem(0, idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
  550. setMat3xElem(1, idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
  551. setMat3xElem(2, idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
  552. break;
  553. case PRISMATIC:
  554. setMat3xElem(0, idx, body.m_body_T_parent_ref(0, 0) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 0) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 0) * body.m_Jac_JT(2),
  555. &body.m_body_Jac_T);
  556. setMat3xElem(1, idx, body.m_body_T_parent_ref(0, 1) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 1) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 1) * body.m_Jac_JT(2),
  557. &body.m_body_Jac_T);
  558. setMat3xElem(2, idx, body.m_body_T_parent_ref(0, 2) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 2) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 2) * body.m_Jac_JT(2),
  559. &body.m_body_Jac_T);
  560. break;
  561. case FLOATING:
  562. setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
  563. setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
  564. setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
  565. // body_Jac_T = body_T_parent.transpose();
  566. setMat3xElem(0, idx + 3, body.m_body_T_parent(0, 0), &body.m_body_Jac_T);
  567. setMat3xElem(0, idx + 4, body.m_body_T_parent(1, 0), &body.m_body_Jac_T);
  568. setMat3xElem(0, idx + 5, body.m_body_T_parent(2, 0), &body.m_body_Jac_T);
  569. setMat3xElem(1, idx + 3, body.m_body_T_parent(0, 1), &body.m_body_Jac_T);
  570. setMat3xElem(1, idx + 4, body.m_body_T_parent(1, 1), &body.m_body_Jac_T);
  571. setMat3xElem(1, idx + 5, body.m_body_T_parent(2, 1), &body.m_body_Jac_T);
  572. setMat3xElem(2, idx + 3, body.m_body_T_parent(0, 2), &body.m_body_Jac_T);
  573. setMat3xElem(2, idx + 4, body.m_body_T_parent(1, 2), &body.m_body_Jac_T);
  574. setMat3xElem(2, idx + 5, body.m_body_T_parent(2, 2), &body.m_body_Jac_T);
  575. break;
  576. case SPHERICAL:
  577. //todo: review
  578. setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
  579. setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
  580. setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
  581. break;
  582. }
  583. }
  584. int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx &q, const vecx &u, const KinUpdateType type)
  585. {
  586. if (q.size() != m_num_dofs || u.size() != m_num_dofs)
  587. {
  588. bt_id_error_message(
  589. "wrong vector dimension. system has %d DOFs,\n"
  590. "but dim(q)= %d, dim(u)= %d\n",
  591. m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
  592. return -1;
  593. }
  594. if (type != POSITION_ONLY && type != POSITION_VELOCITY)
  595. {
  596. bt_id_error_message("invalid type %d\n", type);
  597. return -1;
  598. }
  599. addRelativeJacobianComponent(m_body_list[0]);
  600. for (idArrayIdx i = 1; i < m_body_list.size(); i++)
  601. {
  602. RigidBody &body = m_body_list[i];
  603. RigidBody &parent = m_body_list[m_parent_index[i]];
  604. mul(body.m_body_T_parent, parent.m_body_Jac_R, &body.m_body_Jac_R);
  605. body.m_body_Jac_T = parent.m_body_Jac_T;
  606. mul(tildeOperator(body.m_parent_pos_parent_body), parent.m_body_Jac_R, &m_m3x);
  607. sub(body.m_body_Jac_T, m_m3x, &body.m_body_Jac_T);
  608. addRelativeJacobianComponent(body);
  609. mul(body.m_body_T_parent, body.m_body_Jac_T, &body.m_body_Jac_T);
  610. if (type >= POSITION_VELOCITY)
  611. {
  612. body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
  613. body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
  614. body.m_body_dot_Jac_T_u = body.m_body_T_parent *
  615. (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
  616. parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
  617. 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
  618. }
  619. }
  620. return 0;
  621. }
  622. #endif
  623. static inline void setThreeDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
  624. {
  625. switch (dof)
  626. {
  627. // rotational part
  628. case 0:
  629. Jac_JR(0) = 1;
  630. Jac_JR(1) = 0;
  631. Jac_JR(2) = 0;
  632. setZero(Jac_JT);
  633. break;
  634. case 1:
  635. Jac_JR(0) = 0;
  636. Jac_JR(1) = 1;
  637. Jac_JR(2) = 0;
  638. setZero(Jac_JT);
  639. break;
  640. case 2:
  641. Jac_JR(0) = 0;
  642. Jac_JR(1) = 0;
  643. Jac_JR(2) = 1;
  644. setZero(Jac_JT);
  645. break;
  646. }
  647. }
  648. static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
  649. {
  650. switch (dof)
  651. {
  652. // rotational part
  653. case 0:
  654. Jac_JR(0) = 1;
  655. Jac_JR(1) = 0;
  656. Jac_JR(2) = 0;
  657. setZero(Jac_JT);
  658. break;
  659. case 1:
  660. Jac_JR(0) = 0;
  661. Jac_JR(1) = 1;
  662. Jac_JR(2) = 0;
  663. setZero(Jac_JT);
  664. break;
  665. case 2:
  666. Jac_JR(0) = 0;
  667. Jac_JR(1) = 0;
  668. Jac_JR(2) = 1;
  669. setZero(Jac_JT);
  670. break;
  671. // translational part
  672. case 3:
  673. setZero(Jac_JR);
  674. Jac_JT(0) = 1;
  675. Jac_JT(1) = 0;
  676. Jac_JT(2) = 0;
  677. break;
  678. case 4:
  679. setZero(Jac_JR);
  680. Jac_JT(0) = 0;
  681. Jac_JT(1) = 1;
  682. Jac_JT(2) = 0;
  683. break;
  684. case 5:
  685. setZero(Jac_JR);
  686. Jac_JT(0) = 0;
  687. Jac_JT(1) = 0;
  688. Jac_JT(2) = 1;
  689. break;
  690. }
  691. }
  692. static inline int jointNumDoFs(const JointType &type)
  693. {
  694. switch (type)
  695. {
  696. case FIXED:
  697. return 0;
  698. case REVOLUTE:
  699. case PRISMATIC:
  700. return 1;
  701. case FLOATING:
  702. return 6;
  703. case SPHERICAL:
  704. return 3;
  705. }
  706. // this should never happen
  707. bt_id_error_message("invalid joint type\n");
  708. // TODO add configurable abort/crash function
  709. abort();
  710. return 0;
  711. }
  712. int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool update_kinematics,
  713. const bool initialize_matrix,
  714. const bool set_lower_triangular_matrix,
  715. matxx *mass_matrix)
  716. {
  717. // This calculates the joint space mass matrix for the multibody system.
  718. // The algorithm is essentially an implementation of "method 3"
  719. // in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
  720. // (Later named "Composite Rigid Body Algorithm" by Featherstone).
  721. //
  722. // This implementation, however, handles branched systems and uses a formulation centered
  723. // on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
  724. if (q.size() != m_num_dofs || mass_matrix->rows() != m_num_dofs ||
  725. mass_matrix->cols() != m_num_dofs)
  726. {
  727. bt_id_error_message(
  728. "Dimension error. System has %d DOFs,\n"
  729. "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
  730. m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
  731. static_cast<int>(mass_matrix->cols()));
  732. return -1;
  733. }
  734. // TODO add optimized zeroing function?
  735. if (initialize_matrix)
  736. {
  737. for (int i = 0; i < m_num_dofs; i++)
  738. {
  739. for (int j = 0; j < m_num_dofs; j++)
  740. {
  741. setMatxxElem(i, j, 0.0, mass_matrix);
  742. }
  743. }
  744. }
  745. if (update_kinematics)
  746. {
  747. // 1. update relative kinematics
  748. // 1.1 for revolute joints
  749. for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
  750. {
  751. RigidBody &body = m_body_list[m_body_revolute_list[i]];
  752. // from reference orientation (q=0) of body-fixed frame to current orientation
  753. mat33 body_T_body_ref;
  754. bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &body_T_body_ref);
  755. body.m_body_T_parent = body_T_body_ref * body.m_body_T_parent_ref;
  756. }
  757. // 1.2 for prismatic joints
  758. for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
  759. {
  760. RigidBody &body = m_body_list[m_body_prismatic_list[i]];
  761. // body.m_body_T_parent= fixed
  762. body.m_parent_pos_parent_body =
  763. body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
  764. }
  765. // 1.3 fixed joints: nothing to do
  766. // 1.4 6dof joints:
  767. for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
  768. {
  769. RigidBody &body = m_body_list[m_body_floating_list[i]];
  770. body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
  771. transformY(q(body.m_q_index + 1)) *
  772. transformX(q(body.m_q_index));
  773. body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
  774. body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
  775. body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
  776. body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
  777. }
  778. for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
  779. {
  780. //todo: review
  781. RigidBody &body = m_body_list[m_body_spherical_list[i]];
  782. mat33 T;
  783. T = transformX(q(body.m_q_index)) *
  784. transformY(q(body.m_q_index + 1)) *
  785. transformZ(q(body.m_q_index + 2));
  786. body.m_body_T_parent = T * body.m_body_T_parent_ref;
  787. body.m_parent_pos_parent_body(0)=0;
  788. body.m_parent_pos_parent_body(1)=0;
  789. body.m_parent_pos_parent_body(2)=0;
  790. body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
  791. }
  792. }
  793. for (int i = m_body_list.size() - 1; i >= 0; i--)
  794. {
  795. RigidBody &body = m_body_list[i];
  796. // calculate mass, center of mass and inertia of "composite rigid body",
  797. // ie, sub-tree starting at current body
  798. body.m_subtree_mass = body.m_mass;
  799. body.m_body_subtree_mass_com = body.m_body_mass_com;
  800. body.m_body_subtree_I_body = body.m_body_I_body;
  801. for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++)
  802. {
  803. RigidBody &child = m_body_list[m_child_indices[i][c]];
  804. mat33 body_T_child = child.m_body_T_parent.transpose();
  805. body.m_subtree_mass += child.m_subtree_mass;
  806. body.m_body_subtree_mass_com += body_T_child * child.m_body_subtree_mass_com +
  807. child.m_parent_pos_parent_body * child.m_subtree_mass;
  808. body.m_body_subtree_I_body +=
  809. body_T_child * child.m_body_subtree_I_body * child.m_body_T_parent;
  810. if (child.m_subtree_mass > 0)
  811. {
  812. // Shift the reference point for the child subtree inertia using the
  813. // Huygens-Steiner ("parallel axis") theorem.
  814. // (First shift from child origin to child com, then from there to this body's
  815. // origin)
  816. vec3 r_com = body_T_child * child.m_body_subtree_mass_com / child.m_subtree_mass;
  817. mat33 tilde_r_child_com = tildeOperator(r_com);
  818. mat33 tilde_r_body_com = tildeOperator(child.m_parent_pos_parent_body + r_com);
  819. body.m_body_subtree_I_body +=
  820. child.m_subtree_mass *
  821. (tilde_r_child_com * tilde_r_child_com - tilde_r_body_com * tilde_r_body_com);
  822. }
  823. }
  824. }
  825. for (int i = m_body_list.size() - 1; i >= 0; i--)
  826. {
  827. const RigidBody &body = m_body_list[i];
  828. // determine DoF-range for body
  829. const int q_index_min = body.m_q_index;
  830. const int q_index_max = q_index_min + jointNumDoFs(body.m_joint_type) - 1;
  831. // loop over the DoFs used by this body
  832. // local joint jacobians (ok as is for 1-DoF joints)
  833. vec3 Jac_JR = body.m_Jac_JR;
  834. vec3 Jac_JT = body.m_Jac_JT;
  835. for (int col = q_index_max; col >= q_index_min; col--)
  836. {
  837. // set jacobians for 6-DoF joints
  838. if (FLOATING == body.m_joint_type)
  839. {
  840. setSixDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
  841. }
  842. if (SPHERICAL == body.m_joint_type)
  843. {
  844. //todo: review
  845. setThreeDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
  846. }
  847. vec3 body_eom_rot =
  848. body.m_body_subtree_I_body * Jac_JR + body.m_body_subtree_mass_com.cross(Jac_JT);
  849. vec3 body_eom_trans =
  850. body.m_subtree_mass * Jac_JT - body.m_body_subtree_mass_com.cross(Jac_JR);
  851. setMatxxElem(col, col, Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans), mass_matrix);
  852. // rest of the mass matrix column upwards
  853. {
  854. // 1. for multi-dof joints, rest of the dofs of this body
  855. for (int row = col - 1; row >= q_index_min; row--)
  856. {
  857. if (SPHERICAL == body.m_joint_type)
  858. {
  859. //todo: review
  860. setThreeDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
  861. const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
  862. setMatxxElem(col, row, Mrc, mass_matrix);
  863. }
  864. if (FLOATING == body.m_joint_type)
  865. {
  866. setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
  867. const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
  868. setMatxxElem(col, row, Mrc, mass_matrix);
  869. }
  870. }
  871. // 2. ancestor dofs
  872. int child_idx = i;
  873. int parent_idx = m_parent_index[i];
  874. while (parent_idx >= 0)
  875. {
  876. const RigidBody &child_body = m_body_list[child_idx];
  877. const RigidBody &parent_body = m_body_list[parent_idx];
  878. const mat33 parent_T_child = child_body.m_body_T_parent.transpose();
  879. body_eom_rot = parent_T_child * body_eom_rot;
  880. body_eom_trans = parent_T_child * body_eom_trans;
  881. body_eom_rot += child_body.m_parent_pos_parent_body.cross(body_eom_trans);
  882. const int parent_body_q_index_min = parent_body.m_q_index;
  883. const int parent_body_q_index_max =
  884. parent_body_q_index_min + jointNumDoFs(parent_body.m_joint_type) - 1;
  885. vec3 Jac_JR = parent_body.m_Jac_JR;
  886. vec3 Jac_JT = parent_body.m_Jac_JT;
  887. for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--)
  888. {
  889. if (SPHERICAL == parent_body.m_joint_type)
  890. {
  891. //todo: review
  892. setThreeDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
  893. }
  894. // set jacobians for 6-DoF joints
  895. if (FLOATING == parent_body.m_joint_type)
  896. {
  897. setSixDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
  898. }
  899. const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
  900. setMatxxElem(col, row, Mrc, mass_matrix);
  901. }
  902. child_idx = parent_idx;
  903. parent_idx = m_parent_index[child_idx];
  904. }
  905. }
  906. }
  907. }
  908. if (set_lower_triangular_matrix)
  909. {
  910. for (int col = 0; col < m_num_dofs; col++)
  911. {
  912. for (int row = 0; row < col; row++)
  913. {
  914. setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
  915. }
  916. }
  917. }
  918. return 0;
  919. }
  920. // utility macro
  921. #define CHECK_IF_BODY_INDEX_IS_VALID(index) \
  922. do \
  923. { \
  924. if (index < 0 || index >= m_num_bodies) \
  925. { \
  926. bt_id_error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
  927. return -1; \
  928. } \
  929. } while (0)
  930. int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p)
  931. {
  932. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  933. *p = m_parent_index[body_index];
  934. return 0;
  935. }
  936. int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const
  937. {
  938. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  939. *user_int = m_user_int[body_index];
  940. return 0;
  941. }
  942. int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const
  943. {
  944. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  945. *user_ptr = m_user_ptr[body_index];
  946. return 0;
  947. }
  948. int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int)
  949. {
  950. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  951. m_user_int[body_index] = user_int;
  952. return 0;
  953. }
  954. int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr)
  955. {
  956. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  957. m_user_ptr[body_index] = user_ptr;
  958. return 0;
  959. }
  960. int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const
  961. {
  962. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  963. const RigidBody &body = m_body_list[body_index];
  964. *world_origin = body.m_body_T_world.transpose() * body.m_body_pos;
  965. return 0;
  966. }
  967. int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const
  968. {
  969. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  970. const RigidBody &body = m_body_list[body_index];
  971. if (body.m_mass > 0)
  972. {
  973. *world_com = body.m_body_T_world.transpose() *
  974. (body.m_body_pos + body.m_body_mass_com / body.m_mass);
  975. }
  976. else
  977. {
  978. *world_com = body.m_body_T_world.transpose() * (body.m_body_pos);
  979. }
  980. return 0;
  981. }
  982. int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const
  983. {
  984. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  985. const RigidBody &body = m_body_list[body_index];
  986. *world_T_body = body.m_body_T_world.transpose();
  987. return 0;
  988. }
  989. int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const
  990. {
  991. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  992. const RigidBody &body = m_body_list[body_index];
  993. *world_omega = body.m_body_T_world.transpose() * body.m_body_ang_vel;
  994. return 0;
  995. }
  996. int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
  997. vec3 *world_velocity) const
  998. {
  999. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1000. const RigidBody &body = m_body_list[body_index];
  1001. *world_velocity = body.m_body_T_world.transpose() * body.m_body_vel;
  1002. return 0;
  1003. }
  1004. int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
  1005. vec3 *world_velocity) const
  1006. {
  1007. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1008. const RigidBody &body = m_body_list[body_index];
  1009. vec3 com;
  1010. if (body.m_mass > 0)
  1011. {
  1012. com = body.m_body_mass_com / body.m_mass;
  1013. }
  1014. else
  1015. {
  1016. com(0) = 0;
  1017. com(1) = 0;
  1018. com(2) = 0;
  1019. }
  1020. *world_velocity =
  1021. body.m_body_T_world.transpose() * (body.m_body_vel + body.m_body_ang_vel.cross(com));
  1022. return 0;
  1023. }
  1024. int MultiBodyTree::MultiBodyImpl::getBodyAngularAcceleration(int body_index,
  1025. vec3 *world_dot_omega) const
  1026. {
  1027. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1028. const RigidBody &body = m_body_list[body_index];
  1029. *world_dot_omega = body.m_body_T_world.transpose() * body.m_body_ang_acc;
  1030. return 0;
  1031. }
  1032. int MultiBodyTree::MultiBodyImpl::getBodyLinearAcceleration(int body_index,
  1033. vec3 *world_acceleration) const
  1034. {
  1035. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1036. const RigidBody &body = m_body_list[body_index];
  1037. *world_acceleration = body.m_body_T_world.transpose() * body.m_body_acc;
  1038. return 0;
  1039. }
  1040. int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const
  1041. {
  1042. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1043. *joint_type = m_body_list[body_index].m_joint_type;
  1044. return 0;
  1045. }
  1046. int MultiBodyTree::MultiBodyImpl::getJointTypeStr(const int body_index,
  1047. const char **joint_type) const
  1048. {
  1049. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1050. *joint_type = jointTypeToString(m_body_list[body_index].m_joint_type);
  1051. return 0;
  1052. }
  1053. int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3 *r) const
  1054. {
  1055. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1056. *r = m_body_list[body_index].m_parent_pos_parent_body_ref;
  1057. return 0;
  1058. }
  1059. int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33 *T) const
  1060. {
  1061. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1062. *T = m_body_list[body_index].m_body_T_parent_ref;
  1063. return 0;
  1064. }
  1065. int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
  1066. {
  1067. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1068. if (m_body_list[body_index].m_joint_type == REVOLUTE)
  1069. {
  1070. *axis = m_body_list[body_index].m_Jac_JR;
  1071. return 0;
  1072. }
  1073. if (m_body_list[body_index].m_joint_type == PRISMATIC)
  1074. {
  1075. *axis = m_body_list[body_index].m_Jac_JT;
  1076. return 0;
  1077. }
  1078. setZero(*axis);
  1079. return 0;
  1080. }
  1081. int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const
  1082. {
  1083. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1084. *q_index = m_body_list[body_index].m_q_index;
  1085. return 0;
  1086. }
  1087. int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass)
  1088. {
  1089. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1090. m_body_list[body_index].m_mass = mass;
  1091. return 0;
  1092. }
  1093. int MultiBodyTree::MultiBodyImpl::setBodyFirstMassMoment(const int body_index,
  1094. const vec3 &first_mass_moment)
  1095. {
  1096. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1097. m_body_list[body_index].m_body_mass_com = first_mass_moment;
  1098. return 0;
  1099. }
  1100. int MultiBodyTree::MultiBodyImpl::setBodySecondMassMoment(const int body_index,
  1101. const mat33 &second_mass_moment)
  1102. {
  1103. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1104. m_body_list[body_index].m_body_I_body = second_mass_moment;
  1105. return 0;
  1106. }
  1107. int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const
  1108. {
  1109. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1110. *mass = m_body_list[body_index].m_mass;
  1111. return 0;
  1112. }
  1113. int MultiBodyTree::MultiBodyImpl::getBodyFirstMassMoment(const int body_index,
  1114. vec3 *first_mass_moment) const
  1115. {
  1116. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1117. *first_mass_moment = m_body_list[body_index].m_body_mass_com;
  1118. return 0;
  1119. }
  1120. int MultiBodyTree::MultiBodyImpl::getBodySecondMassMoment(const int body_index,
  1121. mat33 *second_mass_moment) const
  1122. {
  1123. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1124. *second_mass_moment = m_body_list[body_index].m_body_I_body;
  1125. return 0;
  1126. }
  1127. void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments()
  1128. {
  1129. for (int index = 0; index < m_num_bodies; index++)
  1130. {
  1131. RigidBody &body = m_body_list[index];
  1132. setZero(body.m_body_force_user);
  1133. setZero(body.m_body_moment_user);
  1134. }
  1135. }
  1136. int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force)
  1137. {
  1138. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1139. m_body_list[body_index].m_body_force_user += body_force;
  1140. return 0;
  1141. }
  1142. int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment)
  1143. {
  1144. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1145. m_body_list[body_index].m_body_moment_user += body_moment;
  1146. return 0;
  1147. }
  1148. #if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
  1149. int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
  1150. {
  1151. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1152. const RigidBody &body = m_body_list[body_index];
  1153. *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
  1154. return 0;
  1155. }
  1156. int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
  1157. {
  1158. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1159. const RigidBody &body = m_body_list[body_index];
  1160. *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
  1161. return 0;
  1162. }
  1163. int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
  1164. {
  1165. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1166. const RigidBody &body = m_body_list[body_index];
  1167. mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
  1168. return 0;
  1169. }
  1170. int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
  1171. {
  1172. CHECK_IF_BODY_INDEX_IS_VALID(body_index);
  1173. const RigidBody &body = m_body_list[body_index];
  1174. mul(body.m_body_T_world.transpose(), body.m_body_Jac_R, world_jac_rot);
  1175. return 0;
  1176. }
  1177. #endif
  1178. } // namespace btInverseDynamics