robot_description_builder/joint/joint_data/
limit_data.rs

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