43 void SpatialTransform(
const btMatrix3x3 &rotation_matrix,
50 top_out = rotation_matrix * top_in;
51 bottom_out = -displacement.
cross(top_out) + rotation_matrix * bottom_in;
54 void InverseSpatialTransform(
const btMatrix3x3 &rotation_matrix,
61 top_out = rotation_matrix.
transpose() * top_in;
62 bottom_out = rotation_matrix.
transpose() * (bottom_in + displacement.
cross(top_in));
70 return a_bottom.
dot(b_top) + a_top.
dot(b_bottom);
84 : base_quat(0, 0, 0, 1),
86 base_inertia(inertia),
88 fixed_base(fixed_base_),
90 can_sleep(can_sleep_),
93 m_linearDamping(0.04f),
94 m_angularDamping(0.04f),
96 m_maxAppliedImpulse(1000.f),
97 m_hasSelfCollision(true)
120 bool disableParentCollision)
122 links[i].mass = mass;
123 links[i].inertia = inertia;
124 links[i].parent = parent;
125 links[i].zero_rot_parent_to_this = rot_parent_to_this;
126 links[i].axis_top.setValue(0,0,0);
127 links[i].axis_bottom = joint_axis;
128 links[i].e_vector = r_vector_when_q_zero;
129 links[i].is_revolute =
false;
130 links[i].cached_rot_parent_to_this = rot_parent_to_this;
131 if (disableParentCollision)
134 links[i].updateCache();
145 bool disableParentCollision)
147 links[i].mass = mass;
148 links[i].inertia = inertia;
149 links[i].parent = parent;
150 links[i].zero_rot_parent_to_this = zero_rot_parent_to_this;
151 links[i].axis_top = joint_axis;
152 links[i].axis_bottom = joint_axis.
cross(my_axis_position);
153 links[i].d_vector = my_axis_position;
154 links[i].e_vector = parent_axis_position;
155 links[i].is_revolute =
true;
156 if (disableParentCollision)
158 links[i].updateCache();
167 return links[i].parent;
172 return links[i].mass;
177 return links[i].inertia;
182 return links[i].joint_pos;
192 links[i].joint_pos = q;
193 links[i].updateCache();
203 return links[i].cached_r_vector;
208 return links[i].cached_rot_parent_to_this;
266 for (
int i = 0; i < num_links; ++i) {
267 const int parent =
links[i].parent;
271 omega[parent+1], vel[parent+1],
272 omega[i+1], vel[i+1]);
292 for (
int i = 0; i < num_links; ++i) {
293 result +=
links[i].mass * vel[i+1].dot(vel[i+1]);
294 result += omega[i+1].dot(
links[i].inertia * omega[i+1]);
297 return 0.5f * result;
312 for (
int i = 0; i < num_links; ++i) {
313 rot_from_world[i+1] =
links[i].cached_rot_parent_to_this * rot_from_world[
links[i].parent+1];
314 result += (
quatRotate(rot_from_world[i+1].
inverse() , (links[i].inertia * omega[i+1])));
327 links[i].applied_force.setValue(0, 0, 0);
328 links[i].applied_torque.setValue(0, 0, 0);
329 links[i].joint_torque = 0;
342 links[i].applied_force += f;
347 links[i].applied_torque += t;
352 links[i].joint_torque += Q;
357 return links[i].applied_force;
362 return links[i].applied_torque;
367 return links[i].joint_torque;
374 v0.
x() * v1Transposed.
x(),
375 v0.
x() * v1Transposed.
y(),
376 v0.
x() * v1Transposed.
z());
378 v0.
y() * v1Transposed.
x(),
379 v0.
y() * v1Transposed.
y(),
380 v0.
y() * v1Transposed.
z());
382 v0.
z() * v1Transposed.
x(),
383 v0.
z() * v1Transposed.
y(),
384 v0.
z() * v1Transposed.
z());
387 row1[0],row1[1],row1[2],
388 row2[0],row2[1],row2[2]);
422 scratch_r.
resize(2*num_links + 6);
423 scratch_v.
resize(8*num_links + 6);
424 scratch_m.
resize(4*num_links + 4);
427 btScalar * output = &scratch_r[num_links];
431 btVector3 * vel_top_angular = v_ptr; v_ptr += num_links + 1;
432 btVector3 * vel_bottom_linear = v_ptr; v_ptr += num_links + 1;
435 btVector3 * zero_acc_top_angular = v_ptr; v_ptr += num_links + 1;
436 btVector3 * zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1;
439 btVector3 * coriolis_top_angular = v_ptr; v_ptr += num_links;
440 btVector3 * coriolis_bottom_linear = v_ptr; v_ptr += num_links;
445 btMatrix3x3 * inertia_top_left = &scratch_m[num_links + 1];
446 btMatrix3x3 * inertia_top_right = &scratch_m[2*num_links + 2];
447 btMatrix3x3 * inertia_bottom_left = &scratch_m[3*num_links + 3];
457 btVector3 * accel_top = v_ptr; v_ptr += num_links + 1;
458 btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1;
461 btScalar * Y = r_ptr; r_ptr += num_links;
465 btScalar * joint_accel = output + 6;
475 vel_top_angular[0] = rot_from_parent[0] * base_omega;
476 vel_bottom_linear[0] = rot_from_parent[0] * base_vel;
479 zero_acc_top_angular[0] = zero_acc_bottom_linear[0] =
btVector3(0,0,0);
481 zero_acc_top_angular[0] = - (rot_from_parent[0] * (
base_force
482 -
base_mass*(DAMPING_K1_LINEAR+DAMPING_K2_LINEAR*base_vel.norm())*base_vel));
484 zero_acc_bottom_linear[0] =
488 zero_acc_bottom_linear[0]+=vel_top_angular[0].
cross(
base_inertia * vel_top_angular[0] );
490 zero_acc_bottom_linear[0] +=
base_inertia * vel_top_angular[0] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[0].norm());
496 inertia_top_left[0] =
btMatrix3x3(0,0,0,0,0,0,0,0,0);
506 rot_from_world[0] = rot_from_parent[0];
508 for (
int i = 0; i < num_links; ++i) {
509 const int parent =
links[i].parent;
513 rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];
516 SpatialTransform(rot_from_parent[i+1],
links[i].cached_r_vector,
517 vel_top_angular[parent+1], vel_bottom_linear[parent+1],
518 vel_top_angular[i+1], vel_bottom_linear[i+1]);
522 coriolis_bottom_linear[i] = vel_top_angular[i+1].
cross(vel_top_angular[i+1].
cross(
links[i].cached_r_vector))
524 if (
links[i].is_revolute) {
528 coriolis_top_angular[i] =
btVector3(0,0,0);
537 zero_acc_top_angular[i+1] = - (rot_from_world[i+1] * (
links[i].applied_force));
538 zero_acc_top_angular[i+1] +=
links[i].mass * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR*vel_bottom_linear[i+1].
norm()) * vel_bottom_linear[i+1];
540 zero_acc_bottom_linear[i+1] =
541 - (rot_from_world[i+1] *
links[i].applied_torque);
544 zero_acc_bottom_linear[i+1] += vel_top_angular[i+1].
cross(
links[i].inertia * vel_top_angular[i+1] );
547 zero_acc_bottom_linear[i+1] +=
links[i].inertia * vel_top_angular[i+1] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[i+1].
norm());
550 inertia_top_left[i+1] =
btMatrix3x3(0,0,0,0,0,0,0,0,0);
553 0, 0,
links[i].mass);
555 0,
links[i].inertia[1], 0,
556 0, 0,
links[i].inertia[2]);
562 for (
int i = num_links - 1; i >= 0; --i) {
564 h_top[i] = inertia_top_left[i+1] *
links[i].axis_top + inertia_top_right[i+1] *
links[i].axis_bottom;
565 h_bottom[i] = inertia_bottom_left[i+1] *
links[i].axis_top + inertia_top_left[i+1].
transpose() *
links[i].axis_bottom;
566 btScalar val = SpatialDotProduct(
links[i].axis_top,
links[i].axis_bottom, h_top[i], h_bottom[i]);
568 Y[i] =
links[i].joint_torque
569 - SpatialDotProduct(
links[i].axis_top,
links[i].axis_bottom, zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1])
570 - SpatialDotProduct(h_top[i], h_bottom[i], coriolis_top_angular[i], coriolis_bottom_linear[i]);
572 const int parent =
links[i].parent;
576 const btScalar one_over_di = 1.0f / D[i];
588 0, -
links[i].cached_r_vector[2],
links[i].cached_r_vector[1],
589 links[i].cached_r_vector[2], 0, -
links[i].cached_r_vector[0],
590 -
links[i].cached_r_vector[1],
links[i].cached_r_vector[0], 0);
592 inertia_top_left[parent+1] += rot_from_parent[i+1].
transpose() * ( TL - TR * r_cross ) * rot_from_parent[i+1];
593 inertia_top_right[parent+1] += rot_from_parent[i+1].
transpose() * TR * rot_from_parent[i+1];
594 inertia_bottom_left[parent+1] += rot_from_parent[i+1].
transpose() *
595 (r_cross * (TL - TR * r_cross) + BL - TL.
transpose() * r_cross) * rot_from_parent[i+1];
599 btVector3 in_top, in_bottom, out_top, out_bottom;
600 const btScalar Y_over_D = Y[i] * one_over_di;
601 in_top = zero_acc_top_angular[i+1]
602 + inertia_top_left[i+1] * coriolis_top_angular[i]
603 + inertia_top_right[i+1] * coriolis_bottom_linear[i]
604 + Y_over_D * h_top[i];
605 in_bottom = zero_acc_bottom_linear[i+1]
606 + inertia_bottom_left[i+1] * coriolis_top_angular[i]
607 + inertia_top_left[i+1].
transpose() * coriolis_bottom_linear[i]
608 + Y_over_D * h_bottom[i];
609 InverseSpatialTransform(rot_from_parent[i+1],
links[i].cached_r_vector,
610 in_top, in_bottom, out_top, out_bottom);
611 zero_acc_top_angular[parent+1] += out_top;
612 zero_acc_bottom_linear[parent+1] += out_bottom;
621 accel_top[0] = accel_bottom[0] =
btVector3(0,0,0);
640 btVector3 rhs_top (zero_acc_top_angular[0][0], zero_acc_top_angular[0][1], zero_acc_top_angular[0][2]);
641 btVector3 rhs_bot (zero_acc_bottom_linear[0][0], zero_acc_bottom_linear[0][1], zero_acc_bottom_linear[0][2]);
646 for (
int i = 0; i < 3; ++i) {
647 accel_top[0][i] = -result[i];
648 accel_bottom[0][i] = -result[i+3];
654 for (
int i = 0; i < num_links; ++i) {
655 const int parent =
links[i].parent;
656 SpatialTransform(rot_from_parent[i+1],
links[i].cached_r_vector,
657 accel_top[parent+1], accel_bottom[parent+1],
658 accel_top[i+1], accel_bottom[i+1]);
659 joint_accel[i] = (Y[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])) / D[i];
660 accel_top[i+1] += coriolis_top_angular[i] + joint_accel[i] *
links[i].axis_top;
661 accel_bottom[i+1] += coriolis_bottom_linear[i] + joint_accel[i] *
links[i].axis_bottom;
666 output[0] = omegadot_out[0];
667 output[1] = omegadot_out[1];
668 output[2] = omegadot_out[2];
671 output[3] = vdot_out[0];
672 output[4] = vdot_out[1];
673 output[5] = vdot_out[2];
713 btVector3 vtop = invI_upper_left*rhs_top;
715 tmp = invIupper_right * rhs_bot;
717 btVector3 vbot = invI_lower_left*rhs_top;
718 tmp = invI_lower_right * rhs_bot;
738 scratch_r.
resize(num_links);
739 scratch_v.
resize(4*num_links + 4);
741 btScalar * r_ptr = num_links == 0 ? 0 : &scratch_r[0];
745 btVector3 * zero_acc_top_angular = v_ptr; v_ptr += num_links + 1;
746 btVector3 * zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1;
754 btVector3 * accel_top = v_ptr; v_ptr += num_links + 1;
755 btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1;
758 btScalar * Y = r_ptr; r_ptr += num_links;
761 btAssert(num_links == 0 || r_ptr - &scratch_r[0] == scratch_r.
size());
769 btVector3 input_force(force[3],force[4],force[5]);
770 btVector3 input_torque(force[0],force[1],force[2]);
776 zero_acc_top_angular[0] = zero_acc_bottom_linear[0] =
btVector3(0,0,0);
779 zero_acc_top_angular[0] = - (rot_from_parent[0] * input_force);
780 zero_acc_bottom_linear[0] = - (rot_from_parent[0] * input_torque);
782 for (
int i = 0; i < num_links; ++i)
784 zero_acc_top_angular[i+1] = zero_acc_bottom_linear[i+1] =
btVector3(0,0,0);
788 for (
int i = num_links - 1; i >= 0; --i)
791 Y[i] = - SpatialDotProduct(
links[i].axis_top,
links[i].axis_bottom, zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1]);
792 Y[i] += force[6 + i];
794 const int parent =
links[i].parent;
797 btVector3 in_top, in_bottom, out_top, out_bottom;
798 const btScalar Y_over_D = Y[i] / D[i];
799 in_top = zero_acc_top_angular[i+1] + Y_over_D * h_top[i];
800 in_bottom = zero_acc_bottom_linear[i+1] + Y_over_D * h_bottom[i];
801 InverseSpatialTransform(rot_from_parent[i+1],
links[i].cached_r_vector,
802 in_top, in_bottom, out_top, out_bottom);
803 zero_acc_top_angular[parent+1] += out_top;
804 zero_acc_bottom_linear[parent+1] += out_bottom;
808 btScalar * joint_accel = output + 6;
813 accel_top[0] = accel_bottom[0] =
btVector3(0,0,0);
816 btVector3 rhs_top (zero_acc_top_angular[0][0], zero_acc_top_angular[0][1], zero_acc_top_angular[0][2]);
817 btVector3 rhs_bot (zero_acc_bottom_linear[0][0], zero_acc_bottom_linear[0][1], zero_acc_bottom_linear[0][2]);
823 for (
int i = 0; i < 3; ++i) {
824 accel_top[0][i] = -result[i];
825 accel_bottom[0][i] = -result[i+3];
831 for (
int i = 0; i < num_links; ++i) {
832 const int parent =
links[i].parent;
833 SpatialTransform(rot_from_parent[i+1],
links[i].cached_r_vector,
834 accel_top[parent+1], accel_bottom[parent+1],
835 accel_top[i+1], accel_bottom[i+1]);
836 joint_accel[i] = (Y[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])) / D[i];
837 accel_top[i+1] += joint_accel[i] *
links[i].axis_top;
838 accel_bottom[i+1] += joint_accel[i] *
links[i].axis_bottom;
843 omegadot_out = rot_from_parent[0].
transpose() * accel_top[0];
844 output[0] = omegadot_out[0];
845 output[1] = omegadot_out[1];
846 output[2] = omegadot_out[2];
849 vdot_out = rot_from_parent[0].
transpose() * accel_bottom[0];
851 output[3] = vdot_out[0];
852 output[4] = vdot_out[1];
853 output[5] = vdot_out[2];
866 const btScalar omega_times_dt = omega_norm * dt;
867 const btScalar SMALL_ROTATION_ANGLE = 0.02f;
868 if (
fabs(omega_times_dt) < SMALL_ROTATION_ANGLE)
870 const btScalar xsq = omega_times_dt * omega_times_dt;
871 const btScalar sin_term = dt * (xsq / 48.0f - 0.5f);
872 const btScalar cos_term = 1.0f - xsq / 8.0f;
884 for (
int i = 0; i < num_links; ++i)
887 links[i].joint_pos += dt * jointVel;
888 links[i].updateCache();
902 scratch_v.
resize(2*num_links + 2);
903 scratch_m.
resize(num_links + 1);
906 btVector3 * p_minus_com = v_ptr; v_ptr += num_links + 1;
907 btVector3 * n_local = v_ptr; v_ptr += num_links + 1;
910 scratch_r.
resize(num_links);
911 btScalar * results = num_links > 0 ? &scratch_r[0] : 0;
919 p_minus_com[0] = rot_from_world[0] * p_minus_com_world;
920 n_local[0] = rot_from_world[0] * normal;
924 omega_coeffs = p_minus_com_world.
cross(normal);
925 jac[0] = omega_coeffs[0];
926 jac[1] = omega_coeffs[1];
927 jac[2] = omega_coeffs[2];
934 for (
int i = 6; i < 6 + num_links; ++i) {
939 if (num_links > 0 && link > -1) {
946 for (
int i = 0; i < num_links; ++i) {
949 const int parent =
links[i].parent;
951 rot_from_world[i+1] = mtx * rot_from_world[parent+1];
953 n_local[i+1] = mtx * n_local[parent+1];
954 p_minus_com[i+1] = mtx * p_minus_com[parent+1] -
links[i].cached_r_vector;
957 if (
links[i].is_revolute) {
958 results[i] = n_local[i+1].dot(
links[i].axis_top.cross(p_minus_com[i+1]) +
links[i].axis_bottom );
960 results[i] = n_local[i+1].dot(
links[i].axis_bottom );
966 jac[6 + link] = results[link];
967 link =
links[link].parent;
995 for (
int i = 0; i < 6 + num_links; ++i) {
999 if (motion < SLEEP_EPSILON) {
btMatrix3x3 inverse() const
Return the inverse of the matrix.
void calcAccelerationDeltas(const btScalar *force, btScalar *output, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v) const
const btVector3 getBaseVel() const
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
bool gDisableDeactivation
const btVector3 & getLinkForce(int i) const
btVector3 localDirToWorld(int i, const btVector3 &vec) const
btAlignedObjectArray< btScalar > m_real_buf
void addLinkForce(int i, const btVector3 &f)
btScalar getJointPos(int i) const
btMatrix3x3 cached_inertia_top_right
btMatrix3x3 cached_inertia_lower_left
btQuaternion inverse(const btQuaternion &q)
Return the inverse of a quaternion.
btAlignedObjectArray< btVector3 > vector_buf
btScalar dot(const btVector3 &v) const
Return the dot product.
void applyDeltaVee(const btScalar *delta_vee)
void clearForcesAndTorques()
const btScalar & x() const
Return the x value.
btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
btVector3 getAngularMomentum() const
btAlignedObjectArray< btMatrix3x3 > matrix_buf
int size() const
return the number of elements in the array
btQuaternion & normalize()
Normalize the quaternion Such that x^2 + y^2 + z^2 +w^2 = 1.
const btVector3 & getLinkTorque(int i) const
void addLinkTorque(int i, const btVector3 &t)
static float4 fabs(const float4 &a)
void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
void addJointTorque(int i, btScalar Q)
void setValue(const btScalar &xx, const btScalar &xy, const btScalar &xz, const btScalar &yx, const btScalar &yy, const btScalar &yz, const btScalar &zx, const btScalar &zy, const btScalar &zz)
Set the values of the matrix explicitly (row major)
void solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, float result[6]) const
const btVector3 & getRVector(int i) const
void setJointVel(int i, btScalar qdot)
void setJointPos(int i, btScalar q)
btScalar norm() const
Return the norm (length) of the vector.
const btScalar & y() const
Return the y value.
void checkMotionAndSleepIfRequired(btScalar timestep)
btVector3 can be used to represent 3D points and vectors.
btScalar getLinkMass(int i) const
btMatrix3x3 vecMulVecTranspose(const btVector3 &v0, const btVector3 &v1Transposed)
btVector3 getBaseOmega() const
btAlignedObjectArray< btMultibodyLink > links
void resize(int newsize, const T &fillData=T())
btMatrix3x3 cached_inertia_top_left
void setupPrismatic(int i, btScalar mass, const btVector3 &inertia, int parent, const btQuaternion &rot_parent_to_this, const btVector3 &joint_axis, const btVector3 &r_vector_when_q_zero, bool disableParentCollision=false)
btMatrix3x3 transpose() const
Return the transpose of the matrix.
static float4 cross(const float4 &a, const float4 &b)
btMultiBody(int n_links, btScalar mass, const btVector3 &inertia, bool fixed_base_, bool can_sleep_)
btVector3 worldPosToLocal(int i, const btVector3 &vec) const
const btQuaternion & getParentToLocalRot(int i) const
const Matrix3 transpose(const Matrix3 &mat)
void fillContactJacobian(int link, const btVector3 &contact_point, const btVector3 &normal, btScalar *jac, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m) const
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
btVector3 worldDirToLocal(int i, const btVector3 &vec) const
const btVector3 & getLinkInertia(int i) const
void setupRevolute(int i, btScalar mass, const btVector3 &inertia, int parent, const btQuaternion &zero_rot_parent_to_this, const btVector3 &joint_axis, const btVector3 &parent_axis_position, const btVector3 &my_axis_position, bool disableParentCollision=false)
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
btScalar getJointTorque(int i) const
const btQuaternion & getWorldToBaseRot() const
void stepPositions(btScalar dt)
int getParent(int link_num) const
const btVector3 & getBasePos() const
btVector3 localPosToWorld(int i, const btVector3 &vec) const
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
btScalar m_angularDamping
void stepVelocities(btScalar dt, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m)
btScalar getJointVel(int i) const
btScalar getKineticEnergy() const
const btScalar & z() const
Return the z value.
btMatrix3x3 cached_inertia_lower_right