비전→SPOT - zero1ne-26/doc GitHub Wiki
기준일: 2026-10-05
위치 메시지
Vision → Spot 으로 발행하는 토픽입니다. 사람과 스팟의 최신 월드 좌표를 같은 발행 시각으로 묶어 1초마다 발행합니다.
| Topic | 주기 | 설명 |
|---|---|---|
cctv/sync/pose |
1초 | 사람 + 스팟의 위치·방향 |
{
"timestamp": 1789732503.04,
"person": { "session_id": "abc123", "x": 12.3, "y": 45.6, "measured_at": 1789732502.71 },
"spot": { "x": 149.4, "y": -11.6, "yaw": 155.4, "conf": 0.845, "stable": true, "measured_at": 1789732502.93 }
}
| 필드 | 타입 | 설명 |
|---|---|---|
timestamp |
number | 발행 시각 (Unix epoch 초). |
person |
object/null | 세션 주체. 세션이 없거나 1초 이상 안 보이면 null |
person.x, person.y |
number | 좌표계 기준 위치, cm |
spot |
object/null | 스팟. 1초 이상 안 보이면 null |
spot.x, spot.y |
number | 좌표계 기준 위치, cm. 카메라 4대 평균 측정값 |
spot.yaw |
number/null | 방향(도). +X축 방향이 0°, 반시계(CCW) 양수, 0~360. 방향 판정 불가 시 null |
spot.conf |
number | 검출 confidence (0~1) |
spot.stable |
bool | false 면 가림 등으로 방향이 불안정 |
person.measured_at, spot.measured_at |
number | 각 값이 실제로 측정된 시각 (Unix epoch 초). |
- yaw 는 나침반 방위각이 아니라 수학 표준(atan2) 입니다!
- 스팟 위치는 카메라별 측정(바운딩박스 바닥 중심의 바닥 투영)을 평균한 값, 방향은 신뢰도 가중 원형 평균입니다.
- stable 여부를 함께 보내드리는데요. 가림 등으로 방향이 불안정하다면 stable=false로 나갑니다. 이 값은 신뢰하지 않는다던가 하는 로직을 넣으시면 좋을 것 같습니다.
- 사람 추적, spot 추적이 서로 다른 파이프라인에서 돌아가서 둘의 측정 시간이 다릅니다. timestamp 기준 가장 최근에 관측된 값으로 보내드리는데, 사람과 spot의 위치 결과가 완전히 equal 하지 않습니다! 그래서 measured_at도 같이 보내드립니다. 참고 부탁드려요.
좌표계 정의
| 항목 | 값 |
|---|---|
| 단위 · 평면 | cm, 바닥 평면 (z = 0) |
| 원점 (0, 0) | 바닥 마커 10번의 정중앙 |
| +X 방향 | 마커 10 → 마커 13 → 11 |
| +Y 방향 | 마커 10 → 마커 5 → 1 |
| 마커 | AprilTag 36h11, 한 변 15 cm |
| 카메라 55 | (271.2, -148.8), 높이 280 cm |
| 카메라 56 | (-90.5, -213.1), 높이 280 cm |
| 카메라 57 | (583.9, 423.5), 높이 260 cm |
| 카메라 58 | (70.5, 437.5), 높이 270 cm |
지도
![월드 좌표 지도]
구역 꼭짓점
home (집)
X -165.2 ~ 293.1, Y -303.5 ~ 3.0, 약 13.6 m²
| # | X (cm) | Y (cm) |
|---|---|---|
| 1 | 288.5 | 1.6 |
| 2 | -154.0 | 3.0 |
| 3 | -165.2 | -303.5 |
| 4 | 293.1 | -297.7 |
mart (마트)
X -160.4 ~ 250.5, Y 286.1 ~ 548.7, 약 9.8 m²
| # | X (cm) | Y (cm) |
|---|---|---|
| 1 | -160.4 | 548.7 |
| 2 | 250.5 | 527.4 |
| 3 | 249.2 | 286.1 |
| 4 | -150.0 | 305.6 |
park (공원)
X 401.6 ~ 660.5, Y 188.6 ~ 525.9, 약 8.1 m²
| # | X (cm) | Y (cm) |
|---|---|---|
| 1 | 401.6 | 188.6 |
| 2 | 401.7 | 493.0 |
| 3 | 660.5 | 525.9 |
| 4 | 656.9 | 197.6 |
vehicle (차량)
X 344.6 ~ 610.9, Y -114.2 ~ 128.0, 약 3.2 m²
| # | X (cm) | Y (cm) |
|---|---|---|
| 1 | 610.9 | -14.2 |
| 2 | 471.7 | 128.0 |
| 3 | 344.6 | -4.5 |
| 4 | 453.7 | -114.2 |
정렬용 마커 좌표 (정중앙)
| 마커 | X (cm) | Y (cm) |
|---|---|---|
| 1 | 0.0 | 340.0 |
| 2 | 150.0 | 340.0 |
| 3 | 300.0 | 340.0 |
| 4 | 450.0 | 340.0 |
| 5 | 0.0 | 170.0 |
| 6 | 150.0 | 170.0 |
| 7 | 300.0 | 170.0 |
| 8 | 450.0 | 170.0 |
| 10 | 0.0 | 0.0 |
| 11 | 300.0 | 0.0 |
| 13 | 150.0 | 0.0 |
JSON
위 표와 동일한 값입니다.
{
"frame": {
"unit": "cm",
"plane": "floor z=0",
"origin": "center of floor marker 10 (AprilTag 36h11)",
"x_axis": "marker 10 -> marker 13 -> 11",
"y_axis": "marker 10 -> marker 5 -> 1",
"handedness": "right-handed, z up"
},
"zones": {
"home": [
[
288.5,
1.6
],
[
-154.0,
3.0
],
[
-165.2,
-303.5
],
[
293.1,
-297.7
]
],
"mart": [
[
-160.4,
548.7
],
[
250.5,
527.4
],
[
249.2,
286.1
],
[
-150.0,
305.6
]
],
"park": [
[
401.6,
188.6
],
[
401.7,
493.0
],
[
660.5,
525.9
],
[
656.9,
197.6
]
],
"vehicle": [
[
610.9,
-14.2
],
[
471.7,
128.0
],
[
344.6,
-4.5
],
[
453.7,
-114.2
]
]
},
"marker_centers": {
"1": [
0.0,
340.0
],
"2": [
150.0,
340.0
],
"3": [
300.0,
340.0
],
"4": [
450.0,
340.0
],
"5": [
0.0,
170.0
],
"6": [
150.0,
170.0
],
"7": [
300.0,
170.0
],
"8": [
450.0,
170.0
],
"10": [
0.0,
0.0
],
"11": [
300.0,
0.0
],
"13": [
150.0,
0.0
]
},
"cameras": {
"55": {
"x": 271.2,
"y": -148.8,
"height": 280.4
},
"56": {
"x": -90.5,
"y": -213.1,
"height": 280.0
},
"57": {
"x": 583.9,
"y": 423.5,
"height": 259.8
},
"58": {
"x": 70.5,
"y": 437.5,
"height": 270.2
}
}
}