How to Perform Visual Collision Checking Between CAD Parts in text-to-cad
The text-to-cad repository implements visual collision checking by parsing URDF/SDF files to separate visual and collision geometry, loading meshes via Python URDF sources, and executing runtime collision queries through a MoveIt2 planning scene that respects SRDF disabled collision pairs.
The text-to-cad pipeline enables roboticists and CAD designers to verify that mechanical parts do not intersect before fabrication. This article examines how the repository handles visual collision checking by coordinating JavaScript parsers, Python mesh loaders, and the MoveIt2 motion planning framework. Understanding this architecture allows you to programmatically validate CAD assemblies and prevent physical collisions in robotic applications.
Understanding the Collision Checking Architecture
The collision checking system operates through five distinct layers that convert raw CAD definitions into actionable collision reports. Each layer handles a specific transformation from XML parsing to geometric intersection testing.
-
URDF/SDF Parsing: JavaScript utilities in
packages/cadjs/src/lib/urdf/parseSdf.jsextract<visual>and<collision>elements and resolve mesh URLs, whileparseSrdf.jsmanages disabled collision pairs. -
Python URDF Sources: The
UrdfSourceclass inskills/urdf/scripts/urdf/source.py(lines 60-109) builds objects containingvisual_mesh_pathsandcollision_mesh_paths, whileskills/sdf/scripts/sdf/source.pyhandles SDF equivalents. -
SRDF Configuration: The
SrdfSourceclass inskills/srdf/scripts/srdf/source.py(lines 70-212) interprets<disable_collisions>entries that instruct the system to ignore specific contact pairs. -
MoveIt2 Integration: The planning scene server in
viewer/moveit2_server/moveit2_server/context.py(lines 442-713) createsCollisionObjectinstances and performs runtime geometric queries. -
Export Validation: The generation module in
packages/cadpy/src/cadpy/generation.py(lines 548-572) aborts exports if mesh intersections are detected during file conversion.
Parsing Visual and Collision Geometry
The collision checking process begins in the JavaScript parsing layer where URDF and SDF files are analyzed to distinguish between visual representation and physical collision boundaries.
In packages/cadjs/src/lib/urdf/parseSdf.js, line 251 implements the logic that determines mesh classification:
labelKind = kind === "collision" ? "collision" : "visual"
When a <link> element contains only a <visual> child, the parser automatically uses the visual mesh for collision calculations. This default behavior ensures that every link possesses collision geometry even when designers omit explicit <collision> tags. The parser collects these mesh URLs and maintains separate arrays for visual and collision types within each link object.
For SRDF processing, packages/cadjs/src/lib/urdf/parseSrdf.js handles collision pair exclusions. Lines 392-408 validate <disable_collisions> entries, ensuring that specified link pairs are properly formatted before reaching the MoveIt2 planning scene.
Loading Mesh Data with Python URDF Sources
After parsing, the Python layer transforms file paths into structured mesh sources ready for geometric computation. The UrdfSource class in skills/urdf/scripts/urdf/source.py (lines 60-109) populates two critical attributes:
visual_mesh_paths: References to meshes used for renderingcollision_mesh_paths: References to simplified meshes used for intersection testing
If collision meshes are unspecified, the system falls back to visual geometry for intersection checks. The SrdfSource class in skills/srdf/scripts/srdf/source.py (lines 70-212) complements this by parsing SrdfDisabledCollisionPair objects that represent intentional mechanical contacts between adjacent parts.
Runtime Collision Checking with MoveIt2
The actual geometric intersection testing occurs within the MoveIt2 planning framework. The MoveIt2Context class in viewer/moveit2_server/moveit2_server/context.py (lines 442-713) initializes a planning scene containing CollisionObject instances for each link's collision geometry.
When performing collision queries, the system checks all enabled collision pairs while automatically excluding those listed in the SRDF configuration. This allows the collision checker to ignore intentional contacts between connected joints while flagging unintended intersections between moving parts.
The collision checking API exposes methods to query specific link pairs, returning boolean results indicating whether geometric overlap exists between the specified CAD components.
Export-Time Safety Validation
Beyond runtime checking, text-to-cad validates collisions during file export operations. The generation module in packages/cadpy/src/cadpy/generation.py (lines 548-572) implements a safety check that aborts the export process if converted meshes would intersect in the output format.
The code raises a Native GLB output collision error (line 572) when the generator detects mesh intersections, preventing the creation of physically impossible assemblies in exported GLB, STL, or 3MF files.
Implementation Examples
Querying Collisions in Python
The following example demonstrates loading URDF/SRDF sources and checking for collisions between specific links:
from skills.urdf.scripts.urdf.source import UrdfSource
from skills.srdf.scripts.srdf.source import SrdfSource
from viewer.moveit2_server.moveit2_server.context import MoveIt2Context
from pathlib import Path
# Load URDF and SRDF sources
urdf_src = UrdfSource(source_path=Path("models/robot.urdf"))
srdf_src = SrdfSource(source_path=Path("models/robot.srdf"))
# Initialize MoveIt2 planning context
ctx = MoveIt2Context(
urdf_source=urdf_src,
srdf_source=srdf_src,
# Additional required arguments omitted for brevity
)
# Check collision between specific links
is_colliding = ctx.check_collision("base_link", "wrist")
print(f"Collision detected: {is_colliding}")
Inspecting Parsed Geometry in JavaScript
For web-based viewers, inspect parsed collision meshes using the SDF parser:
import { parseSdf } from "./packages/cadjs/src/lib/urdf/parseSdf.js";
const sdfData = parseSdf(sdfXml, { sourceUrl: "/models/robot.sdf" });
sdfData.links.forEach(link => {
console.log(`${link.name} collision meshes:`,
link.collisions.map(c => c.meshUrl));
});
Disabling Known Collision Pairs
Exclude adjacent links from collision checking by adding entries to your SRDF file:
<disable_collisions link1="base_link" link2="shoulder_link" reason="adjacent"/>
According to the source code in skills/srdf/scripts/srdf/source.py, these entries create SrdfDisabledCollisionPair objects that the MoveIt2 server respects during planning scene initialization.
Summary
-
Separate geometry types: The text-to-cad pipeline distinguishes between visual meshes for rendering and collision meshes for intersection testing, falling back to visual geometry when collision meshes are unspecified.
-
Multi-layer architecture: Collision checking flows from JavaScript URDF/SDF parsers through Python source objects to the MoveIt2 planning scene, with SRDF configuration controlling which pairs to ignore.
-
Runtime and export validation: The system checks for collisions both during MoveIt2 planning queries and during mesh export operations, preventing the generation of physically intersecting CAD assemblies.
-
Disabled collision support: SRDF files define intentional contacts between adjacent parts using
<disable_collisions>tags, which the parser validates and the MoveIt2 server respects during geometric queries.
Frequently Asked Questions
What happens if a URDF link lacks explicit collision geometry?
When a <link> element contains only <visual> tags, the JavaScript parser in packages/cadjs/src/lib/urdf/parseSdf.js (line 251) automatically uses the visual mesh for collision calculations. The Python UrdfSource class then populates collision_mesh_paths with the visual mesh paths, ensuring every link participates in collision checking.
How do I exclude specific part pairs from collision detection?
Add <disable_collisions link1="part_a" link2="part_b" reason="adjacent"/> entries to your SRDF file. The SrdfSource class in skills/srdf/scripts/srdf/source.py (lines 70-212) parses these into SrdfDisabledCollisionPair objects. When initializing the MoveIt2Context in viewer/moveit2_server/moveit2_server/context.py, these pairs are automatically excluded from collision queries.
Can collision checking run during mesh export to GLB or STL?
Yes. The generation module in packages/cadpy/src/cadpy/generation.py (lines 548-572) performs collision validation during the export process. If the code detects intersecting meshes when generating GLB, STL, or 3MF files, it raises a "Native GLB output collision" error and aborts the export to prevent manufacturing physically impossible assemblies.
What is the difference between visual and collision meshes in the pipeline?
Visual meshes define the high-resolution appearance of parts for rendering, while collision meshes provide simplified geometric representations optimized for fast intersection calculations. The UrdfSource class stores these separately in visual_mesh_paths and collision_mesh_paths attributes. MoveIt2 uses collision meshes exclusively for planning scene queries, whereas export validators check both types depending on availability.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →