drlukeparry / libslm Goto Github PK
View Code? Open in Web Editor NEWlibSLM is a c++ library for generating and transfering to SLM Machine Systems
Home Page: http://lukeparry.uk/projects
License: GNU Lesser General Public License v2.1
libSLM is a c++ library for generating and transfering to SLM Machine Systems
Home Page: http://lukeparry.uk/projects
License: GNU Lesser General Public License v2.1
This file format was a consortium agreed standard that provided a efficient format for scan vector information originally designed for SLA systems. This file format is recognised as the precursor to the native proprietary EOS .sli file format.
The specification has been documented on the following page:
https://www.hmilch.net/downloads/cli_format.html
The file format has limited uses now on most machines, but is a useful agnostic and open file format for those wishing to explore and learn about the structure and generation of machine build files typically used in AM process featuring 1D point source sources.
Thanks to Lu for the .cli file format example below:
Following code excerpt reads the .cli
file format
import re
import os
import struct
import numpy as np
import pyslm
import pyslm.geometry
import pyslm.visualise
def read_uint32(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint32)
def read_int32(file, count=1):
return np.fromfile(file, count=count, dtype=np.int32)
def read_int16(file, count=1):
return np.fromfile(file, count=count, dtype=np.int16)
def read_uint16(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint16)
def read_uint8(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint8)
def read_floats(file, count=1):
return np.fromfile(file, count=count, dtype=np.float32)
# Read the layer
LONG_HATCH_SECTION = 132
SHORT_HATCH_SECTION = 131
LONG_POLYLINE_SECTION = 130
SHORT_POLYLINE_SECTION = 129
SHORT_LAYER_SECTION = 128
LONG_LAYER_SECTION = 127
filename ="cube-10mm_000_s1_vs.cli"
file = open(filename, "rb")
"""
Read the .cli header
"""
header = file.readline().decode("ascii").rstrip("\n")
if header != "$$HEADERSTART":
raise ValueError("Not .cls file")
fileType = file.readline().decode("ascii").rstrip("\n")
if fileType != "$$BINARY":
raise ValueError("not binary file")
line = file.read(11)
params = {}
while line != "$$HEADEREND":
file.seek(-11, 1)
# Read the textual line in the header
line = file.readline()
if not line:
break
line = line.decode("latin-1").rstrip("\n")
m = re.search("^\${2}(.*)/(.*)", line)
params[m.group(1)] = m.group(2)
line = file.read(11).decode("ascii")
id = read_uint16(file)
layers = []
params['UNITS'] = float(params['UNITS'])
while id == SHORT_LAYER_SECTION or id == LONG_LAYER_SECTION:
layer = pyslm.geometry.Layer()
layer.z = 0
if id == LONG_LAYER_SECTION:
layer.z = read_floats(file,1)
elif id == SHORT_LAYER_SECTION:
layer.z = read_uint16(file)
id = read_uint16(file)
while id == SHORT_POLYLINE_SECTION or id == LONG_POLYLINE_SECTION or id == SHORT_HATCH_SECTION or id == LONG_HATCH_SECTION:
geom = None
if id == SHORT_POLYLINE_SECTION:
geom = pyslm.geometry.ContourGeometry()
geom.bid = read_uint8(file)
geom.dir = read_uint16(file)
numPoints = read_uint16(file)
geom.coods = read_int16(file, 2*int(numPoints)).astype(np.float32).reshape(-1,2) * params['UNITS']
elif id == LONG_POLYLINE_SECTION:
geom = pyslm.geometry.ContourGeometry()
geom.bid = read_uint32(file)
geom.dir = read_uint32(file)
numPoints = read_uint32(file)
geom.coords = read_floats(file, 2 * int(numPoints)).reshape(-1,2)
elif id == SHORT_HATCH_SECTION:
geom = pyslm.geometry.HatchGeometry()
geom.bid = read_uint16(file)
numPoints = read_uint16(file)
geom.coords = read_int16(file, 4 * int(numPoints)).astype(np.float32).reshape(-1,2) * params['UNITS']
elif id == LONG_HATCH_SECTION:
geom = pyslm.geometry.HatchGeometry()
geom.bid = read_uint32(file)
numPoints = read_uint32(file)
geom.coords = read_floats(file, 4 * int(numPoints)).reshape(-1,2)
layer.geometry.append(geom)
id = read_uint16(file)
print('id', id)
layers.append(layer)
print('Total Path Distance: {:.1f} mm'.format(pyslm.analysis.getLayerPathLength(layers[0])))
pyslm.visualise.plot(layers[1], plot3D=False, plotOrderLine=True, plotArrows=False)
`
SLM Solutions were originally split from the MTT Technologies Group into both Marcam (now Renishaw) and SLM Solutions in Germany.
The original .mtt file can be used as input into the machine system, however, further information is required to diagnose any cross-over compatibility with the original .mtt specification. A more modern machine build file format is .slm, which for example can be used on the SLM Solution SLM280 HL.
A new interpreter will be created to read and write to this new file format, if the format does not use an encrypted sections.
The .sli file format is the 'internal' EOS file format used for defining the scan vectors within the job package archive file (.openjz).
The job manifest file, typically compressed, consists of the following:
These files are collectively can be used and referenced within the supplied EOS preprocessor toolset (RPTools or EOSPrint 1.7-2.8)
Part of the binary .sli file format has been partially documented here. The exact file format specification required by the SLM System is not available.
The .sli file format is based on the former open .cli specification, but has specific extensions adopted for more efficient access to each layers. These include a header offset and a 'layer seek table' used for efficient access to the LayerGeometry
across each Layer
.
An excerpt taken from a job file is displayed below:
A preliminary example script for interpreting the .sli is shared below for reference:
`
import numpy as np
import pyslm
import pyslm.geometry
import pyslm.visualise
def read_uint32(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint32)
def read_int32(file, count=1):
return np.fromfile(file, count=count, dtype=np.int32)
def read_int16(file, count=1):
return np.fromfile(file, count=count, dtype=np.int16)
def read_uint16(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint16)
def read_uint8(file, count=1):
return np.fromfile(file, count=count, dtype=np.uint8)
def read_floats(file, count=1):
return np.fromfile(file, count=count, dtype=np.float32)
"""
Read the .sli header
"""
filename = "../models/cube 01_p.sli"
file = open(filename, "rb")
header = file.read(40).decode("ascii")
"""
Read and locate the file preamble
"""
if "EOS 1993 SLI FILE" not in header:
raise ValueError("Not .sls file")
"""
Read the header information
"""
vMajor = read_uint16(file)
i2 = read_uint16(file)
headerSize = int(read_uint32(file))
i3 = read_uint32(file)
i4 = read_uint32(file)
"""
Locate the slice offset position
"""
sliceOffset = int(read_uint32(file))
print('file pos', file.tell())
print('slice offset, ')
"""
Locate the seek table position in the file
"""
seekTablePos = int(read_uint32(file))
creator = file.read(40).decode("ascii")
numLayers = int(read_uint32(file))
polyLineCount = read_uint32(file)
i6 = read_uint32(file)
unknown = file.read(32).decode("ascii")
"""
Locate the scale factor for the entire part and the part bounding box
"""
scaleFactor = read_floats(file, 1)[0]
bbox = read_floats(file, 6)
# Move to the layer seek table
file.seek(seekTablePos+headerSize)
def parseLayer(file, layer):
file.seek(layer.seekPos)
print('layer seek pos', layer.seekPos)
opCode = 0
while opCode != 2:
opCode = read_uint8(file)
if opCode == 1:
# Read the layer header
layerZPos = int(read_uint16(file)) * scaleFactor # scale factor height as a uin16,
layerThickness = read_floats(file, 2)
print("Layer z pos: {:.3f}, thickness: {:.3f}, {:.3f}".format(layerZPos, *layerThickness))
# padding
unknownId = read_uint8(file) # Typically zero
elif opCode == 2:
""" Upon reaching op-code 2 - the layer has been successfully parsed"""
return
elif opCode == 3:
# Parse a contour
geom = pyslm.geometry.ContourGeometry()
geom.bid = read_uint8(file)
numPoints = read_uint16(file)
# Note a closed closed loop must be created for the contours
geom.coords = read_int16(file, 2*int(numPoints)).astype(np.float32).reshape(-1,2) * scaleFactor
layer.geometry.append(geom)
elif opCode == 4:
# Prase the hatch
geom = pyslm.geometry.HatchGeometry()
geom.bid = read_uint8(file)
numPoints = read_uint16(file)
geom.coords = read_int16(file, 4 * int(numPoints)).astype(np.float32).reshape(-1,2) * scaleFactor
layer.geometry.append(geom)
else:
raise ValueError("unknown layer op-code")
layers = []
currentFilePos = file.tell()
for i in range(numLayers):
layer = pyslm.geometry.Layer()
# The layer position is stored in the layer seek table, but also later in the Layer Definition Header
layer.z = read_uint16(file) * scaleFactor
layer.seekPos = int(read_uint32(file)) + headerSize
layer.layerId = i # not used in the sli implementation but used for reference in PySLM
# Store current file pos
currentFilePos = file.tell()
parseLayer(file, layer)
layers.append(layer)
file.seek(currentFilePos)
pyslm.visualise.plot(layers[1], plot3D=False, plotOrderLine=True, plotArrows=False)
`
Sir , I want CLI to SLM translator for commercial purpose .
Dear Mr. Perry
I am currently writing my Master thesis at the advanced manufacturing laboratory at ETH Zurich on the topic of "Implementation and evaluation of a dynamic slicing and scan-path generation software for laser powder bed fusion (L-PBF)". In the README.rst it is stated that it would be possible to gain access to a CLI specific translator as a pre-compiled module on request. My question would now be, whether it is possible to the mentioned translator to be used in my research project?
Thank you very much for your answer and best regards
Luca Stalder
Hi @drlukeparry.
I wanted to test your library in python by cloning + running pip install .\libSLM but unfortunately I get an error:
CMake Error at CMakeLists.txt:139 (add_subdirectory):
add_subdirectory given source "Translators" which is not an existing
directory.
The directory seems to be missing in the repository.
Best regards,
Mattis
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.