Skip to main content

openscad-integration

Create OpenSCAD files for complex 3D geometry in URDF, leveraging available libraries and automatic STL conversion

Jump to install

Source facts

Repository
Ranch-Hand-Robotics/rde-urdf
Last source activity
February 6, 2026 at 06:57
Detected SKILL.md language
English
Stars
15
Forks
7

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
openscad-integration
description
Create OpenSCAD files for complex 3D geometry in URDF, leveraging available libraries and automatic STL conversion
# OpenSCAD Integration for URDF Skill This skill guides the creation and use of OpenSCAD files for custom 3D geometry in URDF robot descriptions. ## When to Use This Skill Use OpenSCAD when: - Basic URDF geometry (box, cylinder, sphere) is insufficient - You need parametric, programmable 3D shapes - You want to leverage existing OpenSCAD libraries - You need maintainable, version-control-friendly geometry (vs binary STL) ## ⚠️ Important: Always Verify with Screenshots **CRITICAL: Always take a screenshot after creating or modifying OpenSCAD files** to verify the generated geometry renders correctly. OpenSCAD syntax errors or invalid geometry will cause rendering failures. Use the MCP `take_screenshot` tool after save to confirm: - The .scad file compiles without errors - The geometry matches expectations - The STL conversion succeeded If the screenshot times out or shows errors, check the OpenSCAD code for syntax issues. ## ⚠️ Important: Always Ask Permission Before creating OpenSCAD files, ask the user: - Creating .scad files adds complexity - User may prefer different CAD workflow - May require understanding OpenSCAD syntax **Always ask**: "I can create an OpenSCAD file to generate this geometry. It will be automatically converted to STL. Would you like me to do that?" ## OpenSCAD Basics ### What is OpenSCAD? OpenSCAD is a script-based 3D CAD modeler: - Write code to describe geometry - Parametric (easy to modify dimensions) - Text-based (works great with version control) - Rich ecosystem of libraries ### How the Extension Handles OpenSCAD 1. You create a `.scad` file in your project 2. Extension automatically converts it to `.stl` when saved 3. Reference the `.stl` file in your URDF 4. Preview updates automatically when `.scad` changes **File watching**: The extension monitors `.scad` files and regenerates STL on save. ## Basic OpenSCAD Syntax ### Primitive Shapes ```scad // Cube cube([width, depth, height]); cube([10, 20, 30]); // 10mm × 20mm × 30mm box // Sphere sphere(radius); sphere(r=15); // 15mm radius sphere // Cylinder cylinder(h=height, r=radius); cylinder(h=50, r=10); // 50mm tall, 10mm radius // Cylinder with different top/bottom radii (cone) cylinder(h=30, r1=15, r2=5); ``` ### Transformations ```scad // Translate (move) translate([x, y, z]) cube([10, 10, 10]); // Rotate (in degrees) rotate([rx, ry, rz]) cylinder(h=20, r=5); // Scale scale([sx, sy, sz]) sphere(r=10); // Combine transformations translate([0, 0, 10]) rotate([0, 90, 0]) cylinder(h=30, r=5); ``` ### Boolean Operations ```scad // Union (combine shapes) - default behavior union() { cube([20, 20, 20]); translate([10, 10, 10]) sphere(r=12); } // Difference (subtract) difference() { cube([30, 30, 30]); // Main shape translate([15, 15, 0]) // Subtract this cylinder(h=30, r=8); } // Intersection (only overlapping parts) intersection() { cube([20, 20, 20]); sphere(r=15); } ``` ### Modules (Functions) ```scad // Define a reusable module module bracket(width, height, thickness) { difference() { cube([width, height, thickness]); // Mounting holes translate([5, height/2, 0]) cylinder(h=thickness, r=2); translate([width-5, height/2, 0]) cylinder(h=thickness, r=2); } } // Use the module bracket(50, 30, 5); bracket(width=60, height=40, thickness=8); ``` ## Common Patterns for Robotics ### Pattern 1: Wheel with Tread ```scad // wheel_tread.scad module wheel_with_tread(radius=50, width=30, tread_depth=3, tread_count=12) { difference() { // Main wheel body cylinder(h=width, r=radius, center=true); // Tread grooves for (i = [0:tread_count-1]) { rotate([0, 0, i * 360/tread_count]) translate([radius - tread_depth/2, 0, 0]) cube([tread_depth, 3, width+1], center=true); } } } // Generate wheel wheel_with_tread(radius=100, width=40, tread_depth=5, tread_count=16); ``` **URDF reference:** ```xml <link name="wheel"> <visual> <geometry> <!-- Extension auto-converts wheel_tread.scad to wheel_tread.stl --> <mesh filename="package://my_robot/meshes/wheel_tread.stl" scale="0.001 0.001 0.001"/> </geometry> </visual> </link> ``` ### Pattern 2: Gripper Finger ```scad // gripper_finger.scad module gripper_finger(length=60, width=15, thickness=8) { difference() { // Main finger body hull() { cube([thickness, width, thickness]); translate([length-10, 0, 0]) cube([10, width, thickness]); } // Grip texture (small bumps) for (i = [10:10:length-15]) { translate([i, width/2, thickness]) sphere(r=2); } } } gripper_finger(length=70, width=18, thickness=10); ``` ### Pattern 3: Sensor Housing ```scad // sensor_housing.scad module sensor_housing(sensor_diameter=20, wall_thickness=3) { difference() { // Outer shell cylinder(h=30, r=sensor_diameter/2 + wall_thickness); // Inner cavity for sensor translate([0, 0, wall_thickness]) cylinder(h=25, r=sensor_diameter/2); // Mounting holes for (angle = [0:90:270]) { rotate([0, 0, angle]) translate([sensor_diameter/2 + wall_thickness/2, 0, 15]) rotate([90, 0, 0]) cylinder(h=wall_thickness+2, r=2); } } } sensor_housing(sensor_diameter=25, wall_thickness=4); ``` ### Pattern 4: Custom Bracket ```scad // mounting_bracket.scad module l_bracket(width=50, height=40, depth=30, thickness=5) { union() { // Vertical plate cube([thickness, depth, height]); // Horizontal plate cube([width, depth, thickness]); // Reinforcement gusset hull() { translate([0, depth/2, 0]) cube([thickness, 1, thickness]); translate([0, depth/2, height-thickness]) cube([thickness, 1, 1]); } } } l_bracket(width=60, height=50, depth=35, thickness=6); ``` ## Using OpenSCAD Libraries ### Checking Available Libraries Before writing custom code, check what's available: 1. **Run**: Command Palette → "URDF: Generate OpenSCAD Libraries Documentation" 2. **Review**: Generated markdown shows all available modules/functions 3. **Use**: Include or use the library in your .scad file ### Library Locations The extension automatically loads libraries from: - **Workspace root**: Any .scad files in your project - **SCAD file directory**: Same directory as your .scad file (highest priority) - **OS-specific defaults**: - Linux: `~/.local/share/OpenSCAD/libraries` - macOS: `~/Documents/OpenSCAD/libraries` - Windows: `%USERPROFILE%\Documents\OpenSCAD\libraries` - **Custom paths**: Configured in `urdf-editor.OpenSCADLibraryPaths` setting ### Common Libraries #### MCAD (Mechanical CAD) ```scad include <MCAD/motors.scad> use <MCAD/gears.scad> use <MCAD/bearing.scad> // Standard stepper motor stepper_motor_mount(28); // Spur gear gear(number_of_teeth=20, circular_pitch=5, gear_thickness=5, rim_thickness=5); ``` #### BOSL2 (Belfry OpenSCAD Library 2) ```scad include <BOSL2/std.scad> // Rounded box cuboid([50, 30, 20], rounding=5); // Threaded rod threaded_rod(d=10, l=50, pitch=2); // Grid of holes grid_copies(spacing=20, n=3) cylinder(h=10, r=3); ``` ### Include vs Use ```scad // include: Makes everything available (variables, modules) include <MCAD/motors.scad> // use: Only makes modules available (not variables) use <MCAD/gears.scad> ``` **Best practice**: Use `use` unless you need the library's variables. ## Integration with URDF ### File Organization Recommended structure: ``` my_robot/ ├── urdf/ │ └── robot.urdf.xacro ├── meshes/ │ ├── wheel.scad ← OpenSCAD source │ ├── wheel.stl ← Auto-generated │ ├── gripper.scad │ └── gripper.stl └── scad/ ← Optional: keep .scad separate └── library.scad ``` ### Workflow 1. **Create .scad file** in `meshes/` directory 2. **Save file** → Extension auto-generates `.stl` 3. **IMMEDIATELY take screenshot** to verify geometry renders correctly 4. **Reference .stl in URDF**: ```xml <link name="custom_part"> <visual> <geometry> <mesh filename="package://my_robot/meshes/wheel.stl"/> </geometry> </visual> </link> ``` 5. **Preview URDF** → See the generated geometry 6. **Modify .scad** → Auto-regenerates STL on save, take another screenshot to verify ### Units and Scaling **Important**: OpenSCAD typically uses millimeters, URDF uses meters. ```xml <!-- Scale from mm to m (divide by 1000) --> <mesh filename="package://my_robot/meshes/part.stl" scale="0.001 0.001 0.001"/> ``` **Tip**: Document units in your .scad file: ```scad // Units: millimeters // This will be scaled to meters in URDF (scale="0.001 0.001 0.001") module wheel(diameter=100) { // 100mm = 0.1m cylinder(h=40, r=diameter/2); } ``` ## Advanced Techniques ### Parametric Design Create families of related parts: ```scad // parametric_wheel.scad // Parameters can be overridden when including this file wheel_diameter = 100; // mm wheel_width = 40; // mm hub_diameter = 20; // mm spoke_count = 5; module parametric_wheel() { difference() { // Rim cylinder(h=wheel_width, r=wheel_diameter/2, center=true); // Hub cavity cylinder(h=wheel_width+2, r=hub_diameter/2, center=true); // Spokes (material removal between spokes) for (i = [0:spoke_count-1]) { rotate([0, 0, i * 360/spoke_count + 360/(2*spoke_count)]) translate([hub_diameter/2 + (wheel_diameter-hub_diameter)/4, 0, 0]) cube([wheel_diameter/2, 5, wheel_width+2], center=true); } } } parametric_wheel(); ``` ### Animation and Testing Use animation to verify moving parts: ```scad // Animate to test range of motion $fn = 50; // Resolution module articulated_part(angle=0) { // Base cube([50, 30, 10]); // Moving part translate([25, 15, 10]) rotate([angle, 0, 0]) translate([0, 0, 20]) cube([20, 10, 40], center=true); } // Use $t for animation (0 to 1) articulated_part(angle=$t * 180 - 90); ``` ### Resolution Control ```scad // $fn controls circle resolution $fn = 100; // High quality (slower) // $fn = 30; // Medium (default-ish) // $fn = 12; // Low quality (faster) cylinder(h=10, r=5); // Uses $fn setting // Override for specific shapes cylinder(h=10, r=5, $fn=6); // Hexagon ```
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub