MultiBodyTreeImpl.cpp 39 KB

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