photoneo_vision
로봇 측에서 Photoneo Bin Picking Studio(BPS) 1.11.0의 통신 프로토콜
(TCP/IP, 바이너리)에 접속해 Bin Picking 작업(초기화/스캔/트래젝토리 조회)과
솔루션 관리(변경/시작/중지/조회)를 수행하기 위한 Python 패키지입니다.
../MechMind/ (mechmind_vision)와 동일한 계층 구조 철학을 따르지만,
Photoneo BPS는 ASCII가 아닌 바이너리·다중 채널 프로토콜이라 세부 구현은
다릅니다 — 자세한 배경은 docs/implementation_plan.md
참고.
아키텍처
robot program
│
▼
vision/ AbstractVisionClient (ABC) ─ PhotoneoClient
│ │
▼ ▼
protocol/ codec.py (encode/decode, 순수 함수) transport/ PhotoneoTcpClient (Request-Response 채널 소켓 I/O)
messages.py (Pose, TrajectoryResponse, ...) StateServer (옵션, State Server 채널)
constants.py (Request/Message/Error 코드)
rotation.py (RotationFormalism별 Pose ↔ 4x4 변환)
protocol/: I/O 없는 순수 인코딩/디코딩 함수 + 공용 데이터 타입.transport/:PhotoneoTcpClient(Request-Response, 포트 11003, BPS=서버),StateServer(State Server 채널, 포트 11004, 로봇 컨트롤러가 서버 — 옵션, 기본 비활성화).vision/:AbstractVisionClientABC +PhotoneoClient구현체.
설치
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
설정
config/default_config.yaml을 복사해 실제 장비 IP/포트/Vision System ID에
맞게 수정하세요.
photoneo:
host: "192.168.1.1"
request_port: 11003
vision_system_id: 1
rotation_formalism: "zyx_intrinsic" # RainbowRobotics "rzyx"와 동일 포맷
brand_id_prefix: "DOOSAN/1.11.0_" # 실제 Brand ID는 Photoneo 지원팀과 확인 필요
Rotation Formalism: 이 패키지는 기본적으로 RainbowRobotics의 "rzyx"
오일러(수학적으로 ZYX_INTRINSIC과 동일 — 근거는
protocol/rotation.py 모듈
docstring)를 타깃으로 합니다. RainbowRobotics는 Photoneo가 공식 등재한
Brand ID 목록(Integrator Guide Appendix 2)에 없으므로, brand_id_prefix는
동일한 회전 포맷을 쓰는 DOOSAN/1.11.0_으로 placeholder 설정되어 있습니다 —
실기 연결 전 Photoneo 지원팀에 실제 인식 가능한 Brand ID 문자열을 확인하세요.
RotationFormalism.QUATERNION/XYZ_EXTRINSIC/ROTATION_VECTOR도 지원되므로
다른 로봇 브랜드로 전환 시 rotation_formalism/brand_id_prefix만 바꾸면
됩니다.
사용법
from photoneo_vision import PhotoneoClient, PhotoneoConfig
config = PhotoneoConfig.from_yaml("config/local_config.yaml")
with PhotoneoClient(config) as bps:
bps.initialize_vision_system(start_joints=[...], end_joints=[...]) # 4, 최초 1회
bps.scan() # 1
trajectory = bps.get_trajectory() # 2
for segment in trajectory.segments:
for wp in segment.waypoints:
print(wp.joints) # 6 joint values, degrees
for gripper in trajectory.gripper_commands:
print(gripper.action) # 1=Attach, 2=Detach, 3-5=User1-3
전체 예제:
- examples/connection_check.py — Initialize → Scan → Get Object Pose → Get Trajectory 순서로 호출하며 디코드 결과를 출력 (실기 연결 시 가장 먼저 실행할 진단 스크립트).
- examples/pick_and_place_demo.py — 전형적인 pick 루프.
- examples/solution_management_demo.py — 솔루션 조회/변경/시작/중지.
- examples/state_server_demo.py — State Server 옵션 기능 데모 (더미 관절값 콜백).
.venv/bin/python examples/connection_check.py config/local_config.yaml
State Server (옵션)
BPS 6장의 State Server 채널은 캘리브레이션/시각화 목적의 보조 채널로,
로봇 컨트롤러가 TCP 서버 역할을 하며 관절/툴포즈를 10Hz 이상 스트리밍해야
합니다. 기본적으로 비활성화되어 있으며(config.state_server.enabled=False),
활성화하려면 실제 로봇의 현재 관절값/툴포즈를 반환하는 콜백을
transport.state_server.StateServer에 연결해야 합니다:
from photoneo_vision import StateServer, Pose
from photoneo_vision.protocol.constants import pad_brand_id
def pose_provider():
return robot.get_joint_positions_deg(), robot.get_tool_pose_mm_deg() # -> (list[float], Pose)
server = StateServer(
bind_host="0.0.0.0", port=11004,
brand_id=pad_brand_id(config.brand_id_prefix),
formalism=config.rotation_formalism,
pose_provider=pose_provider,
)
server.start() # 데몬 스레드
...
server.stop()
명령/프로토콜 레퍼런스
- docs/protocol_reference.md — Request ID 표, 바이트 레이아웃, Rotation Formalism/Brand ID, mm↔m 단위 변환 규칙, 확인됨/ 미확인 표기.
- docs/implementation_plan.md — 이 패키지를 설계할 때의 배경/범위 결정 기록.
구현 범위는 8개 요청(Initialize Vision System, Scan, Get Object Pose,
Trajectory, Change/Start/Stop Solution, Get Running Solution)으로 한정되어
있습니다 — Capture/Reuse Scan/Pick Failed/Get Status/Change Bounding Box/
Calibration 4종/Communication Check는 미구현이며, protocol/constants.py의
RequestID에 참고용으로만 값이 남아 있습니다.
테스트
.venv/bin/pytest
test_codec.py는 Integrator Guide의 hex 예시를 golden vector로 사용해
바이트 단위로 인코딩/디코딩을 검증합니다. test_tcp_client.py/
test_photoneo_client.py/test_state_server.py는 로컬 fake TCP 서버를 띄워
실제 하드웨어 없이 전체 round-trip을 검증합니다.
주의: brand_id_prefix, mm/m 단위 가정(비-EXT_DEVICE 포맷), Get Object
Pose의 payload size 불일치 등은 실장비로 검증되지 않았습니다 — 실기 연결 전
반드시 docs/protocol_reference.md의 "미확인"
항목을 examples/connection_check.py로 재확인하세요.
Release files for rb-photoneo 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rb_photoneo-0.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.17+ x86-64 | Details |
| rb_photoneo-0.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.17+ ARM64 | Details |
Total release size: 5.9 MB
Release files / rb_photoneo-0.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | rb_photoneo-0.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
36e00ee5d42164004491d08bce18aebdd4c7d55f679358e728cdd6994af3c242
|
|
BLAKE2b-256 checksum How to use checksums |
532f3a5d3568cb4f22e237d26d36c5ee64c3a84fd06fd3cf7c84d0c5ff55925e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.5
|
Release files / rb_photoneo-0.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | rb_photoneo-0.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
ccd84ecb96b78d5338ca2d54e170543d44ad22ec6c273488c68f8e5ad78f6b78
|
|
BLAKE2b-256 checksum How to use checksums |
1ccb9969157100c5bca5e96f5b8bef7e1086ae5a81a33f1fdf8ff99a7d02eb5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.5
|