1use na::{DVectorSliceMut, Isometry3, RealField, Unit, Vector3};
2
3use crate::joint::{Joint, PrismaticJoint, RevoluteJoint};
4use crate::math::{JacobianSliceMut, Velocity};
5use crate::object::{BodyPartHandle, Multibody, MultibodyLink};
6use crate::solver::{ConstraintSet, GenericNonlinearConstraint, IntegrationParameters};
7
8#[derive(Copy, Clone, Debug)]
12pub struct PinSlotJoint<N: RealField + Copy> {
13 prism: PrismaticJoint<N>,
14 revo: RevoluteJoint<N>,
15}
16
17impl<N: RealField + Copy> PinSlotJoint<N> {
18 pub fn new(axis_v: Unit<Vector3<N>>, axis_w: Unit<Vector3<N>>, position: N, angle: N) -> Self {
21 let prism = PrismaticJoint::new(axis_v, position);
22 let revo = RevoluteJoint::new(axis_w, angle);
23
24 PinSlotJoint { prism, revo }
25 }
26
27 pub fn offset(&self) -> N {
29 self.prism.offset()
30 }
31
32 pub fn angle(&self) -> N {
34 self.revo.angle()
35 }
36}
37
38impl<N: RealField + Copy> Joint<N> for PinSlotJoint<N> {
39 #[inline]
40 fn ndofs(&self) -> usize {
41 2
42 }
43
44 fn body_to_parent(&self, parent_shift: &Vector3<N>, body_shift: &Vector3<N>) -> Isometry3<N> {
45 self.prism.translation() * self.revo.body_to_parent(parent_shift, body_shift)
46 }
47
48 fn update_jacobians(&mut self, body_shift: &Vector3<N>, vels: &[N]) {
49 self.prism.update_jacobians(body_shift, vels);
50 self.revo.update_jacobians(body_shift, &[vels[1]]);
51 }
52
53 fn jacobian(&self, transform: &Isometry3<N>, out: &mut JacobianSliceMut<N>) {
54 self.prism.jacobian(transform, &mut out.columns_mut(0, 1));
55 self.revo.jacobian(transform, &mut out.columns_mut(1, 1));
56 }
57
58 fn jacobian_dot(&self, transform: &Isometry3<N>, out: &mut JacobianSliceMut<N>) {
59 self.prism
60 .jacobian_dot(transform, &mut out.columns_mut(0, 1));
61 self.revo
62 .jacobian_dot(transform, &mut out.columns_mut(1, 1));
63 }
64
65 fn jacobian_dot_veldiff_mul_coordinates(
66 &self,
67 transform: &Isometry3<N>,
68 vels: &[N],
69 out: &mut JacobianSliceMut<N>,
70 ) {
71 self.prism.jacobian_dot_veldiff_mul_coordinates(
72 transform,
73 vels,
74 &mut out.columns_mut(0, 1),
75 );
76 self.revo.jacobian_dot_veldiff_mul_coordinates(
77 transform,
78 &[vels[1]],
79 &mut out.columns_mut(1, 1),
80 );
81 }
82
83 fn jacobian_mul_coordinates(&self, vels: &[N]) -> Velocity<N> {
84 self.prism.jacobian_mul_coordinates(vels) + self.revo.jacobian_mul_coordinates(&[vels[1]])
85 }
86
87 fn jacobian_dot_mul_coordinates(&self, vels: &[N]) -> Velocity<N> {
88 self.revo.jacobian_dot_mul_coordinates(&[vels[1]])
91 }
92
93 fn default_damping(&self, out: &mut DVectorSliceMut<N>) {
94 self.prism.default_damping(&mut out.rows_mut(0, 1));
95 self.revo.default_damping(&mut out.rows_mut(1, 1));
96 }
97
98 fn integrate(&mut self, parameters: &IntegrationParameters<N>, vels: &[N]) {
99 self.prism.integrate(parameters, vels);
100 self.revo.integrate(parameters, &[vels[1]]);
101 }
102
103 fn apply_displacement(&mut self, disp: &[N]) {
104 self.prism.apply_displacement(disp);
105 self.revo.apply_displacement(&[disp[1]]);
106 }
107
108 #[inline]
109 fn clone(&self) -> Box<dyn Joint<N>> {
110 Box::new(*self)
111 }
112
113 fn num_velocity_constraints(&self) -> usize {
114 self.prism.num_velocity_constraints() + self.revo.num_velocity_constraints()
115 }
116
117 fn velocity_constraints(
118 &self,
119 parameters: &IntegrationParameters<N>,
120 multibody: &Multibody<N>,
121 link: &MultibodyLink<N>,
122 assembly_id: usize,
123 dof_id: usize,
124 ext_vels: &[N],
125 ground_j_id: &mut usize,
126 jacobians: &mut [N],
127 constraints: &mut ConstraintSet<N, (), (), usize>,
128 ) {
129 self.prism.velocity_constraints(
130 parameters,
131 multibody,
132 link,
133 assembly_id,
134 dof_id,
135 ext_vels,
136 ground_j_id,
137 jacobians,
138 constraints,
139 );
140 self.revo.velocity_constraints(
141 parameters,
142 multibody,
143 link,
144 assembly_id,
145 dof_id + 1,
146 ext_vels,
147 ground_j_id,
148 jacobians,
149 constraints,
150 );
151 }
152
153 fn num_position_constraints(&self) -> usize {
154 2
156 }
157
158 fn position_constraint(
159 &self,
160 i: usize,
161 multibody: &Multibody<N>,
162 link: &MultibodyLink<N>,
163 handle: BodyPartHandle<()>,
164 dof_id: usize,
165 jacobians: &mut [N],
166 ) -> Option<GenericNonlinearConstraint<N, ()>> {
167 if i == 0 {
168 self.prism
169 .position_constraint(0, multibody, link, handle, dof_id, jacobians)
170 } else {
171 self.revo
172 .position_constraint(0, multibody, link, handle, dof_id + 1, jacobians)
173 }
174 }
175}
176
177prismatic_motor_limit_methods!(PinSlotJoint, prism);
178revolute_motor_limit_methods!(PinSlotJoint, revo);