robot_description_builder/link/
inertial.rs1use nalgebra::Matrix3;
2
3use crate::transform::{Mirror, Transform};
4
5#[cfg(feature = "urdf")]
6use crate::to_rdf::to_urdf::ToURDF;
7#[cfg(feature = "xml")]
8use quick_xml::{events::attributes::Attribute, name::QName};
9
10#[derive(Debug, PartialEq, Clone, Copy, Default)]
12pub struct Inertial {
13 pub transform: Option<Transform>,
19 pub mass: f32,
21 pub ixx: f32,
23 pub ixy: f32,
25 pub ixz: f32,
27 pub iyy: f32,
29 pub iyz: f32,
31 pub izz: f32,
33}
34
35impl Mirror for Inertial {
36 fn mirrored(&self, mirror_matrix: &Matrix3<f32>) -> Self {
37 Self {
38 transform: self
39 .transform
40 .as_ref()
41 .map(|transform| transform.mirrored(mirror_matrix)),
42 ..*self
43 }
44 }
45}
46
47#[cfg(feature = "urdf")]
48impl ToURDF for Inertial {
49 fn to_urdf(
50 &self,
51 writer: &mut quick_xml::Writer<std::io::Cursor<Vec<u8>>>,
52 urdf_config: &crate::to_rdf::to_urdf::URDFConfig,
53 ) -> Result<(), quick_xml::Error> {
54 let element = writer.create_element("inertial");
55 element.write_inner_content(|writer| -> quick_xml::Result<()> {
56 if let Some(transform) = &self.transform {
57 transform.to_urdf(writer, urdf_config)?;
58 }
59
60 writer
61 .create_element("mass")
62 .with_attribute(Attribute {
63 key: QName(b"value"),
64 value: format!("{}", self.mass).as_bytes().into(),
65 })
66 .write_empty()?;
67
68 writer
69 .create_element("inertia")
70 .with_attributes([
71 ("ixx", self.ixx.to_string().as_str()),
72 ("ixy", self.ixy.to_string().as_str()),
73 ("ixz", self.ixz.to_string().as_str()),
74 ("iyy", self.iyy.to_string().as_str()),
75 ("iyz", self.iyz.to_string().as_str()),
76 ("izz", self.izz.to_string().as_str()),
77 ])
78 .write_empty()?;
79
80 Ok(())
81 })?;
82
83 Ok(())
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::Inertial;
90 use test_log::test;
91
92 #[cfg(feature = "urdf")]
93 mod to_urdf {
94 use super::{test, *};
95
96 use crate::{
97 to_rdf::to_urdf::{ToURDF, URDFConfig},
98 transform::Transform,
99 };
100
101 use std::io::Seek;
102
103 fn test_to_urdf_inertial(
104 inertial_data: Inertial,
105 result: String,
106 urdf_config: &URDFConfig,
107 ) {
108 let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
109 assert!(inertial_data.to_urdf(&mut writer, urdf_config).is_ok());
110
111 writer.get_mut().rewind().unwrap();
112
113 assert_eq!(
114 std::io::read_to_string(writer.into_inner()).unwrap(),
115 result
116 )
117 }
118
119 #[test]
120 fn no_transform() {
121 test_to_urdf_inertial(
122 Inertial {
123 mass: 0.12,
124 ixx: 1.23,
125 ixy: 2.34,
126 ixz: 3.45,
127 iyy: 4.56,
128 iyz: 5.67,
129 izz: 6.78,
130 ..Default::default()
131 },
132 String::from(
133 r#"<inertial><mass value="0.12"/><inertia ixx="1.23" ixy="2.34" ixz="3.45" iyy="4.56" iyz="5.67" izz="6.78"/></inertial>"#,
134 ),
135 &URDFConfig::default(),
136 );
137 }
138
139 #[test]
140 fn with_transform() {
141 test_to_urdf_inertial(
142 Inertial {
143 transform: Some(Transform {
144 translation: Some((10.1, 20.2, 30.3)),
145 ..Default::default()
146 }),
147 mass: 100.,
148 ixx: 123.,
149 iyy: 456.,
150 izz: 789.,
151 ..Default::default()
152 },
153 String::from(
154 r#"<inertial><origin xyz="10.1 20.2 30.3"/><mass value="100"/><inertia ixx="123" ixy="0" ixz="0" iyy="456" iyz="0" izz="789"/></inertial>"#,
155 ),
156 &URDFConfig::default(),
157 );
158 }
159 }
160}