Laplacian Robotics
경력근거: 고객사 물류창고, 공장 현장에 Laplacian 플랫폼(Control Plane, Robot OS 등)을 직접 배포 및 안착합니다
※ 실제 산출물이 아닌 AI 예측 시안입니다.
라플라시안 로보틱스는 완전 자율 물류창고와 공장을 목표로 Control Plane 과 Robot OS 를 고객사 현장에 직접 올려 안착시키는 초기 팀이고, 이 자리는 계약 이후에도 현장에 남아 WMS 와 WES 를 연동하고 반복 수작업을 대시보드로 옮기는 사람을 뽑습니다. 안착 첫 주에 현장이 가장 먼저 묻는 것은 플랫폼이 얼마나 정교한가가 아니라 오늘 나갈 오더를 어느 장비에 붙여도 되는가이고, 그 판단이 지금은 반장 머릿속에 있습니다. 기종이 섞인 fleet 과 구역마다 다른 통로 폭은 고객사 창고에 실제로 들어가야 보이는 조건이라 다른 회사 데이터로는 같은 표가 나오지 않습니다. 이 포트폴리오는 현장 조건을 규칙으로 옮겨 오더와 장비를 맞추는 기술을 보여줍니다. 로봇 제어나 경로 계획, 창고 자동화 설비 전문성은 주장하지 않습니다. 그 너머는 면접에서 모른다고 답하는 편이 서로에게 낫습니다.
공고가 고객사 물류창고와 공장에 플랫폼을 직접 올려 안착시키는 일을 첫 업무로 적었습니다. 안착 첫 주에 현장이 바로 쓰는 화면을 산출물로 잡았습니다.
현장 시스템 연동과 커스텀 통합이 업무로 적혀 있고, 모호한 요구를 기술 스펙으로 옮기는 일이 그 앞에 놓입니다. WMS 오더를 받아 장비 사양과 맞추는 일이 그 두 가지가 만나는 자리입니다.
반복 수작업을 스크립트와 대시보드로 옮기고 배포된 장비의 가동시간과 신뢰성을 추적하라고 적혀 있습니다. 사람 머릿속에 있던 배정 규칙을 화면으로 옮기는 일이 그 첫 걸음입니다.
고객사 창고에서 그날 아침 WMS 가 뱉은 출하 오더와, 현장에 세워 둔 장비의 사양과 잔량, 구역별 통로 폭과 바닥, 충전기까지의 거리를 한 화면에 올려 오더 하나하나가 붙어 있는 장비로 실제로 나갈 수 있는지 정하는 관리자 페이지입니다. 파렛트 무게를 적재 한도와 견주고, 파렛트 규격이 그 기종이 받는 목록에 있는지 보고, 오더가 놓인 통로 폭이 기종이 돌아 나올 최소 폭에 드는지 보고, 집을 선반 높이가 마스트가 닿는 높이 안인지 보고, 마감까지 돌다 충전기까지 돌아갈 잔량이 남는지 계산합니다. 막힌 오더는 사유별로 묶이고 각 줄에는 대신 붙일 장비 번호가 따라붙어, 현장 운영자가 그 자리에서 오더를 옮깁니다.
고객사 창고에서 그날 나갈 WMS 오더를 현장 장비에 나눠 붙이는 현장 운영자 — 기종과 사양이 섞여 있어 어떤 오더를 어떤 장비가 집을 수 있는지가 사람 머릿속에만 있고, 한 대라도 잘못 붙이면 통로가 막힌다
장비가 집을 수 있는 무게와 파렛트 규격, 돌아 나올 통로 폭, 마스트가 닿는 높이는 기종 사양서에 숫자로 적혀 있고, 통로 폭과 충전기 거리는 현장 도면에 이미 있습니다. 그래서 오더 한 줄과 이 두 표를 맞춰 보는 계산만 붙이면, 배정이 통로에서 멈춘 뒤가 아니라 오더가 나가기 전에 갈라진다는 가정입니다.
WMS 오더 표와 장비 목록, 구역 지도를 올리면 오더마다 여섯 판정 중 하나를 정하고 마감까지 남은 시간과 필요한 잔량을 붙여 사유별로 묶어 보여주는 관리자 페이지입니다. 오더 표는 공개된 WMS 내보내기 양식으로 지원자가 직접 만들어 넣고, 장비 사양은 공개된 지게차·AMR 사양서 값을 옮겨 적습니다.
출하 오더 412건에 현장 반장이 손으로 매긴 정답 배정을 붙여 자동 판정과 대조해 사유별 일치율과 어긋난 오더의 목록을 내고, 장비마다 그날 몇 건을 받아 몇 분을 도는지 가동 표로 함께 보여주는 단계입니다.
같은 사유가 몰린 통로와 기종을 찾아 오더를 어느 장비로 옮기면 그날 출하가 가장 적게 밀리는지 순서를 내고, 사람 픽으로 넘길 오더를 따로 모아 반장이 아침 회의에 그대로 올리는 목록으로 붙이는 단계입니다.
현장 운영자가 WMS 오더 표와 장비 목록, 구역 지도를 올리면 막히는 배정이 사유별로 묶여 화면에 나오는 과정을 시연합니다.
출하 오더 412건에 반장이 손으로 매긴 정답 배정을 붙여 대조하고 사유별 일치율을 냅니다. 단, 정답과 오더를 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
입력 30종을 일부러 흐트러뜨려 돌립니다. 무게가 안 적힌 오더와 지도에 없는 통로, 사양서에 없는 기종 번호가 섞여도 화면이 그대로 서고, 견줄 값이 없어 건너뛴 조건은 hedge 한 줄로 남습니다.
장비 한 대를 점검으로 돌렸을 때 대체 장비를 못 찾는 오더가 몇 건 늘어나는지 회귀로 확인합니다.
성능 이야기는 여기서 끊습니다. 위 수치는 제가 만든 오더를 제가 채점한 값이고, 출하 지연이 실제로 줄었는지는 라플라시안이 안착시킨 고객사 창고의 실 오더와 실 가동 기록을 넣어야 나옵니다. 그 대조를 첫날 바로 돌릴 수 있게 평가 러너와 정답 서식까지 붙여 둡니다.
화면에 뜨는 판정과 수치는 제가 만든 오더를 제가 채점한 값이라 성능 증명이 아닙니다. 면접에서는 데모가 도는 범위와, 고객사 실 오더로 검증할 준비가 어디까지 됐는지를 그대로 말합니다.
규칙을 짠 사람이 정답 배정도 붙였으니 일치율이 높게 나오는 것은 당연합니다. 무게가 빈 오더와 바닥에서 그대로 집는 오더, 어느 기종도 닿지 않는 높이를 데이터에 심어 두어 쉬운 오더만 통과시키는 화면이 되지 않게 했습니다.
이 포트폴리오는 현장 조건을 규칙으로 옮겨 오더와 장비를 맞추는 기술을 보여줍니다. 로봇 제어나 경로 계획, 창고 자동화 설비 전문성은 주장하지 않습니다. 판정은 숫자 비교와 목록 대조가 하고 모델은 목록에 뜨는 문장만 맡습니다.
필요한 잔량은 분당 소모율과 분당 이동거리를 사양서 값 그대로 쓴 계산이라 짐 무게와 바닥 상태에 따라 현장에서 달라집니다. 그래서 잔량 부족은 확정이 아니라 반장이 열어 볼 후보로 냅니다.
실제 도입 때는 기종이 늘고 통로 배치가 바뀌므로, 장비 사양표와 구역 지도를 고객사 설비 담당과 이어서 갱신하는 일을 운영 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
고객사 창고에서 그날 아침 WMS 가 뱉은 출하 오더입니다. 오더 번호와 품목, 파렛트 무게, 파렛트 규격, 오더가 놓인 통로, 집을 선반 높이, 마감 시각, 오더가 내려온 시각, 아침에 붙여 둔 장비 번호를 한 줄에 둡니다. 지원자는 공개된 WMS 내보내기 양식으로 이 표를 스스로 만듭니다. 검량이 안 돼 무게 칸이 비어 있는 줄과 바닥에서 그대로 집어 높이가 0 인 줄, 어느 기종도 닿지 않는 높이의 줄을 일부러 섞어 판정이 갈리게 둡니다.
| order_id | sku | weight_kg | pallet_type | aisle_id | pick_height_cm | due_at | released_at | planned_machine_id |
|---|---|---|---|---|---|---|---|---|
| SO-20418 | SKU-88214 | 1,180 | EUR2 | A3 | 210 | 2026-09-08T12:00:00 | 2026-09-08T09:00:00 | M-03 |
| SO-20422 | SKU-30117 | 420 | EUR1 | A1 | 180 | 2026-09-08T11:30:00 | 2026-09-08T09:00:00 | M-01 |
| SO-20431 | SKU-51260 | 640 | GMA | A5 | 320 | 2026-09-08T11:00:00 | 2026-09-08T09:00:00 | M-01 |
| SO-20455 | SKU-77043 | 380 | EUR1 | A7 | 150 | 2026-09-08T11:45:00 | 2026-09-08T09:00:00 | M-01 |
| SO-20472 | SKU-24988 | 520 | EUR2 | B2 | 620 | 2026-09-08T12:30:00 | 2026-09-08T09:00:00 | M-09 |
아래 JSON Schema 를 그대로 만족하는 출하 오더 행을 400개 더 만들어 주세요. 오더 번호는 SO- 뒤에 다섯 자리를 붙이고 품목은 SKU- 뒤에 다섯 자리를 붙입니다. weight_kg 는 80 에서 1900 사이로 흩되 스무 줄쯤은 비웁니다. pallet_type 은 EUR1 을 절반쯤 두고 나머지를 EUR2·GMA·CP3 으로 나눕니다. aisle_id 는 구역 지도에 있는 통로에서 고르되 지도에 없는 통로도 열 줄쯤 넣습니다. pick_height_cm 은 0 에서 700 사이로 두고 몇 줄은 0 으로 둡니다. released_at 은 오전 9시 앞뒤로 흩고 due_at 은 그보다 60분에서 300분 뒤로 둡니다. planned_machine_id 는 장비 목록에서 고르되 사양서에 없는 번호도 몇 줄 넣습니다. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: 무게가 비어 있는 줄, 집을 높이가 0 인 줄, 어느 기종의 마스트 높이보다도 높은 줄, 마감이 내려온 시각보다 앞선 줄. 형식을 깨뜨리는 시도 10건은 데이터가 아니라 별도 파일로 두고 화면이 그 줄만 이슈로 세우는지 봅니다.
{"type": "object", "properties": {"order_id": {"type": "string"}, "sku": {"type": "string"}, "weight_kg": {"type": ["number", "null"], "minimum": 0}, "pallet_type": {"type": "string", "enum": ["EUR1", "EUR2", "GMA", "CP3"]}, "aisle_id": {"type": "string"}, "pick_height_cm": {"type": "integer", "minimum": 0, "maximum": 900}, "due_at": {"type": "string"}, "released_at": {"type": "string"}, "planned_machine_id": {"type": "string"}}, "required": ["order_id", "sku", "weight_kg", "pallet_type", "aisle_id", "pick_height_cm", "due_at", "released_at", "planned_machine_id"]}{"type": "object", "properties": {"order_id": {"type": "string"}, "sku": {"type": "string"}, "weight_kg": {"type": ["number", "null"], "minimum": 0}, "pallet_type": {"type": "string", "enum": ["EUR1", "EUR2", "GMA", "CP3"]}, "aisle_id": {"type": "string"}, "pick_height_cm": {"type": "integer", "minimum": 0, "maximum": 900}, "due_at": {"type": "string"}, "released_at": {"type": "string"}, "planned_machine_id": {"type": "string"}}, "required": ["order_id", "sku", "weight_kg", "pallet_type", "aisle_id", "pick_height_cm", "due_at", "released_at", "planned_machine_id"]}현장에 세워 둔 장비 목록입니다. 장비 번호와 적재 한도, 받는 파렛트 규격, 돌아 나올 최소 통로 폭, 마스트가 닿는 높이, 남은 잔량, 지금 상태, 분당 소모율, 분당 이동거리를 한 줄로 둡니다. 지원자는 공개된 지게차와 AMR 사양서 값을 그대로 옮겨 적어 이 표를 만듭니다. 적재 한도와 지원 파렛트 목록이 이 표에만 있어야 오더 쪽에서 판정이 도출됩니다.
| machine_id | payload_kg | supported_pallets | min_aisle_width_cm | max_lift_height_cm | battery_pct | status | drain_pct_per_min | travel_m_per_min |
|---|---|---|---|---|---|---|---|---|
| M-01 | 1,200 | EUR1|EUR2 | 150 | 550 | 82 | 가동 | 0.14 | 65 |
| M-02 | 1,500 | EUR1|EUR2|GMA | 150 | 600 | 74 | 가동 | 0.15 | 60 |
| M-03 | 1,000 | EUR1|GMA | 140 | 500 | 91 | 가동 | 0.13 | 70 |
| M-04 | 1,300 | EUR1|EUR2 | 145 | 560 | 18 | 가동 | 0.2 | 60 |
| M-05 | 900 | EUR1 | 120 | 480 | 66 | 가동 | 0.12 | 75 |
아래 JSON Schema 를 그대로 만족하는 장비 행을 30개 더 만들어 주세요. 장비 번호는 M- 뒤에 두 자리를 붙입니다. payload_kg 는 600 에서 2000 사이, min_aisle_width_cm 은 110 에서 170 사이, max_lift_height_cm 은 400 에서 620 사이로 두고 기종마다 서로 다르게 흩습니다. supported_pallets 는 EUR1·EUR2·GMA·CP3 을 세로줄로 이어 한 개에서 네 개까지 적습니다. battery_pct 는 5 에서 100 사이로 두고 몇 대는 100 으로 둡니다. status 는 대부분 가동으로 두고 점검과 충전을 몇 대 섞습니다. drain_pct_per_min 은 0.1 에서 0.25 사이, travel_m_per_min 은 50 에서 90 사이로 둡니다.
{"type": "object", "properties": {"machine_id": {"type": "string"}, "payload_kg": {"type": "number", "minimum": 0}, "supported_pallets": {"type": "string"}, "min_aisle_width_cm": {"type": "integer", "minimum": 0}, "max_lift_height_cm": {"type": "integer", "minimum": 0}, "battery_pct": {"type": "integer", "minimum": 0, "maximum": 100}, "status": {"type": "string", "enum": ["가동", "점검", "충전"]}, "drain_pct_per_min": {"type": "number", "minimum": 0}, "travel_m_per_min": {"type": "number", "minimum": 1}}, "required": ["machine_id", "payload_kg", "supported_pallets", "min_aisle_width_cm", "max_lift_height_cm", "battery_pct", "status", "drain_pct_per_min", "travel_m_per_min"]}{"type": "object", "properties": {"machine_id": {"type": "string"}, "payload_kg": {"type": "number", "minimum": 0}, "supported_pallets": {"type": "string"}, "min_aisle_width_cm": {"type": "integer", "minimum": 0}, "max_lift_height_cm": {"type": "integer", "minimum": 0}, "battery_pct": {"type": "integer", "minimum": 0, "maximum": 100}, "status": {"type": "string", "enum": ["가동", "점검", "충전"]}, "drain_pct_per_min": {"type": "number", "minimum": 0}, "travel_m_per_min": {"type": "number", "minimum": 1}}, "required": ["machine_id", "payload_kg", "supported_pallets", "min_aisle_width_cm", "max_lift_height_cm", "battery_pct", "status", "drain_pct_per_min", "travel_m_per_min"]}창고 구역 지도입니다. 통로마다 실측 폭과 바닥 종류, 가장 가까운 충전기까지의 거리를 한 줄로 둡니다. 지원자는 물류창고 설계 사무소와 지자체가 인허가 자료로 공개해 둔 창고 평면도에서 통로 폭과 바닥 마감을 재어 옮기고, 충전기까지의 거리는 그 도면 위에서 통로 끝까지를 축척으로 환산해 채워 이 표를 만듭니다. 실제 현장 값이 아니라 모양만 같은 값이라는 사실을 화면 아래 고지에 함께 적습니다. 통로 폭은 이 표에만 있어 오더가 놓인 통로와 장비 최소 폭을 견주는 판정이 여기서 도출되고, 충전기 거리는 필요한 잔량을 내는 계산에 들어갑니다.
| aisle_id | width_cm | floor_type | charger_distance_m |
|---|---|---|---|
| A1 | 175 | 콘크리트 | 40 |
| A3 | 168 | 콘크리트 | 55 |
| A5 | 152 | 에폭시 | 70 |
| A7 | 138 | 콘크리트 | 65 |
| A9 | 122 | 에폭시 | 90 |
아래 JSON Schema 를 그대로 만족하는 구역 행을 30개 더 만들어 주세요. 통로 번호는 A·B·C 구역에 홀수 번호를 붙여 적습니다. width_cm 은 110 에서 200 사이로 흩되 좁은 통로를 삼분의 일쯤 두어 진입이 갈리게 합니다. floor_type 은 콘크리트를 절반쯤 두고 에폭시와 그레이팅을 섞습니다. charger_distance_m 은 20 에서 150 사이로 두고 충전기에서 먼 통로를 몇 줄 넣어 잔량 판정이 갈리게 합니다.
{"type": "object", "properties": {"aisle_id": {"type": "string"}, "width_cm": {"type": "integer", "minimum": 0}, "floor_type": {"type": "string", "enum": ["콘크리트", "에폭시", "그레이팅"]}, "charger_distance_m": {"type": "integer", "minimum": 0}}, "required": ["aisle_id", "width_cm", "floor_type", "charger_distance_m"]}{"type": "object", "properties": {"aisle_id": {"type": "string"}, "width_cm": {"type": "integer", "minimum": 0}, "floor_type": {"type": "string", "enum": ["콘크리트", "에폭시", "그레이팅"]}, "charger_distance_m": {"type": "integer", "minimum": 0}}, "required": ["aisle_id", "width_cm", "floor_type", "charger_distance_m"]}| Python | 오더와 장비 사양, 구역 지도를 맞춰 오더마다 막힌 사유를 정하고 대체 장비를 고르는 판정 엔진을 맡습니다. |
| TypeScript | 사유별로 묶은 목록과 오더 하나를 펼쳐 보는 상세, 대체 장비 칸을 그리는 화면 코드를 맡습니다. |
| Next.js | 현장 사무실 노트북에서 바로 여는 관리자 페이지를 띄우고, 오더 표를 올리는 화면을 붙입니다. |
| WMS/WES | 그날 출하 오더를 내보내기 파일로 받아 오는 통로로 씁니다. 연동 규격이 고객사마다 달라 열 이름 맞추기를 어댑터로 분리합니다. |
| Claude | 막힌 사유와 대체 장비를 현장 운영자가 목록에서 한 줄로 읽을 문장으로 줄이는 데 씁니다. |
✗ fail → 사양이 없는 기종이나 지도에 없는 통로가 절반을 넘으면 고객사 설비 담당에게 받아 먼저 채웁니다.
✓ pass → 2주차 정답 배정 대조로 넘어갑니다.
✗ fail → 어긋난 오더를 모아 사유 우선순위와 잔량 산식의 계수를 다시 봅니다.
✓ pass → 3주차 옮길 순서 계산으로 넘어갑니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
dispatch_verdict사유 라벨 · order_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
배정 가능배정 가능적재 한도 초과적재 초과다루지 못하는 파렛트파렛트 불가통로 폭 미달통로 폭 미달선반 높이 밖높이 밖마감까지 잔량 부족잔량 부족오더 하나마다 붙어 있는 장비로 실제로 나갈 수 있는지 정합니다. 막히면 적재·파렛트·통로 폭·선반 높이·잔량 중 어느 쪽인지 싣고, 마감까지 남은 시간과 필요한 잔량, 대신 붙일 장비 번호를 함께 냅니다. 화면은 이 사유를 기준으로 줄을 나눕니다.
{"type": "object", "properties": {"verdict_no": {"type": "string"}, "order_id": {"type": "string"}, "planned_machine_id": {"type": "string"}, "dispatch_verdict": {"type": "string", "enum": ["배정 가능", "적재 한도 초과", "다루지 못하는 파렛트", "통로 폭 미달", "선반 높이 밖", "마감까지 잔량 부족"]}, "alternative_machine_id": {"type": ["string", "null"], "description": "dispatch_verdict 가 배정 가능이 아닐 때만 채웁니다. status 가 가동인 장비에서 붙어 있던 장비를 뺀 뒤 장비 번호 오름차순으로 훑어, 적재 한도·파렛트 규격·통로 폭·마스트 높이·잔량 다섯 조건을 모두 통과하는 첫 장비입니다. 통과하는 장비가 없거나 판정이 배정 가능이면 비웁니다."}, "minutes_to_due": {"type": ["integer", "null"], "minimum": 0, "description": "due_at 에서 released_at 을 뺀 분 수입니다."}, "required_battery_pct": {"type": ["number", "null"], "minimum": 0, "description": "minutes_to_due 에 charger_distance_m 를 travel_m_per_min 으로 나눈 분 수를 더하고 drain_pct_per_min 을 곱해 소수 둘째 자리까지 남긴 잔량입니다. 마감까지 계속 움직이고 충전기까지 돌아가는 데 드는 몫입니다."}, "evidence": {"type": "array", "items": {"type": "object", "properties": {"field": {"type": "string"}, "agg": {"type": ["string", "null"]}, "value": {}}, "required": ["field", "value"]}}, "summary": {"type": "string"}, "hedge": {"type": ["string", "null"]}}, "required": ["verdict_no", "order_id", "planned_machine_id", "dispatch_verdict", "evidence", "summary"]}[
{
"verdict_no": "DV-001",
"order_id": "SO-20422",
"planned_machine_id": "M-01",
"dispatch_verdict": "배정 가능",
"alternative_machine_id": null,
"minutes_to_due": 150,
"required_battery_pct": 21.09,
"evidence": [
{
"field": "weight_kg",
"agg": null,
"value": 420
},
{
"field": "payload_kg",
"agg": null,
"value": 1200
},
{
"field": "width_cm",
"agg": null,
"value": 175
},
{
"field": "min_aisle_width_cm",
"agg": null,
"value": 150
},
{
"field": "battery_pct",
"agg": null,
"value": 82
}
],
"summary": "무게와 파렛트, 통로 폭, 선반 높이가 모두 M-01 사양 안에 들고 잔량도 필요한 몫의 네 배라 이 배정 그대로 내보냅니다.",
"hedge": null
},
{
"verdict_no": "DV-002",
"order_id": "SO-20524",
"planned_machine_id": "M-09",
"dispatch_verdict": "배정 가능",
"alternative_machine_id": null,
"minutes_to_due": 225,
"required_battery_pct": 36.11,
"evidence": [
{
"field": "pick_height_cm",
"agg": null,
"value": 0
},
{
"field": "max_lift_height_cm",
"agg": null,
"value": 580
},
{
"field": "weight_kg",
"agg": null,
"value": 1450
},
{
"field": "payload_kg",
"agg": null,
"value": 1600
},
{
"field": "battery_pct",
"agg": null,
"value": 88
}
],
"summary": "바닥에서 그대로 집는 오더라 높이가 걸리지 않고 1,450킬로그램도 M-09 적재 한도 안에 들어 배정이 섭니다.",
"hedge": "높이가 0 으로 적힌 줄은 바닥 픽이라는 뜻이라 높이 검사를 건너뛰었습니다."
},
{
"verdict_no": "DV-003",
"order_id": "SO-20418",
"planned_machine_id": "M-03",
"dispatch_verdict": "적재 한도 초과",
"alternative_machine_id": "M-01",
"minutes_to_due": 180,
"required_battery_pct": 23.5,
"evidence": [
{
"field": "weight_kg",
"agg": null,
"value": 1180
},
{
"field": "payload_kg",
"agg": null,
"value": 1000
}
],
"summary": "1,180킬로그램짜리 파렛트를 적재 한도가 1,000킬로그램인 M-03 에 붙여 두어 그대로 내보내면 통로에서 멈춥니다.",
"hedge": "M-01 로 옮기면 적재 한도와 파렛트, 통로 폭, 마스트 높이, 잔량이 함께 통과합니다."
},
{
"verdict_no": "DV-004",
"order_id": "SO-20431",
"planned_machine_id": "M-01",
"dispatch_verdict": "다루지 못하는 파렛트",
"alternative_machine_id": "M-02",
"minutes_to_due": 120,
"required_battery_pct": 16.95,
"evidence": [
{
"field": "pallet_type",
"agg": null,
"value": "GMA"
},
{
"field": "supported_pallets",
"agg": null,
"value": "EUR1|EUR2"
}
],
"summary": "GMA 파렛트인데 M-01 은 EUR1 과 EUR2 만 받는 포크 간격이라 집는 순간 파렛트가 어긋납니다.",
"hedge": null
},
{
"verdict_no": "DV-005",
"order_id": "SO-20455",
"planned_machine_id": "M-01",
"dispatch_verdict": "통로 폭 미달",
"alternative_machine_id": "M-05",
"minutes_to_due": 165,
"required_battery_pct": 23.24,
"evidence": [
{
"field": "width_cm",
"agg": null,
"value": 138
},
{
"field": "min_aisle_width_cm",
"agg": null,
"value": 150
}
],
"summary": "A7 통로가 138센티미터인데 M-01 은 150센티미터가 있어야 돌아 나올 수 있어 그 자리에서 막힙니다.",
"hedge": null
},
{
"verdict_no": "DV-006",
"order_id": "SO-20472",
"planned_machine_id": "M-09",
"dispatch_verdict": "선반 높이 밖",
"alternative_machine_id": null,
"minutes_to_due": 210,
"required_battery_pct": 33.72,
"evidence": [
{
"field": "pick_height_cm",
"agg": null,
"value": 620
},
{
"field": "max_lift_height_cm",
"agg": null,
"value": 580
}
],
"summary": "620센티미터 선반은 M-09 가 올릴 수 있는 580센티미터를 넘고 다른 기종도 600센티미터에서 멈춰 사람 픽으로 넘깁니다.",
"hedge": "가동 상태인 여덟 대 어디에도 대신 붙일 장비가 없어 대체 칸을 비웠습니다."
},
{
"verdict_no": "DV-007",
"order_id": "SO-20503",
"planned_machine_id": "M-04",
"dispatch_verdict": "마감까지 잔량 부족",
"alternative_machine_id": "M-01",
"minutes_to_due": 140,
"required_battery_pct": 28.15,
"evidence": [
{
"field": "battery_pct",
"agg": null,
"value": 18
},
{
"field": "drain_pct_per_min",
"agg": null,
"value": 0.2
},
{
"field": "charger_distance_m",
"agg": null,
"value": 45
},
{
"field": "travel_m_per_min",
"agg": null,
"value": 60
},
{
"field": "due_at",
"agg": null,
"value": "2026-09-08T11:20:00"
},
{
"field": "released_at",
"agg": null,
"value": "2026-09-08T09:00:00"
}
],
"summary": "마감까지 140분을 돌고 충전기까지 45미터를 더 가려면 28퍼센트가 드는데 M-04 에는 18퍼센트만 남아 중간에 선 채로 통로를 막습니다.",
"hedge": null
},
{
"verdict_no": "DV-008",
"order_id": "SO-20517",
"planned_machine_id": "M-05",
"dispatch_verdict": "통로 폭 미달",
"alternative_machine_id": null,
"minutes_to_due": 135,
"required_battery_pct": 16.4,
"evidence": [
{
"field": "width_cm",
"agg": null,
"value": 118
},
{
"field": "min_aisle_width_cm",
"agg": null,
"value": 120
},
{
"field": "weight_kg",
"agg": null,
"value": null
}
],
"summary": "C3 통로가 118센티미터라 M-05 가 요구하는 120센티미터에 두 센티미터 못 미쳐 진입 자체가 안 됩니다.",
"hedge": "무게 칸이 비어 있어 적재 검사는 건너뛰었고, 통로 폭이 120센티미터 아래인 가동 장비가 없어 대체 칸도 비웠습니다."
}
][자동 검증 · 코드가 판정합니다] 1. dispatch_verdict 가 enum 여섯 값 중 하나인지 확인합니다. 2. verdict_no·order_id·planned_machine_id·dispatch_verdict·evidence·summary 가 모두 채워졌는지 확인합니다. 3. order_id 가 오더 목록에 실재하는 번호인지, planned_machine_id 와 alternative_machine_id 가 장비 목록에 실재하는 번호인지 대조합니다. 4. weight_kg 가 planned_machine_id 의 payload_kg 보다 크면 dispatch_verdict 가 적재 한도 초과인지 확인합니다. 다만 weight_kg 가 비어 있으면 이 조건은 건너뛰고 그 사실을 hedge 에 적습니다. 5. pallet_type 이 supported_pallets 를 세로줄로 나눈 목록에 없으면 dispatch_verdict 가 다루지 못하는 파렛트인지 확인합니다. 6. aisle_id 로 짝지은 width_cm 이 min_aisle_width_cm 보다 작으면 dispatch_verdict 가 통로 폭 미달인지 확인하고, floor_type 이 그레이팅인 구역은 목록에서 따로 묶어 보여줍니다. 7. pick_height_cm 이 max_lift_height_cm 보다 크면 dispatch_verdict 가 선반 높이 밖인지 확인합니다. 8. minutes_to_due 를 due_at 에서 released_at 을 빼 다시 계산하고, required_battery_pct 를 minutes_to_due 에 charger_distance_m 를 travel_m_per_min 으로 나눈 분 수를 더해 drain_pct_per_min 을 곱하는 산식으로 다시 계산합니다. battery_pct 가 그 값보다 작으면 dispatch_verdict 가 마감까지 잔량 부족인지 확인합니다. 9. dispatch_verdict 가 배정 가능이면 위 다섯 조건 어디에도 안 걸리는지 다시 확인하고, 사유가 둘 이상 걸리면 적재·파렛트·통로·높이·잔량 순으로 앞선 것을 세웁니다. 10. alternative_machine_id 는 dispatch_verdict 가 배정 가능이 아닐 때만 채웁니다. 붙어 있던 장비가 이미 나갈 수 있는 줄에는 대체를 세우지 않으므로 배정 가능이면 이 칸은 비어 있어야 합니다. 막힌 줄에서는 status 가 가동인 장비에서 planned_machine_id 를 뺀 뒤 장비 번호 오름차순으로 훑어 4~8번의 다섯 조건을 모두 통과하는 첫 번호를 세우고, 통과하는 장비가 없으면 비웁니다. 가장 가깝거나 가장 덜 바쁜 장비를 고르는 것이 현장 감각에 가깝지만 그러려면 장비 위치와 그날 배정 현황이 입력에 있어야 해서, 1주차는 번호 차례로 고르고 그 선택 규칙을 화면에도 적어 둡니다. 11. evidence 의 field 이름이 오더 목록·장비 목록·구역 지도에 실재하는 컬럼인지 대조합니다. 12. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 13. weight_kg 가 비어 있거나 대체 장비가 하나도 없으면 그 사실이 hedge 에 적혔는지 확인합니다. 14. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 출하 오더 412건에 현장 반장이 손으로 매긴 정답 배정을 붙여 자동 판정과 대조하고, 사유별 일치율과 어긋난 오더의 목록을 냅니다. [수동 검증 · 사람이 봅니다] 1. 막힌 오더를 사람 픽으로 넘길지 다음 파동으로 미룰지는 현장 운영자가 목록을 보고 정합니다. 2. 장비 사양과 구역 지도가 실제 현장과 같은지는 도입 첫 주에 고객사 설비 담당과 맞춰 갱신합니다.
근거: 고객사 물류창고, 공장 현장에 Laplacian 플랫폼(Control Plane, Robot OS 등)을 직접 배포 및 안착합니다