dynamics_joint/
prismatic.rs1use dynamics_spatial::{
4 configuration::Configuration,
5 motion::{SpatialMotion, SpatialRotation},
6 se3::SE3,
7 vector3d::Vector3D,
8};
9use rand::rngs::ThreadRng;
10
11use crate::{
12 joint::{JointModel, JointType, JointWrapper},
13 joint_data::{JointData, JointDataWrapper, JointError},
14 limits::JointLimits,
15};
16
17#[derive(Clone, Debug)]
21pub struct JointModelPrismatic {
22 pub axis: Vector3D,
24 pub limits: JointLimits,
26}
27
28impl JointModelPrismatic {
29 #[must_use]
38 pub fn new(axis: Vector3D) -> Self {
39 JointModelPrismatic {
40 axis,
41 limits: JointLimits::new_unbounded(1),
42 }
43 }
44
45 #[must_use]
50 pub fn new_px() -> Self {
51 Self::new(Vector3D::x())
52 }
53
54 #[must_use]
59 pub fn new_py() -> Self {
60 Self::new(Vector3D::y())
61 }
62
63 #[must_use]
68 pub fn new_pz() -> Self {
69 Self::new(Vector3D::z())
70 }
71}
72
73impl JointModel for JointModelPrismatic {
74 fn get_joint_type(&self) -> JointType {
75 JointType::Prismatic
76 }
77
78 fn nq(&self) -> usize {
79 1
80 }
81
82 fn nv(&self) -> usize {
83 1
84 }
85
86 fn neutral(&self) -> Configuration {
87 Configuration::from_row_slice(&[0.0])
88 }
89
90 fn create_joint_data(&self) -> JointDataWrapper {
91 JointDataWrapper::prismatic(JointDataPrismatic::new(self))
92 }
93
94 fn get_axis(&self) -> Vec<SpatialMotion> {
95 vec![SpatialMotion::from_translational_axis(&self.axis)]
96 }
97
98 fn random_configuration(&self, rng: &mut ThreadRng) -> Configuration {
99 Configuration::random(
100 1,
101 rng,
102 &self.limits.min_configuration,
103 &self.limits.max_configuration,
104 )
105 }
106
107 fn subspace(&self, v: &Configuration) -> SpatialMotion {
108 assert_eq!(
109 v.len(),
110 1,
111 "Prismatic joint model expects a single velocity value."
112 );
113 v[0] * SpatialMotion::from_translational_axis(&self.axis)
114 }
115
116 fn subspace_dual(&self, f: &dynamics_spatial::force::SpatialForce) -> Configuration {
117 Configuration::from_row_slice(&[f.translation().dot(&self.axis)])
118 }
119
120 fn bias(&self) -> SpatialMotion {
121 SpatialMotion::zero()
122 }
123}
124
125#[derive(Clone, Debug)]
127pub struct JointDataPrismatic {
128 pub joint_q: Configuration,
130 pub joint_v: Configuration,
132 pub placement: SE3,
134 pub joint_velocity: SpatialMotion,
136}
137
138impl JointDataPrismatic {
139 #[must_use]
148 pub fn new(_model: &JointModelPrismatic) -> Self {
149 JointDataPrismatic {
150 joint_q: Configuration::zeros(1),
151 joint_v: Configuration::zeros(1),
152 placement: SE3::identity(),
153 joint_velocity: SpatialMotion::zero(),
154 }
155 }
156}
157
158impl JointData for JointDataPrismatic {
159 fn get_joint_placement(&self) -> SE3 {
160 self.placement
161 }
162
163 fn get_joint_q(&self) -> &Configuration {
164 &self.joint_q
165 }
166
167 fn get_joint_v(&self) -> &Configuration {
168 &self.joint_v
169 }
170
171 fn update(
172 &mut self,
173 joint_model: &JointWrapper,
174 joint_q: &Configuration,
175 joint_v: Option<&Configuration>,
176 ) -> Result<(), JointError> {
177 assert_eq!(
178 joint_q.len(),
179 1,
180 "Prismatic joint data update expects a single position value."
181 );
182 if let Some(joint_v) = joint_v {
183 assert_eq!(
184 joint_v.len(),
185 1,
186 "Prismatic joint model expects a single velocity value."
187 );
188 }
189
190 let axis = match joint_model.get_axis().len() {
191 1 => &joint_model.get_axis()[0],
192 _ => return Err(JointError::MissingAttributeError("axis".to_string())),
193 };
194
195 self.joint_q = joint_q.clone();
197 if let Some(joint_v) = joint_v {
198 self.joint_v = joint_v.clone();
199 self.joint_velocity = self.joint_v[0] * joint_model.get_axis()[0].clone();
200 }
201
202 self.placement =
203 SE3::from_parts(axis.translation() * joint_q[0], SpatialRotation::identity());
204 Ok(())
205 }
206
207 fn get_joint_velocity(&self) -> &SpatialMotion {
208 &self.joint_velocity
209 }
210}