0. 왜 구동 방식부터 잡고 가야 할까?
모바일 로봇은 겉보기엔 단순합니다. 속도 값을 넣으면 움직이니까요.
그런데 조금만 깊게 들어가면, 같은 속도 명령이더라도 섀시 구조에 따라 “해석”이 완전히 달라집니다.
- 어떤 로봇은 조향각이 먼저 정해지고 추진력이 따라옵니다.
- 어떤 로봇은 바퀴 네 개를 조합해서 옆으로도 움직입니다.
- 어떤 로봇은 회전할 때 미끄러짐을 피하려고 설계되고,
- 어떤 로봇은 회전할 때 미끄러짐이 어느 정도 전제인 구조도 있습니다.
그래서 이 챕터에서는 “구동 방식별로 속도가 어떻게 바퀴/서보로 변환되는지”를 한 번에 정리해둡니다.
이걸 알고 있으면, 나중에 주행이 이상해질 때도 어디를 먼저 확인할지 감이 생길 가능성이 큽니다.
1. 큰 그림: 결국은 “목표 속도 → 액추에이터 명령” 변환입니다
상위(키보드/조이스틱/네비게이션)가 로봇에 주는 목표는 보통 아래 3가지로 정리됩니다.
- 전진/후진 속도: vxv_x
- 좌/우(측면) 속도: vyv_y
- 회전 속도: ω\omega 또는 vωv_\omega
구동 방식의 차이는 이 세 값을 “바퀴/트랙/조향각”으로 바꾸는 운동학(kinematics)이 다르다는 뜻입니다.

2. 구동 방식별 “성격” 먼저 잡아보기
공식부터 보면 머리가 아프니까, 먼저 성격을 정리해두는 게 좋습니다.
- Ackermann: 자동차처럼 “조향”이 따로 있고, 추진은 보통 후륜에서 만듭니다.
- Mecanum/Omni: 바퀴 구조로 vyv_y가 살아 있어서 전방향 이동이 가능합니다.
- Tank/Skid: 좌/우 트랙(또는 바퀴 묶음) 속도 차로 회전합니다.
- Differential: 좌/우 바퀴 속도만으로 직진/회전을 만듭니다.

3. Ackermann Steering 분석 (Ch04-01)
3-1. 하드웨어 구조: 전륜 조향 + 후륜 구동
Ackermann 섀시는 크게 두 블록으로 나뉩니다.
- 전륜 조향 메커니즘: 서보 → 링키지 → 전륜 바퀴 조향
- 후륜 구동: 모터 → 후륜 바퀴 회전(전진/후진/속도)
여기서 중요한 포인트는, 회전할 때 전륜은 “같은 각도로 꺾이기”보다
내측 전륜이 더 크게 꺾이는 구조가 자연스럽다는 점입니다.
그래야 회전 중 타이어 슬립이 줄어듭니다.

3-2. Pure Rolling 가정과 회전 중심(COR)
Ackermann 기구의 이상적인 목표는 Pure Rolling입니다.
네 바퀴가 슬립 없이 굴러가면서, 모두 같은 회전 중심(Center of Rotation)을 공유하는 상태입니다.
조건을 말로 풀면 아래처럼 정리됩니다.
- 각 바퀴의 진행 방향에 대한 **수직선(법선)**을 그렸을 때,
- 그 선들이 한 점에서 교차해야 합니다.
- 그 점이 회전 중심(COR)입니다.
그리고 모델을 단순화할 때는 전륜을 “가상 휠” 하나로 놓고 계산하는 경우가 많습니다.
3-3. 운동학 공식(제공 내용 기반)
각속도 일관성
ω=VR=VLRL=VRRR\omega=\frac{V}{R}=\frac{V_L}{R_L}=\frac{V_R}{R_R}
- ω\omega: 차체 각속도
- VV: 차체 선속도
- RR: 차체 회전 반경
- VL,VRV_L, V_R: 좌/우(후륜) 속도
- RL,RRR_L, R_R: 좌/우 회전 반경
조향각과 회전 반경
tanθ=HR,RL=R−D2,RR=R+D2\tan \theta=\frac{H}{R} \quad,\quad R_L=R-\frac{D}{2} \quad,\quad R_R=R+\frac{D}{2}
- θ\theta: 조향각
- HH: 축간 거리(wheelbase)
- DD: 윤거(track width)
좌/우 바퀴 속도
VL=ω(R−D2),VR=ω(R+D2)V_L=\omega \left(R-\frac{D}{2}\right), \quad V_R=\omega \left(R+\frac{D}{2}\right)
정리하면 “조향각이 주어지면 회전 반경이 정해지고, 그로부터 좌/우 바퀴 속도가 갈라진다”가 핵심입니다.

4. Holonomic / Omni Drive 분석 (Ch04-02)
4-1. 전방향 이동이 가능한 이유
메카넘/옴니는 바퀴 둘레에 롤러가 달려 있고, 롤러의 배치 때문에 추진력이 분해됩니다.
그 결과 “앞으로 가는 힘” 말고도 “옆으로 미는 힘” 성분이 생깁니다.
- 메카넘: 롤러 축이 보통 45도
- 옴니: 측면 자유도를 주는 구조
즉, 바퀴 회전 속도를 조합하면 vx,vy,ωv_x, v_y, \omega를 동시에 만들 수 있습니다.

4-2. 메카넘 운동학(제공 내용 기반)
파라미터:
- VxV_x: 전/후
- VyV_y: 좌/우
- VωV_\omega: 회전
- LL: 좌/우 휠 중심 간 거리
- HH: 전/후 휠 중심 간 거리
최종 식(제공 내용):
[VAVBVCVD]=[1−1−L+H211L+H211−L+H21−1L+H2][VxVyVω]\begin{bmatrix} V_A \\[6pt] V_B \\[6pt] V_C \\[6pt] V_D \end{bmatrix} = \begin{bmatrix} 1 & -1 & -\dfrac{L+H}{2} \\ 1 & 1 & \dfrac{L+H}{2} \\ 1 & 1 & -\dfrac{L+H}{2} \\ 1 & -1 & \dfrac{L+H}{2} \end{bmatrix} \begin{bmatrix} V_x \\[6pt] V_y \\[6pt] V_\omega \end{bmatrix}
이 식을 직관적으로 보면:
- VxV_x: 모든 바퀴에 “같은 방향” 성분
- VyV_y: 좌우 이동을 위해 바퀴마다 부호가 갈림
- VωV_\omega: 회전을 위해 대각선 패턴으로 들어감

5. Tank(궤도) 구동 분석 (Ch04-03)
Tank는 구조적으로 “좌/우 트랙”이 차체를 끌고 갑니다.
구동 스프로킷이 트랙을 당기고, 로드 휠이 하중을 지지하며, 아이들러가 궤도 이탈을 방지하는 형태입니다.
운동학은 두 속도로 정리됩니다.
- BB: 좌/우 트랙 간 거리
- VL,VRV_L, V_R: 좌/우 트랙 속도
순운동학(속도 계산)
Vx=VR+VL2,Vω=VR−VLBV_x=\frac{V_R+V_L}{2}, \quad V_\omega=\frac{V_R-V_L}{B}
역운동학(명령 생성)
VL=Vx−B2Vω,VR=Vx+B2VωV_L = V_x-\frac{B}{2}V_\omega,\quad V_R = V_x+\frac{B}{2}V_\omega

6. Differential Drive / Skid Steering 분석 (Ch04-04)
6-1. Differential Drive
Differential은 좌/우 바퀴 두 개(그리고 보조 캐스터 휠)로 구성되는 경우가 많습니다.
구조가 단순해서 “기본형”으로 많이 등장합니다.
파라미터:
- LL: 좌/우 바퀴 간 거리
- vl,vrv_l, v_r: 좌/우 바퀴 선속도
순운동학
vx=vr+vl2,ω=vr−vlLv_x=\frac{v_r+v_l}{2}, \quad \omega=\frac{v_r-v_l}{L}
역운동학
vr=vx+L2ω,vl=vx−L2ωv_r=v_x+\frac{L}{2}\omega, \quad v_l=v_x-\frac{L}{2}\omega

6-2. Skid Steering
Skid는 탱크처럼 좌/우를 묶어서 돌리되, 바퀴가 여러 개일 수 있고, 회전 시 슬립을 허용하는 구조입니다.
이상적인 모델은 Differential과 유사하지만, 실제 주행에서는 바닥 마찰과 슬립이 개입할 수 있습니다.
제공된 정리처럼, “좌측 앞/뒤, 우측 앞/뒤 속도”를 평균 내서 표현할 수 있습니다.
Vx=VLf+VLr+VRf+VRr4V_x=\frac{V_{Lf}+V_{Lr}+V_{Rf}+V_{Rr}}{4} Vω=(VRf+VRr)−(VLf+VLr)BV_\omega=\frac{(V_{Rf}+V_{Rr})-(V_{Lf}+V_{Lr})}{B}
또는 좌측을 VLV_L, 우측을 VRV_R로 묶으면:
Vx=VR+VL2,Vω=VR−VLBV_x=\frac{V_R+V_L}{2}, \quad V_\omega=\frac{V_R-V_L}{B}
7. 속도제어 코드 분석: 수식이 실제로 어떻게 구현되는지
여기부터는 “공식이 실제 제어 메시지로 바뀌는 지점”이라서 한 번 꼼꼼히 보는 게 좋습니다.
7-1. Ackermann 구현 코드 해석
구현 위치:
- ros2_ws/src/driver/controller/controller/ackermann.py
(1) 파라미터 초기화
- HH에 해당하는 wheelbase
- DD에 해당하는 track_width
- RPS 변환에 필요한 wheel_diameter
이 값이 실제 기구와 어긋나면 “모델이 맞는데도” 궤적이 어긋나는 일이 생길 수 있습니다.
(2) 속도 변환: m/s → rps
바퀴 둘레 C=πDC = \pi D 이므로:
RPS=VπDRPS=\frac{V}{\pi D}
(3) set_velocity: 조향각 + 모터 속도 메시지 생성
핵심은 이 부분입니다.
- θ=arctan(Hωv)\theta=\arctan(\frac{H\omega}{v}) 형태로 조향각을 만들고
- 조향각을 ±45°로 제한한 뒤
- PWM(중립 1500 기준)으로 선형 매핑합니다.
그리고 좌/우 바퀴 속도를 분해합니다.
마지막으로 RPS로 변환하고 메시지를 만듭니다.

7-2. Mecanum 구현 코드 해석
구현 위치:
- ros2_ws/src/driver/controller/controller/mecanum.py
핵심 계산은 아래입니다.
그리고 모터 방향 보정을 포함해 RPS로 바꿉니다.
여기서 중요한 건 “공식 자체”보다도, 부호/모터 순서가 실제 하드웨어 구성에 맞게 들어가 있다는 점입니다.
바퀴 방향이 조금만 달라져도 vyv_y 방향이 깨지는 일이 생길 수 있어서, 이 매핑은 특히 민감합니다.

8. 자주 헷갈리는 지점
여기서부터는 “공식은 맞는데 동작이 이상하다”에서 자주 튀어나오는 것들입니다.
- 섀시 타입이 맞는가? (Ackermann/Mecanum/Diff/Skid)
- 좌표계 정의가 일관적인가? (x 전방, y 좌측, ω\omega 반시계 +)
- wheelbase / track_width / wheel_diameter 값이 실제와 크게 다르지 않은가?
- 메카넘은*바퀴 배치(롤러 방향)가 올바른 조합인가?
- 메카넘은 모터 부호/순서 매핑이 맞는가?
- Ackermann은 조향 중립/오프셋이 맞는가? (직진에서 쏠림 체크)
- Skid/Tank는 바닥/하중에 따라 회전이 과하게 미끄러질 수 있는가?
한 줄로 정리하면, “모델”보다 먼저 확인할 게 생각보다 많습니다.
특히 부호/순서/치수는 한번만 어긋나도 궤적이 이상해질 수 있습니다.
'Side Project > ROS2 & LLM Autonomous Robot' 카테고리의 다른 글
| [최종 프로젝트] ROS2 기반 RGB-D 객체 탐지 VLM 서비스 로봇 (0) | 2026.03.10 |
|---|---|
| ROS 2 디버깅 (0) | 2026.02.11 |
| MentorPi 개발 환경 구성하기 (0) | 2026.01.29 |