dynamics_joint/
prismatic.rs1use std::fmt::Display;
4
5use dynamics_spatial::{
6 configuration::Configuration,
7 motion::{SpatialMotion, SpatialRotation},
8 se3::SE3,
9 vector3d::Vector3D,
10};
11use rand::rngs::ThreadRng;
12
13use crate::{
14 joint::{JointModel, JointType, JointWrapper},
15 joint_data::{JointData, JointDataWrapper},
16 limits::JointLimits,
17};
18
19#[derive(Clone, Debug)]
23pub struct JointModelPrismatic {
24 pub axis: SpatialMotion,
26 pub limits: JointLimits,
28 pub bias: SpatialMotion,
30}
31
32impl JointModelPrismatic {
33 #[must_use]
44 pub fn new(axis: Vector3D) -> Self {
45 JointModelPrismatic {
46 axis: SpatialMotion::from_translational_axis(&axis),
47 limits: JointLimits::new_unbounded(1),
48 bias: SpatialMotion::zero(),
49 }
50 }
51
52 #[must_use]
57 pub fn new_px() -> Self {
58 Self::new(Vector3D::x())
59 }
60
61 #[must_use]
66 pub fn new_py() -> Self {
67 Self::new(Vector3D::y())
68 }
69
70 #[must_use]
75 pub fn new_pz() -> Self {
76 Self::new(Vector3D::z())
77 }
78}
79
80impl JointModel for JointModelPrismatic {
81 fn get_joint_type(&self) -> JointType {
82 JointType::Prismatic
83 }
84
85 fn nq(&self) -> usize {
86 1
87 }
88
89 fn nv(&self) -> usize {
90 1
91 }
92
93 fn neutral(&self) -> Configuration {
94 Configuration::from_row_slice(&[0.0])
95 }
96
97 fn create_joint_data(&self) -> JointDataWrapper {
98 JointDataWrapper::prismatic(JointDataPrismatic::new())
99 }
100
101 fn get_axis(&self) -> &SpatialMotion {
102 &self.axis
103 }
104
105 fn random_configuration(&self, rng: &mut ThreadRng) -> Configuration {
106 Configuration::random(
107 1,
108 rng,
109 &self.limits.min_configuration,
110 &self.limits.max_configuration,
111 )
112 }
113
114 fn subspace(&self, v: &Configuration) -> SpatialMotion {
115 assert_eq!(
116 v.len(),
117 1,
118 "Prismatic joint model expects a single velocity value."
119 );
120 SpatialMotion::from_translational_axis(&(v[0] * self.axis.translation()))
121 }
122
123 fn subspace_dual(&self, f: &dynamics_spatial::force::SpatialForce) -> Configuration {
124 Configuration::from_row_slice(&[f.translation().dot(&self.axis.translation())])
125 }
126
127 fn subspace_se3(&self, se3: &SE3) -> SpatialMotion {
128 let trans = se3.translation();
129 let v = trans.dot(&self.axis.translation()) * self.axis.translation();
130 SpatialMotion::from_translational_axis(&v)
131 }
132
133 fn bias(&self) -> &SpatialMotion {
134 &self.bias
135 }
136
137 fn integrate(&self, q: &Configuration, v: &Configuration) -> Configuration {
138 Configuration::from_row_slice(&[q[0] + v[0]])
139 }
140}
141
142impl Display for JointModelPrismatic {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 write!(f, "JointModelPrismatic(axis: {:?})", self.axis.as_slice())
145 }
146}
147
148#[derive(Clone, Debug)]
150pub struct JointDataPrismatic {
151 pub joint_q: Configuration,
153 pub joint_v: Configuration,
155 pub placement: SE3,
157 pub joint_velocity: SpatialMotion,
159}
160
161impl JointDataPrismatic {
162 #[must_use]
171 pub fn new() -> Self {
172 JointDataPrismatic {
173 joint_q: Configuration::zeros(1),
174 joint_v: Configuration::zeros(1),
175 placement: SE3::identity(),
176 joint_velocity: SpatialMotion::zero(),
177 }
178 }
179}
180
181impl Default for JointDataPrismatic {
182 fn default() -> Self {
183 JointDataPrismatic::new()
184 }
185}
186
187impl JointData for JointDataPrismatic {
188 fn get_joint_placement(&self) -> SE3 {
189 self.placement
190 }
191
192 fn get_joint_q(&self) -> &Configuration {
193 &self.joint_q
194 }
195
196 fn get_joint_v(&self) -> &Configuration {
197 &self.joint_v
198 }
199
200 fn update(
201 &mut self,
202 joint_model: &JointWrapper,
203 joint_q: &Configuration,
204 joint_v: Option<&Configuration>,
205 ) {
206 assert_eq!(
207 joint_q.len(),
208 1,
209 "Prismatic joint data update expects a single position value."
210 );
211 if let Some(joint_v) = joint_v {
212 assert_eq!(
213 joint_v.len(),
214 1,
215 "Prismatic joint model expects a single velocity value."
216 );
217 }
218
219 self.joint_q = joint_q.clone();
221 if let Some(joint_v) = joint_v {
222 self.joint_v = joint_v.clone();
223 self.joint_velocity = self.joint_v[0] * joint_model.get_axis().clone();
224 }
225
226 self.placement = SE3::from_parts(
227 joint_model.get_axis().translation() * joint_q[0],
228 SpatialRotation::identity(),
229 );
230 }
231
232 fn get_joint_velocity(&self) -> &SpatialMotion {
233 &self.joint_velocity
234 }
235}