S-curve 속도 프로파일
저크 제한 모션 프로파일로 소음과 진동을 줄인 부드러운 리프트 동작 구현
firmware
배경
Wally (벽면 리프트)는 가이드 레일을 따라 수직으로 움직입니다.
문제: 사다리꼴 속도 프로파일에서는 가속도가 급격하게 변합니다. 전환 지점에서 소음과 진동이 발생합니다.
목표: 반응성은 유지하면서 부드럽고 조용한 움직임 구현.
핵심 문제
사다리꼴 프로파일은 전환점에서 저크가 무한대입니다:
사다리꼴: S-curve:
___ ___
/ \ / \
/ \ / \ ← 부드러운 전환
각 지점에서 가속도가 순간적으로 변경됩니다. 기계적 충격이 발생하고, 소음과 진동으로 이어집니다.
핵심 아이디어
저크(가속도 변화율)를 제한해서 급격한 전환을 제거합니다. S-curve 프로파일은 양 끝에서 저크가 0인 연속적인 가속도를 제공합니다.
접근 방식
1) S-curve 형태를 위한 Smoothstep 함수
Hermite 보간(smoothstep)을 사용합니다:
S(t) = t² × (3 - 2t) t ∈ [0, 1]
특성:
- S(0) = 0, S(1) = 1
- S’(0) = 0, S’(1) = 0 (양 끝에서 기울기 0)
- 1차, 2차 미분 연속
2) 대칭 저크의 2단계 가속
가속 시간을 두 단계로 분할합니다:
| 단계 | 구간 | 저크 | 가속도 |
|---|---|---|---|
| 1단계 | 0 → T/2 | +J | 증가 (0 → 최대) |
| 2단계 | T/2 → T | -J | 감소 (최대 → 0) |
저크 계산식: J = 4 × (v_target - v_current) / T²
4는 대칭 S-curve의 수학적 유도에서 나옵니다. 저크 크기는 일정하고 중간점에서 부호만 바뀝니다.
3) 적분 체인: 저크 → 가속도 → 속도
매 제어 루프마다:
// 1단계: 가속도 증가
if (step < stage1) {
accel += jerk × dt;
}
// 2단계: 가속도 감소
else if (step < stage2) {
accel -= jerk × dt;
}
velocity += accel × dt;
결과: 속도가 현재 값에서 목표까지 부드러운 S-curve를 따라갑니다.
4) 모션 구간 상태 머신
STOP ←→ ACCELERATING → CONSTANT_VELOCITY → DECELERATING → STOP
각 상태:
- STOP: 속도 0, 명령 대기
- ACCELERATING: S-curve 증속
- CONSTANT_VELOCITY: 목표 속도로 정속 주행
- DECELERATING: S-curve 감속
트레이드오프
- 약간 긴 이동 시간: S-curve는 속도 대신 부드러움을 선택
- 누적 오차: 저크→가속도→속도 적분이 긴 이동에서 오차를 쌓을 수 있음
- 고정 대칭: 증속/감속 시간이 동일해서 비대칭 최적화 불가
검증
배포된 Wally 제품에서 테스트했습니다:
- A/B 비교: 같은 목표 속도와 가속 시간으로 사다리꼴 vs S-curve
- 소음 측정: 시작/정지 전환에서 딸깍 소리가 제거됨
- 진동 확인: 가속 중 가이드 레일 진동 없음
- 장기 운용: 수개월 작동 후에도 문제 없음
결과
| 지표 | 사다리꼴 | S-curve |
|---|---|---|
| 전환점 저크 | 무한대 | 제한됨 |
| 소음 | 딸깍 소리 | 조용함 |
| 진동 | 있음 | 거의 없음 |
- 동일 알고리즘, 두 플랫폼: ESP-IDF C (v1)와 ROS2 C++ (v2)
- 현장 검증: 소음 문제 없이 Wally에 배포
핵심 교훈
저크 제한 S-curve 프로파일로 사다리꼴의 기계적 충격을 제거했습니다:
- Smoothstep 함수:
t² × (3 - 2t)로 부드러운 전환 - 대칭 저크: 전반 +J, 후반 -J
- 적분 체인: 저크 → 가속도 → 속도로 연속 모션
- 결과: 조용하고 진동 없는 리프트 동작