7장. 관절 하나에 열 하나: 자코비안 바로 읽기와 특이점
자코비안의 열 하나는 관절 하나가 손끝에 보태는 속도다. 이 장은 관절 축과 "관절에서 손끝까지의 화살표"만 보고 자코비안을 바로 적는 법을 배운다. 그리고 손끝이 어떤 방향으로 못 가게 되는 자세(특이점)를 본다. 강의 7강(69분)에 해당한다.
7.1 6장에서 이어서: 열 하나 = 관절 하나
6장에서는 손끝 위치를 관절 각도로 편미분해 자코비안을 만들었다(6.3절). 종이 팔은 아래와 같았다. s₁ = sin θ₁, c₁₂ = cos(θ₁ + θ₂)처럼 줄여 쓴다.
6장에서 본 두 가지를 다시 떠올리자. 열 하나는 관절 하나가 손끝을 미는 속도였다. 그리고 첫 열 (−y, x)는 손끝 위치 (x, y)를 90° 돌린 화살표였다.
6장 뒷부분에서는 외적 ω × p와 속도 전파도 배웠다. 속도 전파로도 J가 나오지만, J는 긴 식 속에 숨어 있다(6.8절). 이 장의 질문은 이것이다. 로봇을 보기만 하고 자코비안의 열을 하나씩 바로 적을 수 있을까?
잠깐, 생각해 보기. 관절이 6개인 팔이면 자코비안의 열은 몇 개인가? 열 하나를 구할 때 다른 관절은 어떻게 둔다고 생각하면 되나?
열은 6개다. 관절 하나에 열 하나다. 열 i를 구할 때는 나머지 관절을 모두 얼려 두고 관절 i만 움직인다고 생각한다. 그러면 "관절 하나가 손끝을 어떻게 움직이나"라는 쉬운 질문 여섯 개가 된다.
영상에서 보기: 06:58 오늘은 자코비안을 눈으로 본다 · 08:32 관절 축마다 따져 본다
7.2 관절 하나가 손끝에 보태는 몫
관절 i만 움직이고 나머지는 얼렸다고 하자. 관절 i 뒤에 달린 것은 모두 한 덩어리처럼 함께 움직인다. 손끝 E도 그 덩어리에 붙어 있다. 관절은 두 종류뿐이니 두 경우만 보면 된다.
직동 관절: 미는 대로 간다
직동 관절은 축 zi를 따라 미끄러진다. 늘어난 길이를 di, 그 빠르기를 ḋi라 하자. 관절 뒤의 덩어리 전체가 같은 속도로 미끄러지므로, 손끝도 똑같이 미끄러진다.
- 손끝 속도: v = zi ḋi
- 손끝 각속도: ω = 0 (미끄러지기만 하고 돌지 않는다)
회전 관절: 축에서 손끝까지의 화살표가 필요하다
회전 관절은 축 zi를 중심으로 θ̇i의 빠르기로 돈다. 각속도는 zi θ̇i다. 덩어리 전체가 같이 돌므로 손끝도 같은 각속도로 돈다.
손끝의 선속도는 축에서 얼마나 떨어졌는지에 달렸다. 그래서 관절 i의 축 위 한 점(좌표계 {i}의 원점)에서 손끝 E까지 화살표를 긋고 piE라 부른다. 그리고 6장의 v = ω × p를 쓴다.
수학 더하기: 외적 다시 보기. a × b는 a와 b 모두에 수직인 벡터다. 방향은 오른손 네 손가락을 a에서 b 쪽으로 감을 때 엄지가 가리키는 쪽이다. 길이는 |a||b| sin φ다(φ는 둘 사이 각도).
칸으로는 a × b = (a₂b₃ − a₃b₂, a₃b₁ − a₁b₃, a₁b₂ − a₂b₁)이다. 순서를 바꾸면 방향이 반대가 된다.
- 손끝 속도: v = (zi × piE) θ̇i
- 손끝 각속도: ω = zi θ̇i
| 관절 i의 종류 | 손끝 선속도에 보태는 것 | 손끝 각속도에 보태는 것 |
|---|---|---|
| 직동 (prismatic) | zi ḋi | 0 |
| 회전 (revolute) | (zi × piE) θ̇i | zi θ̇i |
잠깐, 생각해 보기. 축이 화면 밖을 보는 z = (0, 0, 1)이고, 손끝이 오른쪽 p = (1, 0, 0)에 있다. z × p와 p × z 가운데 어느 것이 손끝 속도인가?
z × p = (0·0 − 1·0, 1·1 − 0·0, 0·0 − 0·1) = (0, 1, 0)으로 위쪽이다. 축이 화면 밖을 보면 관절은 시계 반대 방향으로 돌고, 오른쪽에 있는 손끝은 위로 간다. 맞다.
p × z는 아래쪽이라 틀린다. 순서를 기억하는 말은 이것이다. 축이 앞, 화살표가 뒤다.
영상에서 보기: 09:34 회전 관절의 각속도 · 11:41 직동·회전 표 만들기 · 14:56 관절에서 손끝까지의 화살표 · 15:26 ω × p
7.3 열을 모으면 자코비안: 명시적 형태
이제 관절들의 몫을 모두 더한다. 관절이 동시에 움직이면 손끝 속도는 관절별 몫의 합이다. 관절 변수는 한꺼번에 qi로 쓴다. 회전 관절이면 θi, 직동 관절이면 di다.
강의는 관절 종류를 숫자 εi로 표시한다. 직동이면 εi = 1, 회전이면 0이다. ε̄i = 1 − εi는 그 반대다. 그러면 두 경우를 한 줄로 쓸 수 있다.
합에서 q̇i 앞에 붙은 것이 바로 i번째 열이다. 자코비안을 위아래 두 덩어리로 나누어 적는다. 위는 선속도를 만드는 Jv, 아래는 각속도를 만드는 Jω다.
이것을 자코비안의 명시적 형태(explicit form)라 한다. 3차원에서 v와 ω는 숫자가 3개씩이라 J는 6줄이다. 관절이 n개면 6 × n 행렬이다.
바로 나오는 두 가지
- 직동 관절만 있는 팔: Jv = [z₁ z₂ ⋯ zn], Jω = 0. 축을 늘어놓으면 끝이다. x, y, z로만 미끄러지는 3D 프린터가 이런 기계다.
- 회전 관절만 있는 팔: Jω = [z₁ z₂ ⋯ zn]. 각속도 쪽은 축만 늘어놓으면 된다.
잠깐, 생각해 보기. piE는 "축 위의 한 점"에서 긋는다. 축 위의 다른 점에서 그으면 열이 달라질까?
달라지지 않는다. 출발점을 축을 따라 옮기면 piE에 zi 방향 성분만 더해진다. zi × zi = 0이라 그 성분은 외적에서 사라진다. 손끝 속도는 손끝이 축에서 떨어진 수직 거리만 본다.
알아 두기. 열 하나를 틀려도 다른 열에는 영향이 없다. 그래서 자코비안을 검산할 때는 열마다 "관절 i만 움직이면 손끝이 정말 이쪽으로 가나?"를 그림으로 확인한다. z × p 대신 p × z로 쓴 부호 실수가 이렇게 가장 잘 잡힌다.
영상에서 보기: 17:08 ε로 한 줄에 쓰기 · 22:01 선속도·각속도 두 덩어리 · 26:18 직동만, 회전만 있는 팔
7.4 종이 팔로 확인하기
종이 팔에 명시적 형태를 써 보자. 두 관절 모두 회전 관절이다. 축은 둘 다 책상 면에 수직으로 화면 밖을 본다. z₁ = z₂ = (0, 0, 1)이다.
화살표는 두 개다.
- p1E: 어깨에서 손끝까지 = (x, y, 0). 어깨가 받침 원점에 있으니 손끝 위치 그대로다.
- p2E: 팔꿈치에서 손끝까지 = (8c₁₂, 8s₁₂, 0). 링크 2 그 자체다.
평면에서는 z × p가 아주 쉽다. 외적 칸 공식에 z = (0, 0, 1), p = (a, b, 0)을 넣으면 (−b, a, 0)이다. (a, b)를 시계 반대 방향으로 90° 돌린 것이고, 길이는 그대로다. 6.3절의 첫 열 (−y, x)가 바로 이것이었다.
7.1절의 J와 열 하나하나가 똑같다. 미분하지 않고 화살표를 돌리기만 했는데 같은 답이 나왔다. 둘째 열도 팔꿈치에서 손끝까지의 화살표를 돌린 것이다. 슬라이더로 직접 확인해 보자.
해 볼 것 세 가지:
- 기본값 θ₁ = 30°, θ₂ = 60°에서 J = [[−13.0, −8.0], [8.7, 0]]이다. 6.3절에서 미분으로 구한 값과 같다.
- θ₁만 돌려 본다. 팔과 두 화살표가 통째로 함께 돈다. 두 화살표 사이의 모양은 그대로다.
- θ₂를 0°로 가져가 본다. 두 화살표가 같은 쪽을 본다. 7.9절에서 다시 본다.
각속도 쪽까지 쓰면
Jω의 두 열은 z₁, z₂ = (0, 0, 1)이다. 6줄을 다 쓰면 이렇다. 6.5절의 기본 자코비안(3 × 2)에 늘 0인 세 줄을 채운 것이다.
셋째 줄(vz)과 넷째·다섯째 줄(ωx, ωy)은 늘 0이다. 팔이 책상 면을 떠나지 않고, 책상 면에 수직인 축으로만 돌기 때문이다. 마지막 줄은 손끝이 도는 빠르기가 θ̇₁ + θ̇₂라는 뜻이다. 1장에서 본 "링크 2의 방향은 θ₁ + θ₂"를 미분한 것이다.
알아 두기. 6.3절에서 본 대로 Jv 칸의 단위는 cm/rad다. Jω 칸은 rad/s를 rad/s로 나눈 것이라 단위가 없다. 한 행렬 안에 단위가 다른 칸이 섞여 있으니, 자코비안의 "크기"를 따질 때는 위와 아래를 따로 보는 것이 안전하다.
영상에서 보기: 24:40 첫 관절이 회전이면 첫 열은? · 27:23 열은 z × p 아니면 z
7.5 3차원 팔: 돌림판 위의 종이 팔
명시적 형태가 진짜 쓸모 있는 곳은 3차원이다. 종이 팔을 책상에서 들어 올려 돌림판 위에 세워 보자. 관절이 3개가 된다.
- 관절 1, 돌림판: 축 z₁은 위를 본다. 팔이 놓인 세로 판을 통째로 돌린다.
- 관절 2, 어깨: 돌림판 한가운데, 높이 0에 있다고 둔다. 축 z₂는 수평이고 팔이 놓인 세로 판에 수직이다.
- 관절 3, 팔꿈치: 축 z₃은 z₂와 나란하다.
링크 길이는 그대로 10 cm, 8 cm다. 세로 판 안에서 보면 어깨와 팔꿈치는 종이 팔과 똑같이 움직인다.
그림에서 두 열을 읽어 보자.
- 열 1 = z₁ × p1E: 돌림판이 돌면 손끝은 수평 고리를 따라 돌고, 속도는 고리에 접하는 수평 방향이다. 크기는 손끝이 축에서 떨어진 수평 거리 r이다. p1E의 높이 성분은 z₁과 나란해서 외적에서 사라진다. 7.3절에서 본 그대로다.
- 열 3 = z₃ × p3E: 팔꿈치만 돌면 손끝은 세로 판 안에서 팔뚝에 수직으로 움직인다. 종이 팔의 열 2와 같은 그림이다.
열 2(어깨)도 같은 방법으로 구한다. 각속도 쪽은 축만 늘어놓아 Jω = [z₁ z₂ z₃]이다. 이 팔의 자코비안은 6 × 3이고, 손끝 위치 (x, y, z)를 만드는 Jv는 3 × 3이다.
잠깐, 생각해 보기. 손끝을 돌림판 축 바로 위로 가져가면(r = 0) 열 1은 어떻게 되나?
0이 된다. p1E가 z₁과 나란해져 외적이 0이다. 돌림판을 아무리 돌려도 손끝은 제자리에서 방향만 바뀐다.
손끝 위치로 보면 관절 하나를 잃은 셈이다. 이런 자세가 7.9절의 특이점이다.
영상에서 보기: 37:21 지금까지 정리 · 42:00 z는 관절 축이다
7.6 숫자로 적기: 좌표계 {0}과 동차변환
명시적 형태는 화살표(벡터)로 쓴 식이다. 아직 "어느 좌표계의 숫자로 적는지"를 정하지 않았다. 숫자로 계산하려면 좌표계 하나를 고르고, 모든 zi와 piE를 그 좌표계의 숫자로 적어야 한다. 외적도 같은 좌표계의 숫자끼리만 계산할 수 있다.
보통은 받침 좌표계 {0}을 고른다. 손끝이 책상 위에서 어디로 가는지를 받침 기준으로 알고 싶기 때문이다. 그러면 필요한 것은 두 가지다. 관절 축 ⁰zi와 손끝 위치 ⁰P다.
축은 회전행렬의 셋째 열에 있다
zi는 좌표계 {i}의 z축이다. 자기 좌표계에서 보면 언제나 (0, 0, 1)이다. 이것을 {0}의 숫자로 바꾸려면 회전행렬을 곱한다.
(0, 0, 1)을 곱하면 셋째 열만 뽑힌다. 2장의 "회전행렬의 열은 돌린 축이다"를 다시 쓴 것이다. 그러니 ⁰ᵢT를 알면 셋째 열 위 세 칸에서 ⁰zi를 그냥 읽는다.
손끝 위치는 넷째 열에 있다
⁰ₙT의 넷째 열 위 세 칸은 손끝 위치 ⁰P = (x, y, z)다. 그러면 Jv는 두 가지로 구할 수 있다.
- 열마다 ⁰zi × ⁰piE를 계산한다. piE는 ⁰P에서 ⁰ᵢT의 넷째 열(관절 i 원점)을 뺀 것이다.
- ⁰P를 q₁, q₂, …, qn으로 하나씩 편미분한다. 6장의 방법이다. i번째 편미분이 i번째 열이다.
두 방법은 같은 답을 준다. 하나로 구하고 다른 하나로 검산하면 좋다.
곱하는 순서: 받침부터 바깥으로
순기구학을 계산할 때 곱하는 순서를 정해 두면 일이 준다. ⁰₁T에 ¹₂T를 곱해 ⁰₂T를 얻고, 거기에 ²₃T를 곱해 ⁰₃T를 얻는 식으로 받침 쪽부터 곱해 나간다.
이렇게 하면 중간 결과 ⁰₁T, ⁰₂T, …가 모두 {0}의 숫자로 남는다. 그 셋째 열이 곧 Jω의 열이다. 바깥쪽부터 곱하면(¹₂T ²₃T부터) 마지막 답은 같지만 중간 결과가 {1}의 숫자라서 축을 다시 계산해야 한다.
알아 두기. Jv를 미분으로 구하는 것은 손끝 위치를 직교좌표 (x, y, z)로 적었을 때만 맞다(6.5절). 오일러 각을 미분한 것은 각속도 ω가 아니므로 Jω는 미분으로 구하지 않는다. 축 zi를 늘어놓는 명시적 형태가 고마운 까닭이 이것이다.
영상에서 보기: 28:58 어느 좌표계로 적나 · 30:03 위치를 미분해 J 구하기 · 35:45 z는 셋째 열 · 51:26 받침부터 곱한다
7.7 다른 좌표계로 옮기기
자코비안을 {0}이 아닌 좌표계로 적어야 할 때도 있다. 손에 단 카메라 기준으로 속도를 명령하거나, 식이 더 간단해지는 좌표계로 계산하고 싶을 때다. 옮기는 법은 간단하다.
J q̇가 주는 것은 v와 ω라는 두 화살표다. 둘 다 "어디에 있나"가 아니라 "어느 쪽이냐"다. 2장에서 본 대로 방향은 돌리기만 하면 된다. v는 v대로, ω는 ω대로 같은 회전행렬로 돌린다.
수학 더하기: 블록 행렬. 큰 행렬을 작은 행렬 덩어리로 나누어 쓴 것을 블록 행렬이라 한다. 위의 6 × 6 행렬은 3 × 3 회전행렬 두 개를 대각선에 놓고 나머지를 0으로 채운 것이다. 곱할 때는 덩어리를 숫자처럼 다룬다.
위 덩어리는 R Jv, 아래 덩어리는 R Jω가 된다. 대각선 밖이 0이라 v와 ω가 섞이지 않는다.
종이 팔을 링크 1의 좌표계로
링크 1에 붙어 함께 도는 좌표계 {1}을 생각하자. x₁은 링크 1 방향이다. {1}의 축을 {0}으로 적은 회전행렬은 R(θ₁)이므로, 거꾸로 가려면 전치 R(θ₁)ᵀ를 곱한다(2장). 계산하면 θ₁이 모두 사라진다.
Jω는 그대로다. 축 (0, 0, 1)은 z축으로 돌려도 (0, 0, 1)이기 때문이다.
잠깐, 생각해 보기. 그림 7-5에서 θ₁만 움직이면 ⁰J의 숫자는 바뀌는데 ¹J의 숫자는 그대로다. 왜 그럴까?
어깨를 돌리면 팔과 열 화살표, 그리고 {1}의 축이 한꺼번에 돈다. {1}에 서서 보면 아무것도 돌지 않았다. 링크 1에서 본 팔 모양은 팔꿈치 θ₂만 정한다. 그래서 ¹J에는 θ₂만 남는다.
¹J처럼 간단한 좌표계를 고르면 손 계산이 훨씬 쉬워진다. 7.9절에서 이 덕을 본다.
알아 두기. 여기서 바꾼 것은 "숫자를 적는 축"뿐이다. 속도를 재는 점(손끝 E)은 그대로다.
손목에서 잰 속도를 집게 끝에서 잰 속도로 바꾸는 것처럼 점을 옮기는 일은 다르다. 그때는 선속도에 ω × (두 점 사이 화살표)가 더해진다. 8강에서 다룬다.
영상에서 보기: 33:09 좌표계 사이의 관계
7.8 스탠퍼드 Scheinman 팔의 자코비안
이제 강의의 3차원 팔에 써 보자. 스탠퍼드 팔(Scheinman 팔)은 1969년 Victor Scheinman이 스탠퍼드에서 만든 6관절 팔이다. 관절은 이렇다.
| 관절 | 종류 | 하는 일 |
|---|---|---|
| 1 | 회전 | 몸통 전체를 세로축 z₁으로 돌린다 |
| 2 | 회전 | 어깨. 팔(붐)을 위아래로 기울인다. 붐은 옆으로 d₂만큼 비켜 있다 |
| 3 | 직동 | 붐이 z₃ 방향으로 늘었다 줄었다 한다(d₃) |
| 4, 5, 6 | 회전 | 손목. 세 축이 한 점 W에서 만난다 |
점은 손목점 W로 잡는다
강의는 속도를 재는 점을 손목점 W로 잡는다. 손목의 세 축이 만나는 점이고, 좌표계 {3}~{6}의 원점이 모두 여기 있다. 이렇게 잡으면 자코비안이 아주 간단해진다. 7.2절의 표만 써서 열을 하나씩 채운다.
- 관절 1 (회전): 위는 z₁ × p1W, 아래는 z₁
- 관절 2 (회전): 위는 z₂ × p2W, 아래는 z₂
- 관절 3 (직동): 위는 z₃, 아래는 0
- 관절 4, 5, 6 (회전): 아래는 z₄, z₅, z₆. 위는 zi × piW인데, 축이 W를 지나므로 piW = 0이다. 그래서 0이다.
손목 관절은 W를 옮기지 못하고 손 방향만 돌린다. 이 사실이 오른쪽 위의 0 덩어리로 그대로 나타난다. 강의에서 교수가 "이제 자코비안이 보이나?"라고 묻는 장면이 이것이다.
숫자로 채우기
6.4절에서 손목점 위치를 미분해 Jv는 이미 구했다. 이번에는 7.6절의 순서대로 축을 읽어 Jω를 채우고, Jv는 명시적 형태로 맞춰 본다. 5장의 DH 표로 ⁰₁T, ¹₂T, …, ⁵₆T를 만들고 받침부터 곱해 나가며 셋째 열을 읽는다.
z₁은 받침의 세로축 그대로다. z₂는 수평이고 θ₁을 따라 돈다. z₃는 붐 방향이고, θ₄는 붐을 축으로 도니 z₄도 같은 방향이다. z₅와 z₆은 ⁰₅T, ⁰₆T의 셋째 열이며, θ₄, θ₅까지 들어가 식이 길어진다.
손목점 위치는 ⁰₃T의 넷째 열이고, ⁰₆T의 넷째 열과 똑같다. 원점이 같은 점이기 때문이다. 6.4절의 식과 같다.
6.4절에서 미분으로 구한 열을 명시적 형태와 맞춰 보자.
- 셋째 열: d₃로 미분한 (c₁s₂, s₁s₂, c₂)는 z₃와 같다. 직동 관절의 열은 축 그 자체라는 7.2절 결과와 맞는다. 강의에서 교수가 학생들과 함께 하는 검산이다.
- 첫째 열: z₁ × ⁰PW = (−Py, Px, 0)이다. 6.4절의 (−y, x, 0)과 같다. 7.4절의 "90° 돌리기"가 3차원에서 수평면 위로 일어난 것이다.
둘째 열 z₂ × p2W도 같다. 어깨 원점에서 W까지의 화살표는 붐 방향으로 d₃ z₃이라서, 열 = d₃ (z₂ × z₃)이다. 길이가 d₃인 까닭이 여기서도 보인다. 긴 식은 7.11절의 파이썬 코드가 숫자로 계산해, 위치를 미분한 값과 맞춰 본다.
알아 두기. 집게 끝 E를 속도 재는 점으로 잡으면 4, 5열의 위 칸이 0이 아니게 된다(문제 8). 그래도 W에서 구한 자코비안에서 출발해 점만 옮기면 된다(8강). 손 계산은 W를 고를 때 가장 쉽다.
영상에서 보기: 36:16 스탠퍼드 Scheinman 팔 · 38:54 빈 자코비안 채우기 · 47:14 순기구학과 자코비안을 한 번에 · 58:49 셋째 열 검산
7.9 특이점: 자코비안이 무너지는 자세
자코비안을 쓸 때 조심할 자세가 있다. 그 자세에서는 열들이 서로 기대어 버리고, 손끝이 어떤 방향으로는 아예 못 간다.
종이 팔의 det J
종이 팔의 J는 2 × 2 정사각 행렬이다. 행렬식(det)을 계산해 보자.
수학 더하기: 2 × 2 행렬식. [[a, b], [c, d]]의 행렬식은 det = ad − bc다. 두 열 (a, c)와 (b, d)로 만든 평행사변형의 넓이라는 뜻이 있다(부호 포함). 두 열이 같은 줄 위에 있으면 평행사변형이 납작해져 넓이가 0이다. 거꾸로 det ≠ 0이면 두 열을 섞어 평면의 모든 방향을 만들 수 있다.
마지막 단계는 sin(A − B) = sin A cos B − cos A sin B에 A = θ₁ + θ₂, B = θ₁을 넣은 것이다. 7.7절의 ¹J로 하면 더 빠르다. (−8s₂)(8c₂) − (−8s₂)(10 + 8c₂) = 80s₂로 같은 답이다.
det J = 10 × 8 × sin θ₂다. 어깨 각 θ₁은 들어 있지 않다.
θ₂ = 0°(쭉 편 팔)나 180°(다 접은 팔)에서 det J = 0이다. 이런 자세를 특이점(singularity)이라 한다. 정확히는 기구학적 특이점이다.
알아 두기. 좌표계를 바꿔도 det J는 같다. det(RJ) = det R × det J이고, 회전행렬은 det R = 1이기 때문이다. 그래서 특이점은 어느 좌표계에서 찾아도 같다. 식이 가장 간단한 좌표계를 골라 det를 계산하면 된다.
특이점에서 무슨 일이 생기나
팔을 쭉 펴면 p1E와 p2E가 같은 줄 위에 놓인다. 그러면 둘을 90° 돌린 두 열도 같은 줄(팔에 수직인 방향) 위에 놓인다. 어깨를 돌려도, 팔꿈치를 돌려도 손끝은 팔에 수직으로만 움직인다. 두 관절을 어떻게 섞어도 팔 방향의 속도는 0이다.
- (가) 쭉 편 팔: 손끝이 닿는 고리의 바깥 끝(18 cm)이다. 더 멀리 나갈 수 없으니 당연하다.
- (나) 다 접은 팔: 고리의 안쪽 끝(2 cm)이다. 이때는 받침 쪽으로도, 받침에서 멀어지는 쪽으로도 그 순간에는 움직이지 못한다.
정리하면 특이점에서는 열들이 서로 기대어 자코비안의 계수(rank)가 줄어든다. 종이 팔은 계수가 2에서 1로 준다. 손끝이 움직일 수 있는 방향이 평면 전체에서 한 줄로 줄었다는 뜻이다.
수학 더하기: 계수(rank). 행렬의 열 가운데 서로 기대지 않는 열의 최대 개수를 계수라 한다. "기대지 않는다"는 다른 열을 섞어서 만들 수 없다는 뜻이다. 정사각 행렬은 계수가 꽉 찼을 때만 det ≠ 0이다. 정사각이 아닌 자코비안은 det 대신 계수로 특이점을 판단한다.
관절이 6개인 스탠퍼드 팔의 J는 6 × 6이다. 보통은 계수가 6이고, 특이점에서 5 이하로 떨어진다.
잠깐, 생각해 보기. 7.4절의 6줄 자코비안은 θ₁ = θ₂ = 0°에서도 두 열이 비례하지 않는다. 열 1은 (0, 18, 0, 0, 0, 1), 열 2는 (0, 8, 0, 0, 0, 1)이다. 그런데 왜 특이점이라고 하나?
종이 팔에 시키는 일은 손끝 위치 (x, y) 두 개다(2장의 작업 좌표 m₀ = 2). 그래서 그 일에 쓰는 Jv의 x, y 두 줄만 본다. 그 2 × 2의 계수가 1로 떨어지니 위치로는 특이점이다. 손 방향까지 고르려면 평면에서도 관절이 3개 필요하다(2장).
영상에서 보기: 1:05:38 기구학적 특이점 · 1:06:38 팔을 쭉 펴면 · 1:07:09 두 열이 기댄다
7.10 특이점 가까이: 관절이 너무 빨리 돌아야 한다
특이점 바로 위만 문제가 아니다. 가까이 가기만 해도 문제가 생긴다.
손끝을 바깥으로 1 cm/s 밀려면
받침에서 손끝까지의 거리를 r이라 하자. 코사인 법칙으로 r² = 10² + 8² + 2·10·8 cos θ₂ = 164 + 160 cos θ₂다. r은 θ₂만으로 정해진다. 어깨는 팔을 통째로 돌릴 뿐 거리를 바꾸지 못한다.
양변을 시간으로 미분하면 2r ṙ = −160 sin θ₂ · θ̇₂다. 손끝을 받침에서 멀어지는 쪽으로 ṙ = 1 cm/s 보내려면, 팔꿈치는 이 빠르기로 돌아야 한다.
| θ₂ | 90° | 30° | 10° | 3° | 1° |
|---|---|---|---|---|---|
| r (cm) | 12.8 | 17.4 | 17.9 | 18.0 | 18.0 |
| 팔꿈치 빠르기 (rad/s) | 0.16 | 0.43 | 1.29 | 4.30 | 12.89 |
| 1초에 도는 각도 | 9° | 25° | 74° | 246° | 739° |
θ₂가 0°에 가까워지면 sin θ₂가 0으로 가고, 필요한 빠르기는 끝없이 커진다. 손끝은 겨우 1 cm/s로 움직이는데, θ₂ = 1°에서는 팔꿈치가 1초에 두 바퀴 넘게 돌아야 한다. 진짜 모터는 그렇게 못 돈다.
해 볼 것 세 가지:
- θ₂ = 90° 근처에서는 타원이 통통하다. 손끝이 어느 방향으로나 비슷하게 움직일 수 있다.
- θ₂를 0°로 천천히 내린다. 타원이 팔에 수직인 선분으로 납작해지고, det J 그래프의 점이 0으로 내려간다. 아래 숫자(필요한 팔꿈치 빠르기)는 폭발한다.
- θ₂를 180°로 올려도 마찬가지다. 다 접은 팔의 특이점이다.
수학 더하기: 2 × 2 역행렬. [[a, b], [c, d]]의 역행렬은 (1/det) × [[d, −b], [−c, a]]다. 손끝 속도에서 관절 속도를 구할 때(θ̇ = J⁻¹ẋ) 이 1/det가 곱해진다. det가 0에 가까우면 아주 큰 수가 나온다. 이런 행렬을 "조건이 나쁘다"(ill-conditioned)고 한다.
종이 팔에 쓰면 아래와 같다. 앞에 붙은 1/(80 sin θ₂) 때문에 위 표의 숫자가 커진다.
알아 두기. 실제 로봇에서 특이점 근처의 손끝 속도 명령을 J⁻¹로 그대로 바꾸면 모터 속도 한계를 넘거나 팔이 덜컥거린다. 그래서 길을 짤 때 특이점을 비켜 가거나, 가까워지면 속도를 줄인다. 손끝 속도로 팔을 움직이는 방법(resolved-rate 제어)은 8장에서 다룬다.
스탠퍼드 팔의 특이점 미리 보기
7.8절의 스탠퍼드 팔 자코비안은 오른쪽 위가 0인 덩어리 모양이었다. 이런 행렬의 det는 왼쪽 위 3 × 3의 det와 오른쪽 아래 3 × 3의 det를 곱한 것이다. 계산하면 이렇다.
그래서 특이점은 세 가지다.
- d₃ = 0: 손목점이 어깨 축 위에 온다. 어깨를 돌려도 W가 움직이지 않는다.
- θ₂ = 0° 또는 180°: 붐이 똑바로 위나 아래를 보아 z₁과 나란해진다.
- θ₅ = 0° 또는 180°: 손목 축 z₄와 z₆이 한 줄이 된다. 손이 한 방향으로는 돌 수 없다.
교수는 다음 강의에 실제 스탠퍼드 팔을 가져와 손목 특이점을 보여 준다. 8장에서 자세히 본다.
영상에서 보기: 1:07:42 다음 시간: 손목 특이점 · 1:08:14 특이점 근처는 조건이 나쁘다
7.11 연습문제
종이에 화살표를 그리면서 푼다. 답은 문제 8개 아래에 있다.
- 관절이 회전–직동–회전(RPR) 순서인 팔이 있다. 손끝 점은 E다. Jv와 Jω의 세 열을 zi와 piE로 적어라.
- 종이 팔이 θ₁ = 60°, θ₂ = 30°에 있다.
- p1E와 p2E를 구하라.
- 두 화살표를 90° 돌려 J를 만들어라.
- 7.1절의 미분 꼴에 각도를 넣은 값과 비교하라.
- det J를 구하라.
- 문제 2의 자세에서 θ̇₁ = 0.3 rad/s, θ̇₂ = 0.1 rad/s로 돌린다. 손끝 속도 (vx, vy)와 손끝 각속도 ωz는?
- 문제 2의 J를 링크 1 좌표계 {1}로 옮겨라. 7.7절의 ¹Jv 식에 θ₂ = 30°를 넣은 값과 같은지, det도 같은지 확인하라.
- 돌림판 종이 팔(7.5절)이 θ₁ = 0°, θ₂ = 0°, θ₃ = 90°에 있다. 링크 1은 x₀ 방향으로 누워 있고 팔뚝은 똑바로 위를 본다. 이때 어깨·팔꿈치 축은 z₂ = z₃ = (0, −1, 0)이다. Jv와 Jω, det Jv를 구하라.
- 종이 팔이 θ₁ = 0°, θ₂ = 180°(다 접은 자세)에 있다. J를 구하고, 손끝이 움직일 수 없는 방향을 말하라.
- θ₁ = 0°에서 손끝을 받침에서 멀어지는 쪽으로 1 cm/s 보내려 한다. θ₂ = 30°일 때와 3°일 때 필요한 관절 속도 θ̇ = J⁻¹ẋ를 구하라. 팔꿈치 빠르기는 몇 배가 되나?
- 스탠퍼드 팔에서 속도를 재는 점을 W가 아니라 집게 끝 E로 바꾼다. E는 z₆ 축 위, W에서 10 cm 앞에 있다. Jv의 4, 5, 6열 가운데 여전히 0인 열은?
답
답 1. 7.2절의 표대로 관절마다 한 열씩 적는다. 직동인 관절 2는 선속도에 z₂만 보태고 각속도에는 아무것도 보태지 않는다.
답 2.
- 손끝 = 10(cos 60°, sin 60°) + 8(cos 90°, sin 90°) = (5, 8.66) + (0, 8) = (5, 16.66)이다. 어깨가 원점이라 p1E = (5, 16.66)이다. 팔꿈치는 (5, 8.66)이므로 p2E = (0, 8)이다.
- (a, b)를 (−b, a)로 돌린다. 열 1 = (−16.66, 5), 열 2 = (−8, 0)이다.
- 미분 꼴: −10 sin 60° − 8 sin 90° = −16.66, 10 cos 60° + 8 cos 90° = 5, −8 sin 90° = −8, 8 cos 90° = 0. 같다.
- det J = (−16.66)(0) − (−8)(5) = 40이다. 80 sin 30° = 40과 맞는다.
답 3. 열을 섞는다. v = 0.3 × (−16.66, 5) + 0.1 × (−8, 0) = (−5.00 − 0.80, 1.50) = (−5.80, 1.50) cm/s다. 각속도는 Jω의 마지막 줄 (1, 1)로 ωz = 0.3 + 0.1 = 0.4 rad/s다. 손끝 방향이 시계 반대 방향으로 돈다.
답 4. R(60°)ᵀ = [[0.5, 0.866], [−0.866, 0.5]]를 곱한다.
- 열 1: (0.5 × (−16.66) + 0.866 × 5, −0.866 × (−16.66) + 0.5 × 5) = (−4.00, 16.93)
- 열 2: (0.5 × (−8), −0.866 × (−8)) = (−4.00, 6.93)
식으로는 −8 sin 30° = −4, 10 + 8 cos 30° = 16.93, 8 cos 30° = 6.93이다. 같다. det = (−4)(6.93) − (−4)(16.93) = 40으로 {0}에서와 같다.
답 5. 손끝 E = (10, 0, 8), 팔꿈치 = (10, 0, 0)이다. 돌림판 축과 어깨 축은 원점을 지난다.
- 열 1: z₁ × p1E = (0, 0, 1) × (10, 0, 8) = (0, 10, 0). 돌림판을 돌리면 손끝이 y₀ 쪽으로 간다. 높이 8은 사라졌다.
- 열 2: z₂ × p2E = (0, −1, 0) × (10, 0, 8) = (−8, 0, 10). 어깨를 들면 손끝이 뒤로 8, 위로 10의 비율로 움직인다.
- 열 3: z₃ × p3E = (0, −1, 0) × (0, 0, 8) = (−8, 0, 0). 팔꿈치를 돌리면 위를 보던 팔뚝이 뒤로 눕는다.
det Jv = −800이라 특이점이 아니다. 아무 자세에서나 계산하면 det Jv = −80 r sin θ₃이다. r = 10 cos θ₂ + 8 cos(θ₂ + θ₃)는 손끝에서 돌림판 축까지의 수평 거리다. θ₃ = 0°, 180°(종이 팔과 같은 특이점)와 r = 0(7.5절의 손끝이 축 위)에서 0이 된다.
답 6. 손끝 = (10 − 8, 0) = (2, 0)이다. p1E = (2, 0)을 돌리면 열 1 = (0, 2), p2E = (−8, 0)을 돌리면 열 2 = (0, −8)이다.
첫 줄이 모두 0이라 vx를 만들 수 없다. 손끝은 x 방향(팔이 놓인 방향)으로 그 순간 움직이지 못하고, y 방향으로만 갈 수 있다.
답 7. θ₂ = 30°에서 손끝은 (10 + 8 cos 30°, 8 sin 30°) = (16.93, 4.0), r = 17.39다. 바깥 방향 단위벡터 (0.973, 0.230)을 ẋ로 놓고 J⁻¹을 곱하면 θ̇ = (0.19, −0.43) rad/s다. θ₂ = 3°에서는 θ̇ = (1.91, −4.30) rad/s다.
팔꿈치 빠르기가 약 10배(4.30 ÷ 0.43)가 된다. 각도가 10분의 1이 되면서 sin θ₂도 거의 10분의 1이 되었기 때문이다. 팔꿈치 값이 음수인 것은 팔을 펴는 쪽(θ₂를 줄이는 쪽)으로 돈다는 뜻이다.
답 8. 6열만 0이다. 6열의 위 칸은 z₆ × p6E인데, p6E가 z₆ 축 위에 놓여 z₆과 나란하므로 0이다.
4, 5열은 z₄ × p4E, z₅ × p5E로 보통 0이 아니다. 손목을 꺾으면 집게 끝이 움직이기 때문이다. Jω는 점과 상관없이 그대로다.
파이썬으로 확인
파이썬(numpy)이 있으면 아래를 붙여 넣어 돌려 본다. 주석의 값이 그대로 나온다. 명시적 형태(z × p)로 만든 자코비안을 미분 꼴과 맞춰 보고, 스탠퍼드 팔은 위치를 조금씩 움직여 잰 미분값과 맞춰 본다.
import numpy as np
np.set_printoptions(precision=2, suppress=True)
D = np.pi / 180
def jacobian_explicit(kinds, axes, points, E):
"""명시적 형태: 회전 관절 열 = [z × p ; z], 직동 관절 열 = [z ; 0].
points[i]는 관절 i의 축 위 한 점, p = E - points[i]."""
cols = []
for k, z, o in zip(kinds, axes, points):
z = np.asarray(z, float)
if k == 'R':
cols.append(np.r_[np.cross(z, E - o), z])
else:
cols.append(np.r_[z, 0, 0, 0])
return np.array(cols).T
def rot_z(deg):
c, s = np.cos(deg * D), np.sin(deg * D)
return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
def paper_arm(t1, t2):
"""종이 팔의 팔꿈치와 손끝 (z = 0인 3차원 점)."""
elbow = np.array([10 * np.cos(t1 * D), 10 * np.sin(t1 * D), 0])
hand = elbow + [8 * np.cos((t1 + t2) * D), 8 * np.sin((t1 + t2) * D), 0]
return elbow, hand
def paper_J(t1, t2):
"""명시적 형태로 만든 종이 팔 자코비안 (6 × 2)."""
elbow, hand = paper_arm(t1, t2)
z = [0, 0, 1]
return jacobian_explicit('RR', [z, z], [np.zeros(3), elbow], hand)
def paper_J_diff(t1, t2):
"""6장: 손끝 위치를 미분한 꼴 (2 × 2)."""
s1, c1 = np.sin(t1 * D), np.cos(t1 * D)
s12, c12 = np.sin((t1 + t2) * D), np.cos((t1 + t2) * D)
return np.array([[-10 * s1 - 8 * s12, -8 * s12], [10 * c1 + 8 * c12, 8 * c12]])
# 7.4: 그림 7-2의 처음 자세 (6.3절과 같은 값)
print(paper_J(30, 60)[:2]) # [[-13. -8. ] [ 8.66 0. ]]
# 문제 2: 두 방법이 같다
J = paper_J(60, 30)
print(J.T) # [[-16.66 5. 0. 0. 0. 1. ] [ -8. 0. 0. 0. 0. 1. ]]
print(paper_J_diff(60, 30)) # [[-16.66 -8. ] [ 5. 0. ]]
print(round(np.linalg.det(J[:2]), 2)) # 40.0 (= 80 sin 30°)
# 문제 3: 열을 섞는다
print(J @ [0.3, 0.1]) # [-5.8 1.5 0. 0. 0. 0.4]
# 7.7, 문제 4: {1}로 옮기기 [[R, 0], [0, R]]
R10, Z = rot_z(60).T, np.zeros((3, 3))
J1 = np.block([[R10, Z], [Z, R10]]) @ J
print(J1[:2]) # [[-4. -4. ] [16.93 6.93]]
print(round(np.linalg.det(J1[:2]), 2)) # 40.0
# 7.9: det J = 80 sin θ2, θ1과 상관없다
print([float(round(np.linalg.det(paper_J(t1, 45)[:2]), 2)) for t1 in (0, 70, -120)]) # [56.57, 56.57, 56.57]
# 문제 6: 다 접은 팔
print(np.round(paper_J(0, 180)[:2], 6) + 0.0) # [[ 0. 0.] [ 2. -8.]]
# 문제 7: 특이점 가까이, 바깥으로 1 cm/s
for t2 in (30, 3):
_, hand = paper_arm(0, t2)
out = hand[:2] / np.linalg.norm(hand[:2])
print(t2, np.linalg.solve(paper_J(0, t2)[:2], out)) # 30 [ 0.19 -0.43] / 3 [ 1.91 -4.3 ]
# 문제 5: 돌림판 종이 팔 (θ1, θ2, θ3) = (0°, 0°, 90°)
z1, z2 = [0, 0, 1], [0, -1, 0]
O, elbow, hand = np.zeros(3), np.array([10.0, 0, 0]), np.array([10.0, 0, 8])
Jt = jacobian_explicit('RRR', [z1, z2, z2], [O, O, elbow], hand)
print(Jt) # [[ 0. -8. -8.] [10. 0. 0.] [ 0. 10. 0.] [ 0. 0. 0.] [ 0. -1. -1.] [ 1. 0. 0.]]
print(round(np.linalg.det(Jt[:3]), 2)) # -800.0
# 7.8: 스탠퍼드 팔. T를 받침부터 곱하며 셋째 열(z)과 넷째 열(원점)을 모은다
def dh(alpha, a, d, theta):
ca, sa, ct, st = np.cos(alpha * D), np.sin(alpha * D), np.cos(theta * D), np.sin(theta * D)
return np.array([[ct, -st, 0, a], [st * ca, ct * ca, -sa, -sa * d],
[st * sa, ct * sa, ca, ca * d], [0, 0, 0, 1]])
def stanford(q, d2=15):
t1, t2, d3, t4, t5, t6 = q
rows = [(0, 0, 0, t1), (-90, 0, d2, t2), (90, 0, d3, 0),
(0, 0, 0, t4), (-90, 0, 0, t5), (90, 0, 0, t6)]
T, Ts = np.eye(4), []
for r in rows:
T = T @ dh(*r) # 0→1, 0→2, 0→3, ... 차례로
Ts.append(T)
return Ts
q = np.array([30, 50, 40, 20, 60, 10.0]) # 각도는 도, d3는 cm
Ts = stanford(q)
W = Ts[-1][:3, 3] # 손목점 = 넷째 열
Js = jacobian_explicit('RRPRRR', [T[:3, 2] for T in Ts], [T[:3, 3] for T in Ts], W)
print(np.round(Js[:3, 3:], 6) + 0.0) # [[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]] 손목은 W를 못 옮긴다
num = np.zeros((3, 6))
for i in range(6): # 위치를 조금씩 움직여 잰 미분
h = 1e-6 if i == 2 else 1e-6 / D
dq = np.zeros(6); dq[i] = h
num[:, i] = (stanford(q + dq)[-1][:3, 3] - W) / 1e-6
print(np.allclose(Js[:3], num, atol=1e-4)) # True
print(round(np.linalg.det(Js), 2), round(40**2 * np.sin(50 * D) * np.sin(60 * D), 2)) # 1061.46 1061.46
스탠퍼드 숙제
스탠퍼드 강의 페이지의 Homework 3을 이 장으로 마저 푼다. 1번은 6장으로도 풀 수 있지만, 변환행렬의 셋째 열(축)과 넷째 열(위치)을 읽는 7.6절 방법으로 다시 풀어 보면 좋다. 2번 (c)는 7.9절의 특이점이다.
3번은 (a)(b)가 4~5장의 DH 표와 순기구학이고, (c)가 7.6절, (d)가 7.7절, (e)(f)가 7.9절이다. 풀이는 같은 페이지의 Solution 3에 있다.
다 풀었으면 7강 영상을 한 번 본다.