def main():

    # import python's standard time module
    import time

    # import Controller and other blocks from modules
    from pyctrl import Controller
    from pyctrl.block import Printer, Constant

    # initialize controller
    hello = Controller()

    # add a Printer as a timer
    hello.add_timer('message',
                    Printer(message='Hello World @ {:3.1f} s '), ['clock'],
                    None,
                    period=1,
                    repeat=True)

    # Add a timer to stop the controller
    hello.add_timer('stop',
                    Constant(value=0),
                    None, ['is_running'],
                    period=5,
                    repeat=False)

    # add a Printer as a sink
    hello.add_sink('message',
                   Printer(message='Current time {:5.3f} s', endln='\r'),
                   ['clock'])

    # print controller info
    print(hello.info('all'))

    try:

        # run the controller
        print('> Run the controller.')
        with hello:

            # wait for the controller to finish on its own
            hello.join()

        print('> Done with the controller.')

    except KeyboardInterrupt:
        pass
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)