Code Monkey home page Code Monkey logo

libslm's People

Contributors

drlukeparry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libslm's Issues

Support binary .cli (Common Layer Interface) Build FIles via libslm

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:

cube-10mm_000_s1_vs.cli.zip

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)

`

Support for SLM Solution Systems via .mtt and .slm Build Files

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.

cube-10mm.zip

Support binary .sli EOS File Format

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:

  • .job file - specifying the metadata, parameters used for the EOS system and the build consisting of multiple parts with their individual transformations.
  • .eospar file - an encrypted and proprietary laser parameter file which stores the material file containing the scan and hatch parameters used by the SLM system and during EOS's internal preprocessing tool.
  • .sli file storing the laser scan geometry and references to the laser parameters for each part

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:

cube.openjob.txt

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)

`

Access to CLI translator

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

pip install is not working

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.