How to Create Named Mating Datums and Positioning in Assemblies with Text-to-CAD
Text-to-CAD implements assembly mating through the AssemblyHelper class in packages/cadpy/src/cadpy/assembly.py, which provides a three-step workflow to define named datums on parts, create kinematic joint frames, and connect them to generate export-ready STEP payloads.
The earthtojake/text-to-cad repository provides a Python API for programmatically defining mechanical assemblies with fully-typed mating relationships. Built on top of build123d, the AssemblyHelper class bridges geometric modeling with STEP-compatible assembly metadata, enabling precise positioning through named reference frames and joint definitions.
The Three-Stage Assembly Workflow
Creating named mating datums and positioning in assemblies follows a deterministic pipeline implemented in packages/cadpy/src/cadpy/assembly.py. The workflow progresses from reference frame definition to kinematic connection, culminating in structured export data.
1. Define Named Datums with datum()
Use the datum() method (lines 32-39) to assign STEP-friendly labels to specific locations on part geometries. This method wraps label_shape and utilizes label_text() to generate compact, unique identifiers like mount:center or base:front_left that serve as standardized anchor points during assembly operations.
from cadpy.assembly import AssemblyHelper
import build123d as bd
asm = AssemblyHelper("robot_arm")
base_plate = bd.Box(100, 100, 10)
asm.add(base_plate, "base_plate")
asm.datum(base_plate, "mount", "center") # Creates label "mount:center"
2. Create Joint Frames
Joint frames define the kinematic relationship between mating parts. AssemblyHelper provides specialized factory methods—rigid_frame(), revolute_frame(), linear_frame(), cylindrical_frame(), and ball_frame()—that delegate to internal builders including add_rigid_frame, add_axis_frame, and add_joint_frame (lines 61-67 and 70-78).
link_body = bd.Cylinder(5, 50)
asm.add(link_body, "link_body")
# Create rigid frame at specific location
link_tip = asm.rigid_frame(link_body, "link_tip", bd.Location((0, 0, 0)))
3. Connect Frames with connect()
The connect() method (lines 71-87) establishes MateRelation records by normalizing targets and creating native build123d joints. It accepts MateTarget objects or tuples specifying the part and datum frame, recording the relationship for downstream export pipelines.
asm.connect(
fixed=(base_plate, "mount:center"),
moving=link_tip,
relation="rigid",
label="base_to_link"
)
Working with MateTarget and MateRelation
MateTarget is a lightweight wrapper exposing part and frame attributes that reference specific datums within the assembly hierarchy. MateRelation stores the complete connection metadata—including label, relation type, fixed and moving targets, and kinematic parameters—for consumption by STEP/URDF exporters.
During export, the helper aggregates all relations via assembly_mate_payload() (lines 60-89) into a JSON-compatible structure. This payload is attached to the final STEP scene through _attach_assembly_mates in packages/cadpy/src/cadpy/step_export.py (line 48), ensuring mating data persists in the exported CAD file.
Offsetting Frames for Precise Positioning
Use offset_target() (lines 92-108) to create displaced reference frames relative to existing datums. This method accepts an existing part and datum label along with an offset vector, returning a new MateTarget without modifying the base geometry—essential for defining tool clearances, standoffs, or accommodation features.
# Create frame 5mm above the center datum
offset_mount = asm.offset_target(
base_plate,
"mount:center",
offset=(0, 0, 5)
)
Complete Assembly Implementation
The following implementation demonstrates the full pipeline from datum creation to mate relation export:
from cadpy.assembly import AssemblyHelper
import build123d as bd
# Initialize assembly helper
asm = AssemblyHelper("robot_arm")
# Define base with named datum
base = bd.Box(100, 100, 10)
asm.add(base, "base_plate")
asm.datum(base, "mount", "center")
# Define link with rigid frame
link = bd.Cylinder(5, 50)
asm.add(link, "link_body")
link_frame = asm.rigid_frame(link, "link_tip", bd.Location((0, 0, 0)))
# Create rigid connection
asm.connect(
fixed=(base, "mount:center"),
moving=link_frame,
relation="rigid",
label="base_to_link"
)
# Build final assembly (includes MateRelation payload)
assembly = asm.build()
The resulting assembly compound contains embedded mate metadata. When exported through the STEP pipeline, the payload includes structured entries like:
{
"id": "m1",
"label": "m1",
"sourceLabel": "base_to_link",
"type": "rigid",
"relation": "rigid",
"fixed": "mount:center",
"moving": "link_tip",
"parameters": {}
}
Summary
- Named datums are created via
AssemblyHelper.datum()inpackages/cadpy/src/cadpy/assembly.py(lines 32-39), utilizinglabel_shapeandlabel_text()to generate STEP-compatible identifiers for part reference frames. - Joint frames support multiple kinematic types—rigid, revolute, linear, cylindrical, and ball—through factory methods delegating to
add_rigid_frame,add_axis_frame, andadd_joint_frame(lines 61-78). - Frame connections are recorded as
MateRelationobjects viaconnect()(lines 71-87), storing fixed/movingMateTargetreferences, relationship types, and parameters. - Export pipeline aggregates mates through
assembly_mate_payload()(lines 60-89) and attaches them to STEP scenes via_attach_assembly_matesinpackages/cadpy/src/cadpy/step_export.py(line 48). - Position offsets are achieved using
offset_target()(lines 92-108) to create derived reference frames for clearance and tooling requirements.
Frequently Asked Questions
How does Text-to-CAD generate STEP-compatible labels for assembly datums?
Text-to-CAD generates labels through the label_text() utility, which creates compact, STEP-safe identifiers like part_name:datum_name. These are assigned to shapes via label_shape within the datum() method (lines 32-39 of packages/cadpy/src/cadpy/assembly.py), ensuring reference frames remain unique and readable in exported STEP files.
What types of joint frames does AssemblyHelper support?
AssemblyHelper supports five kinematic frame types: rigid, revolute, linear, cylindrical, and ball. Each type has a corresponding factory method that constructs the appropriate build123d joint geometry and delegates to internal methods like add_rigid_frame or add_axis_frame (lines 61-78).
How are assembly connections stored before export?
Connections are stored as MateRelation objects containing the relationship label, kinematic type, fixed and moving MateTarget references, and optional parameters. These records are collected by assembly_mate_payload() (lines 60-89) and attached to the export artifact via _attach_assembly_mates in packages/cadpy/src/cadpy/step_export.py (line 48).
Can I create offset datum frames for clearance requirements?
Yes. Use offset_target() (lines 92-108 in packages/cadpy/src/cadpy/assembly.py) to generate new reference frames displaced from existing datums. This method accepts an offset vector and creates a derived MateTarget without modifying the original part geometry, enabling precise positioning for clearance zones or tooling attachments.
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 →