로봇 관절 P 제어 게인을 올려도 왜 시간상수 1/Kp만큼 빨라지지 않을까: 속도 한계에서 선형 모델이 맞는 오차 범위 계산하기
정지한 목표 관절각을 P 제어로 맞출 때 교재는 시간상수가 1/Kp이고 Kp가 클수록 오차가 빨리 0으로 줄어든다고 설명한다. 그대로 읽으면 게인을 5배 올린 관절은 5배 빨리 도착해야 한다. 그런데 최대 속도가 2 rad/s인 관절을 1 rad 떨어진 목표로 보내는 설명용 예제에서 Kp를 2에서 10으로 올리면, 오차가 처음의 2%로 줄어드는 시간은 1.956초에서 0.630초가 된다. 약 3.1배다. 로봇 관절 P 제어 게인을 올려도 시간상수 1/Kp만큼 빨라지지 않는 까닭은 명령 속도가 관절 최대 속도를 넘는 동안에는 시간상수가 응답을 설명하지 못하고, 그 구간이 오차가 vmax/Kp까지 줄어들어야 끝나기 때문이다.
판단에 쓰는 수는 두 개다. 첫 명령 속도 Kp×e0을 관절 최대 속도 vmax와 비교하면 포화가 생기는지 알 수 있고, 경계 오차 vmax/Kp를 구하면 시간상수 설명을 어느 오차부터 믿어도 되는지 정해진다. rad, rad/s, 초 단위와 나눗셈이면 따라올 수 있다. 오차에 비례해 관절 속도를 명령하는 식 θ̇ = Kp·e는 아래에서 다시 풀어 쓰고, 자연로그 ln은 2% 도달 시간을 구하는 한 절에서만 쓴다.
숫자의 근거는 Northwestern 대학의 Modern Robotics 강의 자료와, 2026년 9월 26일 Python 3.12.3에서 돌린 산술 검산·수치 계산이다. 로봇이나 물리 엔진, 모터 드라이버를 움직인 실험은 없다. 2 rad/s와 Kp 값들도 특정 로봇의 사양이나 권장 게인이 아닌 설명용 숫자다.
시간상수는 오차가 약 37%로 줄어드는 시간이다
오차(error)는 목표 각도 θd와 현재 각도 θ의 차이이며 θe = θd − θ로 쓴다(Modern Robotics 11.2.1). 0 rad에 멈춰 있는 관절을 1 rad으로 보내려 하면 처음 오차는 1 rad이다.
비례 제어(proportional control, P 제어)는 이 오차에 비례 게인(proportional gain) Kp를 곱한 값을 명령으로 쓴다. Modern Robotics 11.3 Part 1은 관절에 힘이나 토크 대신 속도를 직접 명령한다고 가정한다. 관절마다 붙은 로컬 제어기가 요청받은 속도를 실제로 낸다고 믿을 수 있을 때 성립하는 가정이다. 그래서 명령은 θ̇ = Kp·θe, 즉 관절 속도 = Kp × 오차가 되고, 안정적으로 수렴하려면 Kp는 양수여야 한다.
단위를 먼저 맞춰 두면 뒤가 쉬워진다. 오차(rad)에 Kp를 곱해 속도(rad/s)가 나오므로 Kp의 단위는 1/s다. 따라서 1/Kp는 초이고, 뒤에서 쓸 vmax/Kp는 (rad/s)÷(1/s) = rad, 곧 각도다.
목표가 한 자리에 멈춰 있는 경우를 설정값 제어(setpoint control)라고 한다. 목표가 움직이지 않으면 오차가 줄어드는 속도는 관절 속도 그 자체이므로 θ̇e = −Kp·θe가 된다. 오차가 클 때는 빨리, 작아질수록 천천히 줄어드는 모양이다. 교재는 이를 시간상수(time constant) 1/Kp의 1차 형태라고 부르고 Kp가 클수록 오차가 더 빨리 0으로 수렴한다고 설명한다.
이 식의 해는 θe(t) = e^(−t/τ)·θe(0), τ = 1/Kp다(Modern Robotics 11.2.2.1). τ만큼 시간이 지날 때마다 오차는 그 시점 값의 약 37%(e^−1 ≈ 0.368)로 줄어든다. 오차가 처음의 2%까지 줄어드는 시간인 2% 정착 시간(2% settling time)을 교재는 약 4τ로 소개한다. 정확히 계산하면 ln 50 ≈ 3.912배다.
Kp = 2로 두면 τ = 0.5초다. 1 rad 오차는 0.5초 뒤 약 0.37 rad이 되고, 3.912 × 0.5 = 1.956초 뒤 0.02 rad이 된다.
머릿속 그림으로는 “남은 거리에 비례하는 속도로 다가가는 관절”을 떠올리면 된다. 멀리 있으면 빠르게, 가까워지면 느리게 움직인다. 이 그림의 한계는 멀리 있을수록 속도가 얼마든지 커질 수 있다는 점이다. 실제 관절은 그렇게 움직이지 못한다. 교재도 같은 강의에서 두 가지를 경고한다. 큰 Kp는 작은 위치 오차에도 큰 속도를 만들어 과도한 진동을 부를 수 있다. 그리고 액추에이터(actuator, 관절을 돌리는 모터 같은 구동 장치)에는 최대 속도가 있어서 제어 법칙이 그 한계에 자주 걸리면 응답이 더 이상 단순한 선형 미분방정식으로 잘 설명되지 않는다. 다만 “자주”가 어느 오차부터인지는 수로 제시하지 않는다. 그 경계를 아래에서 계산한다.
Kp = 10이면 첫 명령이 최대 속도의 5배가 된다
최대 속도(maximum velocity) vmax는 관절이 낼 수 있는 가장 큰 속도다. 예제에서는 vmax = 2 rad/s로 둔다.
Kp = 10, 처음 오차 e0 = 1 rad이면 첫 명령 속도는 10 × 1 = 10 rad/s로 vmax의 5배다. 관절은 이 명령만큼 빨리 돌 수 없다. 명령이 한계를 넘어도 실제 출력은 한계에 머무는 상태를 포화(saturation)라고 한다. 포화된 동안에는 “명령 속도 = 실제 속도”라는 교재의 출발 가정이 깨지므로, θ̇e = −Kp·θe도 시간상수 1/Kp도 그 구간의 움직임을 설명하지 못한다.
포화는 명령 속도가 vmax 이하로 내려오면 풀린다. 이 조건을 오차로 바꾸면 다음과 같다.
Kp·e ≤ vmax ⇔ e ≤ vmax / Kp
Kp = 10, vmax = 2 rad/s → e ≤ 0.2 rad
이 글은 이 값 vmax/Kp를 경계 오차라고 부른다. 교과서의 표준 용어가 아니라 설명을 위해 붙인 이름이다. 오차가 0.2 rad 이하로 내려온 뒤에야 시간상수 0.1초라는 교재의 설명이 그대로 적용된다.
그럼 1 rad에서 0.2 rad까지는 얼마나 걸릴까. 여기서는 교육용 가정을 하나 더 둔다. 포화된 동안 관절이 정확히 vmax로 움직인다는 가정이다. Modern Robotics가 한 말이 아니라 계산을 위해 둔 가정이다. 이 가정 아래에서 0.8 rad을 2 rad/s로 이동하므로 (1 − 0.2) / 2 = 0.4초가 걸린다. 선형 구간 시간상수 0.1초의 4배다.
경계 지점에서 명령은 10 × 0.2 = 2 rad/s로 vmax와 정확히 같다. 그래서 속도가 끊기지 않고 그때부터 오차는 0.2 rad에서 시작해 시간상수 0.1초로 지수적으로 줄어든다. 응답은 “일정한 속도로 줄어드는 직선 구간 + 지수 곡선 구간”으로 나뉜다.

반대 사례도 있다. 같은 Kp = 10이라도 목표 변화가 0.1 rad이면 첫 명령은 10 × 0.1 = 1 rad/s로 한계 2 rad/s보다 작다. 이때는 처음부터 포화 없이 교재의 선형 모델 안에서 움직인다. 포화 여부를 정하는 것은 Kp 하나가 아니라 Kp × 오차다. 같은 게인이 작은 보정에서는 교재대로 움직이고, 큰 스텝에서는 최대 속도에 묶인다.
게인을 5배 올리면 시간상수가 맞는 범위도 5배 좁아진다
두 값을 나란히 쓰면 관계가 드러난다.
시간상수 τ = 1 / Kp
경계 오차 b = vmax / Kp = vmax × τ
둘 다 1/Kp에 비례한다. Kp를 2에서 10으로 5배 올리면 시간상수는 0.5초에서 0.1초로 줄지만 그 시간상수가 맞는 오차 범위도 1.0 rad에서 0.2 rad으로 똑같이 5배 좁아진다. 빨라진다는 약속과 그 약속이 통하는 범위가 함께 줄어드는 셈이다.
같은 1 rad 스텝, vmax = 2 rad/s에서 Kp만 바꿔 보면 다음과 같다.
| Kp (1/s) | 첫 명령 Kp·e0 (rad/s) | 최대 속도 대비 | 경계 오차 vmax/Kp (rad) | 포화 구간 시간 (s) | 시간상수 1/Kp (s) |
|---|---|---|---|---|---|
| 2 | 2 | 1배 | 1.0 | 0 | 0.5 |
| 4 | 4 | 2배 | 0.5 | 0.25 | 0.25 |
| 10 | 10 | 5배 | 0.2 | 0.4 | 0.1 |
포화 구간 시간은 앞의 교육용 가정으로 계산한 값이다. Kp = 10의 모든 값과 Kp = 2의 경계 오차·시간상수, Kp = 4의 포화 구간 시간은 아래에서 소개하는 공개 예제 파일에 고정돼 있다. 나머지 칸은 같은 식을 나눗셈 한 번으로 계산한 값이다.
Kp = 2는 첫 명령이 vmax와 정확히 같아 포화 없이 출발하는 경계 사례다. 1 rad 전체가 시간상수 0.5초의 선형 구간이다. Kp = 4에서는 0.5 rad까지 0.25초 동안 포화되는데, 이 길이가 시간상수 0.25초와 같다. Kp = 10에서는 포화 구간이 0.4초로 시간상수의 4배가 된다. 게인을 올릴수록 전체 응답에서 포화 구간이 차지하는 몫이 커지고 시간상수로 설명되는 부분은 작아진다.
2% 도달 시간은 두 구간의 합이고, 거리÷최대 속도 아래로 내려가지 않는다
“몇 배 빨라지나”에 답하려면 같은 기준으로 끝나는 시간을 비교해야 한다. 교재가 쓰는 2% 기준을 그대로 써서, 오차가 ε = 0.02 × e0 = 0.02 rad에 닿는 시간을 구한다. 경계 오차 b = vmax/Kp가 어디에 있느냐에 따라 세 경우로 나뉜다.
e0 ≤ b (포화 없음) t = (1/Kp) · ln(e0/ε)
ε < b < e0 (포화 뒤 선형 구간) t = (e0 − b)/vmax + (1/Kp) · ln(b/ε)
b ≤ ε (끝까지 포화) t = (e0 − ε)/vmax
Kp = 10을 손으로 계산하면 b = 0.2 rad이므로 두 번째 경우다. 포화 구간 0.4초에 선형 구간 0.1 × ln(0.2/0.02) = 0.1 × 2.3026 ≈ 0.230초를 더해 약 0.630초가 나온다. 속도 한계가 없다고 보면 0.1 × 3.912 ≈ 0.391초였을 것이다. Kp = 2는 첫 번째 경우라 1.956초이므로, Kp를 5배 올린 효과는 1.956 ÷ 0.630 ≈ 3.1배다. 이 3.1배는 e0 = 1 rad, vmax = 2 rad/s, 2% 기준에서만 나오는 값이지 일반 법칙이 아니다.
교재의 “2% 정착 시간은 약 4 시간상수”는 Kp = 2에서 1.956초 = 3.912 × 0.5초로 그대로 맞는다. Kp = 10에서 같은 규칙은 약 0.4초(정확히 0.391초)를 예측하지만, 속도 한계를 넣은 계산은 0.630초다. 교재가 틀린 것이 아니다. “Kp가 클수록 빨리 수렴한다”는 선형 모델 안의 설명이고, 교재가 경고한 “최대 속도에 자주 걸리는” 경우가 바로 이 상황이다. 경계 오차는 두 진술 사이에 빠져 있던 숫자다.
아래 스크립트는 세 경우의 식과, 같은 조건을 오일러 방법(Euler method)으로 따라간 수치 계산을 비교한다. 오일러 방법은 0.00001초라는 아주 짧은 간격마다 오차 -= min(Kp×오차, vmax) × dt를 반복해 시간을 더해 가는 계산이다. 속도 한계를 넣은 같은 식을 잘게 나눠 풀기 때문에, 닫힌 식에서 경우를 잘못 나누면 두 값이 어긋난다. 외부 패키지 없이 파일을 만들지 않고 표준 입력으로 실행한다.
python3 -I - <<'EOF'
import math
vmax, e0, eps = 2.0, 1.0, 0.02
def limited(Kp):
b = vmax / Kp
if e0 <= b: return (1/Kp)*math.log(e0/eps) # 포화 없음
if b <= eps: return (e0 - eps) / vmax # 2% 지점까지 전부 포화 구간
return (e0 - b)/vmax + (1/Kp)*math.log(b/eps) # 포화 구간 + 선형 구간
def euler(Kp, dt=1e-5):
e, t = e0, 0.0
while e > eps:
e -= min(Kp*e, vmax)*dt; t += dt
return t
for Kp in (2, 4, 10, 50, 1000):
print(f"Kp={Kp:>5} t2%_limited={limited(Kp):.4f} s euler={euler(Kp):.4f} s t2%_ideal={(1/Kp)*math.log(e0/eps):.4f} s")
print("(e0-eps)/vmax =", (e0-eps)/vmax, "s")
EOF
echo "exit=$?"
Kp= 2 t2%_limited=1.9560 s euler=1.9560 s t2%_ideal=1.9560 s
Kp= 4 t2%_limited=1.0547 s euler=1.0547 s t2%_ideal=0.9780 s
Kp= 10 t2%_limited=0.6303 s euler=0.6302 s t2%_ideal=0.3912 s
Kp= 50 t2%_limited=0.4939 s euler=0.4939 s t2%_ideal=0.0782 s
Kp= 1000 t2%_limited=0.4900 s euler=0.4900 s t2%_ideal=0.0039 s
(e0-eps)/vmax = 0.49 s
exit=0
t2%_limited는 위의 세 경우 식, euler는 수치 계산, t2%_ideal은 속도 한계가 없다고 볼 때의 값이다. Kp = 10의 0.0001초 차이를 빼면 식과 수치 계산이 소수 넷째 자리까지 같다. 속도 한계가 없다면 Kp를 1000으로 올릴 때 0.0039초까지 줄어들 시간이, 한계가 있으면 0.49초에서 멈춘다.
세 번째 경우를 빠뜨리기 쉽다. Kp = 1000이면 경계 오차가 0.002 rad으로 2% 기준 0.02 rad보다 작다. 두 번째 식을 그대로 쓰면 ln(0.002/0.02)가 음수가 되어 (1 − 0.002)/2 + 0.001 × ln 0.1 ≈ 0.4967초라는 값이 나오는데, 같은 조건의 수치 계산은 0.4900초다. 오차가 2% 지점에 닿을 때까지 포화가 한 번도 풀리지 않으므로 선형 구간 자체가 없다. 경계 오차가 목표 허용 오차보다 작으면 시간상수는 응답의 어느 부분도 설명하지 않는다.
마지막 줄의 0.49초가 하한이다. 0.98 rad을 최대 2 rad/s로 가면 아무리 빨라도 0.49초가 걸린다. 이 하한은 “포화 중 정확히 vmax로 움직인다”는 교육용 가정이 없어도 성립한다. 관절 속도가 vmax를 넘지 못한다는 조건만 있으면 어떤 제어기를 쓰든 그보다 빨리 도착할 수 없기 때문이다. 게인을 올리는 효과는 처음 오차가 경계 오차보다 충분히 작을 때 가장 크고, 큰 스텝에서는 거리÷최대 속도에 막힌다.
공개 예제로 경계 오차와 포화 시간을 다시 계산한다
앞 표의 핵심 숫자는 공개 저장소에 고정한 산술 예제 파일 example.py로 다시 계산할 수 있다. 파일은 9개 사례마다 계산값을 기대값과 math.isclose로 비교하고 하나라도 다르면 AssertionError로 멈춘다. 기대값·실제값·실행 환경은 검증 기록 verification.json에 남아 있다.
준비물은 Python 3과 curl뿐이고 외부 패키지나 가상환경은 필요 없다. 아래 흐름은 Linux의 새 임시 폴더에서 그대로 확인했다. 내려받은 파일은 실행하기 전에 한 번 열어 내용을 읽고, curl … | python3처럼 곧바로 파이프로 실행하지 않는 편이 안전하다.
python3 --version
curl -fsSLo example.py "https://raw.githubusercontent.com/sungpyo9053/blog/ef34b56819954b15411983670703228b56dfc34c/editorial/generated-foundations/20260926T082859Z-40870a3269-robot-joint-p-control-velocity-saturation-boundary/example.py"
sha256sum example.py
python3 -I example.py
echo "exit=$?"
sha256sum 결과가 398812acedf902b52faeb848d9a5a473705544b93878fda9a9aabb5e972788fb이면 이 글이 검산한 파일과 같은 파일이다. 실행 출력은 다음과 같다.
$ python3 --version
Python 3.12.3
$ python3 -I example.py
[{"name": "Kp=10, 초기 오차 1 rad일 때의 초기 명령 속도(rad/s)", "actual": 10}, {"name": "Kp=10 초기 명령이 최대 속도 2 rad/s의 몇 배인지", "actual": 5.0}, {"name": "Kp=10에서 포화가 풀리는 경계 오차 vmax/Kp(rad)", "actual": 0.2}, {"name": "Kp=10에서 1 rad부터 경계 0.2 rad까지 최대 속도로 이동하는 시간(s, 교육용 가정)", "actual": 0.4}, {"name": "Kp=10에서 선형 구간의 시간상수 1/Kp(s)", "actual": 0.1}, {"name": "Kp=2의 경계 오차: 초기 오차 1 rad와 같아 포화가 없는 경계 사례(rad)", "actual": 1.0}, {"name": "Kp=2의 시간상수(s)", "actual": 0.5}, {"name": "Kp=4에서 경계 오차 0.5 rad까지 최대 속도로 이동하는 시간(s, 교육용 가정)", "actual": 0.25}, {"name": "반례: Kp=10이라도 목표가 0.1 rad면 초기 명령 속도는 최대 속도보다 작다(rad/s)", "actual": 1.0}]
exit=0

출력의 아홉 값이 앞 절 표와 반례의 숫자다. 이 stdout은 verification.json에 기록된 출력과 같고, 공개 파일을 새로 내려받아 실행해도 해시와 출력이 바뀌지 않았다. 종료 코드 0은 아홉 개 assertion이 모두 통과했다는 뜻이다. 2% 도달 시간은 이 파일에 없으며, 앞 절의 보강 계산으로만 확인했다.
검산이 틀린 값을 실제로 걸러내는지도 확인할 수 있다. 포화 구간 시간의 기대값 0.4를 흔한 오답 0.5로 바꾼 사본을 만든다. 0.5초는 1 rad 전체를 최대 속도로 간다고 착각할 때 나오는 값이다. 앞 블록으로 내려받은 example.py가 있는 폴더에서 실행한다.
sed 's/math.isclose(value, 0.4,/math.isclose(value, 0.5,/' example.py > broken.py
python3 -I broken.py
echo "exit=$?"
Traceback (most recent call last):
File ".../broken.py", line 15, in <module>
assert math.isclose(value, 0.5, rel_tol=1e-9, abs_tol=1e-9)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
exit=1
출력에서 바꾼 곳은 File 줄의 절대경로를 ...로 줄인 한 군데뿐이다. Python 3.12.3은 실패한 assert 식 아래에 ^ 표시 줄을 함께 찍는다. 계산값 0.4와 기대값 0.5가 달라 15번째 줄에서 멈추고 종료 코드 1을 돌려준다. 판정은 표시 줄이 아니라 AssertionError와 종료 코드로 한다. 정상 파일에서 0, 기대값을 바꾼 사본에서 1이 나오면 검산이 틀린 값을 걸러낸다.
확인 문제: 경계 오차를 직접 그어 본다
세 문제 모두 vmax = 2 rad/s, 멈춰 있는 목표, 앞과 같은 포화 가정을 쓴다.
문제 1. Kp = 4일 때 시간상수 설명을 그대로 쓸 수 있는 최대 오차는 얼마인가?
답은 2 ÷ 4 = 0.5 rad이다. 오차가 0.5 rad일 때 명령 4 × 0.5 = 2 rad/s가 vmax와 같아지고 그보다 작은 오차에서는 명령이 한계 아래에 머물기 때문이다.
문제 2. 같은 Kp = 4에서 0.3 rad짜리 스텝은 처음부터 시간상수 0.25초로 설명해도 되는가?
된다. 0.3 rad은 경계 오차 0.5 rad보다 작고, 첫 명령 4 × 0.3 = 1.2 rad/s도 2 rad/s보다 작다. 이 스텝에서는 포화 구간이 없다.
문제 3. 1 rad 스텝에서 Kp를 10에서 50으로 5배 올리면 2% 도달 시간도 5배 줄어드는가?
아니다. Kp = 50이면 경계 오차가 0.04 rad이어서 포화 구간이 (1 − 0.04)/2 = 0.48초, 선형 구간이 0.02 × ln(0.04/0.02) ≈ 0.014초로 합계 약 0.494초다. 0.630초에서 0.494초로 약 1.3배 줄어들 뿐이다. 응답 대부분이 이미 최대 속도 구간이라 하한 0.49초에 거의 붙어 있다.
이 계산이 다루지 않는 것과 실물 관절에서 먼저 볼 것
위의 숫자는 속도를 직접 명령받는 이상적인 관절 하나에서 나온 값이다. 가속도 한계, 토크 입력, 관성, 마찰, 중력, 통신 지연, 제어 주기, 센서 노이즈는 모델에 없다. 가속도 한계가 있으면 vmax에 도달하는 데도 시간이 걸리므로 포화 구간은 이 계산보다 길어질 수 있다. 방향만 말할 수 있을 뿐 얼마나 길어지는지는 계산하지 않았다. 여러 관절이 동시에 한계에 걸릴 때 드라이버가 명령을 어떻게 줄이는지, 한계를 넘는 명령을 단순히 잘라내는지 오류로 멈추는지도 장비마다 다르며 여기서는 확인하지 않았다. 목표가 현재보다 작은 음의 오차는 |e|로 바꾸면 같은 식이 되지만, 공개 예제는 양의 오차만 계산했다.
vmax 후보 값을 찾을 때는 로봇 모델 파일이 출발점이 될 수 있다. ROS의 URDF 참조 파서 urdfdom은 <limit> 요소에 velocity 속성이 없으면 joint limit: no velocity 오류를 남기고 읽기에 실패한다(urdfdom joint.cpp 149–154행). 회전 관절(revolute)인데 <limit> 요소 자체가 없어도 읽기에 실패한다(joint.cpp 446–463행). 그래서 이 파서로 읽히는 URDF라면 회전 관절마다 velocity 값이 적혀 있다. 같은 저장소의 XML 스키마 urdf.xsd 201–206행은 velocity를 기본값 0인 선택 속성으로 선언하므로, “URDF 형식에서 필수”가 아니라 “urdfdom 파서가 요구한다”까지만 말할 수 있다. 모델 파일의 숫자가 실제 하드웨어가 낼 수 있는 속도라거나 드라이버가 그 값에서 명령을 잘라낸다는 보장도 아니다.
실물 관절에서 게인을 바꾸기 전에는 제조사가 밝힌 관절 속도·가속도·토크 제한, 드라이버가 한계를 넘는 명령을 처리하는 방식, 비상 정지와 보호 정지 수단을 먼저 확인해야 한다. 소프트웨어 명령 하나를 유일한 안전 장치로 삼지 않는다. 교재가 경고한 진동 문제는 속도 한계와 별개로 게인을 올리는 데 제동을 거는 이유이며, 이 계산은 진동을 다루지 않는다.
게인 비교표를 보기 전에 적어 둘 한 줄
두 게인의 시간상수 비율만 보고 “몇 배 빨라진다”고 말하기 전에, 예상하는 가장 큰 오차에 Kp를 곱해 최대 속도와 비교한다.
예상 최대 오차 × Kp ≤ vmax ? 경계 오차 = vmax / Kp
예를 들어 예상 최대 오차 1 rad, Kp = 10, vmax = 2 rad/s면 10 > 2이므로 포화가 생긴다. 이때는 1 rad에서 경계 오차 0.2 rad까지를 최대 속도 구간으로, 그 아래만 시간상수 0.1초 구간으로 나눠 읽는다. 처음 오차가 경계 오차보다 작으면 교재의 시간상수 설명과 “Kp를 올린 만큼 빨라진다”는 판단을 그대로 써도 된다.
이 점검은 속도 입력형 P 제어를 교재 수준에서 이해하고 게인 후보들을 개념적으로 비교할 때 쓸 수 있다. 토크로 관절을 구동하는 제어, 여러 관절이 한꺼번에 제한되는 상황, 실제 장비의 게인 결정에는 그대로 쓰지 않는다. 목표가 일정한 속도로 움직일 때 P 제어에 남는 오차는 움직이는 로봇 관절을 P 제어하면 왜 오차가 남을까에서 이어서 계산할 수 있다.
참고 링크
- Modern Robotics 11.3 Motion Control with Velocity Inputs (Part 1 of 3) — 속도 입력 가정, P 제어, 설정값 제어의 시간상수 1/Kp, 큰 게인과 최대 속도에 대한 경고. 2026-09-26 확인.
- Modern Robotics 11.2.2.1 First-Order Error Dynamics — 1차 오차 응답의 해와 2% 정착 시간 약 4 시간상수. 2026-09-26 확인.
- Modern Robotics 11.2.1 Error Response — 오차 정의와 정착 시간 정의. 2026-09-26 확인.
- ROS urdfdom urdf_parser/src/joint.cpp (commit bfcf29f) —
<limit>에velocity가 없거나 회전 관절에<limit>이 없을 때의 파싱 실패. 2026-09-26 확인. - HuntLab 공개 예제 example.py (commit ef34b56)
- HuntLab 공개 검증 기록 verification.json (commit ef34b56)