바퀴 로봇이 정해진 경로를 따라가게 만들 때 가장 먼저 정해야 하는 값이 look-ahead 거리예요. 경로 위에서 지금 위치보다 얼마나 앞선 지점을 목표로 삼을지의 거리인데, 이 값 하나로 주행 품질이 크게 달라져요.
감으로 정하면 근거가 남지 않으니 값만 바꾸고 나머지를 고정한 통제 실험으로 설계했어요. 작을수록 정밀해지지도, 클수록 안정되지도 않는 U자가 나왔어요.
전방의 한 점만 좇는 제어
경로 추종에 쓰는 방법은 크게 셋이에요. 기하로 푸는 Pure Pursuit, 앞바퀴 기준의 횡오차와 헤딩오차를 함께 줄이는 Stanley, 미래 구간을 예측해 최적화로 푸는 MPC예요. 이번에 쓴 건 첫 번째고, 고른 이유는 튜닝 파라미터가 look-ahead 거리 하나로 압축되기 때문이에요. 값 하나만 움직이면 통제 실험이 그대로 성립해요.
동작은 단순해요. 로봇 앞쪽 경로 위에 목표점 하나를 잡고, 현재 위치에서 그 점을 지나는 원호를 그린 뒤 그 곡률만큼 조향해요. 목표점이 계속 앞으로 밀려나므로 로봇은 영원히 닿지 않는 점을 좇게 되고, 그 결과로 경로를 따라가요.
곡률을 계산한다고 하지만 실질은 cross-track error, 즉 경로와의 횡방향 거리에 대한 비례 제어에 가까워요. 목표점이 옆으로 벌어질수록 원호가 급해지고 조향이 세지니까요. Nav2의 기본 컨트롤러인 Regulated Pure Pursuit도 같은 계열이라, 여기서 익힌 감각이 그대로 이어져요.
값을 바꿔가며 오차를 재요
한 변 1미터 사각 경로를 5센티미터 간격으로 조밀화하고, 매 제어 주기마다 현재 위치에서 가장 가까운 경로점까지의 거리를 cross-track error 표본으로 모았어요. 주행 조건은 난수 시드를 고정해 슬립 4%, 회전 오차 ±6%가 매 시행 동일하게 재현되도록 했고요.
| look-ahead | 이탈 RMS | 최대 | 완주 시간 | 판정 |
|---|---|---|---|---|
| 0.10 m | 14.3 cm | 17.9 cm | 68.5 초 | 진동 |
| 0.15 m | 7.0 cm | 11.9 cm | 39.2 초 | 개선 |
| 0.20 m | 4.0 cm | 8.3 cm | 28.4 초 | 최적 |
| 0.30 m | 9.3 cm | 18.5 cm | 41.2 초 | 코너 절삭 |
0.20미터에서 오차와 시간이 동시에 최소예요. 0.10에서 0.20으로 옮기면 RMS가 72% 줄고, 거기서 0.30으로 더 키우면 다시 2.3배로 늘어요.
왜 U자가 되는지
너무 가까운 점을 좇으면 조향이 과해져요. 목표점이 코앞이라 조금만 벗어나도 원호의 곡률이 커지고, 그 조향이 다시 반대쪽 이탈을 만들면서 경로 주변을 지그재그로 진동해요. 0.10미터에서 완주 시간이 최적의 2.4배로 늘어난 게 그 흔적이에요. 같은 거리를 가는데 훨씬 많이 꺾었다는 뜻이니까요.
반대로 목표점이 너무 멀면 코너에서 안쪽을 크게 잘라요. 로봇 입장에서는 저 멀리 있는 점을 향해 직선에 가깝게 가는 셈이라, 그 사이의 굽은 경로를 무시하게 돼요.
실험 환경이 만든 오차 셋
측정값이 시행마다 널뛰어서 원인을 좁히는 데 시간이 더 걸렸어요. 잡고 보니 알고리즘이 아니라 실험 환경 쪽 문제가 대부분이었어요.
로봇이 경로를 거꾸로 감
시작 헤딩이 79도로 고정됨
/odom을 계속 발행. 새 시행의 추종기가 옛 로봇의 자세를 읽고 있었어요도메인을 나눴더니 노드끼리 서로를 못 찾음
ROS_DOMAIN_ID는 0~101만 안전해요. 그 위 값은 DDS가 계산한 포트가 운영체제의 임의 할당 범위와 겹쳐요셋 다 알고리즘을 한 줄도 안 건드렸는데 측정값이 달라졌어요. 통제 실험은 값을 재기 전에 무엇이 고정돼 있는지부터 재야 성립해요.
실물에서는 회전이 측정되지 않았어요
같은 실험을 실제 로봇에서 먼저 시도했는데, 추종기가 제자리 회전만 반복했어요. 로그를 보니 원인이 분명했어요.
기준 yaw -1338.8도
회전 H80 (헤딩오차 +80도, yaw -3도)
회전 H64 (헤딩오차 +64도, yaw -4도)정지 상태에서 누적 yaw가 1338도까지 폭주해 있고, 80도 회전 명령을 보내도 yaw는 1도씩 드리프트만 해요. 로봇은 실제로 도는데 자이로가 그 회전을 반영하지 못하니, 추종기 입장에서는 “아직 방향이 안 맞았다”는 판단이 계속 유지되고 같은 명령을 무한히 내보내게 돼요.
회전 방향 부호를 뒤집어도 증상이 같았던 게 단서였어요. 부호 문제라면 반대로 바꿨을 때 달라져야 하니까요.
남는 기준
파라미터 하나를 정하는 일이 왜 실험 설계 문제가 되는지가 이번의 요점이에요. 0.20이라는 값 자체는 이 경로에서만 쓰는 숫자고, 옮겨 갈 수 있는 건 경로 곡률 대비 비율로 잡는다와 RMS·최대·시간을 함께 본다는 절차예요. 셋 중 하나만 보면 진동하는 주행도 정밀해 보일 수 있어요.
실물 검증은 센서를 복구한 뒤로 미루고, 그 사이 알고리즘과 실험 절차는 시뮬레이터에서 완결시켰어요. 하드웨어가 막혀 있어도 진행할 수 있는 부분을 분리해 두면 시간을 덜 잃어요.
같은 스크립트로 실물에서 다시 돌려 시뮬레이터와 오차를 나란히 놓는 것이 다음 차례예요. 그 대조표가 나오면 파라미터 하나를 왜 그 값으로 정했는지, 그리고 시뮬과 실물이 어디서 갈라지는지를 같은 지표로 말할 수 있게 돼요. joint_states와 robot_description, 그리고 서보 두 점 캘리브레이션에서 만든 오도메트리가 여기서 위치 피드백으로 쓰여요.