robot_description_builder/cluster_objects/
robot.rs1use std::{
2 collections::HashMap,
3 sync::{Arc, PoisonError, RwLockWriteGuard},
4};
5
6#[cfg(feature = "urdf")]
7use crate::to_rdf::to_urdf::{ToURDF, URDFConfig};
8#[cfg(feature = "xml")]
9use quick_xml::{events::attributes::Attribute, name::QName};
10
11use super::{
12 kinematic_data_errors::AddTransmissionError, kinematic_data_tree::KinematicDataTree,
13 KinematicInterface,
14};
15use crate::{
16 identifiers::GroupID,
17 joint::Joint,
18 link::Link,
19 material::{data::MaterialData, Material},
20 transmission::{
21 transmission_builder_state::{WithActuator, WithJoints},
22 Transmission, TransmissionBuilder,
23 },
24 utils::{ArcLock, WeakLock},
25};
26
27#[derive(Debug)]
28pub struct Robot {
29 name: String,
31 data: Arc<KinematicDataTree>,
32}
33
34impl Robot {
35 pub(crate) fn new(name: impl Into<String>, data: Arc<KinematicDataTree>) -> Self {
36 Self {
37 name: name.into(),
38 data,
39 }
40 }
41
42 pub fn name(&self) -> &String {
54 &self.name
55 }
56}
57
58impl KinematicInterface for Robot {
59 fn get_root_link(&self) -> ArcLock<Link> {
60 Arc::clone(&self.data.root_link)
61 }
62
63 fn get_newest_link(&self) -> ArcLock<Link> {
64 self.data.newest_link.read().unwrap().upgrade().unwrap()
65 }
66
67 fn get_links(&self) -> ArcLock<HashMap<String, WeakLock<Link>>> {
68 Arc::clone(&self.data.links)
69 }
70
71 fn get_joints(&self) -> ArcLock<HashMap<String, WeakLock<Joint>>> {
72 Arc::clone(&self.data.joints)
73 }
74
75 fn get_materials(&self) -> ArcLock<HashMap<String, ArcLock<MaterialData>>> {
76 Arc::clone(&self.data.material_index)
77 }
78
79 fn get_transmissions(&self) -> ArcLock<HashMap<String, ArcLock<Transmission>>> {
80 Arc::clone(&self.data.transmissions)
81 }
82
83 fn get_link(&self, name: &str) -> Option<ArcLock<Link>> {
84 self.data
85 .links
86 .read()
87 .expect("The RwLock of the Link Index was poisoned. In the future this will be recoverable (mutex_unpoison).")
90 .get(name)
91 .and_then(|weak_link| weak_link.upgrade())
92 }
93
94 fn get_joint(&self, name: &str) -> Option<ArcLock<Joint>> {
95 self.data
96 .joints
97 .read()
98 .expect("The RwLock of the Joint Index was poisoned. In the future this will be recoverable (mutex_unpoison).")
101 .get(name)
102 .and_then(|weak_joint| weak_joint.upgrade())
103 }
104
105 fn get_material(&self, name: &str) -> Option<Material> {
106 self.data
107 .material_index
108 .read()
109 .unwrap() .get(name)
111 .map(Arc::clone)
112 .map(|data| Material::new_named_inited(name, data))
113 }
114
115 fn get_transmission(&self, name: &str) -> Option<ArcLock<Transmission>> {
116 self.data
117 .transmissions
118 .read()
119 .unwrap() .get(name)
121 .map(Arc::clone)
122 }
123
124 fn try_add_transmission(
125 &self,
126 transmission: TransmissionBuilder<WithJoints, WithActuator>,
127 ) -> Result<(), AddTransmissionError> {
128 self.data.try_add_transmission(transmission)
129 }
130
131 fn purge_links(&self) {
132 self.data.purge_links()
133 }
134
135 fn purge_joints(&self) {
136 self.data.purge_joints()
137 }
138
139 fn purge_materials(
140 &self,
141 ) -> Result<(), PoisonError<RwLockWriteGuard<HashMap<String, ArcLock<MaterialData>>>>> {
142 self.data.purge_materials()
143 }
144
145 fn purge_transmissions(
146 &self,
147 ) -> Result<(), PoisonError<RwLockWriteGuard<HashMap<String, ArcLock<Transmission>>>>> {
148 self.data.purge_transmissions()
149 }
150}
151
152#[cfg(feature = "urdf")]
153impl ToURDF for Robot {
154 fn to_urdf(
155 &self,
156 writer: &mut quick_xml::Writer<std::io::Cursor<Vec<u8>>>,
157 urdf_config: &URDFConfig,
158 ) -> Result<(), quick_xml::Error> {
159 let element = writer.create_element("robot").with_attribute(Attribute {
160 key: QName(b"name"),
161 value: self.name.display().as_bytes().into(),
162 });
163 element.write_inner_content(|writer| self.data.to_urdf(writer, urdf_config))?;
164 Ok(())
165 }
166}