3535
3636@runtime_checkable
3737class ITemplateResolver (Protocol ):
38- """Protocol for resolving templated XML strings (e.g., XACRO, Jinja)."""
38+ """Protocol for resolving templated XML strings (e.g., XACRO, Jinja).
39+
40+ Implementing this protocol allows the SRDFParser to handle files that
41+ require preprocessing before they can be parsed as standard XML.
42+ """
3943
4044 def resolve_string (self , xml_string : str ) -> str :
41- """Resolve a templated string into plain XML."""
45+ """Resolve a templated string into plain XML.
46+
47+ Args:
48+ xml_string: The raw string containing template directives.
49+
50+ Returns:
51+ A resolved XML string ready for parsing.
52+ """
4253 ...
4354
4455
4556class SRDFParser (RobotXMLParser [SemanticRobotDescription ]):
46- """Refined SRDF Parser with MoveIt support."""
57+ """Semantic Robot Description Format (SRDF) Parser.
58+
59+ This parser converts SRDF XML content into a structured
60+ `SemanticRobotDescription` model. It supports MoveIt-specific tags
61+ such as planning groups, end effectors, and collision disabling.
62+ """
4763
4864 def __init__ (
4965 self ,
@@ -71,7 +87,14 @@ def __init__(
7187 self .template_resolver = template_resolver
7288
7389 def _parse_planning_group (self , group_elem : ET .Element ) -> PlanningGroup :
74- """Parse a planning group including its nested components."""
90+ """Parse a <group> element into a PlanningGroup model.
91+
92+ Args:
93+ group_elem: The XML element for the group.
94+
95+ Returns:
96+ A populated PlanningGroup instance.
97+ """
7598 name = group_elem .get ("name" , "unnamed_group" )
7699 links : list [str ] = []
77100 joints : list [str ] = []
@@ -102,7 +125,14 @@ def _parse_planning_group(self, group_elem: ET.Element) -> PlanningGroup:
102125 )
103126
104127 def _parse_group_state (self , state_elem : ET .Element ) -> GroupState :
105- """Parse a named group state."""
128+ """Parse a <group_state> element into a GroupState model.
129+
130+ Args:
131+ state_elem: The XML element for the group state.
132+
133+ Returns:
134+ A populated GroupState instance.
135+ """
106136 name = state_elem .get ("name" , "unnamed_state" )
107137 group = state_elem .get ("group" , "" )
108138 joint_values : dict [str , float ] = {}
@@ -120,7 +150,19 @@ def parse_string(
120150 content : str ,
121151 ** kwargs : Any ,
122152 ) -> SemanticRobotDescription :
123- """Parse SRDF from string into a SemanticRobotDescription model."""
153+ """Parse SRDF content from a string.
154+
155+ Args:
156+ content: The raw SRDF XML string.
157+ **kwargs: Additional options for future extensions.
158+
159+ Returns:
160+ A SemanticRobotDescription model representing the SRDF.
161+
162+ Raises:
163+ RobotParserUnexpectedError: If the XML is malformed.
164+ RobotParserXMLRootError: If the root tag is not <robot>.
165+ """
124166 # Handle templating resolution
125167 if self .template_resolver is not None :
126168 content = self .template_resolver .resolve_string (content )
@@ -146,7 +188,14 @@ def parse_string(
146188 return semantic
147189
148190 def _parse_elements (self , root : ET .Element ) -> SemanticRobotDescription :
149- """Internal helper to parse all SRDF elements from root."""
191+ """Iterate through the XML root and parse all supported SRDF tags.
192+
193+ Args:
194+ root: The <robot> XML root element.
195+
196+ Returns:
197+ A SemanticRobotDescription containing all parsed elements.
198+ """
150199 virtual_joints : list [VirtualJoint ] = []
151200 groups : list [PlanningGroup ] = []
152201 group_states : list [GroupState ] = []
@@ -178,7 +227,14 @@ def _parse_elements(self, root: ET.Element) -> SemanticRobotDescription:
178227 )
179228
180229 def _parse_virtual_joint_elem (self , elem : ET .Element ) -> VirtualJoint :
181- """Parse virtual_joint element."""
230+ """Parse a <virtual_joint> element.
231+
232+ Args:
233+ elem: The XML element.
234+
235+ Returns:
236+ A VirtualJoint model.
237+ """
182238 return VirtualJoint (
183239 name = elem .get ("name" , "unnamed_vj" ),
184240 type = elem .get ("type" , "fixed" ),
@@ -187,7 +243,14 @@ def _parse_virtual_joint_elem(self, elem: ET.Element) -> VirtualJoint:
187243 )
188244
189245 def _parse_end_effector_elem (self , elem : ET .Element ) -> EndEffector :
190- """Parse end_effector element."""
246+ """Parse an <end_effector> element.
247+
248+ Args:
249+ elem: The XML element.
250+
251+ Returns:
252+ An EndEffector model.
253+ """
191254 return EndEffector (
192255 name = elem .get ("name" , "unnamed_ee" ),
193256 group = elem .get ("group" , "" ),
@@ -196,15 +259,33 @@ def _parse_end_effector_elem(self, elem: ET.Element) -> EndEffector:
196259 )
197260
198261 def _parse_disable_collisions_elem (self , elem : ET .Element ) -> DisabledCollision :
199- """Parse disable_collisions element."""
262+ """Parse a <disable_collisions> element.
263+
264+ Args:
265+ elem: The XML element.
266+
267+ Returns:
268+ A DisabledCollision model.
269+ """
200270 return DisabledCollision (
201271 link1 = elem .get ("link1" , "" ),
202272 link2 = elem .get ("link2" , "" ),
203273 reason = elem .get ("reason" ),
204274 )
205275
206276 def parse (self , filepath : Path , ** kwargs : Any ) -> SemanticRobotDescription :
207- """Parse SRDF from file."""
277+ """Load and parse an SRDF file from disk.
278+
279+ Args:
280+ filepath: Path to the .srdf file.
281+ **kwargs: Passed to parse_string.
282+
283+ Returns:
284+ A SemanticRobotDescription model.
285+
286+ Raises:
287+ RobotParserIOError: If the file is missing or exceeds max_file_size.
288+ """
208289 if not filepath .exists ():
209290 raise RobotParserIOError (filepath = filepath , reason = "Missing file" )
210291
0 commit comments