사람 손의 궤적을 기계로 옮기는 물리와 제어 이야기
— 위치·속도·가속도·저크, 그리고 Z축의 비대칭 설계 —
지난 글이 생각보다 반응이 좋고, 손글씨를 로봇에게 “가르친다”는 이야기가, 요즘 한창 뜨는 Physical AI(현실에서 몸을 움직이며 배우는 AI) 흐름하고도 맞아떨어졌던 것 같습니다. 그래서 한 편 더 이어가 보려고 합니다.
이번 글에서는 AI 이야기는 일부러 잠깐 접어두고, 그 밑에 깔린 기계랑 제어(control) 이야기만 다뤄보려고 합니다. 아무리 똑똑한 필체 생성 모델이 있어도, 결국 그 글씨를 종이 위에 실제로 그려내는 건 모터와 축(axis)이 하는 일이거든요. 목표는 하나입니다.
설명은 최대한 쉽게, 그런데 내용은 대충 넘어가지 않기. 조금 어려운 대목이 있어도 그러려니 하고 따라와 주시면 됩니다.
1. 사람 손은 느립니다 — 그런데 왜 매끄러울까요
우리가 글씨 쓸 때 손 속도가 얼마쯤 될까요? 대략 20–30 mm/s 정도입니다. 생각보다 느리죠. 그런데도 사람 글씨가 자연스러운 이유는 빠르기 자체가 아니라, 속도가 시간에 따라 어떻게 변하느냐에 있어요.
물론 눈으로 보면서, Real time으로, Feed Back 한다는 것도 있지만, 펜 끝의 위치를 시간으로 계속 미분해 나가면, 글씨의 운동을 지배하는 네 개의 층이 차례로 나옵니다.
각각을 정리하면 이렇습니다. 위에 찍은 점(dot)은 “시간으로 미분했다”는 뜻이에요.
아래 그림을 보면, 저크를 유한한 값으로 눌러놨을 때(이걸 흔히 S-커브라고 불러요) 이 네 층이 서로를 어떻게 쌓아 올리는지 한눈에 들어옵니다.
저크가 네모난 파형으로 켜졌다 꺼지면 가속도는 사다리꼴, 속도는 S자, 위치는 매끄러운 곡선이 되죠. 결국 우리가 손끝에서 느끼는 “부드러움”은, 수학적으로 말하면 저크가 무한대로 안 튄다는 뜻입니다.
2. 왜 저크(Jerk)까지 신경 써야 할까요
가속도까지는 그래도 직관적입니다. 뉴턴 제2법칙 그대로, 축에 필요한 힘은 가속도에 비례하고, 힘이 크면 그만큼 모터 전류랑 발열이 커지니까요.
진짜 문제는 그 다음입니다. 저크는 힘의 변화율이에요. 저크가 크다는 건 힘이 “순식간에 확” 바뀐다는 뜻이고, 이
게 바로 기계가 떠는 원인이 됩니다.
왜 그런지 숫자로 따라가 볼게요. 실제 갠트리나 펜 캐리지는 완벽한 쇳덩이가 아니라, 강성 k와 감쇠 c를 가진 살짝 휘는 구조물입니다. 이걸 가장 단순한 스프링-질량-감쇠계(1자유도)로 놓으면 방정식과 그 성질이 이렇게 나와요.
여기서 ωₙ은 이 구조물이 “울리고 싶어 하는” 고유진동수, ζ는 그 울림이 얼마나 빨리 잦아드는지를 나타내는 감쇠비예요. 위치 명령이 계단처럼 갑자기 꺾이면(저크가 확 튀면) 그 입력에는 온갖 주파수 성분이 다 섞여 들어가는데, 하필 ωₙ 근처 성분이 구조물을 때리면서 링잉(ringing), 즉 잔진동을 만듭니다. 그 울림의 크기는 이렇게 주어져요.
글씨에서는 이게 어떻게 보일까요? 획 끝이 지저분하게 떨리거나, 곧게 그은 선이 미세하게 물결칩니다. 그래서 좀 잘 만든 모션 제어는 위치 명령을 저크가 무한대로 안 튀도록 매끈하게 다듬어요. 사다리꼴 대신, 가속 구간의 시작과 끝을 둥글게 굴린 S-커브가 그겁니다. 두 방식을 나란히 놓고 보면 차이가 확실해요.
시간 면에서도 이득이 있어요. 잔진동이 잦아들어서 “이제 다음 획 그어도 되겠다” 싶은 정착 시간은 대략 이렇게 나옵니다.
저크를 눌러서 공진을 덜 건드리면 이 정착 시간이 짧아지고, 결국 “한 획 긋고 다음 획으로 넘어가기까지” 걸리는 전체 시간이 줄어듭니다. 품질이랑 속도가 서로 싸우지 않고 같이 좋아지는, 흔치 않은 지점이 바로 여기예요.
잠깐 더 깊게 — 다축에서는 왜 “텐서”가 튀어나올까요
여기까지는 축 하나(스칼라)로만 이야기했어요. 그런데 XY(또는 XYZ)가 동시에 움직이면, 관절 좌표 q와 실제 작업 공간 좌표 x 사이의 관계가 벡터 함수가 되고, 그 1차 민감도는 야코비안 행렬 J로 표현됩니다.
한 번 더 미분해서 가속도까지 가면 J가 시간에 따라 변하는 항이 새로 튀어나와요. 이 항이 코너를 돌 때 원심·코리올리 같은 성분을 만들고, “축마다 따로따로 프로파일 돌리면 왜 궤적이 뒤틀리는가”에 대한 수학적 답이 됩니다.
여기서 야코비안의 각 성분을 다시 관절 좌표로 미분하면 첨자가 세 개인 텐서가 나옵니다. 다축 로봇 운동학이 결국 “텐서의 언어”로 정리되는 이유죠. 이번 편에서는 씨앗만 심어두고, 본격적인 이야기는 다음 기회로 넘길게요.
3. 쉬어가기 — Grbl, 그리고 8비트의 미학
제어기를 밑바닥부터 직접 짜는 것도 방법이지만, 이 바닥엔 이미 사실상 표준이 된 오픈소스가 있어요. G-code를 읽어서 스텝 펄스로 바꿔주는 모션 컨트롤러 펌웨어, Grbl입니다.
재미있는 건, 앞에서 수식으로 떠들었던 저크 제한이랑 룩어헤드(look-ahead)가 이 작은 펌웨어 안에 실제로 들어 있다는 점입니다.
Grbl은 룩어헤드로 코너를 미리 내다보면서 최대 30 kHz의 깔끔한 스텝 펄스를 뽑아내요. 코너에서 속도를 얼마나 줄일지는 이런 접합 속도 규칙으로 정해집니다.
여기서 θ는 두 선분이 꺾이는 각도, δ는 허용할 접합 오차예요. 급하게 꺾일수록(θ가 작을수록) 허용 속도가 확 줄어든다는 물리가 한 줄에 담겨 있죠. 이런 계산을 빈약한 8비트 칩 위에서 실시간으로 돌렸다는 게, 개인적으로는 참 대단하다고 생각합니다.
4. 그럼 요즘 나온 ESP32 버전은 어떨까요
“8비트는 좀 옛날 아니야?” 하실 수 있어요. 맞습니다. 그래서 요즘은 32비트로 넘어간 갈래가 있는데, 대표적으로 ESP32 기반 포팅(Grbl_ESP32, 그 후속인 FluidNC)이 인기예요. Wi-Fi도 되고 RAM도 넉넉하고 코어도 둘이라, 여러모로 편합니다. 실제로 오래된 아두이노 UNO 버전보다 훨씬 빨라요.
다만 여기엔 함정이 하나 있습니다. ESP32는 스텝 펄스를 뽑는 GPIO 쪽이 STM32 같은 전용 MCU보다 약한 편이라, 아주 고속으로 밀어붙이면 이 부분에서 문제가 터질 수 있어요. STM32는 타이머 하드웨어가 핀을 직접 정확한 타이밍에 토글해 주는데, ESP32는 그런 고속 스텝 생성을 우회하는 방식(RMT 펄스 생성, 혹은 핀 수를 늘리려 I2S 시프트 레지스터)을 쓰다 보니 상한이 낮고 여유가 빠듯합니다.
막연한 이야기가 아니라, 실제로 커뮤니티에 올라온 사례들이 있어요.
정리하면 이래요. 일반적인 필기 로봇 속도라면 ESP32로도 전혀 문제없습니다. 우리가 1편에서 이야기한 사람 필기 속도가 20–30 mm/s 수준이니, 스텝 레이트로 환산해도 저 상한 근처에 갈 일이 없거든요.
하지만 마이크로스텝을 아주 잘게 쪼개거나, Z축을 극단적으로 빠르게 몰거나, 다축을 동시에 고속으로 돌리는 상황이라면 이야기가 달라집니다. 그럴 땐 STM32처럼 타이머로 핀을 직접 때리는 MCU가 확실히 안전해요. “어디까지 밀어붙일 거냐”에 따라 칩을 고르면 됩니다.
5. 직접 짜본다면 — STM32에서 저크 제한하기
그럼 STM32로 직접 짤 땐 어떤 모습일까요. 타이머 인터럽트 안에서 S-커브를 굴리는 아주 최소한의 뼈대를 하나 보여드릴게요. 핵심은 저크를 상수로 딱 고정해두고, 매 스텝 주기마다 저크 → 가속도 → 속도 → 위치 순서로 차곡차곡 적분하는 겁니다.
/* STM32 HAL 기준 — 스텝 생성 타이머 ISR에서 호출.
저크(jerk)를 유한 상수로 제한하는 3차 적분 프로파일. */
typedef struct {
float pos, vel, acc; /* 위치[mm] 속도[mm/s] 가속도[mm/s^2] */
float jerk; /* 저크 상수 [mm/s^3] */
float v_target, a_max; /* 목표 속도, 가속도 상한 */
} scurve_t;
/* dt: 스텝 주기[s] 예) 20kHz -> dt = 50e-6f */
void scurve_step(scurve_t *s, float dt) {
float dv = s->v_target - s->vel;
float j = (dv > 0.0f) ? s->jerk : -s->jerk;
/* 오버슈트 없이 멈추려면 가속도를 미리 줄여야 하는 시점 */
float dv_stop = (s->acc * s->acc) / (2.0f * s->jerk);
if (dv > 0.0f && dv <= dv_stop) j = -s->jerk;
s->acc += j * dt; /* 저크 -> 가속도 */
if (s->acc > s->a_max) s->acc = s->a_max;
if (s->acc < -s->a_max) s->acc = -s->a_max;
s->vel += s->acc * dt; /* 가속도 -> 속도 */
s->pos += s->vel * dt; /* 속도 -> 위치 */
}
짚고 갈 포인트가 셋 있어요.
첫째, jerk를 상수로 박아두면 가속도가 계단이 아니라 경사로가 되면서 곧바로 S-커브가 됩니다.
둘째, 부동소수점 연산은 FPU가 있는 Cortex-M4F 이상이면 인터럽트 안에서도 부담이 적은데, M0/M3라면 Q16.16 같은 고정소수점으로 바꿔주는 게 지터 면에서 안전해요.
셋째, 실전에서는 XY를 각각 따로 돌리기보다 경로 길이 s 하나에 대해 프로파일을 짠 뒤 각 축으로 나눠주는 편이 궤적이 덜 뒤틀립니다. 아까 텐서 이야기에서 봤던 그 J̇ 항이, 바로 축별로 따로 돌리면 왜 뒤틀리는지의 이유예요.
참고로, 전체 이동 거리 L을 가속·저크 한계 안에서 삼각 프로파일로 주파할 때 걸리는 최소 시간은 이런 스케일을 따릅니다. 거리와 시간이 세제곱근으로 묶인다는 게 저크 제한 시스템의 본질적인 성질이에요.
6. 진짜 승부처는 Z축입니다
보통은 XY 평면(글자 모양)에만 신경을 쓰는데요, 사실 출력 시간을 실제로 좌우하는 건 Z축입니다. 글씨 한 장 쓰는 동안 펜은 획과 획, 글자와 글자 사이에서 쉴 새 없이 내려갔다(Pen Down) 올라오기(Pen Up)를 반복해요.
이 왕복이 굼뜨면 그 지연이 전부 쌓입니다. 반대로 Z축을 시원하게 빠르게 움직이면, 경험상 전체 출력 시간이 30% 가까이 줄어들어요. XY를 아무리 빨리 돌려도 Z에서 매번 기다리면 말짱 도루묵이거든요.
그런데 이 Z축, Up과 Down의 요구가 정반대라는 게 재밌는 지점입니다.
먼저 짚고 갈 것 — 우리 목표는 “빠르고 예쁜 글씨”지, 사람 흉내가 아닙니다
여기서 하나 분명히 하고 갈게요. 우리가 만들려는 건 글자를 빠르고 정확하게 써내는 기계이지, 사람 손동작을 그대로 재현하는 휴머노이드가 아닙니다.
이 구분이 중요한 게, 목표를 헷갈리면 “사람처럼 손목 스냅을 주자” 같은 데 돈과 시간을 쏟게 되거든요. 우리에게 필요한 건 딱 하나, 접촉력을 안정적으로 잡으면서 왕복을 빠르게 하는 것. 그 기준으로 부품을 고르면 답이 꽤 달라집니다.
이상적으로만 따지면, Z축 힘 제어의 정답은 VCM(보이스 코일 모터, Voice Coil Motor)입니다. 스피커 원리와 같은 방식이라 전류로 힘을 직접, 아주 빠르고 정밀하게 제어할 수 있어요. 접촉력을 실시간으로 원하는 값에 맞추는 데 이만한 게 없습니다. 앞에서 이야기한 임피던스 제어를 가장 깔끔하게 구현할 수 있는 물건이죠.
문제는 돈과 시간입니다. VCM은 축당 부속만 해도 대략 50만 원, 여기에 전용 드라이버까지 직접 만들면 축당 100만 원을 훌쩍 넘깁니다. 개발 기간도 한없이 늘어질 수 있고요. 스타트업 입장에서 “이상적인 해”에 무한정 자원을 붓는 건 그 자체로 리스크예요.
그래서 저희는 이렇게 정리했습니다.
글소담 서비스( glsodam.com ) 가 잘 자리 잡으면, 그때에는 VCM 버전으로 넘어간다.
하지만 지금 단계에서는, 훨씬 싸고 검증하기 쉬운 현실적인 해법을 씁니다.
그 현실적인 해법이 스프링 장력의 정밀 조절입니다. 능동적으로 전류를 제어하는 대신, 접촉력을 결정하는 스프링 자체를 잘 고르는 거예요.
말은 단순한데, 실제로는 굵기, 길이가 서로 다른 약 40종류의 스프링을 놓고 하나하나 벤치마크를 돌렸습니다.
스프링 상수 k가 조금만 달라져도 접촉력과 완충 특성이 확 바뀌거든요. 앞의 접촉력 식을 다시 보면 왜 그런지 바로 보입니다.
Pen Up — 무조건 빠르게
펜을 떼는 동작은 이미 종이에서 떨어진 뒤라 글씨 품질에 영향을 안 줍니다. 그러니 목표는 딱 하나, 다음 획으로 넘
어가는 대기 시간을 최대한 줄이는 거예요. 여기서는 저크 제한도 좀 느슨하게 가도 괜찮습니다.
Pen Down — 힘 조절이 전부, 그래서 댐퍼가 필요합니다
내려놓는 동작은 완전히 달라요. 펜이 종이에 닿는 그 순간의 접촉력(contact force)이 획 굵기랑 잉크 번짐을 좌우하거든요. 너무 세게 찍으면 펜촉이 종이를 파거나 잉크가 뭉치고, 너무 약하면 획이 끊깁니다. 문제는 위치 제어만으로는 이 힘을 정밀하게 맞추기 어렵다는 거예요. 종이 두께나 받침대의 미세한 높낮이 차이가 전부 변수로 작용하니까요.
그래서 하강 쪽에 댐퍼(damper)를 답니다. 펜 팁을 질량 mₚ, 감쇠 c, 유효 강성 k로 놓고 보면 접촉력은 이렇게 세 조각의 합으로 나와요.
댐퍼의 감쇠항 c·ż가 닿기 직전의 하강 속도를 부드럽게 죽여서 충격을 흡수하고, 스프링항 k(z−z₀)가 위치 오차를 완만한 힘으로 바꿔줍니다. 덕분에 위치 명령이 살짝 어긋나도 힘이 폭주하지 않아요. 앞에서 스프링 20종을 벤치마크했다는 게 바로 이 k값을 최적점에 맞추는 작업이었습니다.
VCM이라면 이 k를 전류로 실시간에 바꿔주겠지만, 스프링으로도 “가장 잘 맞는 한 점”을 골라내면 웬만한 필기 조건은 충분히 커버됩니다. 이걸 제어 용어로 말하면 접촉 강성을 낮춰 컴플라이언스(compliance)를 확보하는 거고, 더 정교하게 가면(그게 바로 나중의 VCM 버전이죠) 힘을 아예 되먹이는 임피던스 제어(impedance control)로 이어집니다.
이 식이 말하는 건 “원하는 궤적 x_d에서 벗어난 만큼, 마치 가상의 질량 M·감쇠 C·강성 K가 달린 것처럼 반응해라”예요. M·C·K를 부드럽게 잡을수록, 종이라는 예측 불가한 환경에 로봇이 알아서 순응하게 됩니다. 아래 그림이 이 비대칭을 요약해 줘요.
설계 원칙 요약
맺으며 — 다음 편 예고
이번 편은 순수하게 기계랑 제어 이야기만 했어요. 위치를 미분하면 속도·가속도·저크가 나오고, 그중 저크가 공진을 통해 글씨 품질을 쥐락펴락하고, Z축의 비대칭 설계가 생산성과 품질을 동시에 좌우한다는 것까지 왔습니다. 중간에 ESP32냐 STM32냐 하는 현실적인 칩 선택 이야기도 곁들였고요.
다음 편에서는 드디어 AI 파트로 넘어갑니다. 지금까지 본 물리적 제약들(유한한 저크, 유한한 대역폭, 비대칭 Z축)을 이미 아는 상태에서, 사람 필체를 어떻게 학습하고 그걸 “기계가 실제로 낼 수 있는 궤적”으로 번역할 것이냐. Physical AI의 진짜 재미는 바로 거기, 배운 의도와 물리적으로 가능한 것이 만나는 자리에 있거든요. 다음 글에서 뵙겠습니다.
이전 목록
16.손글씨를 로봇에게 가르치는 법(1편)
15.설·어버이날·추석·연말… 카드 한 장으로 1년 매출 흐름을 타는 법
14."카드 한 장에 얼마예요?" ? 사장님이 진짜 궁금한 그 숫자
13."이거 직접 쓰신 거예요?" ? 손글씨 카드를 받은 사람들의 반응
09.나에게 맞는 카드 문구
08.택배 상자 속 ‘인쇄된 감사합니다’를 손님은 기억하지 못합니다
04.글소담 실제 제품 사진
03.글소담 활용 35선
01.글소담 Q&A
#글소담, #손편지, #손글씨, #ai손편지, #로봇손글씨, #감성손편지, #수기모사, #감사카드, #자필편지, #손글씨DM,#손글씨카드, #감사카드, #고객감사카드, #택배동봉카드, #정기배송카드, #기업감사카드, #청첩장답례카드, #감성마케팅, #고객감동, #브랜드마케팅













댓글 없음:
댓글 쓰기