Kinematics ์ฝ๋ ์ค๋ช
Kinematic class ์ค๋ช
1. ํด๋์ค ์์ฑ์ - init
๋ค๋ฆฌ ๊ธธ์ด ๋ฐ ๋ชธํต์ ๊ธธ์ด ๋๋น ๋ฑ์ ํ๋ผ๋ฏธํฐ ์ ๋ ฅ์ ํด์ฃผ๋ ๊ณณ์ ๋๋ค.
def __init__(self):
self.l1=50
self.l2=20
self.l3=100
self.l4=100
self.L = 140
self.W = 75
#leg iterators. ex. LEG_BACK + LEG_LEFT -> array[2]
self.LEG_FRONT = 0
self.LEG_BACK = 2
self.LEG_LEFT = 0
self.LEG_RIGHT =1
#thetas, which will be used on controllers
self.thetas = np.array([[0, 0, 0],[0, 0, 0],[0, 0, 0],[0, 0, 0]], dtype=np.float64)
- L : ๋ก๋ด ๋ชธํต์ ๊ธธ์ด
- W: ๋ก๋ด ๋ชธํต์ ๋๋น
๊ฐ๋ชจํฐ๋ค์ ๊ฐ๋๋ค์ ๋ชจ์ ๋ thetas ๋ฐฐ์ด์ด ์ ์ธ๋์ด ์์ผ๋ฉฐ, ์ด๋ 4๊ฐ์ ๋ค๋ฆฌ * 3๊ฐ์ ๋ชจํฐ์ ๋ฐ๋ผ 12๊ฐ์ ๊ฐ์ ๊ฐ์ต๋๋ค.
#leg iterators. ex. LEG_BACK + LEG_LEFT -> array[2]
self.LEG_FRONT = 0
self.LEG_BACK = 2
self.LEG_LEFT = 0
self.LEG_RIGHT = 1
๊ฐ ๋ค๋ฆฌ์ ์ ๊ทผํ๊ธฐ ์ํด ๋ฒํธ๊ฐ ๋ถ์ผ๋ฉฐ,
์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ์์คํ ์์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ์์๋ก ๋ฒํธ๊ฐ ๋งค๊ฒจ ์์ต๋๋ค.
์ ์ฝ๋๋ ์ด๋ฐ ์ ๊ทผ์ ์ํ ์ฝ๋์ ๋๋ค.
์๋ฅผ ๋ค์ด
- Front Left :
self.LEG_FRONT
+self.LEG_LEFT
= 0
- Back Right :
self.LEG_BACK
+self.LEG_RIGHT
= 3
์ด๋ฐ ์์ผ๋ก ์ ๊ทผ์ด ์ด๋ฃจ์ด์ง๋ ๊ฒ์ด์ง์
2. bodyIK ํจ์
์ํ๋ ๋ก๋ด ๋ชธ์ฒด์ ์์น/๊ฐ๋๋ฅผ Input ํ๋ฉด ์ด์ ๋ํ ๋ณํ ํ๋ ฌ์ Output ํด์ฃผ๋ ํจ์์ ๋๋ค.
def bodyIK(self,omega,phi,psi,xm,ym,zm):
Rx = np.array([[1,0,0,0],
[0,np.cos(omega),-np.sin(omega),0],
[0,np.sin(omega),np.cos(omega),0],[0,0,0,1]])
Ry = np.array([[np.cos(phi),0,np.sin(phi),0],
[0,1,0,0],
[-np.sin(phi),0,np.cos(phi),0],[0,0,0,1]])
Rz = np.array([[np.cos(psi),-np.sin(psi),0,0],
[np.sin(psi),np.cos(psi),0,0],[0,0,1,0],[0,0,0,1]])
Rxyz = Rx.dot(Ry.dot(Rz))
T = np.array([[0,0,0,xm],[0,0,0,ym],[0,0,0,zm],[0,0,0,0]])
Tm = T+Rxyz
sHp=np.sin(pi/2)
cHp=np.cos(pi/2)
(L,W)=(self.L,self.W)
return([Tm.dot(np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]]))])
- ์ฌ๊ธฐ์์ ๋ณํ ํ๋ ฌ์ ํน์ ์ขํ์ ๊ธฐ์ค์ด ๋๋ ์ขํ๊ณ๋ฅผ ๋ณ๊ฒฝํ๋๋ฐ ์ฌ์ฉ๋๋ ํ๋ ฌ์ ๋๋ค.
์ฝ๋์ ์๊ณ ๋ฆฌ์ฆ ์ ๋ณดํํจํด์ ๊ดํ ์ ๋ณด๋ ์์ ์ ๊ธฐ์ค์ผ๋ก ํ ๋ค๋ฆฌ ๋์ ์ ์์น๋ก ์ฃผ์ด์ง๋๋ฐ์,
ํ์ง๋ง ์ด ๋ณดํํจํด์ ๊ตฌํํ๊ธฐ ์ํ ๊ฐ ๋ค๋ฆฌ์ ๋ชจํฐ ๊ฐ๋๋ฅผ ๊ณ์ฐํ๋ Kinematics ๊ณผ์ ์ ์งํํ๋ ค๋ฉด ์์ ์ ๊ธฐ์ค์ผ๋ก ํ ์์น๊ฐ ์๋ ๋ก๋ด์ ๊ฐ ์ด๊นจ ๋ถ๋ถ์ ๊ธฐ์ค์ผ๋ก ํ ๋ค๋ฆฌ ๋์ ์์น๋ฅผ ์์์ผ ํฉ๋๋ค.
⇒ ์ฆ ๊ธฐ์ค ์ขํ๊ณ๋ฅผ ์์ ์์ ๊ฐ ๋ก๋ด์ ์ด๊นจ๋ก ์ฎ๊ฒจ์ผ ํ๋ฏ๋ก ๋ณํ ํ๋ ฌ์ด ํ์ํฉ๋๋ค.
๋ณํ ํ๋ ฌ์ ํ์ ๊ณผ ์ด๋ 2๊ฐ์ง๋ก ๋๋๊ณ , ๊ฐ๊ฐ์ ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์์นํ๊ฒ ๋ฉ๋๋ค. ( ์ ์ผ ํ๋จ ํ์ ๋ฌด์กฐ๊ฑด [0 0 0 1]์ ๊ฐ๊ฒ ๋ฉ๋๋ค.)
⇒ ๋ ์์ธํ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด ๋ก๋ด๊ณตํ ๋์ฐจํ๋ ฌ์ ์ฐพ์๋ณด์๊ธธ
์ ์ฒด์ ์ธ ๋ฐฉํฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ขํ๊ณ๋ฅผ ์์ ์์ ๋ก๋ด ๋ชธ์ฒด ์ค์ฌ์ผ๋ก ๋ฐ๊พธ๋ ํ๋ ฌ๊ณผ
- ๋ก๋ด ๋ชธ์ฒด์์ ๊ฐ ๋ก๋ด ์ด๊นจ๋ก ๋ฐ๊พธ๋ ํ๋ ฌ์ ๊ฐ๊ฐ ๊ตฌํด์ ์๋ก ์ฐ๊ฒฐํ ๊ฒ์ ๋๋ค.
์์ ⇒ ๋ก๋ด ๋ชธ์ฒด ์ค์ฌ์ผ๋ก ์ขํ๊ณ๋ฅผ ๋ณ๊ฒฝ (ํ์ ๋ณํ ํ๋ ฌ)
Rx = np.array([[1,0,0,0],
[0,np.cos(omega),-np.sin(omega),0],
[0,np.sin(omega),np.cos(omega),0],[0,0,0,1]])
Ry = np.array([[np.cos(phi),0,np.sin(phi),0],
[0,1,0,0],
[-np.sin(phi),0,np.cos(phi),0],[0,0,0,1]])
Rz = np.array([[np.cos(psi),-np.sin(psi),0,0],
[np.sin(psi),np.cos(psi),0,0],[0,0,1,0],[0,0,0,1]])
Rxyz = Rx.dot(Ry.dot(Rz))
- ๋ชธ์ฒด์ ๊ธฐ์ธ์ด์ง ๊ฐ๋๋ฅผ ๋ณํ ํ๋ ฌ์ ๋ฐ์ํ๋ ๋ถ๋ถ์ผ๋ก ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ 3์ฐจ์ ํ์ ๋ณํ ํ๋ ฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด๋ ์ฌ์ฉํ๋ 3์ฐจ์ ๊ฐ๋ ํ์ ์ฒด๊ณ๋ ์ค์ผ๋ฌ ๊ฐ๋ ์ด๋ฏ๋ก(z์ถ y์ถ x์ถ ์์๋ก ํ์ ์ํค๋ ์ฒด๊ณ) ๊ณฑํด์ง๋ ํ์ ๋ณํ ํ๋ ฌ์ ์์๋ Rx Ry Rz ๊ฐ ๋ฉ๋๋ค.(๊ณ์ฐ์ ์ค๋ฅธ์ชฝ ํ๋ ฌ๋ถํฐ ์์๋๋ก ๊ณฑํด์ง)
์์ ⇒ ๋ก๋ด ๋ชธ์ฒด ์ค์ฌ(์ด๋ ๋ณํ ํ๋ ฌ)
T = np.array([[0,0,0,xm],[0,0,0,ym],[0,0,0,zm],[0,0,0,0]])
Tm = T + Rxyz
๋ชธ์ฒด์ ์์น์ ๊ดํ ์ ๋ณด๋ฅผ ๋ฐ์ํด ์ฃผ๊ณ ์์์ ๊ตฌํ๋ ํ์ ๋ณํ ํ๋ ฌ๊ณผ ํฉ์ณ ์ต์ข ๋ณํ ํ๋ ฌ์ ์์ฑํฉ๋๋ค.
์ต์ข
์ ์ผ๋ก Tm
ํ๋ ฌ์ ๊ณง, ์์ ์ขํ๊ณ์์ ๋ก๋ด ๋ชธ์ฒด์ ์ค์ฌ ์ขํ๊ณ๋ก ๋ฐ๊พธ์ด์ฃผ๋ ๋ณํ ํ๋ ฌ์ด ๋ฉ๋๋ค.
๋ก๋ด ๋ชธ์ฒด ์ค์ฌ ์ขํ๊ณ ⇒ ์ด๊นจ ์ขํ๊ณ
sHp=np.sin(pi/2)
cHp=np.cos(pi/2)
(L,W)=(self.L,self.W)
return([Tm.dot(np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]])),
Tm.dot(np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]]))])
์์ ์ค๋ช ํ๋ ํ์ &์ด๋ ๋ณํ ํ๋ ฌ์ ํ์ฉํ์ฌ ๋ก๋ด ๋ชธ์ฒด ์ค์ฌ์์ ์ด๊นจ๋ก์ ์ขํ๊ณ ์ด๋์ ์งํํฉ๋๋ค.
- ํ์ ์ y์ถ(๊ทธ๋ฆผ์์์ ๋นจ๊ฐ์ ์ถ) 90๋ ํ์ ์ ์งํํ๊ณ
- ์ด๋์ x์ถ(๊ทธ๋ฆผ์์์ ์ด๋ก์ ์ถ)์ผ๋ก W/2, z์ถ(๊ทธ๋ฆผ์์์ ํ๋์ ์ถ)์ผ๋ก L/2 ์ด๋์ ์งํํฉ๋๋ค.
์ด๋์ ๋ณํ ํ๋ ฌ 4๊ฐ๋ฅผ ๊ณ์ฐํ์ฌ ์ต์ข OUTPUT์ ํฉ๋๋ค.
legIK
์ด๊นจ๋ฅผ ์ค์ฌ์ผ๋ก ํ ๋ค๋ฆฌ ๋์ ์ ์ขํ๊ฐ input ๋๋ฉด ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๊ฐ ๊ด์ ์ ๋ชจํฐ๊ฐ ๊ตฌ๋ํด์ผ ํ ๊ฐ๋๋ฅผ Output ํด์ค๋๋ค.
- image from : mathworks
def legIK(self,point):
(x,y,z)=(point[0],point[1],point[2])
(l1,l2,l3,l4)=(self.l1,self.l2,self.l3,self.l4)
try:
F=sqrt(x**2+y**2-l1**2)
except ValueError:
print("Error in legIK with x {} y {} and l1 {}".format(x,y,l1))
F=l1
G=F-l2
H=sqrt(G**2+z**2)
theta1=-atan2(y,x)-atan2(F,-l1)
D=(H**2-l3**2-l4**2)/(2*l3*l4)
try:
theta3=acos(D)
except ValueError:
print("Error in legIK with x {} y {} and D {}".format(x,y,D))
theta3=0
theta2=atan2(z,G)-atan2(l4*sin(theta3),l3+l4*cos(theta3))
return(theta1,theta2,theta3)
์ด๋ฌํ ๊ณ์ฐ ๊ณผ์ ์ ์ญ๊ธฐ๊ตฌํ(inverse kinematics)๋ผ๊ณ ํ๋ฉฐ, ์ ํํ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ ํ๋ ๊ฒ์ ์ ์ค๋ช ํ๋ ์์์ด ์์ด ๋งํฌ๋ก ๋์ฒดํฉ๋๋ค.
⇒ ์์์ด ๊ธธ์ง ์๊ณ ์ง๊ด์ ์ผ๋ก ์ ์ค๋ช ๋์ด ์์ด ๊ผญ ์์ฒญํ์๊ธธ ์ถ์ฒ๋๋ฆฝ๋๋ค!