def test_clock(): from pyctrl import Controller from pyctrl.block.clock import Clock, TimerClock controller = Controller() period = 0.01 controller.add_signal('clock') clock = Clock() controller.add_source('clock', clock, ['clock']) K = 10 k = 0 while k < K: (t, ) = controller.read_source('clock') k += 1 assert clock.get('count') == 10 controller.set_source('clock', reset=True) (t, ) = controller.read_source('clock') assert t < 0.01 controller.remove_source('clock') clock = TimerClock(period=period) controller.add_source('clock', clock, ['clock']) K = 10 k = 0 while k < K: (t, ) = controller.read_source('clock') k += 1 assert t > 0.9 * K * period controller.set_source('clock', reset=True) (t, ) = controller.read_source('clock') assert t < 0.9 * 2 * period clock.set_enabled(False)
def test_run(): from pyctrl import Controller from pyctrl.block.clock import Clock, TimerClock from pyctrl.block import Map controller = Controller() clock = Clock() controller.add_source('clock', clock, ['clock']) # start/stop with condition controller.add_filter('condition', Map(function=lambda x: x < 1), ['clock'], ['is_running']) controller.set_source('clock', reset=True) controller.start() is_running = controller.get_signal('is_running') while is_running: is_running = controller.get_signal('is_running') controller.stop() tk = controller.get_signal('clock') assert tk > 1 and tk < 1.01 # run with condition controller.set_source('clock', reset=True) controller.run() controller.stop() tk = controller.get_signal('clock') assert tk > 1 and tk < 1.01 controller.remove_source('clock')
def test1(): if not test_ode: return from pyctrl import Controller controller = Controller() Ts = 0.01 clock = TimerClock(period=Ts) controller.add_source('clock', clock, ['clock']) a = -1 b = 1 def f(t, x, u, a, b): return a * x + b * u t0 = 0 uk = 1 x0 = np.array([0]) sys = ODE((1, 1, 1), f, x0=x0, t0=t0, pars=(a, b)) controller.add_signals('input', 'output') controller.add_filter('condition', Map(function=lambda x: x < 1), ['clock'], ['is_running']) controller.add_filter('ode', TimeVaryingSystem(model=sys), ['clock', 'input'], ['output']) controller.add_sink('logger', Logger(), ['clock', 'output']) print(controller.info('all')) controller.set_filter('ode', reset=True) controller.set_source('clock', reset=True) controller.set_sink('logger', reset=True) controller.set_signal('input', uk) controller.run() xk = sys.state log = controller.get_sink('logger', 'log') t0 = log['clock'][0, 0] tk = log['clock'][-1, 0] yk = log['output'][-1, 0] print('t0 = {}'.format(t0)) print('tk = {}'.format(tk)) print('yk = {}'.format(yk)) yyk = uk * (1 - math.exp(a * (tk - t0))) + x0[0] * math.exp(a * (tk - t0)) print(log) print(t0, x0, tk, xk, yk, yyk) assert np.abs(yk - yyk) < 1e-2 uk = 0 x0 = sys.state controller.add_filter('condition', Map(function=lambda x: x < 2), ['clock'], ['is_running']) print(controller.info('all')) print('clock = {}'.format(controller.get_signal('clock'))) #controller.set_source('clock', reset = True) controller.set_sink('logger', reset=True) controller.set_signal('input', uk) controller.run() xk = sys.state print('clock = {}'.format(controller.get_signal('clock'))) log = controller.get_sink('logger', 'log') print('log = {}'.format(log)) t0 = log['clock'][0, 0] tk = log['clock'][-1, 0] yk = log['output'][-1, 0] print('t0 = {}, x0 = {}, tk = {}, xk = {}, yk = {}'.format( t0, x0, tk, xk, yk)) yyk = uk * (1 - math.exp(a * (tk - t0))) + x0 * math.exp(a * (tk - t0)) print(log) print(t0, x0, tk, xk, yk, yyk) assert np.abs(yk - np.array([yyk])) < 1e-2 uk = -1 x0 = sys.state controller.add_filter('condition', Map(function=lambda x: x < 3), ['clock'], ['is_running']) #controller.set_source('clock', reset = True) controller.set_sink('logger', reset=True) controller.set_signal('input', uk) controller.run() xk = sys.state log = controller.get_sink('logger', 'log') t0 = log['clock'][0, 0] tk = log['clock'][-1, 0] yk = log['output'][-1, 0] yyk = uk * (1 - math.exp(a * (tk - t0))) + x0 * math.exp(a * (tk - t0)) print(t0, x0, tk, xk, yk, yyk) assert np.abs(yk - np.array([yyk])) < 1e-2 clock.set_enabled(False)
def testSetBlock(self): from pyctrl import Controller from pyctrl.block import Constant controller = Controller() controller.add_source('block', Constant(), ['s1']) self.assertTrue(controller.get_source('block', 'enabled')) blk = logic.SetSource(parent=controller, label='block', on_rise_and_fall={'enabled': False}) self.assertTrue(blk.state is logic.State.LOW) blk.write(1) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) controller.set_source('block', enabled=True) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) blk.write(0.1) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) controller.set_source('block', enabled=True) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) blk.write(0.9) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) # OnRiseSet blk = logic.SetSource(parent=controller, label='block', on_rise={'enabled': False}) self.assertTrue(blk.state is logic.State.LOW) blk.write(1) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) controller.set_source('block', enabled=True) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) blk.write(0.1) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) controller.set_source('block', enabled=True) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) blk.write(0.9) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) # OnFallSet blk = logic.SetSource(parent=controller, label='block', on_fall={'enabled': False}) controller.set_source('block', enabled=True) self.assertTrue(blk.state is logic.State.LOW) blk.write(1) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) blk.write(0.1) self.assertTrue(not controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) controller.set_source('block', enabled=True) self.assertTrue(controller.get_source('block', 'enabled')) blk.write(0.5) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.LOW) blk.write(0.9) self.assertTrue(controller.get_source('block', 'enabled')) self.assertTrue(blk.state is logic.State.HIGH) # try pickling import pickle pickle.dumps(blk)
def test2(): if not test_ode: return m1 = 30 / 1000 l1 = 7.6 / 100 r1 = (5 - (10 - 7.6) / 2) / 100 w1 = 10 / 100 d1 = 2.4 / 100 J1 = m1 * (w1**2 + d1**2) / 12 m2 = 44 / 1000 w2 = 25.4 / 100 d2 = 2.4 / 100 J2 = m2 * (w2**2 + d2**2) / 12 r2 = (25.4 / 2 - 1.25) / 100 Jm = 0.004106 km = 0.006039 bm = 0.091503 g = 9.8 bPhi = 0 bTheta = 0 def MK(x, u): theta, phi, thetaDot, phiDot = x return ( np.array([[J2 + m2 * r2**2, m2 * r2 * l1 * math.cos(theta - phi)], [ m2 * r2 * l1 * math.cos(theta - phi), J1 + Jm + m1 * r1**2 + m2 * l1**2 ]]), np.array([ bTheta * thetaDot + m2 * r2 * (g * math.sin(theta) + l1 * math.sin(theta - phi) * phiDot**2), g * (m1 * r1 + m2 * l1) * math.sin(phi) - m2 * r2 * l1 * math.sin(theta - phi) * thetaDot**2 + (bm + bPhi) * phiDot - km * u[0] ])) def ff(t, x, u): M, K = MK(x, u) return np.hstack((x[2:4], -la.solve(M, K))) theta0, phi0 = 0 + math.pi / 6, 0 t0, x0, u0 = 0, np.array([theta0, phi0, 0, 0]), [0] M, K = MK(x0, u0) print(M) print(K) print(ff(t0, x0, u0)) sys = ODE(shape=(1, 4, 4), t0=t0, x0=x0, f=ff) tk = 5 uk = [0] yk = sys.update(tk, uk) print('1. [{:3.2f}, {:3.2f}] = {}'.format(t0, tk, yk)) from pyctrl import Controller controller = Controller() Ts = 0.01 controller.add_source('clock', Clock(), ['clock']) condition = Map(function=lambda t: t < T) controller.add_filter('condition', condition, ['clock'], ['is_running']) controller.add_signals('tau', 'x') controller.add_filter( 'ode', TimeVaryingSystem(model=ODE(shape=(1, 4, 4), t0=t0, x0=x0, f=ff)), ['clock', 'tau'], ['x']) controller.add_sink('logger', Logger(), ['clock', 'x']) controller.set_source('clock', reset=True) T = 5 + Ts controller.run() log = controller.get_sink('logger', 'log') t0 = log['clock'][0, 0] tk = log['clock'][0, -1] yk = log['x'][0, -1] # yk = log[-1,1:] print('2. [{:3.2f}, {:3.2f}] = {}'.format(t0, tk, yk)) import control fc = 7 wc = 2 * math.pi * fc lpf = control.tf(wc, [1, wc]) ctr = -2 * 100 def gg(t, x, u): return [x[0]] Ts = 0.01 Ac, Bc, Cc, Dc = map(np.array, control.ssdata(control.ss(lpf * ctr))) nc = Ac.shape[0] def F(t, x, ref): x, xc = x[0:4], x[4:4 + nc] y = ref - gg(t, x, [0]) u = max(-100, min(100, Cc.dot(xc) + Dc.dot(y))) #print(ff(t,x,u)) return np.hstack((ff(t, x, u), Ac.dot(xc) + Bc.dot(y))) eta = 0 kappa = 0 ref = np.array([eta * math.pi]) theta0 = -20 * math.pi / 180 xx0 = [kappa * math.pi - theta0, eta * math.pi, 0, 0] xc0 = np.zeros((nc, )) x0 = np.hstack((xx0, xc0)) t0 = 0 print('F = {}'.format(F(t0, x0, ref))) sys = ODE(shape=(1, 4, 4), t0=t0, x0=x0, f=F) tk = 1 uk = np.array([0]) yk = sys.update(tk, uk) print('1. [{:3.2f}, {:3.2f}] = {}'.format(t0, tk, yk)) controller.reset() Ts = 0.01 controller.add_source('clock', Clock(), ['clock']) condition = Map(function=lambda t: t < T) controller.add_filter('condition', condition, ['clock'], ['is_running']) controller.add_signals('ref', 'x') controller.add_filter( 'ode', TimeVaryingSystem(model=ODE(shape=(1, 4, 4), t0=t0, x0=x0, f=F)), ['clock', 'ref'], ['x']) controller.add_sink('logger', Logger(), ['clock', 'x']) #print(controller.info('all')) controller.set_source('clock', reset=True) controller.set_signal('ref', ref) T = 1 + Ts controller.run() log = controller.get_sink('logger', 'log') t0 = log['clock'][0, 0] tk = log['clock'][0, -1] yk = log['x'][0, -1] #yk = log[-1,1:] print('2. [{:3.2f}, {:3.2f}] = {}'.format(t0, tk, yk))