Machines - sliptonic/FreeCAD GitHub Wiki
Starting with the version 1.2 development cycle, the machine data class and editor were added.
FreeCAD CAM Machine Data Model
Overview
The FreeCAD Machine Data Model (src/Mod/CAM/Machine/models/machine.py) provides a unified configuration system that combines physical machine definitions with post-processor settings. This model serves as the single source of truth for all machine-related configuration, including physical capabilities (axes, spindles) and G-code generation preferences.
Relationship to Postprocessors
Historically, the postprocessors contained a large amount of information which was configuration-oriented. This resulted in extensive code duplication between postprocessors and all the problems that implies.
With the introduction of the machine concept, configuration is moving out of the postprocessor. The post processor scripts should become simpler and highly aligned with various machine controllers available in the market. (.e.g. LinuxCNC, Grbl, Mach3/4, Centroid, Masso, etc). The posts will expose the unique functionality of the machine controllers without the configuration and preference information previously seen.
In short, it should be a rare occurrence to write a new postprocessor. A new postprocessor will likely require more cooperation with the development team.
Conversely, it should become easier to create a new machine and configure the individual preferences necessary to achieve user goals and generate useful gcode.
Architecture
Core Design Principles
- Unified Configuration: Physical machine definition and post-processor settings in one model
- Type Safety: Uses Python dataclasses with type hints for robust configuration
- Serialization: Full JSON persistence for configuration sharing and backup
- Extensibility: Modular design supports adding new machine types and capabilities
Dataclass Hierarchy
Machine
├── LinearAxis[] (dict)
├── RotaryAxis[] (dict)
├── Spindle[] (list)
├── OutputOptions
│ ├── HeaderOptions
│ ├── CommentOptions
│ ├── FormattingOptions
│ ├── PrecisionOptions
│ └── DuplicateOptions
└── ProcessingOptions
Core Components
Machine Class
The main container class that represents a complete CNC machine configuration.
@dataclass
class Machine:
# Physical Machine Definition
name: str = "Default Machine"
manufacturer: str = ""
description: str = ""
linear_axes: Dict[str, LinearAxis] = field(default_factory=dict)
rotary_axes: Dict[str, RotaryAxis] = field(default_factory=dict)
spindles: List[Spindle] = field(default_factory=list)
# Rotary Axis Configuration
primary_rotary_axis: Optional[str] = None
secondary_rotary_axis: Optional[str] = None
compound_moves: bool = True
prefer_positive_rotation: bool = True
# Post-Processor Configuration
output: OutputOptions = field(default_factory=OutputOptions)
processing: ProcessingOptions = field(default_factory=ProcessingOptions)
postprocessor_file_name: str = ""
postprocessor_properties: Dict[str, Any] = field(default_factory=dict)
Physical Machine Components
LinearAxis
Represents a linear axis (X, Y, Z) with physical limits and capabilities:
@dataclass
class LinearAxis:
name: str
direction_vector: FreeCAD.Vector
min_limit: float = 0
max_limit: float = 1000
max_velocity: float = 10000
sequence: int = 0
Key Features:
- Automatic direction vector normalization
- Limit validation with warnings
- Velocity validation
- Sequence ordering for multi-axis synchronization
RotaryAxis
Represents a rotary axis (A, B, C) for 4/5-axis machines:
@dataclass
class RotaryAxis:
name: str
rotation_vector: FreeCAD.Vector
min_limit: float = -360
max_limit: float = 360
max_velocity: float = 36000
sequence: int = 0
prefer_positive: bool = True
Key Features:
- Rotation vector normalization with Z-axis fallback
- Angle limit validation
- RPM velocity validation
- Positive rotation preference for optimal toolpaths
Spindle
Represents a spindle/tool with type-specific capabilities:
@dataclass
class Spindle:
name: str
spindle_type: SpindleType = SpindleType.ROTARY
id: Optional[str] = None
# Power and Performance
max_power_kw: float = 0
max_rpm: float = 0
min_rpm: float = 0
# Tool Change and Coolant
tool_change: str = "manual"
coolant_flood: bool = False
coolant_mist: bool = False
coolant_delay: float = 0.0
# Timing Control
spindle_wait: float = 0.0 # Delay after spindle start
# Type-Specific Parameters
laser_wavelength: Optional[float] = None # nm
waterjet_pressure: Optional[float] = None # bar
plasma_amperage: Optional[float] = None # amps
Spindle Types:
ROTARY: Traditional router/drill spindlesLASER: Laser cutting/engraving systemsWATERJET: Waterjet cutting systemsPLASMA: Plasma cutting systems
Capabilities System: Each spindle type has auto-generated capabilities:
- Motion capabilities (rotate, move Z/XY)
- Power control features
- Coolant/assist gas requirements
- Special features (auto-focus, probing)
Post-Processor Configuration
OutputOptions
Controls G-code output formatting and content:
@dataclass
class OutputOptions:
# Main Options
units: OutputUnits = OutputUnits.METRIC
output_tool_length_offset: bool = True
remote_post: bool = False
output_header: bool = True
# Nested Configuration
header: HeaderOptions = field(default_factory=HeaderOptions)
comments: CommentOptions = field(default_factory=CommentOptions)
formatting: FormattingOptions = field(default_factory=FormattingOptions)
precision: PrecisionOptions = field(default_factory=PrecisionOptions)
duplicates: DuplicateOptions = field(default_factory=DuplicateOptions)
Header Options: Controls G-code header content (date, description, tool list, etc.)
Comment Options: Comment formatting and inclusion policies
Formatting Options: Line numbering, spacing, and output formatting
Precision Options: Numeric precision for axes, feed rates, and spindle speeds
Duplicate Options: Modal output suppression for G/M codes and parameters
ProcessingOptions
Controls path processing and transformation:
@dataclass
class ProcessingOptions:
early_tool_prep: bool = False
filter_inefficient_moves: bool = False
split_arcs: bool = False
tool_change: bool = True
translate_rapid_moves: bool = False
xy_before_z_after_tool_change: bool = False
return_to: Optional[Tuple[float, float, float]] = None
Processing Features:
- Tool preparation timing
- Rapid move optimization
- Arc splitting for compatibility
- Tool change control
- Rapid-to-feed translation
- Safety move decomposition
Usage Patterns
Creating Machine Configurations
Standard 3-Axis Machine
machine = Machine.create_3axis_config()
machine.name = "My CNC Router"
machine.manufacturer = "Shapeoko"
4-Axis Machine
machine = Machine.create_4axis_A_config(a_limits=(-180, 180))
machine.name = "4-Axis Mill"
5-Axis Machine
machine = Machine.create_AC_table_config()
machine.name = "5-Axis Machining Center"
Custom Machine
machine = Machine("Custom Machine")
machine.add_linear_axis("X", FreeCAD.Vector(1, 0, 0), 0, 1000)
machine.add_linear_axis("Y", FreeCAD.Vector(0, 1, 0), 0, 800)
machine.add_linear_axis("Z", FreeCAD.Vector(0, 0, 1), -100, 100)
machine.add_spindle("Main Spindle", max_rpm=24000, max_power_kw=3.5)
Configuration Persistence
# Save configuration
machine.save("/path/to/machine.fcm")
# Load configuration
machine = Machine.from_file("/path/to/machine.fcm")
Post-Processor Integration
# Create post processor with machine config
processor = PostProcessor(machine)
results = processor.export2(job)
# Access machine properties in post processor
if machine.processing.split_arcs:
# Process arc splitting
pass
if machine.spindles[0].spindle_wait > 0:
# Insert spindle wait delay
pass
Advanced Features
Machine Type Detection
The model automatically detects machine type based on available axes:
@property
def machine_type(self) -> str:
"""Returns: 'xyz', 'xyza', 'xyzb', 'xyzac', 'xyzbc', or 'custom'"""
Unit Conversion
Built-in unit conversion between metric and imperial:
@property
def unit_format(self) -> str:
return "mm" if self.configuration_units == "metric" else "in"
@property
def output_unit_format(self) -> str:
return "mm" if self.output.units == OutputUnits.METRIC else "in"
Validation
Automatic validation during initialization:
- Axis limit consistency checks
- Velocity validation
- Unit format validation
- Spindle type-specific defaults
Migration from Legacy Systems
Legacy Post Processor Properties
Command Line Arguments
Legacy command-line arguments are deprecated in favor of machine configuration:
Deprecated:
freecad --postprocessor=grbl --preamble="G18 G55" --modal
New Way:
machine.postprocessor_file_name = "grbl"
machine.postprocessor_properties["preamble"] = "G18 G55"
machine.output.duplicates.commands = False
machine.output.duplicates.parameters = False
Extension Points
Custom Spindle Types
Add new spindle types by extending the SpindleType enum:
class SpindleType(Enum):
ROTARY = "rotary"
LASER = "laser"
WATERJET = "waterjet"
PLASMA = "plasma"
ULTRASONIC = "ultrasonic" # New type
Custom Processing Options
Extend ProcessingOptions for new features:
@dataclass
class ProcessingOptions:
# ... existing fields ...
custom_feature: bool = False # New processing option
Post-Processor Properties
Use postprocessor_properties for machine-specific G-code blocks:
machine.postprocessor_properties = {
"preamble": "G18 G55",
"postamble": "M2",
"pre_tool_change": "G53 Z0",
"post_operation": "M5",
}
Best Practices
Configuration Organization
- Use Descriptive Names: Clear machine names and descriptions
- Set Proper Limits: Accurate axis limits prevent crashes
- Configure Spindles: Complete spindle specifications enable better G-code
- Validate Units: Ensure consistent units throughout configuration
Performance Considerations
- Lazy Loading: Machine configurations are loaded on-demand
- Caching: Serialized configurations are cached for performance
- Validation: Minimal validation overhead during normal operation
Error Handling
- Graceful Degradation: Missing fields use sensible defaults
- Validation Warnings: Invalid configurations log warnings but continue
- Migration Support: Automatic migration from older configuration formats
Integration Points
FreeCAD Integration
- Job Property: Jobs reference machine configurations by name
- UI Integration: Machine editor provides full configuration interface
- Post Processing: Export2 uses machine configuration for G-code generation
Post-Processor System
- Dynamic Loading: Post processors load machine-specific configurations
- Property Injection: Machine properties injected into post processor scope
- Validation: Post processors validate required machine capabilities
File System
- Configuration Files:
.fcmfiles store machine configurations - Search Paths: Multiple configuration directories supported
- Version Control: Configuration files suitable for version control
Troubleshooting
Common Issues
- Missing Spindle: Ensure at least one spindle is configured
- Invalid Limits: Check axis limit consistency (min < max)
- Unit Mismatch: Verify configuration vs output units
Debug Information
Enable debug logging for troubleshooting:
import Path
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
Validation Errors
Configuration validation provides detailed error messages:
LinearAxis X: min_limit (100) >= max_limit (50)
Spindle Main: max_rpm (24000) must be >= min_rpm (25000)
Future Development
Planned Enhancements
- Multi-Axis Support: Support for 4th, 5th axis machines
API Stability
The machine data model API is considered unstable for:
- Core dataclass structures
- Serialization format
- Basic machine operations
Experimental features include:
- Advanced processing options
- Custom spindle types
- Network configuration features