robot_description_builder/joint/joint_data/
dynamics_data.rs

1#[cfg(feature = "xml")]
2use quick_xml::{events::attributes::Attribute, name::QName};
3
4#[derive(Debug, PartialEq, Clone, Copy, Default)]
5pub struct DynamicsData {
6	pub damping: Option<f32>,
7	pub friction: Option<f32>,
8}
9
10impl DynamicsData {
11	/// A function to check if any of the fields are set.
12	///
13	/// It doesn't check if the some fields have the default value, since it can be format depended.
14	///
15	/// ## Example
16	///
17	/// ```
18	/// # use robot_description_builder::joint_data::DynamicsData;
19	/// assert!(DynamicsData {
20	///     damping: Some(1.),
21	///     friction: Some(2.)
22	/// }
23	/// .contains_some());
24	///
25	/// assert!(DynamicsData {
26	///     damping: Some(1.),
27	///     ..Default::default()
28	/// }
29	/// .contains_some());
30	///
31	/// assert!(DynamicsData {
32	///     friction: Some(2.),
33	///     ..Default::default()
34	/// }
35	/// .contains_some());
36	///
37	/// assert!(!DynamicsData::default().contains_some())
38	/// ```
39	pub fn contains_some(&self) -> bool {
40		self.damping.is_some() || self.friction.is_some()
41	}
42}
43
44#[cfg(feature = "urdf")]
45impl crate::to_rdf::to_urdf::ToURDF for DynamicsData {
46	fn to_urdf(
47		&self,
48		writer: &mut quick_xml::Writer<std::io::Cursor<Vec<u8>>>,
49		_urdf_config: &crate::to_rdf::to_urdf::URDFConfig,
50	) -> Result<(), quick_xml::Error> {
51		if self.contains_some() {
52			let mut element = writer.create_element("dynamics");
53
54			if let Some(damping) = self.damping {
55				element = element.with_attribute(Attribute {
56					key: QName(b"damping"),
57					value: damping.to_string().as_bytes().into(),
58				})
59			}
60
61			if let Some(friction) = self.friction {
62				element = element.with_attribute(Attribute {
63					key: QName(b"friction"),
64					value: friction.to_string().as_bytes().into(),
65				})
66			}
67
68			element.write_empty()?;
69		}
70
71		Ok(())
72	}
73}
74
75#[cfg(test)]
76mod tests {
77	use crate::joint::joint_data::DynamicsData;
78
79	#[test]
80	fn contains_some() {
81		assert!(DynamicsData {
82			damping: Some(1.),
83			friction: Some(2.)
84		}
85		.contains_some());
86
87		assert!(DynamicsData {
88			damping: Some(1.),
89			..Default::default()
90		}
91		.contains_some());
92
93		assert!(DynamicsData {
94			friction: Some(2.),
95			..Default::default()
96		}
97		.contains_some());
98
99		assert!(!DynamicsData::default().contains_some())
100	}
101
102	#[cfg(feature = "urdf")]
103	mod to_urdf {
104		use std::io::Seek;
105
106		use super::DynamicsData;
107		use crate::to_rdf::to_urdf::{ToURDF, URDFConfig};
108
109		fn test_to_urdf_dynamics(
110			dynamics_data: DynamicsData,
111			result: String,
112			urdf_config: &URDFConfig,
113		) {
114			let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
115			assert!(dynamics_data.to_urdf(&mut writer, urdf_config).is_ok());
116
117			writer.get_mut().rewind().unwrap();
118
119			assert_eq!(
120				std::io::read_to_string(writer.into_inner()).unwrap(),
121				result
122			);
123		}
124
125		#[test]
126		fn empty() {
127			test_to_urdf_dynamics(
128				DynamicsData::default(),
129				String::from(r#""#),
130				&URDFConfig::default(),
131			);
132		}
133
134		#[test]
135		fn damping() {
136			test_to_urdf_dynamics(
137				DynamicsData {
138					damping: Some(1000.),
139					..Default::default()
140				},
141				String::from(r#"<dynamics damping="1000"/>"#),
142				&URDFConfig::default(),
143			);
144
145			test_to_urdf_dynamics(
146				DynamicsData {
147					damping: Some(0.02),
148					..Default::default()
149				},
150				String::from(r#"<dynamics damping="0.02"/>"#),
151				&URDFConfig::default(),
152			);
153
154			test_to_urdf_dynamics(
155				DynamicsData {
156					damping: Some(9e-6),
157					..Default::default()
158				},
159				String::from(r#"<dynamics damping="0.000009"/>"#),
160				&URDFConfig::default(),
161			);
162		}
163
164		#[test]
165		fn friction() {
166			test_to_urdf_dynamics(
167				DynamicsData {
168					friction: Some(1000.),
169					..Default::default()
170				},
171				String::from(r#"<dynamics friction="1000"/>"#),
172				&URDFConfig::default(),
173			);
174
175			test_to_urdf_dynamics(
176				DynamicsData {
177					friction: Some(0.02),
178					..Default::default()
179				},
180				String::from(r#"<dynamics friction="0.02"/>"#),
181				&URDFConfig::default(),
182			);
183
184			test_to_urdf_dynamics(
185				DynamicsData {
186					friction: Some(9e-6),
187					..Default::default()
188				},
189				String::from(r#"<dynamics friction="0.000009"/>"#),
190				&URDFConfig::default(),
191			);
192		}
193
194		#[test]
195		fn damping_friction() {
196			test_to_urdf_dynamics(
197				DynamicsData {
198					damping: Some(1000.),
199					friction: Some(900000.),
200				},
201				String::from(r#"<dynamics damping="1000" friction="900000"/>"#),
202				&URDFConfig::default(),
203			);
204
205			test_to_urdf_dynamics(
206				DynamicsData {
207					damping: Some(0.02),
208					friction: Some(0.004),
209				},
210				String::from(r#"<dynamics damping="0.02" friction="0.004"/>"#),
211				&URDFConfig::default(),
212			);
213
214			test_to_urdf_dynamics(
215				DynamicsData {
216					damping: Some(9e-6),
217					friction: Some(15e-4),
218				},
219				String::from(r#"<dynamics damping="0.000009" friction="0.0015"/>"#),
220				&URDFConfig::default(),
221			);
222		}
223	}
224}