← BlogAMR 내비게이션 입문· 4/12

Inflation이 뭔가 — 로봇을 '점'으로 만들기 위해 장애물을 부풀린다

장애물 주변에 cost 그라데이션을 둘러 로봇 반경을 보상하는 inflation의 원리. 로봇을 '점'으로 다루기 위한 트릭과, 이기종 플릿에서 단일 반경이 만드는 한계.

약 3분
Nav2inflationcostmaprobot-radiusAMR

Inflation이 뭔가

경로 계획기는 로봇을 점(point) 으로 다룹니다. 그래야 "셀 → 인접 셀" 그래프 위에서 최단 경로를 빠르게 풀 수 있으니까요. 그런데 실제 로봇은 점이 아니라 폭을 가진 물체입니다. 이 모순을 우아하게 해결하는 것이 inflation(팽창) 입니다.

로봇 크기를 장애물 쪽으로 옮긴다

아이디어는 단순합니다. 로봇이 폭을 가진 만큼, 장애물을 그만큼 부풀린다. 그러면 부풀린 장애물에 점-로봇이 닿지만 않으면, 실제 로봇은 진짜 장애물에 닿지 않습니다.

도식 렌더링 중…

inflation layer는 lethal 셀(장애물) 주위로 동심원처럼 cost를 깔되, 거리가 멀어질수록 지수적으로 감쇠시킵니다.

거리:   0     r_robot         inflation_radius
cost:  254 →  ~중간 cost  →  0
        (lethal)  (들어가면 위험)   (자유)
  • inscribed(내접) 반경 안 = 로봇 중심이 들어가면 무조건 충돌 → 사실상 lethal
  • 그 바깥 ~ inflation_radius = 들어갈 수는 있지만 비쌈(cost↑) → 계획기가 가급적 피함
  • inflation_radius 밖 = cost 0, 자유 공간

이 규칙을 의사코드로 적으면 한눈에 들어옵니다 — 각 자유 셀의 cost는 가장 가까운 장애물까지의 거리 하나로 정해집니다.

LETHAL = 254  # 사실상 충돌

def inflation_cost(distance, robot_radius, inflation_radius, decay=3.0):
    # distance = 이 셀에서 가장 가까운 장애물까지의 거리
    if distance <= robot_radius:          # ① 내접 반경 안
        return LETHAL                     #    → 무조건 충돌
    if distance <= inflation_radius:      # ② 부풀린 영역 안
        # 멀어질수록 지수적으로 감쇠
        return round((LETHAL - 1) * exp(-decay * (distance - robot_radius)))
    return 0                              # ③ 그 바깥 = 자유 공간

distance는 보통 거리 변환(distance transform)으로 모든 셀에 대해 한 번에 구합니다. 핵심은 — cost가 "거리의 함수" 라는 것. 그래서 장애물에서 멀어질수록 매끄럽게 0으로 떨어지는 동심원 그라데이션이 나옵니다.

점유 격자(좌, 벽=검정)를 inflation_radius=1.2m로 부풀린 costmap(우). 장애물 주위로 cost가 동심원처럼 감쇠하고(시안→흰색), 경로 계획기는 cost가 낮은 통로 한가운데(주황 경로)로 길을 낸다.점유 격자(좌, 벽=검정)를 inflation_radius=1.2m로 부풀린 costmap(우). 장애물 주위로 cost가 동심원처럼 감쇠하고(시안→흰색), 경로 계획기는 cost가 낮은 통로 한가운데(주황 경로)로 길을 낸다.

이 그라데이션 덕분에 로봇은 벽에 바짝 붙는 위험한 경로 대신, 통로 한가운데로 여유 있게 지나가는 경로를 자연스럽게 선택합니다. 위 그림의 주황 경로가 바로 그 결과입니다 — 저 cost 골짜기를 따라 흐릅니다.

실제 시뮬레이션 — Clearpath AMR이 창고 통로를 주행하는 모습. 위에서 설명한 occupancy grid·costmap·inflation이 합쳐져 이런 주행이 나온다.

반경은 어디서 오나 — 그리고 이기종 플릿의 한계

inflation_radius는 로봇 반경(robot radius)에 여유 계수를 곱해 정합니다 (우리는 보통 반경 × 1.5 를 씁니다). 로봇 반경은 각 로봇의 명세(manifest)에서 읽어옵니다 — 작은 AMR과 큰 운반 로봇은 당연히 다른 값이어야 하니까요.

그런데 여기서 다중 로봇의 한계가 드러납니다.

도식 렌더링 중…

여러 종류의 로봇(예: 소형 AMR + 대형 Husky)이 하나의 costmap을 공유하면, inflation 반경도 하나뿐입니다. 큰 로봇 기준으로 크게 잡으면 작은 로봇이 충분히 지나갈 좁은 통로가 "막힌 것"으로 보여 멈춥니다(stuck). 작은 로봇 기준으로 작게 잡으면 큰 로봇이 벽을 긁습니다. 실제로 이기종 플릿에서 큰 로봇이 좁은 통로에서 멈추는 현상을 겪었고, 근본 원인은 inflation이 로봇별로 분리되지 않은 것이었습니다.

이건 inflation을 "너무 크게 vs 너무 작게"의 트레이드오프로 보여주는 좋은 예입니다 — 정답은 로봇별 footprint를 분리하는 것이고, 단일 costmap 공유는 동질 플릿에서만 안전합니다.

한 줄 정리

📌 Inflation = 로봇의 폭만큼 장애물을 부풀려, 경로 계획기가 로봇을 '점'으로 다루게 하는 트릭. 반경은 로봇 명세에서 오고, inflation_radius = robot_radius × 1.5가 흔한 기본값이다. 단, 한 costmap에 반경은 하나뿐이라 이기종 플릿에선 로봇별 footprint 분리가 필요하다.