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