SAPIEN의 관절 drive에서 mode="force"와 mode="acceleration"은 같은 stiffness·damping 값을 서로 다르게 적용합니다. Force 모드는 위치·속도 오차를 힘으로 연결하고, acceleration 모드는 연결된 링크의 관성을 반영해 실제로 가하는 힘을 조정합니다. 로봇의 질량이 달라졌을 때 같은 이득으로 비슷한 운동을 만들려는 설정이 후자입니다.
따라서 로봇 A의 PD 이득을 로봇 B에 옮겨 비교할 때는 숫자뿐 아니라 구동 모드도 함께 읽어야 합니다. SAPIEN 공식 PID·drive 문서는 이 차이를 설명한 뒤, PhysX 내부 drive와 직접 작성한 외부 PID의 예제를 나란히 보여줍니다. 두 예제는 제어력을 계산하는 위치와 방식에서도 차이가 있습니다.
이득이 정하는 것은 오차에 대한 반응이다
공식 문서는 내부 drive를 다음 PD 관계로 설명합니다.
힘 = stiffness × (목표 위치 − 현재 위치)
+ damping × (목표 속도 − 현재 속도)
stiffness는 위치 오차에, damping은 속도 오차에 대응합니다. 위치와 속도 목표도 별도입니다. set_drive_target(...)은 위치 목표를, set_drive_velocity_target(...)은 속도 목표를 지정합니다. 문서에 따르면 초기 위치·속도 목표는 기본값이 0입니다.
예를 들어 새 위치로 이동한 뒤 멈추는 동작과, 일정한 속도를 따라가는 동작은 목표 설정부터 다릅니다. 위치 목표만 바꾼 상태에서 속도 목표를 따로 지정하지 않았다면 속도 오차 항은 기본 속도 목표를 기준으로 작용합니다. damping을 단순한 제동 숫자로만 외우기보다 어느 목표 속도와 현재 속도의 차이에 곱하는지 읽는 것이 좋습니다.
이 관계를 실제 구동력으로 적용하는 과정에는 모드가 들어갑니다.
| 같은 오차와 같은 이득에서 비교할 항목 | force 모드 | acceleration 모드 |
|---|---|---|
| 힘을 정하는 방식 | PD 오차 항으로 힘을 정함 | 실제 힘에 연결 링크의 관성을 반영함 |
| 질량이 달라진 로봇에 같은 이득을 옮길 때 | 같은 힘에 대한 운동 변화가 달라질 수 있음 | 질량 차이를 반영한 힘 조정으로 비슷한 운동을 만들도록 설계됨 |
문서의 force_limit |
drive가 출력할 최대 힘 또는 토크 | 마찬가지로 drive 출력의 힘 또는 토크 한계 |
Acceleration 모드의 뜻을 실제 힘이 없어지는 것으로 해석하면 혼동하기 쉽습니다. 물리 엔진에서 링크를 움직이는 힘은 여전히 존재하며, 그 힘을 결정할 때 관성을 반영하는 것입니다.
링크가 무거워진 경우를 생각해 보면
두 로봇의 관절 위치·속도 오차가 같고, 같은 이득을 사용한다고 가정해 보겠습니다. 달라진 것은 연결 링크의 관성입니다. 이는 구동 모드의 차이를 설명하기 위한 가상 비교입니다.
Force 모드에서는 두 경우의 PD 오차 항이 같습니다. 더 큰 관성을 가진 링크를 같은 힘으로 움직이면 운동 변화가 작아지는 방향으로 작용합니다. 같은 목표 위치로 가더라도 반응 속도가 달라질 수 있는 이유입니다.
Acceleration 모드는 이 관성 차이를 실제 힘에 반영합니다. 같은 이득으로 서로 다른 질량의 로봇이 비슷하게 움직이도록 한다는 공식 설명은 이 계산 위치를 가리킵니다. 이는 무거운 링크에도 같은 작은 힘만 쓰면서 운동을 같게 만든다는 뜻이 아닙니다. 관성에 맞춰 힘을 바꾸는 쪽입니다.
여기에 force_limit이 걸리면 필요한 힘을 모두 출력할 수 있는지도 함께 영향을 줍니다. 예를 들어 더 큰 관성에 맞춰 요구되는 힘이 커져도 drive 출력은 설정된 한계 안에 있어야 합니다. 모드를 비교할 때 이득과 한계를 함께 읽어야 하는 구체적인 이유입니다.
또 실제 로봇의 한 관절은 주변 링크와 연결돼 있습니다. 위 설명을 단순히 파일에 적힌 링크 질량 하나를 PD 식에 곱하는 사용자 코드로 옮기기보다, PhysX solver 안에서 연결 구조의 관성을 반영하는 drive 설정으로 이해해야 합니다. 공식 문서도 적용 힘이 매 시뮬레이션 단계에서 암시적으로 계산된다고 설명합니다. 위 PD 식은 그 의도를 설명하는 관계이며, 사용자가 힘을 먼저 계산해 명시적으로 적분하는 루프를 그대로 보여주는 식은 아닙니다.
목표 근처에서 멈추는 문제는 관성만으로 설명되지 않는다
관성을 반영하는 모드를 골라도 중력과 같은 수동력의 역할은 남습니다. 목표 위치에서 정지해 위치·속도 오차가 모두 0이면, 위 PD 오차 항도 0입니다. 그런데 그 자세를 유지하려면 중력에 맞서는 힘이 필요한 경우가 있습니다.
그 힘을 drive의 P 항만으로 만들려면 위치 오차가 일부 남아야 합니다. 로봇이 목표 근처에서 조금 처진 자세로 멈추는 정상상태 오차를 이렇게 이해할 수 있습니다. 공식 문서가 passive force를 보상하지 않거나 중력을 끄지 않으면 목표 자세에 정확히 도달하지 못할 수 있다고 설명하는 배경입니다. Acceleration 모드의 관성 반영과 중력 보상은 이처럼 다루는 원인이 다릅니다.
문서의 시뮬레이션 루프는 먼저 다음 값을 계산합니다.
qf = robot.compute_passive_force(
gravity=True,
coriolis_and_centrifugal=True,
)
이 예제에서는 중력뿐 아니라 코리올리·원심력 항까지 포함합니다. 이어 set_qf(qf)로 힘을 전달한 뒤 scene.step()을 호출합니다. 오차로부터 보정력을 만드는 drive와, 모델의 수동력을 계산해 보상하는 경로를 함께 사용하는 구조입니다.
위치·속도·토크 명령이 제어 루프에서 어떤 역할을 맡는지 더 넓은 배경이 필요하다면 로봇 위치·속도·토크 제어 설명과 연결해 볼 수 있습니다. 여기서는 그중 SAPIEN의 drive 설정과 외부 힘 입력이 만나는 지점이 핵심입니다.
외부 PID 예제는 어느 힘에 더해지는가
공식 예제의 use_external_pid 경로에서는 SimplePID가 계산한 힘을 앞서 구한 qf에 더합니다. 핵심 흐름을 문서에서 발췌하면 다음과 같습니다. pids, target_qpos, robot, scene은 예제에서 이미 준비한 객체와 값입니다.
if use_external_pid:
pid_qf = pid_forward(
pids, target_qpos, robot.get_qpos(), scene.get_timestep()
)
qf += pid_qf
robot.set_qf(qf)
scene.step()
따라서 이 경로의 set_qf에 들어가는 값은 PID 출력만이 아니라 수동력 보상과 PID 출력의 합입니다. 내부 drive를 설정하는 use_internal_drive 조건과 외부 PID를 더하는 조건은 코드에서 따로 존재합니다. 외부 PID 코드를 추가하는 것만으로 기존 내부 drive 설정이 자동으로 사라지는 구조로 읽으면 안 됩니다.
외부 SimplePID는 오차에 시간 간격을 곱해 적분항에 누적하고, 현재 오차와 이전 오차의 차이를 시간 간격으로 나눠 미분항을 만듭니다. 내부 drive의 damping × (목표 속도 − 현재 속도)와는 계산 표현이 다릅니다. 외부 예제에서 목표 위치가 갑자기 바뀌면 위치 오차의 차분에도 그 변화가 들어갑니다. 이 때문에 두 구현의 D 관련 숫자가 같다는 것만으로 같은 제어 계산이라고 볼 수 없습니다.
문서는 외부 PID를 적분항이 필요한 경우의 간단한 예로 제시하며, 예제 이득이 세밀하게 조정된 값은 아니라고 명시합니다. 숫자를 다른 조작 작업으로 옮기는 것보다 먼저 읽을 부분은 모드가 힘을 정하는 방식, 보상력을 더하는 위치, 오차를 미분하는 방식입니다. 이 세 요소를 구분하면 같은 PD·PID라는 이름 아래에서도 동작이 달라지는 원인을 설명할 수 있습니다.
이 글은 2026년 10월 15일 확인한 SAPIEN 문서의 표시 버전 3.0과 해당 페이지의 예제 코드를 해석했습니다. 시뮬레이션 실행이나 로봇별 이득 조정은 수행하지 않았습니다.