Arena SDK
Lucid Vision Camera ROS2 Driver with Arena SDK
연결 워크플로우 개요
| 단계 | 메서드 | 설명 |
| 1. 시스템 초기화 | | import 시 자동 초기화 (싱글턴) |
| 2. 장치 검색 | | 네트워크상의 카메라 탐색 |
| 3. 장치 생성 | | 카메라와 제어 채널 연결 |
| 4. 장치 선택 | | 다중 장치 중 선택 |
| 5. 스트림 설정 | | 패킷 크기, 재전송 등 설정 |
| 6. 이미지 획득 | | 스트리밍 시작 및 버퍼 수신 |
| 7. 정리 | | 제어 채널 해제 및 리소스 반환 |
시스템 초기화
ARENA SDK의 시스템 객체는 싱글턴 패턴으로 구현되어 있으며, import 시 자동으로 초기화됩니다.
-
examples/py_enumeration.py(Lines 23-29)
장치 검색 (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']}")
device_infos 반환 정보
system.device_infos는 딕셔너리 리스트를 반환하며, 각 항목은 다음 키를 포함합니다.
| 키 | 설명 | 예시 |
| | 카메라 모델명 | |
| | 제조사 | |
| | 시리얼 번호 | |
| | IP 주소 | |
| | 서브넷 마스크 | |
| | 기본 게이트웨이 | |
| | MAC 주소 | |
| | 사용자 정의 이름 | |
| | 펌웨어 버전 | |
| | DHCP 활성화 여부 | |
| | 고정 IP 활성화 여부 | |
| | Link-Local Address 여부 | |
검색 타임아웃 설정
# 기본값: 100ms
# LUCID 카메라는 100ms 이내 응답, GigE Vision 스펙상 최대 1초
system.DEVICE_INFOS_TIMEOUT_MILLISEC = 200 # 필요시 늘릴 수 있음
device_infos = system.device_infos
-
examples/py_enumeration.py(Lines 63-81)
장치 생성 (연결)
검색된 카메라와 제어 채널을 열어 연결합니다.
모든 장치 연결
재시도 로직 포함
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("장치를 찾을 수 없습니다")
특정 장치만 연결
# 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대만
장치 선택
| NOTE |
| 첫 번째 프로세스가 읽기/쓰기 권한을 획득하며, 이후 프로세스는 읽기 전용으로 접속됩니다. |
-
examples/py_simple_acquisition.py(Lines 32-70) -
examples/py_enumeration_mac.py(Lines 38-74)
네트워크 설정
Force IP (임시 IP 할당)
장치의 IP를 임시로 변경합니다. 재부팅 시 원래 설정으로 복원됩니다.
# 단일 장치
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는 임시 설정입니다. 장치 재부팅 시 초기화됩니다. |
-
examples/py_force_ip.py(Lines 86-133)
고정 IP 설정 (영구)
장치에 영구적인 IP 주소를 설정합니다.
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 설정 관련 노드
| 노드 | 설명 | 타입 |
| | 고정 IP 주소 | Integer (IPv4를 정수로 변환) |
| | 고정 서브넷 마스크 | Integer |
| | 고정 기본 게이트웨이 | Integer |
| | 고정 IP 활성화 | Boolean |
| | DHCP 활성화 | Boolean |
| | Link-Local Address | Boolean (비활성화 불가) |
| | ARP 충돌 감지 | Boolean |
IP 설정 우선순위
| 우선순위 | 조건 | 적용 방식 |
| 1 | 고정 IP + DHCP 모두 활성화 | 고정 IP 사용 |
| 2 | 고정 IP만 활성화 | 고정 IP 사용 |
| 3 | DHCP만 활성화 | DHCP로 할당 |
| 4 | 모두 비활성화 | LLA 자동 사용 (폴백) |
-
examples/py_ipconfig_manual.py(Lines 28-74)
유니캐스트 검색 (다른 서브넷)
브로드캐스트가 도달하지 않는 다른 서브넷의 카메라를 검색합니다.
# 유니캐스트 대상 추가
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)
스트림 설정
이미지를 수신하기 전에 스트림 관련 설정을 구성합니다.
tl_stream = device.tl_stream_nodemap
# 패킷 크기 자동 협상 (권장)
tl_stream['StreamAutoNegotiatePacketSize'].value = True
# 패킷 재전송 활성화 (UDP 손실 복구)
tl_stream['StreamPacketResendEnable'].value = True
# 버퍼 핸들링 모드 설정
tl_stream['StreamBufferHandlingMode'].value = 'NewestOnly'
스트림 설정 노드:
| 노드 | 설명 | 권장값 |
| | 최대 안전 패킷 크기 자동 협상 | |
| | 손실된 UDP 패킷 재전송 요청 | |
| | 버퍼 처리 방식 | |
-
examples/py_simple_acquisition.py(Lines 72-79) -
examples/py_acquisition.py(Lines 59-104)
이미지 획득
# 컨텍스트 매니저 사용 (권장)
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
장치 해제 (연결 종료)
# 모든 장치 해제
system.destroy_device()
# 특정 장치만 해제
system.destroy_device(device)
# 여러 장치 선택 해제
system.destroy_device([device1, device2])
| NOTE |
| |
연결 해제 감지 (콜백)
카메라가 예기치 않게 연결 해제될 때 알림을 받을 수 있습니다.
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)
다중 장치 연결
여러 카메라를 동시에 사용하는 방법입니다.
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
전체 연결 예제 (종합)
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()
관련 예제 파일 목록
| 주제 | 파일 |
| 기본 장치 검색 | |
| MAC 주소로 검색 | |
| 유니캐스트 검색 | |
| Force IP (임시) | |
| 고정 IP 설정 (영구) | |
| 기본 이미지 획득 | |
| 상세 이미지 획득 | |
| 다중 장치 | |
| 연결 해제 콜백 | |
Exposure (노출) 제어
카메라 조도를 조절하는 가장 핵심적인 방법입니다.
| 노드 | 설명 | 비고 |
| | 자동 노출 On/Off | |
| | 수동 노출 시간 | 단위: 마이크로초(μs) |
| | 다중 노출 모드 선택 | HDR 등에서 사용 |
Example:
nodes = nodemap.get_node(['ExposureAuto', 'ExposureTime'])
nodes['ExposureAuto'].value = 'Off'
nodes['ExposureTime'].value = 4000.0 # 마이크로초
-
examples/py_exposure.py— 기본 노출 제어 -
examples/py_exposure_forhdr.py— HDR 노출 -
examples/py_exposure_long.py— 장시간 노출
Gain (게인) 제어
센서 신호를 증폭하여 이미지 밝기를 조절합니다.
| 노드 | 설명 | 값 |
| | 센서 신호 증폭 | |
Example:
-
examples/py_helios_smooth_results.py
Binning (비닝)
여러 픽셀을 하나로 합쳐 노이즈를 줄이고 밝기를 향상시키는 방식입니다.
| 노드 | 설명 | 비고 |
| | 비닝 대상 선택 | |
| | 합칠 행(Row) 수 | 정수값 |
| | 합칠 열(Column) 수 | 정수값 |
| | 수직 비닝 모드 | |
| | 수평 비닝 모드 | |
| NOTE |
| |
-
examples/py_acquisition_sensor_binning.py
LUT (Look Up Table)
입력 밝기 값을 출력 밝기 값으로 매핑하여 감마, 대비 등을 세밀하게 조절합니다.
| 노드 | 설명 | 비고 |
| | LUT 활성화/비활성화 | |
| | 입력 강도 인덱스 | 0 ~ 최대값 |
| | 해당 인덱스의 출력 강도 값 | 매핑 결과값 |
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
프레임 레이트 제어
프레임 레이트를 낮추면 더 긴 노출 시간을 확보할 수 있어, 간접적으로 조도에 영향을 줍니다.
| 노드 | 설명 | 비고 |
| | 프레임 레이트 제어 활성화 | |
| | 프레임 레이트 설정 | 단위: fps |
-
examples/py_exposure_long.py
픽셀 결함 보정
죽은 픽셀(Dead Pixel)이나 고정 픽셀(Stuck Pixel)을 보정합니다.
| 노드 | 설명 | 타입 |
| | 결함 보정 활성화 | Boolean |
| | 보정된 픽셀 수 | Integer (읽기 전용) |
| | 보정 항목 인덱스 | Integer |
| | 보정 대상 X 좌표 | Integer |
| | 보정 대상 Y 좌표 | Integer |
| | 새 결함 픽셀 추가 | Command |
| | 보정 목록 적용 | Command |
| | 보정 정보를 카메라에 저장 | Command |
| | 보정 목록에서 제거 | Command |
-
examples/py_pixel_correction.py
3D 카메라 전용 파라미터 (Helios/HLT)
Helios 시리즈 등 3D 카메라에서 사용할 수 있는 추가 조절 옵션입니다.
| 노드 | 설명 | 비고 |
| | 다중 프레임 누적 | 밝기 및 SNR 향상 |
| | 공간 필터링 활성화 | 노이즈 감소 |
| | 신뢰도 필터링 활성화 | 저품질 데이터 제거 |
-
examples/py_helios_smooth_results.py
공통 사용 패턴
모든 노드는 값 설정 전에 쓰기 가능 여부와 허용 범위를 확인하는 것이 권장됩니다.
# 노드 값 설정 전 범위 확인
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()
조도 조절 방법 요약
| 방법 | 직접/간접 | 효과 | 부작용 |
| ExposureTime 증가 | 직접 | 밝기 증가 | 모션 블러 발생 가능 |
| ConversionGain 증가 | 직접 | 밝기 증가 | 노이즈 증가 |
| Binning (Sum 모드) | 직접 | 밝기 증가 | 해상도 감소 |
| LUT 조절 | 직접 | 밝기/대비 커스터마이징 | 다이나믹 레인지 손실 가능 |
| 프레임 레이트 감소 | 간접 | 더 긴 노출 시간 확보 | 초당 프레임 수 감소 |
| Scan3dImageAccumulation | 직접 (3D 전용) | SNR 및 밝기 향상 | 촬영 시간 증가 |
공통 인터페이스 참고 사항
- 대부분의 노드는
.min,.max속성으로 유효 범위를 확인할 수 있습니다. -
.is_readable,.is_writable속성으로 읽기/쓰기 가능 여부를 확인할 수 있습니다. - 열거형 노드는
.enumentry_names로 사용 가능한 값 목록을 확인할 수 있습니다. - Float/Integer 노드는
.inc속성으로 증분 단위를 확인할 수 있습니다.
See also
- LUCID Vision Labs
- ROS2
- GigE Vision
- Machine Vision
- Machine Vision Camera
- Pylon (Python)
- 바슬러 (Basler)
- FLIR
- 카메라 설정
- 이미지 처리
- CCTV