nphysics3d/joint/
ball_joint.rs1use na::{
2 self, DVectorSliceMut, Isometry3, Matrix3, RealField, Translation3, UnitQuaternion, Vector3,
3 VectorSlice3,
4};
5
6use crate::joint::Joint;
7use crate::math::{JacobianSliceMut, Velocity};
8use crate::solver::IntegrationParameters;
9use crate::utils::GeneralizedCross;
10
11#[derive(Copy, Clone, Debug)]
13pub struct BallJoint<N: RealField + Copy> {
14 rot: UnitQuaternion<N>,
15
16 jacobian_v: Matrix3<N>,
17 jacobian_dot_v: Matrix3<N>,
18}
19
20impl<N: RealField + Copy> BallJoint<N> {
21 pub fn new(axisangle: Vector3<N>) -> Self {
23 BallJoint {
24 rot: UnitQuaternion::new(axisangle),
25 jacobian_v: na::zero(),
26 jacobian_dot_v: na::zero(),
27 }
28 }
29}
30
31impl<N: RealField + Copy> Joint<N> for BallJoint<N> {
32 #[inline]
33 fn ndofs(&self) -> usize {
34 3
35 }
36
37 fn body_to_parent(&self, parent_shift: &Vector3<N>, body_shift: &Vector3<N>) -> Isometry3<N> {
38 let trans = Translation3::from(parent_shift - self.rot * body_shift);
39 Isometry3::from_parts(trans, self.rot)
40 }
41
42 fn update_jacobians(&mut self, body_shift: &Vector3<N>, vels: &[N]) {
43 let shift = self.rot * -body_shift;
44 let angvel = VectorSlice3::from_slice(vels);
45
46 self.jacobian_v = shift.gcross_matrix_tr();
47 self.jacobian_dot_v = angvel.cross(&shift).gcross_matrix_tr();
48 }
49
50 fn jacobian(&self, transform: &Isometry3<N>, out: &mut JacobianSliceMut<N>) {
51 let rotmat = transform.rotation.to_rotation_matrix();
53 out.fixed_rows_mut::<3>(0)
54 .copy_from(&(rotmat * self.jacobian_v));
55 out.fixed_rows_mut::<3>(3).copy_from(rotmat.matrix());
56 }
57
58 fn jacobian_dot(&self, transform: &Isometry3<N>, out: &mut JacobianSliceMut<N>) {
59 let rotmat = transform.rotation.to_rotation_matrix();
60 out.fixed_rows_mut::<3>(0)
61 .copy_from(&(rotmat * self.jacobian_dot_v));
62 }
63
64 fn jacobian_dot_veldiff_mul_coordinates(
65 &self,
66 transform: &Isometry3<N>,
67 acc: &[N],
68 out: &mut JacobianSliceMut<N>,
69 ) {
70 let angvel = Vector3::from_row_slice(&acc[..3]);
71 let rotmat = transform.rotation.to_rotation_matrix();
72 let res = rotmat * angvel.gcross_matrix() * self.jacobian_v;
73 out.fixed_rows_mut::<3>(0).copy_from(&res);
74 }
75
76 fn jacobian_mul_coordinates(&self, acc: &[N]) -> Velocity<N> {
77 let angvel = Vector3::from_row_slice(&acc[..3]);
78 let linvel = self.jacobian_v * angvel;
79 Velocity::new(linvel, angvel)
80 }
81
82 fn jacobian_dot_mul_coordinates(&self, acc: &[N]) -> Velocity<N> {
83 let angvel = Vector3::from_row_slice(&acc[..3]);
84 let linvel = self.jacobian_dot_v * angvel;
85 Velocity::new(linvel, na::zero())
86 }
87
88 fn default_damping(&self, out: &mut DVectorSliceMut<N>) {
89 out.fill(na::convert(0.1f64))
90 }
91
92 fn integrate(&mut self, parameters: &IntegrationParameters<N>, vels: &[N]) {
93 let angvel = Vector3::from_row_slice(&vels[..3]);
94 let disp = UnitQuaternion::new_eps(angvel * parameters.dt(), N::zero());
95 self.rot = disp * self.rot;
96 }
97
98 fn apply_displacement(&mut self, disp: &[N]) {
99 let angle = Vector3::from_row_slice(&disp[..3]);
100 let disp = UnitQuaternion::new(angle);
101 self.rot = disp * self.rot;
102 }
103
104 #[inline]
105 fn clone(&self) -> Box<dyn Joint<N>> {
106 Box::new(*self)
107 }
108}