@@ -46,6 +46,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
4646 result .add_error (
4747 title = "No links" ,
4848 message = "Robot must have at least one link" ,
49+ code = ValidationErrorCode .VALUE_EMPTY ,
4950 suggestion = "Add a link by marking an object as a robot link in the Link panel" ,
5051 )
5152
@@ -78,6 +79,7 @@ def _check_duplicates(names: list[str], kind: str, result: ValidationResult) ->
7879 f"{ names .count (name )} { kind } s. Each { kind } must have a unique name"
7980 ),
8081 affected_objects = [n for n in names if n == name ],
82+ code = ValidationErrorCode .DUPLICATE_NAME ,
8183 suggestion = f"Rename duplicate { kind } s to unique names (e.g., '{ name } _1', '{ name } _2')" ,
8284 )
8385 return # Report once per kind
@@ -100,6 +102,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
100102 f"'{ joint .parent } ' which does not exist"
101103 ),
102104 affected_objects = [joint .name ],
105+ code = ValidationErrorCode .NOT_FOUND ,
103106 suggestion = f"Create a link named '{ joint .parent } ' or update the joint's parent reference" ,
104107 )
105108
@@ -111,6 +114,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
111114 f"'{ joint .child } ' which does not exist"
112115 ),
113116 affected_objects = [joint .name ],
117+ code = ValidationErrorCode .NOT_FOUND ,
114118 suggestion = f"Create a link named '{ joint .child } ' or update the joint's child reference" ,
115119 )
116120
@@ -138,6 +142,7 @@ def _check_cycles(robot: Robot, result: ValidationResult) -> None:
138142 "Kinematic tree contains a cycle. "
139143 "Links must form a tree structure, not a loop."
140144 ),
145+ code = ValidationErrorCode .HAS_CYCLE ,
141146 suggestion = "Review joint connections to ensure they form a tree (no loops)" ,
142147 )
143148 except RobotModelError as e :
@@ -148,6 +153,7 @@ def _check_cycles(robot: Robot, result: ValidationResult) -> None:
148153 result .add_error (
149154 title = "Kinematic graph error" ,
150155 message = str (e ),
156+ code = ValidationErrorCode .INVALID_VALUE ,
151157 suggestion = "Check joint and link consistency" ,
152158 )
153159
@@ -163,6 +169,7 @@ def _check_root(robot: Robot, result: ValidationResult) -> Link | None:
163169 "No root link found. A robot must have exactly one link "
164170 "that is not a child in any joint."
165171 ),
172+ code = ValidationErrorCode .NO_ROOT ,
166173 suggestion = "Ensure exactly one link has no parent joint (the base/root link)" ,
167174 )
168175 return root
@@ -184,6 +191,7 @@ def _check_root(robot: Robot, result: ValidationResult) -> Link | None:
184191 result .add_error (
185192 title = "Root link error" ,
186193 message = str (e ),
194+ code = e .code if hasattr (e , "code" ) else ValidationErrorCode .INVALID_VALUE ,
187195 suggestion = "Check the joint connections in your robot tree" ,
188196 )
189197 else :
@@ -207,6 +215,7 @@ def _check_connectivity(robot: Robot, root: object, result: ValidationResult) ->
207215 title = "Disconnected link" ,
208216 message = f"Link '{ link .name } ' is not connected to the kinematic tree" ,
209217 affected_objects = [link .name ],
218+ code = ValidationErrorCode .DISCONNECTED ,
210219 suggestion = f"Create a joint connecting '{ link .name } ' to another link in the tree" ,
211220 )
212221 elif count > 1 :
@@ -216,6 +225,7 @@ def _check_connectivity(robot: Robot, root: object, result: ValidationResult) ->
216225 f"Link '{ link .name } ' has { count } parent joints (should have exactly 1)"
217226 ),
218227 affected_objects = [link .name ],
228+ code = ValidationErrorCode .MULTIPLE_ROOTS ,
219229 suggestion = "Remove extra joints. Each link can only have one parent" ,
220230 )
221231
@@ -231,6 +241,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
231241 title = "Very low mass" ,
232242 message = f"Link '{ link .name } ' has very low mass ({ link .mass :.6f} kg)." ,
233243 affected_objects = [link .name ],
244+ code = ValidationErrorCode .INVALID_VALUE ,
234245 suggestion = "Consider providing a more realistic mass to avoid simulation instability" ,
235246 )
236247
@@ -239,6 +250,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
239250 title = "Missing inertia" ,
240251 message = f"Link '{ link .name } ' has no inertia tensor defined" ,
241252 affected_objects = [link .name ],
253+ code = ValidationErrorCode .NOT_FOUND ,
242254 suggestion = "Add an inertial element or use automatic inertia calculation" ,
243255 )
244256
@@ -254,6 +266,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
254266 title = "No visual geometry" ,
255267 message = f"Link '{ link .name } ' has no visual geometry" ,
256268 affected_objects = [link .name ],
269+ code = ValidationErrorCode .NOT_FOUND ,
257270 suggestion = "Add visual geometry for better visualization in simulators" ,
258271 )
259272
@@ -262,6 +275,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
262275 title = "No collision geometry" ,
263276 message = f"Link '{ link .name } ' has no collision geometry" ,
264277 affected_objects = [link .name ],
278+ code = ValidationErrorCode .NOT_FOUND ,
265279 suggestion = "Add collision geometry for physics simulation" ,
266280 )
267281
@@ -285,6 +299,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
285299 "does not exist in the kinematic tree"
286300 ),
287301 affected_objects = [rc_joint .name ],
302+ code = ValidationErrorCode .NOT_FOUND ,
288303 suggestion = "Ensure joint name in control matches a robot joint" ,
289304 )
290305
@@ -310,6 +325,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
310325 title = "Invalid mimic target" ,
311326 message = (f"Joint '{ joint .name } ' mimics non-existent joint '{ current } '" ),
312327 affected_objects = [joint .name ],
328+ code = ValidationErrorCode .NOT_FOUND ,
313329 suggestion = (f"Ensure joint '{ current } ' exists or update mimic reference" ),
314330 )
315331 break
@@ -320,6 +336,7 @@ def run(self, robot: Robot, result: ValidationResult) -> None:
320336 title = "Circular mimic dependency" ,
321337 message = f"Circular mimic dependency detected: { chain } " ,
322338 affected_objects = list (visited ),
339+ code = ValidationErrorCode .HAS_CYCLE ,
323340 suggestion = "Break the circular mimic chain by changing mimic targets" ,
324341 )
325342 break
0 commit comments