
Ch6. ROS2 ํ์ต์ ์ํ Python Class ์ดํดํ๊ธฐ
์ด ์ฑํฐ๋ ๋ด์ฉ์ด ์ ์ฒด์ ์ผ๋ก class์ ์ดํด์ ๊ด๋ จ๋์ด ์๊ณ , ROS๊ด๋ จ ๋ด์ฉ์ด ์๋ค๋ ์ ์ ๋ฐํ๊ณ , ์์ํ๋ค.
1. ์ค๋น์์ ๋ฐ ๊ทธ๋ฅ sin ํจ์ ๊ทธ๋ ค๋ณด๊ธฐ
ํ๋ ๊ฒ์ฒ๋ผ python ํด๋์์ jupyter notebook์ ์ด๊ณ ์ด๋ฒ์๋ Class Study์ ๋ํ ๋ด์ฉ์ ๋ด์ ๊ฒ์ด๋ฏ๋ก ๊ทธ๋ ๊ฒ ์ด๋ฆ์ ์ง๋๋ค.
์ด๋ฒ์ ๊ทธ๋ฆด ์ผ๊ฐํจ์์ ์์์ ๋ค์๊ณผ ๊ฐ๋ค.
Asin(2pift)+B
๊ฐ์ฅ ๋จผ์ ์ด sin ํจ์๋ฅผ ๋ํ๋ด๊ธฐ ์ํด์ matplotlib์ ์ค๋นํด์ค์ผ ํ๋ค
๋ค์ ์ฝ๋๋ฅผ ์ด์ฉํด matplotlib์ ์ค์นํ๊ณ , ์ด ํจํค์ง๋ค์ import ํด์ฃผ์
pip3 install matplotlib
import matplotlib.pyplot as plt
import numpy as np
์ดํ numpy๋ฅผ ์ด์ฉํด 0๋ถํฐ 6๊น์ง 0.01 ๊ฐ๊ฒฉ์ผ๋ก ์ซ์๋ฅผ ์์ฑํด ๋ฐฐ์ด๋ก ๋ง๋๋ ์ฝ๋๋ฅผ ์คํํ ํ ์ด๋ฅผ ํ์ธํด ์ค๋ค.
์ด๋์ t๋ ๋ ๋ฆฝ๋ณ์, ์ ์์ญ(domain)์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
t = np.arange(0, 6, 0.01)
t

๋ง์ฝ ๋ฐฐ์ด์ ํฌ๊ธฐ(ํํ)๋ฅผ ํ์ธํ๊ณ ์ถ๋ค๋ฉด ๋ค์ ์ฝ๋๋ฅผ ํตํด ๊ฐ๋ฅํ๋ค.
t.shape

์ดํ ๋ค์ ์ฝ๋๋ฅผ ์ด์ฉํด์ numpy๋ฅผ ์ด์ฉํด์ sin ํจ์์ t๋ค์ ๋ค ์ง์ด๋ฃ๊ณ shape์ ํ์ธํ๋ค๋ฉด ๋์ผํ๊ฒ 600์ด ๋์ค๊ฒ ๋๋ค.
y = np.sin(np.pi * t)
y.shape
์ดํ matplotlib์ ์ด์ฉํด ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆด ๊ฒ์ด๊ณ , ๋ค์์ ์ฝ๋๋ฅผ ์ด์ฉํ๋ฉด sin ํจ์๋ฅผ ๊ทธ๋ฆด ์ ์๋ค.
plt.figure(figsize=(12,6))
plt.plot(t, y)
plt.grid()
plt.show()

๋ํ ๋ฒ์๋ฅผ 6๊น์ง๊ฐ ์๋ 3๊น์ง๋ก ๋ฐ๊พธ๋ฉด ๋ค์์ ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆด ์ ์๋ค.
t1 = np.arange(0, 3, 0.01)
y1 = np.sin(np.pi * 5 * t1)
plt.figure(figsize=(12,6))
plt.plot(t1, y1)
plt.grid()
plt.show()

์ดํ ์ด ์ฝ๋๋ฅผ def๋ฅผ ์ด์ฉํด ํจ์๋ก ๊ตฌํํด๋ณด๊ณ ์ ํ๋ค.
์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ํธํ๊ณ , ์ค๋ฅ๋ฅผ ์ค์ด๊ธฐ ์ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉฐ ๊ทธ ์์๋ค์ ๋ฐ์์ ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆฌ๋ ํจ์๋ฅผ ๋ง๋ค์๋ค.
def draw_sin(t, A, f, b):
y = A * np.sin(np.pi * f * t) + b
plt.figure(figsize=(12, 6))
plt.plot(t1, y1)
plt.grid()
plt.show()
๊ทธ๋ฆฌ๊ณ ๋ค์์ ์ฝ๋๋ฅผ ์ด์ฉํ๋ฉด ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆด ์ ์๋ค.
t = np.arange(0, 3, 0.01)
draw_sin(t, 1, 1, 0)

2. ํด๋์ค๋ก sin ํจ์ ๊ทธ๋ ค๋ณด๊ธฐ
์ดํ ์ด๋ฅผ ํจ์๊ฐ ์๋ class๋ก ๊ตฌํํ๊ณ ์ ํ๋ค.
๊ฐ์ฅ ๋จผ์ ํด๋์ค์ ๋ณ์๋ฅผ ๋ฑ๋กํ๊ธฐ ์ํด์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
class DrawSin:
def __init__(self, amp, freq, bias, end_time) :
self.amp = amp
self.freq = freq
self.bias = bias
self.end_time = end_time
์ด๋ ๊ฒ ์์ฑํ ํด๋์ค๋ DrawSin์ด๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ , ํจ์๋ก ๋๋ init์ ์์ฑํ๊ธฐ ์ํด์ ์ ์ธํ๋ฉฐ, ์ดํ ๋ณ์๋ค์ ๋ฃ์ด๋ฌ์ ์ถํ์ ์ด์ฉํ๋๋ก ํ๋ค.
์ด๋ฅผ ์ด์ฉํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
tmp = DrawSin(1,1,0,3)
tmp.__dict__

๋ํ ๊ฐ๊ฐ์ ์์๋ฅผ ํ์ธํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ํ์ธ์ด ๊ฐ๋ฅํ๋ค.
tmp.amp, tmp.freq, tmp.bias, tmp.end_time

์ถํ ๋ณ์๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ๋ค๋ฉด ๋ค์์ ๋ฐฉ์์ผ๋ก ์งํํ๋ฉด ๋๋ค.
tmp.end_time = float(5)
tmp.__dict__

์ด๋ ๊ฒ ๋ณ์๋ฅผ ์ง์ ํ ๋ค ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํด์ calc_sin, draw_sin ํจ์๋ฅผ ์ถ๊ฐํด sin ํจ์๋ฅผ ๊ทธ๋ฆฌ๋ ์ฝ๋๋ฅผ ์์ฑ๊ฐ๋ฅํ๋ค.
class DrawSin:
def __init__(self, amp, freq, bias, end_time):
self.amp = amp
self.freq = freq
self.bias = bias
self.end_time = end_time
def calc_sin(self):
self.t = np.arange(0, self.end_time, 0.01)
return self.amp * np.sin(2*np.pi*self.freq*self.t) + self.bias
def draw_sin(self):
y= self.calc_sin()
plt.figure(figsize=(12,6))
plt.plot(self.t, y)
plt.grid()
plt.show()
์ดํ ๋ค์ ์ฝ๋๋ฅผ ์ด์ฉํ๋ฉด ๊ทธ๋ํ๋ฅผ ๊ทธ๋ฆด ์ ์๋ค.
ds = DrawSin(1,1,0,3)
ds.draw_sin()

์ด ds์์ freq๋ง ๋ณ๊ฒฝํ๋ฉด ๋ค์๊ณผ ๊ฐ์์ง๋ค.
ds.freq = 2
ds.draw_sin()

3. ํด๋์ค์ ์์ Inheritance
์ด๋ฒ์๋ cos์ ๋ง๋ค์ด๋ณด๊ณ ์ ํ๋ค. ํ์ง๋ง, sin๊ณผ ๋๋ถ๋ถ์ด ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ด์ฉํ๋ฉด ํธํ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์ด๋ ๋๋ถ๋ถ์ ๊ฐ์ ธ์ค๊ณ ์ผ๋ถ๋ถ๋ง ์ถ๊ฐํ๋ ๊ธฐ๋ฅ์ด inheritance์ธ ํด๋์ค์ ์์์ด๋ค.
๋ค์ ์ฝ๋๋ DrawSin์ ์์๋ฐ์ผ๋ฉด์ ๋ง๋ DrawSinusoidal์ด๋ค.
class DrawSinusoidal(DrawSin):
def calc_cos(self):
self.t = np.arange(0, self.end_time, 0.01)
return self.amp * np.cos(2*np.pi*self.freq*self.t) + self.bias
def draw_cos(self):
y = self.calc_cos()
plt.figure(figsize=(12,6))
plt.plot(self.t, y)
plt.grid()
plt.show()
class ํด๋์ค๋ช (์์๋ฐ์ ํด๋์ค) ์ด๋ ๊ฒ ์์ฑํ๋ฉด ์์์ด ๊ฐ๋ฅํ๋ค.
์ดํ ๋ค์ ์ฝ๋๋ฅผ ๋ณด๋ฉด dc๋ผ๋ ์ด๋ฆ์ผ๋ก ๊ฐ์ฒดํํ์๊ณ , ๋๋ init์ด ์์์๋ ์์๋ฐ์๊ธฐ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
dc = DrawSinusoidal(1,1,0,3)
dc.__dict__

dc.__dir__()

๋ฐ๋ผ์ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด cos๊ณผ sin ๋ ๋ค ์ ์๋ํจ์ ์ ์ ์๋ค.
dc.draw_cos()

dc.draw_sin()

4. ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋ฉ Method Overriding
์ค๋ฒ๋ผ์ด๋ฉ์ด๋ ๋ฎ์ด์ฐ๊ธฐ์ด๋ค. ์์ ๊ทธ๋ํ๋ ์ค๋ช ์ด ์๊ณ , ์ดํ ๋ก๋ฒ๋ผ์ด๋ฉํด์ ์ค๋ช ์ ์ถ๊ฐํด์ฃผ๊ณ ์ ํ๋ค.
์ด๋๋ ์์ํ๋ ๊ฒ์ฒ๋ผ ํด๋์ค๋ฅผ ์์ฑํ ๋ค ์ดํ ์์ ๊ฐ์ ์ด๋ฆ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ฎ์ด์ฐ๊ธฐ๊ฐ ๋๋ค.
class DrawSinusoidal2(DrawSinusoidal):
def draw_sin(self):
y = self.calc_sin()
plt.figure(figsize=(12,6))
plt.plot(self.t, y)
plt.title('Sin Graph ')
plt.ylabel('Sin')
plt.xlabel('time (sec)')
plt.grid()
plt.show()
์ดํ ์ด๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
dc2 = DrawSinusoidal2(1,1,0,3)
dc2.draw_sin()

5. ํด๋์ค์์ super()์ ์ฌ์ฉ
์ด๋ฐ ํด๋์ค๋ค์ ๋ง๋ค๋ฉด์ ์ด์ sin/cos, A, f, t, B๋ฅผ ์ ํ ์ ์์๋๋ฐ ๋๋ฉ์ธ์ธ t์ ๊ฐ๊ฒฉ์ ๋ณ๊ฒฝํ ์ ์ด ์๋ค.
๋ฐ๋ผ์ ์ด๋ฅผ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ํจ์๋ฅผ ์์ฑํ๊ณ ์ ํ๋ค.
class DrawSinusoidal3(DrawSinusoidal2) :
def __init__(self, amp, freq, bias, end_time, ts):
self.ts = ts
ds3 = DrawSinusoidal3(1,1,0,3, 0.01)
ds3.__dict__

์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์๊ธฐ๋ ๋ฌธ์ ์ ์ ์์์ ๋๋ init์ ์ค๋ฒ๋ผ์ด๋ฉ์ ์งํํ๋๋ฐ, ๋ณ์๋ฅผ ts๋ง ๋ฃ์ด์คฌ๊ธฐ ๋๋ฌธ์ ts๋ง ๋จ๋ ๋ฌธ์ ์ ์ด ์๊ธด๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ super()๋ฅผ ์ด์ฉํด ์์๋ ์์ฑ๋ค์ ๋์ด์ค๋ ๊ฒ์ด๋ค.
class DrawSinusoidal3(DrawSinusoidal2):
def __init__(self, amp, freq, bias, end_time, ts):
super().__init__(amp, freq, bias, end_time)
self.ts = ts
ds3 = DrawSinusoidal3(1,1,0,3,0.01)
ds3.__dict__

class DrawSinusoidal3(DrawSinusoidal2):
def __init__(self, amp, freq, bias, end_time, ts):
super().__init__(amp, freq, bias, end_time)
self.ts = ts
def calc_sin(self):
self.t = np.arange(0, self.end_time, self.ts)
return self.amp * np.sin(2*np.pi*self.freq*self.t) + self.bias
def draw_sin(self):
y = self.calc_sin()
plt.figure(figsize=(12,6))
plt.plot(self.t, y)
plt.title('Sin Graph ')
plt.ylabel('Sin')
plt.xlabel('time (sec)')
plt.grid()
plt.show()
\์ด๋ ๊ฒ ์ต์ข ์ ์ผ๋ก class๋ฅผ ์์ฑํ ๋ค ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ๋๋ ค ๊ทธ๋ํ๋ฅผ ๋๋ ค๋ณด์๋ค.
ds3 = DrawSinusoidal3(1,1,0,3,0.1)
ds3.draw_sin()

์ด ๊ทธ๋ํ๋ฅผ ๋ณด๋ฉด ๋ฐ์ดํฐ ๊ฐ๊ฒฉ์ด 0.1์ด ๋์ด์ ์ด ๋ฐ์ดํฐ ๊ฐ์๊ฐ 60๊ฐ๊ฐ ๋์๊ธฐ ๋๋ฌธ์ ์กฐ๊ธ์ ๋ญ๊ฐ์ง ๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์๋ค.
6. ๋ง๋ฌด๋ฆฌ
๋ค์์๋ Ch7์ ๋ด์ฉ์ธ ํจํค์ง ๋ง๋ค๊ณ ํ ํฝ ๋ค๋ฃจ๊ธฐ์ ๋ํด์ ์ ์ด๋ณผ ์์ ์ด๋ค.
์๋ ํ์ผ์ ์์์ ์์ฑํ ์ฝ๋๋ค์ ํ ํ์ผ๋ก ๋ง๋ ํ์ผ์ด๋ค.