Micro-Epsilon:scanCONTROL
lastmod 2026-04-17created 2026-03-279 edits
Inline quality inspection with 3D laser scanners
Categories
About
scanCONTROL 3D scanners are used for a wide range of high-precision inline 3D measurements. Scanning is done while the scanner or the target moves, and because the scanners are very lightweight, they can be used both with robots and in inline production monitoring. These 3D laser scanners can quickly detect and measure even small deviations with excellent precision, and offer very high absolute accuracy and a very compact size. With scanCONTROL 3000 and the launch of the new scanCONTROL 3002 series, Micro-Epsilon can not only cover a wide range of measuring ranges but also offer a comprehensive product portfolio with red or blue laser technology and a broad range of accessories.
scanCONTROL 3D laser scanners are based on the latest GigE Vision and GenICam standards, so they can be integrated into a variety of image processing environments. In addition, the powerful 3DInspect software is used for parameter setup, evaluation, and output.
| |
Features
- Real 3D point clouds with no data loss in post-processing
- High-speed 3D scanning up to 10,000 Hz
- Ultra-compact products usable in a variety of measurement environments
- Small, compact size suited to robot applications
- Available with red or blue lasers
- Easy integration via the GenICam / GigE Vision standards
- Measurement, processing, and evaluation with the powerful 3DInspect software
- Compatible with Cognex VisionPro
scanCONTROL series
Micro-Epsilon's scanCONTROL line is a flagship family of industrial laser profile scanners.
The controller is integrated into the sensor housing (integrated controller), and the sensor communicates directly with PC applications via Ethernet and RS422 interfaces and the SDK (LLT.DLL).
| Series | X resolution (points/profile) | Max profile frequency | Max measuring rate | Laser color | Features |
| 25x0 | 640 | 300 Hz | 192,000 pts/s | Red | General-purpose, low cost |
| 26x0 | 640 | 4,000 Hz | 2,560,000 pts/s | Red/blue | High-speed, compact |
| 29x0 | 1,280 | 2,000 Hz | 2,560,000 pts/s | Red/blue | High-resolution, high-speed |
| 30x0 | 1,280 | 300 Hz (standard) | — | Red/blue | Large range, high precision |
| 30x2 | 1,280 | 2,000 Hz (HS) | 2,560,000 pts/s | Red/blue | High-performance 2D/3D |
| 3002 (BL) | 1,280 | 2,000 Hz | — | Blue (Blue Laser) | Specialized for red-hot metal and welding |
| INFORMATION |
| Blue laser (BL) models : Their short wavelength allows stable measurement even on red-hot metal surfaces above 700 °C (a red laser saturates the sensor). Essential for inline weld inspection. |
Data format and structure
Profile data structure
A scanCONTROL sensor produces one profile (cross-section) of data per scan.
Profile (단면 1장)
├── Header
│ ├── Timestamp (uint32, 10 µs 단위)
│ ├── Profile Counter (uint32, 누락 검출용)
│ ├── Encoder Value (int32, 외부 엔코더 값)
│ └── Status Flags (uint16)
└── Points[N] (N = 640 또는 1280)
├── X (float32, mm) — 레이저 라인 방향 횡축
├── Z (float32, mm) — 깊이(높이) 측정값
├── Intensity (uint16) — 수광 강도
└── Width (uint16) — 반사광 선폭 (선택)
- Invalid points (unmeasurable areas) are marked with INVALID_VALUE (usually −32768 or NaN).
- The point array goes through the sensor's internal calibration and is delivered as values corrected to real physical units (mm).
Container mode
Supports the Container Set method, which bundles multiple profiles and transmits them at once.
| Item | Description |
| Container Size | Number of profiles bundled and sent at once (1 ~ N, configurable) |
| Transfer unit | Array or Matrix form |
| Purpose | Reduces network overhead during high-speed measurement, optimizes batch processing |
Binary buffer layout (per the SDK)
The binary buffer returned by the LLT SDK has the following structure per profile.
| Offset | Size | Type | Description |
| 0 | 4 | uint32 | Profile Counter |
| 4 | 4 | uint32 | Timestamp (× 10 µs) |
| 8 | 4 | int32 | Encoder / Trigger Value |
| 12 | 2 | uint16 | Status / Flag |
| 14 | 2 | uint16 | (Reserved) |
| 16 | N × 4 | float32[] | X coordinate array (mm) |
| 16 + N×4 | N × 4 | float32[] | Z coordinate array (mm) |
| 16 + N×8 | N × 2 | uint16[] | Intensity array |
| 16 + N×10 | N × 2 | uint16[] | Width array (optional) |
| WARNING |
| The last 4 bytes are sometimes overwritten by the timestamp → known issue of the last point going missing in ROS drivers, etc. |
Assembling a 3D point cloud
A single profile is a 2D cross-section, so a 3D point cloud is built by physically moving the sensor (robot arm or conveyor) and adding a Y-axis coordinate.
# LVS 프로파일 → 3D 포인트 클라우드 변환 예시
# LVS profile → 3D point cloud conversion example
import numpy as np
def profiles_to_pointcloud(profiles: list[dict], y_step_mm: float) -> np.ndarray:
"""
profiles: [{'x': np.array, 'z': np.array, 'intensity': np.array}, ...]
y_step_mm: 각 프로파일 간 Y 이동 거리 (mm)
반환: (N, 4) 배열 [x, y, z, intensity]
"""
points = []
for i, prof in enumerate(profiles):
x = prof['x'] # X 좌표 배열 (mm)
z = prof['z'] # Z 높이 배열 (mm)
y = np.full_like(x, i * y_step_mm) # Y는 이동 거리로 계산
intensity = prof['intensity'].astype(np.float32)
# 유효 포인트만 필터링 (Filter valid points only)
valid = np.isfinite(x) & np.isfinite(z) & (z > -32767)
pts = np.stack([x[valid], y[valid], z[valid], intensity[valid]], axis=-1)
points.append(pts)
return np.concatenate(points, axis=0) # shape: (N, 4)
File storage formats
| Format | Extension | Description | Use |
| Binary Profile | | SDK binary stream | Real-time saving, playback |
| CSV | | X, Z, Intensity columns | Excel analysis, verification |
| PCD | | Point Cloud Data (PCL standard) | Open3D, PCL processing |
| PLY | | Polygon File Format | MeshLab, visualization |
| STL / OBJ | | 3D mesh | CAD comparison |
| HDF5 | | Hierarchical binary | Deep learning training datasets |
- The scanCONTROL 3D-View software supports export to PCD, PLY, STL, and CSV formats.
- The HDF5 format is recommended for large datasets for deep learning pipelines.
Communication interfaces
Ethernet (GigE)
| Item | Details |
| Protocol | UDP (profile data stream), TCP (configuration and control) |
| Standard | Based on GeniCam / GenApi |
| IP configuration | Static IP assigned with the sensor config software |
| Ports | Default 50000 (data), 50001 (control) — varies by model |
| Latency | < 1 ms (LAN environment) |
| Max bandwidth | 1 Gbps (GigE Vision) |
RS422
- Used for low-speed configuration and result transfer, or exclusively for synchronization and trigger signals
- Supports the Modbus protocol → can connect directly to a PLC
- Pinout : 6-pole connector, built-in 120 Ω termination resistor
Trigger input (External Trigger)
- Has a high-speed external trigger input terminal
- Unit: 10 µs (for setting shutter time and idle time)
- Profile frequency = 100,000 / (shutter_time + idle_time) Hz
- Supports multi-scanner synchronization
Encoder input
- Rotary encoder signal input for calculating the Y-axis coordinate in the direction of travel
- The encoder counter value is included in each profile header
- This enables accurate Y-step calculation → high-quality 3D reconstruction
SDK / API
LLT SDK (Windows)
- Library:
LLT.DLL(C/C++, supports both stdcall and cdecl) - Supports both static and dynamic loading
- Integration examples provided for C#, LabVIEW, and Python (ctypes/cffi)
Main functions (conceptual):
| Function | Description |
| | Create a sensor device instance |
| | Connect to the sensor |
| | Set parameters (resolution, frequency, etc.) |
| | Query current parameters |
| | Start receiving the profile stream |
| | Acquire the latest single profile |
| | Disconnect |
Linux C++ SDK / Open Source
- Provides a C++ library based on the GeniCam standard
- Limited support for ARM embedded PCs (Raspberry Pi, etc.)
- Open-source ROS/ROS2 driver: sam-xl/scancontrol (GitHub)
- Verified on ROS2 Humble (Ubuntu 22.04) and Jazzy (Ubuntu 24.04)
- Output topic:
sensor_msgs/PointCloud2 - Services:
set_feature,get_feature,get_resolutions
Python integration example
# scanCONTROL SDK Python 연동 예시 (ctypes 기반)
# scanCONTROL SDK Python binding example via ctypes
import ctypes
import numpy as np
# DLL 로드 (Load DLL)
llt = ctypes.WinDLL("LLT.dll")
HANDLE = ctypes.c_void_p
N_POINTS = 1280 # 센서 해상도에 따라 변경
def get_profile(handle: HANDLE) -> dict:
"""
단일 프로파일 취득 (Get single profile)
Returns: {'x': np.array, 'z': np.array, 'intensity': np.array}
"""
buf_size = N_POINTS * 10 + 16 # X(4) + Z(4) + Intensity(2) + Header
buf = (ctypes.c_uint8 * buf_size)()
ret = llt.GetActualProfile(handle, buf, buf_size)
if ret < 0:
raise RuntimeError(f"GetActualProfile 실패: {ret}")
# 헤더 파싱 (Parse header)
counter = ctypes.c_uint32.from_buffer_copy(buf, 0).value
timestamp = ctypes.c_uint32.from_buffer_copy(buf, 4).value # ×10 µs
encoder = ctypes.c_int32.from_buffer_copy(buf, 8).value
# 데이터 추출 (Extract data arrays)
x = np.frombuffer(buf, dtype=np.float32, count=N_POINTS, offset=16)
z = np.frombuffer(buf, dtype=np.float32, count=N_POINTS, offset=16 + N_POINTS*4)
inten = np.frombuffer(buf, dtype=np.uint16, count=N_POINTS, offset=16 + N_POINTS*8)
return {
'counter': counter,
'timestamp': timestamp * 1e-5, # 초 단위 변환 (convert to seconds)
'encoder': encoder,
'x': x.copy(),
'z': z.copy(),
'intensity': inten.copy()
}
Application to weld quality inspection
Measured items
Main geometric parameters extracted in weld bead inspection with LVS:
| Measured item | Symbol | Unit | Description |
| Bead height | h | mm | Highest point of the bead relative to the base metal reference plane |
| Bead width | w | mm | Width of the bead footprint (tangent points) |
| Bead cross-sectional area | A | mm² | Area integral of the cross-section profile |
| Undercut depth | u | mm | Depth of the base metal depression at the bead edge |
| Overlap | — | mm | Amount by which the bead excessively covers the base metal |
| Porosity | — | — | Profile discontinuities, depression patterns |
| Crack | — | — | Abrupt Z-value discontinuity patterns |
| Straightness | — | mm/m | Deviation of the bead centerline |
| Start/end point position | — | mm | Position error of the weld start and end points |
Inline inspection layout
[용접 토치]
│
▼ (이동 방향 Y)
[scanCONTROL 센서] ←── 토치 후방 장착 (Post-weld inspection)
│ 또는
└── 토치 전방 장착 (Pre-weld seam tracking)
레이저 라인 (X축)
─────────────────────────────
▲ Z (높이)
│
└──────────────────────── X
- Pre-weld : Seam tracking → real-time position correction of the welding torch
- Post-weld : Bead geometry measurement → quality pass/fail decision, defect classification
Environmental considerations
| Item | Details |
| Red-hot metal | Blue laser (BL) model required (stable measurement above 700 °C) |
| Weld spatter | Protective glass / air purge recommended |
| Smoke and fumes | Airborne particles scatter the laser → set up filtering or an exhaust system |
| Vibration | Reinforce the sensor mounting structure, apply profile averaging |
| Reflectivity variation | Use HDR (High Dynamic Range) mode (scanCONTROL 3000 series) |
| Temperature effects | Compensate for ambient temperature around the sensor, or zero after warm-up |
Applying deep learning models
Input data representations
The main representations used when feeding LVS data into deep learning models are as follows.
| Representation | Description | Suitable models | Pros and cons |
| 2D profile image | Stack profiles into an image (H×W) | CNN, ResNet, U-Net | Existing 2D models can be reused; some 3D geometric information is lost |
| Depth Map | Represent Z values as a grayscale image | CNN family | Simple to implement; easy local anomaly detection |
| Multi-channel Map | X, Z, and Intensity as separate channels (3-ch) | CNN family | Rich features; channel design matters |
| Raw Point Cloud | Set of (X, Y, Z, I) points | PointNet, PointNet++, PTv3 | Preserves geometry; irregular sampling must be handled |
| Voxel Grid | Convert the point cloud into 3D voxels | 3D-CNN, VoxNet | Easy to learn spatial relationships; memory-intensive |
| Cross-section Sequence | Treat consecutive profiles as a time series | LSTM, Transformer | Learns patterns along the welding direction |
Recommended deep learning architectures
Korean: 이상 탐지 (Anomaly Detection)
입력: Depth Map 또는 Multi-channel Map (H × W × C)
모델: Autoencoder (CNN 기반)
Encoder → Bottleneck → Decoder
출력: 재구성 오차(Reconstruction Error) → 임계값 초과 = 불량
적용 사례:
- 기공(Porosity) 탐지
- 언더컷 탐지
- 비드 형상 이상 탐지
Korean: 결함 분류 (Defect Classification)
입력: 비드 단면 프로파일 Crop (고정 크기)
모델: ResNet-18 / EfficientNet-B0 (경량)
출력: 결함 클래스 (정상 / 기공 / 언더컷 / 크랙 / 오버랩 / 미용접)
Geometric parameter regression
Point cloud segmentation
입력: (N, 4) — [x, y, z, intensity]
모델: PointNet++ / PTv3 (Point Transformer v3) / Concerto
출력: 포인트별 클래스 레이블 (비드 영역 / 모재 / 결함)
Data preprocessing pipeline
# LVS 데이터 전처리 파이프라인
# LVS data preprocessing pipeline
import numpy as np
import cv2
class LVSPreprocessor:
"""
LVS 프로파일 데이터 전처리기
LVS profile data preprocessor
"""
def __init__(
self,
n_points: int = 1280, # 프로파일 포인트 수
n_profiles: int = 512, # 수집할 프로파일 수 (Y 방향 길이)
z_min: float = -5.0, # Z 유효 범위 최솟값 (mm)
z_max: float = 10.0, # Z 유효 범위 최댓값 (mm)
):
self.n_points = n_points
self.n_profiles = n_profiles
self.z_min = z_min
self.z_max = z_max
def build_depth_map(self, profiles: list[dict]) -> np.ndarray:
"""
프로파일 리스트 → Depth Map (H × W) float32
Profile list → Depth Map (H × W) float32
"""
depth = np.full((self.n_profiles, self.n_points), np.nan, dtype=np.float32)
for i, prof in enumerate(profiles[:self.n_profiles]):
z = prof['z'].copy()
# 범위 밖 값 무효 처리 (Invalidate out-of-range values)
z[(z < self.z_min) | (z > self.z_max)] = np.nan
depth[i] = z
# NaN을 0으로 대체 후 정규화 (Replace NaN with 0, then normalize)
valid_mask = np.isfinite(depth)
depth = np.where(valid_mask, depth, 0.0)
depth = (depth - self.z_min) / (self.z_max - self.z_min) # [0, 1]
depth = np.clip(depth, 0.0, 1.0)
return depth # shape: (H, W)
def build_multichannel(self, profiles: list[dict]) -> np.ndarray:
"""
프로파일 리스트 → 3채널 맵 (H × W × 3)
Channel 0: Z (깊이), Channel 1: Intensity, Channel 2: X (가로 위치)
"""
dm = self.build_depth_map(profiles)
intensity_map = np.zeros((self.n_profiles, self.n_points), dtype=np.float32)
x_map = np.zeros_like(intensity_map)
for i, prof in enumerate(profiles[:self.n_profiles]):
inten = prof['intensity'].astype(np.float32)
intensity_map[i] = inten / 65535.0 # uint16 정규화
x_map[i] = (prof['x'] - prof['x'].min()) / (prof['x'].ptp() + 1e-8)
return np.stack([dm, intensity_map, x_map], axis=-1) # (H, W, 3)
def extract_bead_roi(
self,
depth_map: np.ndarray,
roi_width_px: int = 200
) -> np.ndarray:
"""
비드 중심 자동 감지 후 ROI 크롭
Auto-detect bead center and crop ROI
"""
# 열 방향 평균으로 비드 중심 추정 (Estimate bead center via column mean)
col_mean = np.nanmean(depth_map, axis=0)
center = int(np.argmax(col_mean))
left = max(0, center - roi_width_px // 2)
right = min(depth_map.shape[1], left + roi_width_px)
return depth_map[:, left:right]
Training dataset design
| Item | Recommendation |
| Labeling scheme | Defect grades per ISO 5817 or AWS D1.1 (A / B / C / D) |
| Class imbalance | Use oversampling (with SMOTE) or Focal Loss |
| Augmentation | Add Z-axis noise, horizontal flip of profiles, Y-direction shift, random crop |
| Storage format | HDF5 (datasets: depth_map, label, params, metadata) |
| Train/Val/Test split | 7 : 1 : 2 (stratified split by welding condition) |
| Minimum sample count | At least 500 samples per class (including defect classes) |
Evaluation metrics
| Metric | Formula / description | Use |
| Accuracy | (TP + TN) / Total | Overall accuracy |
| Precision | TP / (TP + FP) | Defect detection precision (minimize false positives) |
| Recall (Sensitivity) | TP / (TP + FN) | Defect detection recall (minimize missed defects) ← key |
| F1-Score | 2 × (P × R) / (P + R) | Combined metric for imbalanced classes |
| IoU (Segmentation) | TP / (TP + FP + FN) | Segmentation quality of defect regions |
| MAE (Regression) | Σ|y_pred − y_true| / N | Geometric parameter regression error (mm) |
| RMSE (Regression) | √(Σ(y_pred − y_true)² / N) | Geometric parameter regression error (mm) |
Platform architecture (recommended)
Overall data flow
[scanCONTROL 센서]
│ GigE (UDP/TCP)
▼
[Edge PC / 임베디드 호스트]
├── scanCONTROL SDK (LLT.DLL / Linux C++)
├── ROS2 Driver (선택 사항)
├── 실시간 프리프로세싱 (Depth Map / Point Cloud 변환)
└── gRPC 스트림 → [CVP 서비스]
│
▼
[CVP 추론 서버]
├── 딥러닝 모델 (TorchScript / ONNX / TensorRT)
├── 형상 파라미터 추출
└── 결함 분류 / 이상 점수 계산
│
▼
[Supabase DB] [Prometheus / Grafana]
├── 검사 결과 저장 └── 실시간 모니터링
├── 결함 이미지/포인트클라우드 S3
└── RLS 정책 (라인별 접근 제어)
│
▼
[CVP 대시보드 (React / TypeScript)]
├── 실시간 프로파일 시각화
├── 통계 리포트 (합/불 추이)
└── 결함 맵 오버레이 표시
Topic design for ROS2 integration
| Topic | Type | Direction | Description |
| | | Pub | Real-time point cloud |
| | | Pub | Raw profile array |
| | | Pub | Inspection result (defect class + parameters) |
| | | Pub | Seam tracking correction amount |
| | Service | Sub | Change sensor parameters at runtime |
Key parameter reference
Sensor configuration parameters
| Parameter | Unit | Default | Description |
| Shutter Time | 10 µs | Varies by model | Exposure time (shorter reduces motion blur) |
| Idle Time | 10 µs | Varies by model | Wait time between shutters |
| Profile Frequency | Hz | Calculated | = 100,000 / (shutter + idle) |
| Container Size | count | 1 | Number of profiles per bundled transfer |
| Resolution | points | 1280 | Number of X-axis points (choose 640 / 1280) |
| Partial Profile Start | index | 0 | Start index of the valid profile |
| Partial Profile Points | count | 1280 | Number of valid points |
| Flip X | bool | False | Flip X horizontally |
| Flip Z | bool | True | Flip Z vertically (default True) |
| Laser Power | % | 100 | Laser output (20–100%) |
Effective measuring range (per model, for reference)
| Model | Z measuring range | X measuring range | Z reference resolution | X resolution |
| scanCONTROL 2600-25 | 25 mm | 12 mm | 1 µm | ~18 µm |
| scanCONTROL 2600-100 | 100 mm | 55 mm | 2 µm | ~86 µm |
| scanCONTROL 2900-25 | 25 mm | 12 mm | 0.5 µm | ~9 µm |
| scanCONTROL 2900-100 | 100 mm | 55 mm | 1 µm | ~43 µm |
| scanCONTROL 3000-100 | 100 mm | 55 mm | 1 µm | ~43 µm |
| scanCONTROL 3002-100/BL | 100 mm | 55 mm | 1 µm | ~43 µm |
Documentations
- Klarák et al., Autoencoders for Point Cloud Reconstruction, Sensors 2023
- Nature Scientific Reports: Weld seam object detection via 2D+3D fusion, 2024
- ScienceDirect: Graph Neural Networks for patterned welds detection, 2025
- ACM Computing Surveys: Point Cloud Deep Learning in Industrial Production, 2025
See also
- Micro-Epsilon
- Micro-Epsilon:surfaceCONTROL 3D-Snapshot-Sensor
- Micro-Epsilon:reflectCONTROL for shiny surfaces
- Micro-Epsilon:scanCONTROL 3D laser scanners
- LVS
- Machine Vision
- Welding:SurfaceSampleDataGenerator - How to generate virtual "surface" data as ply by taking a single line of csv data from LVS that has only the
(x, z)axes and adding multiple lines along theyaxis.
Favorite site
- scanCONTROL 3D laser scanners | Micro-Epsilon
- Micro-Epsilon Software Integration
- Github - sam-xl/scancontrol - ROS2 scanCONTROL driver (sam-xl, TU Delft)
- - Github - iirob/microepsilon_scancontrol - ROS1 scanCONTROL driver (iirob)