📘 Overview
PEPS (Production Engineering Productivity System) is a macro programming language used in CAD/CAM applications for automating manufacturing processes. This guide covers the essential syntax, commands, and best practices learned through extensive development work.
Automate complex CAD geometry creation and manipulation tasks
Create and manipulate 2D kurves and 3D solid bodies
Persist data using the VDM (Virtual Data Manager) system
Interface with the Parasolid geometry kernel
📁 File Structure
PEPS macro files use the .ovm extension. These are plain text files containing macro definitions and executable code.
Basic File Structure
; File: myMacro.ovm
; Description: Example macro file
mac myMacroName
; Local variable declarations (MUST be at top)
local w_myReal
local i_myInt
local $_myString
; Executable code follows
w_myReal = 10.5
i_myInt = 42
endmac
⚠ Line Endings
The PEPS macro editor expects Windows-style CRLF (\r\n) line endings. Modern editors like Notepad++ handle this automatically, but if you encounter parsing issues, check your line ending settings.
When creating or editing .ovm files programmatically, you may need to ensure CRLF line endings for compatibility with the macro editor:
// In most editors, configure to use CRLF
// In code, explicitly use \r\n for newlines
📊 Variables
PEPS uses Hungarian notation prefixes to denote variable types:
| Prefix | Type | Example | Description |
|---|---|---|---|
w_ |
Real | w_angle, w_distance |
Floating-point numbers |
i_ |
Integer | i_count, i_bodyId |
Whole numbers |
$_ |
String | $_name, $_path |
Text strings |
p |
Point | p1, p99 |
Point geometry |
c |
Circle | c1, c5 |
Circle geometry |
s |
Span | s1, s100 |
Kurve spans (lines/arcs) |
📋 Variable Declaration Rules
NEVER declare local variables inside loops or conditionals. ALL local variable declarations must appear at the top of the macro, before any executable code.
✔ Correct
mac correctExample
; ALL locals declared at top
local w_x
local w_y
local i_count
; Now executable code
for i_count = 1 to 10
w_x = i_count * 2
next
endmac
✘ Wrong
mac wrongExample
for i_count = 1 to 10
local w_x ; WRONG! Cannot declare inside loop
w_x = i_count * 2
next
endmac
PEPS macros cannot contain extended ASCII characters (character codes > 127). Stick to standard ASCII only.
🔄 System Scratch Variables
PEPS provides pre-declared system scratch variables for temporary data storage. Use these instead of declaring new globals:
| Type | Variables | Count |
|---|---|---|
| Real | w_TMP_DATA(1) through w_TMP_DATA(10) |
10 |
| Integer | i_TMP_DATA(1) through i_TMP_DATA(10) |
10 |
| String | $_TMP_DATA(1) through $_TMP_DATA(10) |
10 |
➕ Math Operators
PEPS uses some non-standard operators:
| Operation | PEPS Syntax | Standard Syntax | Example |
|---|---|---|---|
| Power / Exponent | @ |
^ or ** |
w_result = w_base @ 2 |
| Square Root | (x) @ 0.5 |
sqrt(x) |
w_root = (w_val) @ 0.5 |
| Addition | + |
+ |
w_sum = w_a + w_b |
| Subtraction | - |
- |
w_diff = w_a - w_b |
| Multiplication | * |
* |
w_prod = w_a * w_b |
| Division | / |
/ |
w_quot = w_a / w_b |
PEPS does not have a sqrt() function. Always use (x) @ 0.5 for square roots.
📐 Math Functions
Trigonometric Functions
| Function | Syntax | Returns | Notes |
|---|---|---|---|
| Arctangent 2 | atn2 y x |
Degrees | No commas! Arguments are y x (not x, y) |
| Sine | sin(angle) |
Value | Angle in degrees |
| Cosine | cos(angle) |
Value | Angle in degrees |
| Tangent | tan(angle) |
Value | Angle in degrees |
Unlike most programming languages, atn2 returns degrees, not radians. Also note the argument order is y x with NO comma separator.
; Calculate angle from deltas
w_angle = atn2 w_dy w_dx ; Note: y first, then x, NO comma
🪤 Parser Traps
The PEPS parser has some quirks that can cause unexpected errors:
Division in Complex Expressions
Remove spaces around / in complex bracketed expressions:
✔ Correct
w_result = (-w_b-w_disc)/(2*w_a)
✘ Wrong (can confuse parser)
w_result = (-w_b - w_disc) / (2 * w_a) ; Spaces around / can cause issues
When in doubt, remove spaces around the division operator / especially when brackets are involved.
🔍 Value Extraction
Extracting values from geometry uses special syntax. There is no get p1 or get c1 command.
Point Coordinates
; Extract X and Y from point p1
w_x = xp1
w_y = yp1
; For other points
w_x = xp5 ; X coordinate of p5
w_y = yp99 ; Y coordinate of p99
Circle Properties
; Get circle center (assign to a point)
p99 = c1 ; p99 now holds the center of c1
; Get circle radius (assign to a real)
w_radius = c1 ; w_radius now holds the radius of c1
Point at Angle from Circle
; Get point on circle c1 at 45 degrees
p1 = b45 c1 ; b = bearing/angle
Distance Between Points
; Calculate distance from p1 to p2
w_dist = p1 p2
Do NOT use get p1 or get c1. These commands do not exist. Use the direct assignment syntax shown above.
〰 Kurve Syntax
Kurves (curves) are sequences of connected spans (lines and arcs). Each span must be on its own line.
Basic Kurve Structure
kurve
w_startX w_startY ; Starting point
w_endX1 w_endY1 ; Line to this point
tw_endX2 w_endY2 w_ctrX w_ctrY ; CW arc
aw_endX3 w_endY3 w_ctrX w_ctrY ; CCW arc
endkurve
Arc Modifiers
| Modifier | Direction | Syntax |
|---|---|---|
t |
Clockwise (CW) | txEnd yEnd xCenter yCenter |
a |
Counter-Clockwise (CCW) | axEnd yEnd xCenter yCenter |
The arc modifier concatenates directly to the X coordinate with NO space.
✔ Correct
tw_endX w_endY w_ctrX w_ctrY ; t directly attached to w_endX
t-w_rad 0 0 0 ; t attached to negative value
✘ Wrong
t w_endX w_endY w_ctrX w_ctrY ; WRONG! Space after t
t -w_rad 0 0 0 ; WRONG! Space after t
Complete Example
; Draw a rounded rectangle
kurve
0 w_rad ; Start point
0 (w_height-w_rad) ; Line up left side
aw_rad w_height 0 (w_height-w_rad) ; CCW arc top-left
(w_width-w_rad) w_height ; Line across top
aw_width (w_height-w_rad) (w_width-w_rad) (w_height-w_rad) ; CCW arc top-right
w_width w_rad ; Line down right side
a(w_width-w_rad) 0 (w_width-w_rad) w_rad ; CCW arc bottom-right
w_rad 0 ; Line across bottom
a0 w_rad w_rad w_rad ; CCW arc bottom-left (closes)
endkurve
🎯 Geometry Modifiers
When creating geometry that intersects other elements, modifiers specify which solution to use:
| Modifier | Meaning | Use Case |
|---|---|---|
N |
Near | Line-circle intersection: use point nearest to reference |
F |
Far | Line-circle intersection: use point farthest from reference |
L |
Left | Circle-circle, parallel lines, concentric circles |
R |
Right | Circle-circle, parallel lines, concentric circles |
T |
Tangent | Tangent approach |
A |
Anti-tangent | Opposite tangent direction |
Circles are always defined as clockwise (CW). Therefore: L = outside the circle, R = inside the circle.
🗑 Deleting Geometry
Delete ranges of geometry elements with this syntax:
; Delete spans s1 through s500
delete s1>500
; Delete circles c1 through c500
delete c1>500
; Delete points p1 through p500
delete p1>500
No spaces around the > operator. Do NOT use delete s -1 or similar negative indexing.
🔷 SLD Commands Overview
SLD (SoLiD) commands interface with the Parasolid geometry kernel for 3D solid modeling operations.
BLO (block), CYL (cylinder), SPH (sphere)
UNI (union), INT (intersect), SUB (subtract)
ASK, EXA (examine), EXTENT
SEC (section), TAP (taper), THK (thicken)
📦 SLD Primitives
SLD BLO (Block)
Creates a rectangular block (box) primitive.
sld blo w_xSize w_ySize w_zSize w_xPos w_yPos w_zPos i_ret
X, Y = center-referenced (position is at center of X and Y dimensions)
Z = base-referenced (position is at the bottom of the block, not center)
SLD CYL (Cylinder)
sld cyl w_radius w_height w_xPos w_yPos w_zPos i_ret
🔄 SLD CNV ENT (Convert Entity)
Converts between different geometry types.
sld cnv ent i_inputType i_outputType i_pickMode i_inputID i_outputID
Entity Type Codes
| Code | Type | Description |
|---|---|---|
1 |
Kurve | 2D curve geometry |
6 |
Face | Solid face |
7 |
Wire | 3D wire body |
8 |
Sheet | Sheet (surface) body |
Pick Mode
Use i_pickMode = 1 for programmatic selection (no user interaction).
; Convert kurve k1 to sheet body
sld cnv ent 1 8 1 i_kurveId i_sheetId
⊕ SLD Boolean Operations
Single Body Operations
; Union
sld uni i_targetBody i_toolBody i_ret
; Intersection
sld int i_targetBody i_toolBody i_ret
; Subtraction
sld sub i_targetBody i_toolBody i_ret
Batch Boolean Operations
For better performance with multiple bodies, use VDM mode:
; Switch to VDM mode for batch operations
sld mode vdm
; Build tool set
sld pic lis clr ; Clear pick list
sld put bod i_body1 ; Add bodies to set
sld put bod i_body2
sld put bod i_body3
; Perform batch union
sld uni i_targetBody i_toolSet i_resultSet
; Return to list mode
sld mode list
🔎 SLD Body Queries
Body Extent (Bounding Box)
sld body extent i_body w_xMin w_yMin w_zMin w_xMax w_yMax w_zMax
Get Last Created Body
sld ask bod las i_bodyId
Copy Body
sld copy body i_sourceBody i_destBody i_ret
Multi-Part Body Query
sld ask bod part i_body i_partNumber i_ret
◻ SLD Face Operations
Examine Face (SLD EXA FAC)
Query face properties and type.
sld exa fac i_faceId i_class ...
Face Class Codes
| Code | Face Type |
|---|---|
4001 | Plane |
4002 | Cylinder |
4003 | Cone |
4004 | Sphere |
4005 | Torus |
Face Removal / Hole Closing (SLD FAC REM)
Close holes in solid bodies by removing faces:
sld fac rem none i_faceSet 0 0 0 1 0 0 i_ret
Operation mode 1 makes solids with holes capped. You must process one face at a time - batch processing groups connected faces incorrectly. Avoid using face set 611.
✂ SLD SEC (Section)
Slice a solid body with a sheet surface.
sld sec i_body i_sheet i_ret
The sectioning operation consumes (destroys) the sheet. If you need the sheet again, copy the solid first, not the sheet.
; Proper sectioning workflow
sld copy body i_original i_copy i_ret ; Copy solid first
sld sec i_copy i_sheet i_ret ; Section the copy
sld ask bod las i_newPiece ; Get the new piece
📑 SLD Body Thicken
Thicken a sheet body into a solid.
sld body thicken i_count i_body w_startDist w_endDist i_ret
| Parameter | Description |
|---|---|
i_count |
Number of bodies (usually 1) |
i_body |
Sheet body to thicken |
w_startDist |
Thickness in start direction from sheet |
w_endDist |
Thickness in end direction from sheet |
📐 SLD TAP (Taper)
Apply a taper (draft angle) to faces.
sld tap i_ws_body_set i_refFace x1 y1 z1 x2 y2 z2 w_angle i_ret
You must use the i_ws_body_set global variable. Build the face set using sld put fac.
📍 SLD PMK (Position Marks)
Track body creation for later retrieval of newly created bodies.
; Start tracking
sld pmk on
; Create checkpoint
sld pmk now
; ... create some bodies ...
; Query what was created since checkpoint
sld ask new i_bodSet i_assSet i_bodCnt i_assCnt i_ret
; Stop tracking
sld pmk off
PMK may affect partitions. Investigate sld pma restore if you encounter partition issues.
💾 VDM Storage Overview
VDM (Virtual Data Manager) provides persistent data storage within PEPS. Two access patterns exist:
Direct access using set numbers. Simple read/write operations.
File-like I/O using handles. Requires open/close operations.
➕ VDM ADD / GET
Direct access pattern using set numbers (no handle needed):
; Store a value
vdm add i_setNumber w_value
; Retrieve a value
vdm get i_setNumber w_value
📂 VDM File I/O
File-like access pattern using handles:
; Open for writing
vdm open i_handle "filename" "w"
; Write data
vdm write i_handle w_value
; Seek to position
vdm seek i_handle i_position
; Close handle
vdm close i_handle
; Open for reading
vdm open i_handle "filename" "r"
; Read data
vdm read i_handle w_value
; Check for end of file
vdm eof i_handle i_isEof
📸 VDM Body Snapshots
Track newly created bodies by comparing snapshots:
; Take snapshot before operation
fxBodiesSnapshot i_beforeSet
; ... perform operations that create bodies ...
; Take snapshot after operation
fxBodiesSnapshot i_afterSet
; Get list of newly created bodies
fxBodiesCreated i_beforeSet i_afterSet i_newBodiesSet
; Iterate through new bodies
vdm open i_handle i_newBodiesSet "r"
vdm eof i_handle i_done
while i_done == 0
vdm read i_handle i_bodyId
; Process body...
vdm eof i_handle i_done
wend
vdm close i_handle
📁 Macro Organization
Macros that are called from multiple files must be in their own .ovm file. Macros fall out of scope when defined in a file that calls other files containing macros.
Recommended Structure
project/
+-- main.ovm ; Entry point
+-- utils/
| +-- mathUtils.ovm ; Shared math functions
| +-- geometryUtils.ovm ; Shared geometry helpers
| +-- vdmUtils.ovm ; Shared VDM operations
+-- modules/
| +-- featureA.ovm ; Feature-specific logic
| +-- featureB.ovm
+-- config/
+-- constants.ovm ; Global constants
🔄 Transform Order
When rotating geometry around a point, the correct transform order is:
- Translate to origin (T-1) - move the rotation point to 0,0,0
- Rotate (R) - apply the rotation
- Translate back (T) - move back to original position
Mathematically: Result = T * R * T-1 * Point
; Rotate body around point (cx, cy, cz) by angle
; Step 1: Translate to origin
sld tra i_body -w_cx -w_cy -w_cz
; Step 2: Rotate
sld rot i_body 0 0 1 w_angle ; Rotate around Z axis
; Step 3: Translate back
sld tra i_body w_cx w_cy w_cz
⚠ Common Pitfalls
ALL local variables must be declared at the top of the macro, before any executable code. Never inside loops or conditionals.
Arc modifiers (t, a) must attach directly to the X coordinate with NO space: tw_x not t w_x
atn2 takes arguments as y x (no comma) and returns DEGREES, not radians.
Remove spaces around / in complex bracketed expressions to avoid parser confusion.
The section command destroys the sheet body. Copy the solid first if you need to preserve geometry.
Files must use CRLF (\r\n) line endings. Unix-style LF will cause parsing failures.
Character codes > 127 are not supported. Stick to standard ASCII only.
🚫 Commands to Avoid
SLD BLE (Blend)
The sld ble command is unreliable. Use this alternative workflow instead:
; Instead of sld ble, use this pattern:
; 1. Create kurve geometry
kurve
...
endkurve
; 2. Convert kurve to sheet
sld cnv ent 1 8 1 i_kurveId i_sheetId
; 3. Thicken the sheet
sld body thicken 1 i_sheetId w_thickness 0 i_ret
NucleoAvoido is used as a naming convention for safety/collision checking systems in the codebase.