Arena SDK
lastmod 2026-02-21created 2026-02-124 edits
Lucid Vision Camera ROS2 Driver with Arena SDK
Connection workflow overview
| Step | Method | Description |
| 1. System initialization | | Initialized automatically on import (singleton) |
| 2. Device discovery | | Search for cameras on the network |
| 3. Device creation | | Connect a control channel to the camera |
| 4. Device selection | | Choose among multiple devices |
| 5. Stream configuration | | Configure packet size, resend, etc. |
| 6. Image acquisition | | Start streaming and receive buffers |
| 7. Cleanup | | Release the control channel and return resources |
System initialization
The ARENA SDK system object is implemented as a singleton and is initialized automatically on import.
-
examples/py_enumeration.py(Lines 23-29)
Device discovery
Searches for cameras connected to the network.
Basic discovery
device_infos = system.device_infos
print(f"발견된 장치: {len(device_infos)}대")
for info in device_infos:
print(f" 모델: {info['model']}")
print(f" 시리얼: {info['serial']}")
print(f" IP: {info['ip']}")
print(f" MAC: {info['mac']}")
Information returned by device_infos
system.device_infos returns a list of dictionaries, and each item contains the following keys.
| Key | Description | Example |
| | Camera model name | |
| | Manufacturer | |
| | Serial number | |
| | IP address | |
| | Subnet mask | |
| | Default gateway | |
| | MAC address | |
| | User-defined name | |
| | Firmware version | |
| | Whether DHCP is enabled | |
| | Whether persistent IP is enabled | |
| | Whether Link-Local Address is used | |
Discovery timeout setting
# 기본값: 100ms
# LUCID 카메라는 100ms 이내 응답, GigE Vision 스펙상 최대 1초
system.DEVICE_INFOS_TIMEOUT_MILLISEC = 200 # 필요시 늘릴 수 있음
device_infos = system.device_infos
-
examples/py_enumeration.py(Lines 63-81)
Device creation (connection)
Opens a control channel to the discovered cameras and connects to them.
Connect all devices
With retry logic
import time
tries = 0
tries_max = 6
sleep_time_secs = 10
while tries < tries_max:
devices = system.create_device()
if devices:
print(f"{len(devices)}대 연결 성공")
break
print(f"시도 {tries+1}/{tries_max}: {sleep_time_secs}초 대기 중...")
time.sleep(sleep_time_secs)
tries += 1
else:
raise Exception("장치를 찾을 수 없습니다")
Connect specific devices only
# MAC 주소로 필터링
target_mac = "00:30:F1:02:03:04"
target_info = [d for d in system.device_infos if d['mac'] == target_mac]
devices = system.create_device(device_infos=target_info)
# 특정 인덱스의 장치만 연결
device_info = system.device_infos[0]
devices = system.create_device(device_infos=device_info)
# 여러 장치를 선택적으로 연결
all_infos = system.device_infos
devices = system.create_device(device_infos=all_infos[:2]) # 처음 2대만
Device selection
| NOTE |
| The first process gets read/write access, and later processes connect read-only. |
-
examples/py_simple_acquisition.py(Lines 32-70) -
examples/py_enumeration_mac.py(Lines 38-74)
Network configuration
Force IP (temporary IP assignment)
Temporarily changes the device's IP. The original settings are restored on reboot.
# 단일 장치
system.force_ip({
'mac': '00:30:F1:02:03:04',
'ip': '192.168.1.50',
'subnetmask': '255.255.255.0',
'defaultgateway': '192.168.1.1'
})
# 다중 장치 동시 설정
system.force_ip([
{'mac': '00:30:F1:02:03:04', 'ip': '192.168.1.50',
'subnetmask': '255.255.255.0', 'defaultgateway': '192.168.1.1'},
{'mac': '00:30:F1:02:03:05', 'ip': '192.168.1.51',
'subnetmask': '255.255.255.0', 'defaultgateway': '192.168.1.1'}
])
| WARNING |
| Force IP is a temporary setting. It is reset when the device reboots. |
-
examples/py_force_ip.py(Lines 86-133)
Persistent IP configuration (permanent)
Sets a permanent IP address on the device.
import ipaddress
devices = system.create_device()
device = system.select_device(devices)
nodemap = device.nodemap
# IP 주소 설정
new_ip = ipaddress.IPv4Address("169.254.3.2")
new_mask = ipaddress.IPv4Address("255.255.0.0")
nodemap.get_node("GevPersistentIPAddress").value = int(new_ip)
nodemap.get_node("GevPersistentSubnetMask").value = int(new_mask)
# 고정 IP 활성화, DHCP 비활성화
nodemap.get_node("GevCurrentIPConfigurationPersistentIP").value = True
nodemap.get_node("GevCurrentIPConfigurationDHCP").value = False
# (선택) ARP 충돌 감지 비활성화
nodemap.get_node("GevPersistentARPConflictDetectionEnable").value = False
IP configuration nodes
| Node | Description | Type |
| | Persistent IP address | Integer (IPv4 converted to an integer) |
| | Persistent subnet mask | Integer |
| | Persistent default gateway | Integer |
| | Enable persistent IP | Boolean |
| | Enable DHCP | Boolean |
| | Link-Local Address | Boolean (cannot be disabled) |
| | ARP conflict detection | Boolean |
IP configuration priority
| Priority | Condition | Result |
| 1 | Both persistent IP and DHCP enabled | Persistent IP is used |
| 2 | Only persistent IP enabled | Persistent IP is used |
| 3 | Only DHCP enabled | Assigned via DHCP |
| 4 | All disabled | LLA used automatically (fallback) |
-
examples/py_ipconfig_manual.py(Lines 28-74)
Unicast discovery (other subnets)
Searches for cameras on other subnets that broadcasts do not reach.
# 유니캐스트 대상 추가
system.add_unicast_discovery_device("192.168.2.50")
# 검색 시 원격 장치도 포함됨
device_infos = system.device_infos
# 유니캐스트 대상 제거
system.remove_unicast_discovery_device("192.168.2.50")
# 모든 유니캐스트 대상 제거
system.remove_unicast_discovery_device(None)
-
examples/py_enumeration_unicast.py(Lines 59-94)
Stream configuration
Configures stream-related settings before receiving images.
tl_stream = device.tl_stream_nodemap
# 패킷 크기 자동 협상 (권장)
tl_stream['StreamAutoNegotiatePacketSize'].value = True
# 패킷 재전송 활성화 (UDP 손실 복구)
tl_stream['StreamPacketResendEnable'].value = True
# 버퍼 핸들링 모드 설정
tl_stream['StreamBufferHandlingMode'].value = 'NewestOnly'
Stream configuration nodes:
| Node | Description | Recommended value |
| | Automatically negotiate the largest safe packet size | |
| | Request resending of lost UDP packets | |
| | Buffer handling method | |
-
examples/py_simple_acquisition.py(Lines 72-79) -
examples/py_acquisition.py(Lines 59-104)
Image acquisition
# 컨텍스트 매니저 사용 (권장)
with device.start_stream():
buffer = device.get_buffer()
print(f"이미지: {buffer.width}x{buffer.height}, 포맷: {buffer.pixel_format.name}")
device.requeue_buffer(buffer)
# 여러 프레임 획득
with device.start_stream():
for i in range(10):
buffer = device.get_buffer(timeout=2000) # 2초 타임아웃
print(f"프레임 {i}: {buffer.width}x{buffer.height}")
device.requeue_buffer(buffer)
-
examples/py_simple_acquisition.py -
examples/py_acquisition.py
Device release (disconnection)
# 모든 장치 해제
system.destroy_device()
# 특정 장치만 해제
system.destroy_device(device)
# 여러 장치 선택 해제
system.destroy_device([device1, device2])
| NOTE |
| |
Disconnection detection (callback)
You can be notified when a camera disconnects unexpectedly.
from arena_api.callback import callback, callback_function
# 콜백 함수 정의
@callback_function.system.on_device_disconnected
def on_disconnect(device):
print(f'장치 연결 해제됨: {device}')
# 콜백 등록
handle = callback.register(system, on_disconnect, watched_device=device)
# 연결 상태 확인
if device.is_connected():
print("연결됨")
else:
print("연결 해제됨")
# 콜백 해제
callback.deregister(handle)
-
examples/py_callback_on_device_disconnected.py(Lines 61-100)
Multi-device connection
How to use several cameras at the same time.
import threading
# 모든 장치 생성
devices = system.create_device()
# 각 장치 설정
for device in devices:
nodemap = device.nodemap
tl_stream = device.tl_stream_nodemap
nodemap.get_node("AcquisitionMode").value = "Continuous"
tl_stream['StreamAutoNegotiatePacketSize'].value = True
tl_stream['StreamPacketResendEnable'].value = True
tl_stream['StreamBufferHandlingMode'].value = 'NewestOnly'
# 병렬 획득 함수
def acquire(device, num_frames=10):
with device.start_stream():
for i in range(num_frames):
buffer = device.get_buffer(timeout=2000)
print(f"[{device}] 프레임 {i}: {buffer.width}x{buffer.height}")
device.requeue_buffer(buffer)
# 스레드로 병렬 실행
threads = [threading.Thread(target=acquire, args=(d,)) for d in devices]
for t in threads:
t.start()
for t in threads:
t.join()
# 정리
system.destroy_device()
-
examples/py_acquisition_multi_device.py
Complete connection example (all together)
import time
from arena_api.system import system
def main():
# 1. 장치 검색
print("장치 검색 중...")
device_infos = system.device_infos
print(f"발견된 장치: {len(device_infos)}대")
if not device_infos:
print("장치를 찾을 수 없습니다")
return
# 2. 장치 생성 (재시도 포함)
tries = 0
while tries < 6:
devices = system.create_device()
if devices:
break
print(f"대기 중... ({tries+1}/6)")
time.sleep(10)
tries += 1
else:
raise Exception("장치 연결 실패")
# 3. 장치 선택
device = system.select_device(devices)
# 4. 스트림 설정
tl_stream = device.tl_stream_nodemap
tl_stream['StreamAutoNegotiatePacketSize'].value = True
tl_stream['StreamPacketResendEnable'].value = True
# 5. 이미지 획득
with device.start_stream():
buffer = device.get_buffer()
print(f"이미지: {buffer.width}x{buffer.height}")
print(f"포맷: {buffer.pixel_format.name}")
device.requeue_buffer(buffer)
# 6. 정리
system.destroy_device()
print("연결 종료")
if __name__ == '__main__':
main()
Related example files
| Topic | File |
| Basic device discovery | |
| Discovery by MAC address | |
| Unicast discovery | |
| Force IP (temporary) | |
| Persistent IP configuration (permanent) | |
| Basic image acquisition | |
| Detailed image acquisition | |
| Multiple devices | |
| Disconnection callback | |
Exposure control
The most essential way to adjust camera brightness.
| Node | Description | Notes |
| | Auto exposure On/Off | |
| | Manual exposure time | Unit: microseconds (μs) |
| | Select multi-exposure mode | Used for HDR, etc. |
Example:
nodes = nodemap.get_node(['ExposureAuto', 'ExposureTime'])
nodes['ExposureAuto'].value = 'Off'
nodes['ExposureTime'].value = 4000.0 # 마이크로초
-
examples/py_exposure.py— Basic exposure control -
examples/py_exposure_forhdr.py— HDR exposure -
examples/py_exposure_long.py— Long exposure
Gain control
Adjusts image brightness by amplifying the sensor signal.
| Node | Description | Value |
| | Sensor signal amplification | |
Example:
-
examples/py_helios_smooth_results.py
Binning
Combines several pixels into one to reduce noise and increase brightness.
| Node | Description | Notes |
| | Select the binning target | |
| | Number of rows to combine | Integer value |
| | Number of columns to combine | Integer value |
| | Vertical binning mode | |
| | Horizontal binning mode | |
| NOTE |
| |
-
examples/py_acquisition_sensor_binning.py
LUT (Look Up Table)
Maps input brightness values to output brightness values to fine-tune gamma, contrast, and so on.
| Node | Description | Notes |
| | Enable/disable LUT | |
| | Input intensity index | 0 to maximum |
| | Output intensity value for that index | Mapped result value |
Example:
nodemap.get_node("LUTEnable").value = True
node_lut_index = nodemap.get_node("LUTIndex")
node_lut_value = nodemap.get_node("LUTValue")
# 강도 반전 예시
SLOPE = -1
for i in range(node_lut_index.max + 1):
node_lut_index.value = i
node_lut_value.value = SLOPE * i + node_lut_index.max
-
examples/py_lut.py
Frame rate control
Lowering the frame rate allows longer exposure times, which indirectly affects brightness.
| Node | Description | Notes |
| | Enable frame rate control | |
| | Set the frame rate | Unit: fps |
-
examples/py_exposure_long.py
Pixel defect correction
Corrects dead pixels and stuck pixels.
| Node | Description | Type |
| | Enable defect correction | Boolean |
| | Number of corrected pixels | Integer (read-only) |
| | Correction entry index | Integer |
| | X coordinate of the pixel to correct | Integer |
| | Y coordinate of the pixel to correct | Integer |
| | Add a new defective pixel | Command |
| | Apply the correction list | Command |
| | Save correction data to the camera | Command |
| | Remove from the correction list | Command |
-
examples/py_pixel_correction.py
3D camera parameters (Helios/HLT)
Additional tuning options available on 3D cameras such as the Helios series.
| Node | Description | Notes |
| | Multi-frame accumulation | Improves brightness and SNR |
| | Enable spatial filtering | Noise reduction |
| | Enable confidence filtering | Removes low-quality data |
-
examples/py_helios_smooth_results.py
Common usage patterns
For every node, it is recommended to check whether it is writable and its allowed range before setting a value.
# 노드 값 설정 전 범위 확인
node = nodemap.get_node('ExposureTime')
if node.is_writable:
value = min(max(desired_value, node.min), node.max)
node.value = value
# 열거형 노드의 사용 가능한 값 확인
enum_node = nodemap.get_node('ExposureAuto')
print(enum_node.enumentry_names) # ['Off', 'Once', 'Continuous']
# 커맨드 노드 실행
cmd_node = nodemap.get_node('DefectCorrectionApply')
cmd_node.execute()
Summary of brightness adjustment methods
| Method | Direct/indirect | Effect | Side effect |
| Increase ExposureTime | Direct | Brighter image | Possible motion blur |
| Increase ConversionGain | Direct | Brighter image | More noise |
| Binning (Sum mode) | Direct | Brighter image | Lower resolution |
| LUT adjustment | Direct | Custom brightness/contrast | Possible loss of dynamic range |
| Lower frame rate | Indirect | Allows longer exposure time | Fewer frames per second |
| Scan3dImageAccumulation | Direct (3D only) | Improves SNR and brightness | Longer capture time |
Common interface notes
- For most nodes, you can check the valid range with the
.minand.maxproperties. - You can check whether a node is readable/writable with the
.is_readableand.is_writableproperties. - For enumeration nodes, you can check the list of available values with
.enumentry_names. - For Float/Integer nodes, you can check the increment with the
.incproperty.
See also
- LUCID Vision Labs
- ROS2
- GigE Vision
- Machine Vision
- Machine Vision Camera
- Pylon (Python)
- Korean: 바슬러 (Basler)
- FLIR
- Camera settings
- Image processing
- CCTV