Example #1
0
    def __init__(self, context, name):
        self._context = context
        self._name = name
        self._eventSource = EventSource()
        self._timer = None
        self._duration = 60

        self._eventSource.registerEvent(GameState.NOT_INITIALIZED, None)
        self._eventSource.registerEvent(GameState.READY_TO_START, None)
        self._eventSource.registerEvent(GameState.GENERATE_TASK, None)
        self._eventSource.registerEvent(GameState.GAME_STARTED, None)
        self._eventSource.registerEvent(GameState.TIMEOUT, None)
        self._eventSource.registerEvent(GameState.RESULTS_READY, None)

        self._eventSource.registerHandler(GameState.NOT_INITIALIZED,
                                          self.onNotInitialized)
        self._eventSource.registerHandler(GameState.READY_TO_START,
                                          self.onReadyToStart)
        self._eventSource.registerHandler(GameState.GENERATE_TASK,
                                          self.onGenerateTask)
        self._eventSource.registerHandler(GameState.GAME_STARTED,
                                          self.onGameStarted)
        self._eventSource.registerHandler(GameState.TIMEOUT,
                                          self.__onTimeoutInternal)

        self._state = State(self._eventSource, GameState.NOT_INITIALIZED)
Example #2
0
class TestFollower(unittest.TestCase):

    def setUp(self):
        self.mock_logger = Mock()
        self.mock_logger.error = Mock(side_effect=print_msg)
        self.exchange = Exchange(self.mock_logger)
        self.timer = StubTimer()
        self.timeshift = TimeShift(self.exchange, self.timer.time)
        self.event_source = EventSource(self.exchange,self.timer,self.mock_logger,{'tick interval':0.2})
    	gps = FakeMovingGPS([Position(10,10),Position(11,11),Position(12,12),Position(13,13)])
        self.navigator = Navigator(gps,Globe(),self.exchange,self.mock_logger, {'min time to steer': 5,'max time to steer': 20})

    def test_should_navigate_along_list_of_waypoints_with_logging(self):
        waypoint1 = Waypoint(Position(11,11),10)
        waypoint2 = Waypoint(Position(13,13),10)
        follower = Follower(self.exchange,[waypoint1,waypoint2],self.mock_logger)

        self.event_source.start()

        self.mock_logger.info.assert_has_calls(
            [call('Follower, next waypoint +11.000000,+11.000000'),
             call('Navigator, steering to +11.000000,+11.000000, bearing  44.4, distance 155941.2m, review after 20s'),
             call('Navigator, arrived at +11.000000,+11.000000'),
             call('Follower, next waypoint +13.000000,+13.000000'),
             call('Navigator, steering to +13.000000,+13.000000, bearing  44.2, distance 155399.6m, review after 20s'),
             call('Navigator, arrived at +13.000000,+13.000000'),
             call('**************************************************************'),
             call('Follower, all waypoints reached, navigation complete'),
             call('**************************************************************')])
Example #3
0
class SimWiring():
    def __init__(self):
        self.globe = Globe()
        self.console_logger = self._console_logger()
        self.exchange = Exchange(self.console_logger)
        self.gps = SimulatedGPS(CHORLTON.position,0,0.1)
        self.vehicle = SimulatedVehicle(self.gps, self.globe,self.console_logger,single_step=False)
        self.timeshift = TimeShift(self.exchange,self.vehicle.timer.time)
        self.event_source = EventSource(self.exchange,self.vehicle.timer,self.console_logger,CONFIG['event source'])
        self.sensors = Sensors(self.vehicle.gps, self.vehicle.windsensor,self.vehicle.compass,self.vehicle.timer.time,self.exchange,self.console_logger,CONFIG['sensors'])
        self.steerer = Steerer(self.vehicle.rudder,self.console_logger,CONFIG['steerer'])
        self.helm = Helm(self.exchange, self.sensors, self.steerer, self.console_logger, CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors,self.helm,self.vehicle.timer, CONFIG['course steerer'])
        self.navigator_simulator = Navigator(self.sensors,self.globe,self.exchange,self.console_logger,CONFIG['navigator'])

        self.tracking_timer = Timer()
        self.tracker_simulator = Tracker(self.console_logger,self.sensors,self.tracking_timer)

    def _console_logger(self):
        logging.basicConfig(format=LOGGING_FORMAT, level=CONFIG['wiring']['logging level'])
        return logging.getLogger("simulate")

    def _follower(self,waypoints):
        self.follower_simulator =  Follower(self.exchange,waypoints,self.console_logger)
        return self.follower_simulator

    def follow(self,waypoints):
        self.gps.set_position(waypoints[0].position,0,0.8,True)
        self.vehicle.position = waypoints[0].position
        self.follower_simulator =  self._follower(waypoints)
        self.event_source.start()
Example #4
0
    def test_should_publish_a_tick_event(self):
        self.listen(EventName.tick)
        self.timer.wait_for = Mock(side_effect=self.finish)

        event_source = EventSource(self.exchange, self.timer, self.mock_logger, CONFIG)
        event_source.start()

        self.assertEqual(self.last_listened_event.name,EventName.tick)
Example #5
0
    def test_should_publish_a_tick_event(self):
        self.listen(EventName.tick)
        self.timer.wait_for = Mock(side_effect=self.finish)

        event_source = EventSource(self.exchange, self.timer, self.mock_logger,
                                   CONFIG)
        event_source.start()

        self.assertEqual(self.last_listened_event.name, EventName.tick)
Example #6
0
    def test_should_publish_multiple_events_until_nav_complete(self):
        self.listen(EventName.tick)
        self.after(5,EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        event_source = EventSource(self.exchange,self.timer, self.mock_logger,CONFIG)
        event_source.start()

        self.assertEqual(self.event_count,5)
Example #7
0
    def test_should_publish_multiple_events_until_nav_complete(self):
        self.listen(EventName.tick)
        self.after(5, EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        event_source = EventSource(self.exchange, self.timer, self.mock_logger,
                                   CONFIG)
        event_source.start()

        self.assertEqual(self.event_count, 5)
Example #8
0
    def test_errors_should_be_logged_and_events_continue(self):
        self.listen(EventName.tick)
        self.after(2,EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        self.exchange.original_publish = self.exchange.publish
        self.exchange.publish = self.intercept_publish

        event_source = EventSource(self.exchange,self.timer, self.mock_logger,CONFIG)
        event_source.start()

        self.mock_logger.error.assert_has_calls([call('EventSource, RuntimeError: oops')])
        self.assertEqual(self.event_count,2)
Example #9
0
    def __init__(self, gps=False, servo_port=SERVO_PORT):
        # devices
        self._gps = gps
        self.windsensor = WindSensor(I2C(WINDSENSOR_I2C_ADDRESS))
        self.compass = Compass(I2C(COMPASS_I2C_ADDRESS),
                               I2C(ACCELEROMETER_I2C_ADDRESS))
        self.red_led = GpioWriter(17, os)
        self.green_led = GpioWriter(18, os)

        # Navigation
        self.globe = Globe()
        self.timer = Timer()
        self.application_logger = self._rotating_logger(APPLICATION_NAME)
        self.position_logger = self._rotating_logger("position")
        self.exchange = Exchange(self.application_logger)
        self.timeshift = TimeShift(self.exchange, self.timer.time)
        self.event_source = EventSource(self.exchange, self.timer,
                                        self.application_logger,
                                        CONFIG['event source'])

        self.sensors = Sensors(self.gps, self.windsensor, self.compass,
                               self.timer.time, self.exchange,
                               self.position_logger, CONFIG['sensors'])
        self.gps_console_writer = GpsConsoleWriter(self.gps)
        self.rudder_servo = Servo(serial.Serial(servo_port),
                                  RUDDER_SERVO_CHANNEL, RUDDER_MIN_PULSE,
                                  RUDDER_MIN_ANGLE, RUDDER_MAX_PULSE,
                                  RUDDER_MAX_ANGLE)
        self.steerer = Steerer(self.rudder_servo, self.application_logger,
                               CONFIG['steerer'])
        self.helm = Helm(self.exchange, self.sensors, self.steerer,
                         self.application_logger, CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors, self.helm,
                                            self.timer,
                                            CONFIG['course steerer'])
        self.navigator = Navigator(self.sensors, self.globe, self.exchange,
                                   self.application_logger,
                                   CONFIG['navigator'])
        self.self_test = SelfTest(self.red_led, self.green_led, self.timer,
                                  self.rudder_servo, RUDDER_MIN_ANGLE,
                                  RUDDER_MAX_ANGLE)

        # Tracking
        self.tracking_logger = self._rotating_logger("track")
        self.tracking_sensors = Sensors(self.gps, self.windsensor,
                                        self.compass, self.timer.time,
                                        self.exchange, self.tracking_logger,
                                        CONFIG['sensors'])
        self.tracker = Tracker(self.tracking_logger, self.tracking_sensors,
                               self.timer)
Example #10
0
class TestFollower(unittest.TestCase):
    def setUp(self):
        self.mock_logger = Mock()
        self.mock_logger.error = Mock(side_effect=print_msg)
        self.exchange = Exchange(self.mock_logger)
        self.timer = StubTimer()
        self.timeshift = TimeShift(self.exchange, self.timer.time)
        self.event_source = EventSource(self.exchange, self.timer,
                                        self.mock_logger,
                                        {'tick interval': 0.2})
        gps = FakeMovingGPS([
            Position(10, 10),
            Position(11, 11),
            Position(12, 12),
            Position(13, 13)
        ])
        self.navigator = Navigator(gps, Globe(), self.exchange,
                                   self.mock_logger, {
                                       'min time to steer': 5,
                                       'max time to steer': 20
                                   })

    def test_should_navigate_along_list_of_waypoints_with_logging(self):
        waypoint1 = Waypoint(Position(11, 11), 10)
        waypoint2 = Waypoint(Position(13, 13), 10)
        follower = Follower(self.exchange, [waypoint1, waypoint2],
                            self.mock_logger)

        self.event_source.start()

        self.mock_logger.info.assert_has_calls([
            call('Follower, next waypoint +11.000000,+11.000000'),
            call(
                'Navigator, steering to +11.000000,+11.000000, bearing  44.4, distance 155941.2m, review after 20s'
            ),
            call('Navigator, arrived at +11.000000,+11.000000'),
            call('Follower, next waypoint +13.000000,+13.000000'),
            call(
                'Navigator, steering to +13.000000,+13.000000, bearing  44.2, distance 155399.6m, review after 20s'
            ),
            call('Navigator, arrived at +13.000000,+13.000000'),
            call(
                '**************************************************************'
            ),
            call('Follower, all waypoints reached, navigation complete'),
            call(
                '**************************************************************'
            )
        ])
Example #11
0
    def test_errors_should_be_logged_and_events_continue(self):
        self.listen(EventName.tick)
        self.after(2, EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        self.exchange.original_publish = self.exchange.publish
        self.exchange.publish = self.intercept_publish

        event_source = EventSource(self.exchange, self.timer, self.mock_logger,
                                   CONFIG)
        event_source.start()

        self.mock_logger.error.assert_has_calls(
            [call('EventSource, RuntimeError: oops')])
        self.assertEqual(self.event_count, 2)
Example #12
0
    def __init__(self,gps=False,servo_port=SERVO_PORT):
        # devices
        self._gps = gps
        self.windsensor = WindSensor(I2C(WINDSENSOR_I2C_ADDRESS))
        self.compass = Compass(I2C(COMPASS_I2C_ADDRESS),I2C(ACCELEROMETER_I2C_ADDRESS))
        self.red_led = GpioWriter(17,os)
        self.green_led = GpioWriter(18,os)

        # Navigation
        self.globe = Globe()
        self.timer = Timer()
        self.application_logger = self._rotating_logger(APPLICATION_NAME)
        self.position_logger = self._rotating_logger("position")
        self.exchange = Exchange(self.application_logger)
        self.timeshift = TimeShift(self.exchange,self.timer.time)
        self.event_source = EventSource(self.exchange,self.timer,self.application_logger,CONFIG['event source'])

        self.sensors = Sensors(self.gps,self.windsensor,self.compass,self.timer.time,self.exchange,self.position_logger,CONFIG['sensors'])
        self.gps_console_writer = GpsConsoleWriter(self.gps)
        self.rudder_servo = Servo(serial.Serial(servo_port),RUDDER_SERVO_CHANNEL,RUDDER_MIN_PULSE,RUDDER_MIN_ANGLE,RUDDER_MAX_PULSE,RUDDER_MAX_ANGLE)
        self.steerer = Steerer(self.rudder_servo,self.application_logger,CONFIG['steerer'])
        self.helm = Helm(self.exchange,self.sensors,self.steerer,self.application_logger,CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors,self.helm,self.timer,CONFIG['course steerer'])
        self.navigator = Navigator(self.sensors,self.globe,self.exchange,self.application_logger,CONFIG['navigator'])
        self.self_test = SelfTest(self.red_led,self.green_led,self.timer,self.rudder_servo,RUDDER_MIN_ANGLE,RUDDER_MAX_ANGLE)

        # Tracking
        self.tracking_logger = self._rotating_logger("track")
        self.tracking_sensors = Sensors(self.gps,self.windsensor,self.compass,self.timer.time,self.exchange,self.tracking_logger,CONFIG['sensors'])
        self.tracker = Tracker(self.tracking_logger,self.tracking_sensors,self.timer)
Example #13
0
    def __init__(self):
        self.globe = Globe()
        self.console_logger = self._console_logger()
        self.exchange = Exchange(self.console_logger)
        self.gps = SimulatedGPS(CHORLTON.position,0,0.1)
        self.vehicle = SimulatedVehicle(self.gps, self.globe,self.console_logger,single_step=False)
        self.timeshift = TimeShift(self.exchange,self.vehicle.timer.time)
        self.event_source = EventSource(self.exchange,self.vehicle.timer,self.console_logger,CONFIG['event source'])
        self.sensors = Sensors(self.vehicle.gps, self.vehicle.windsensor,self.vehicle.compass,self.vehicle.timer.time,self.exchange,self.console_logger,CONFIG['sensors'])
        self.steerer = Steerer(self.vehicle.rudder,self.console_logger,CONFIG['steerer'])
        self.helm = Helm(self.exchange, self.sensors, self.steerer, self.console_logger, CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors,self.helm,self.vehicle.timer, CONFIG['course steerer'])
        self.navigator_simulator = Navigator(self.sensors,self.globe,self.exchange,self.console_logger,CONFIG['navigator'])

        self.tracking_timer = Timer()
        self.tracker_simulator = Tracker(self.console_logger,self.sensors,self.tracking_timer)
Example #14
0
    def test_errors_during_logging_should_be_ignored_and_event_processing_continues(self):
        failing_logger = Mock()
        failing_logger.configure_mock(**{'error.side_effect': RuntimeError})

        self.listen(EventName.tick)
        self.after(2,EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        self.exchange.original_publish = self.exchange.publish
        self.exchange.publish = self.intercept_publish

        event_source = EventSource(self.exchange,self.timer, failing_logger,CONFIG)
        event_source.start()

        failing_logger.error.assert_has_calls([call('EventSource, RuntimeError: oops')])
        self.assertEqual(self.event_count,2)
Example #15
0
 def setUp(self):
     self.mock_logger = Mock()
     self.mock_logger.error = Mock(side_effect=print_msg)
     self.exchange = Exchange(self.mock_logger)
     self.timer = StubTimer()
     self.timeshift = TimeShift(self.exchange, self.timer.time)
     self.event_source = EventSource(self.exchange,self.timer,self.mock_logger,{'tick interval':0.2})
 	gps = FakeMovingGPS([Position(10,10),Position(11,11),Position(12,12),Position(13,13)])
     self.navigator = Navigator(gps,Globe(),self.exchange,self.mock_logger, {'min time to steer': 5,'max time to steer': 20})
Example #16
0
    def test_errors_during_logging_should_be_ignored_and_event_processing_continues(
            self):
        failing_logger = Mock()
        failing_logger.configure_mock(**{'error.side_effect': RuntimeError})

        self.listen(EventName.tick)
        self.after(2, EventName.end)
        self.timer.wait_for = Mock(side_effect=self.count_down_ticks)

        self.exchange.original_publish = self.exchange.publish
        self.exchange.publish = self.intercept_publish

        event_source = EventSource(self.exchange, self.timer, failing_logger,
                                   CONFIG)
        event_source.start()

        failing_logger.error.assert_has_calls(
            [call('EventSource, RuntimeError: oops')])
        self.assertEqual(self.event_count, 2)
Example #17
0
 def setUp(self):
     self.mock_logger = Mock()
     self.mock_logger.error = Mock(side_effect=print_msg)
     self.exchange = Exchange(self.mock_logger)
     self.timer = StubTimer()
     self.timeshift = TimeShift(self.exchange, self.timer.time)
     self.event_source = EventSource(self.exchange, self.timer,
                                     self.mock_logger,
                                     {'tick interval': 0.2})
     gps = FakeMovingGPS([
         Position(10, 10),
         Position(11, 11),
         Position(12, 12),
         Position(13, 13)
     ])
     self.navigator = Navigator(gps, Globe(), self.exchange,
                                self.mock_logger, {
                                    'min time to steer': 5,
                                    'max time to steer': 20
                                })
Example #18
0
class Game:
    def __init__(self, context, name):
        self._context = context
        self._name = name
        self._eventSource = EventSource()
        self._timer = None
        self._duration = 60

        self._eventSource.registerEvent(GameState.NOT_INITIALIZED, None)
        self._eventSource.registerEvent(GameState.READY_TO_START, None)
        self._eventSource.registerEvent(GameState.GENERATE_TASK, None)
        self._eventSource.registerEvent(GameState.GAME_STARTED, None)
        self._eventSource.registerEvent(GameState.TIMEOUT, None)
        self._eventSource.registerEvent(GameState.RESULTS_READY, None)

        self._eventSource.registerHandler(GameState.NOT_INITIALIZED,
                                          self.onNotInitialized)
        self._eventSource.registerHandler(GameState.READY_TO_START,
                                          self.onReadyToStart)
        self._eventSource.registerHandler(GameState.GENERATE_TASK,
                                          self.onGenerateTask)
        self._eventSource.registerHandler(GameState.GAME_STARTED,
                                          self.onGameStarted)
        self._eventSource.registerHandler(GameState.TIMEOUT,
                                          self.__onTimeoutInternal)

        self._state = State(self._eventSource, GameState.NOT_INITIALIZED)

    def initState(self):
        self._state.setState(GameState.NOT_INITIALIZED)

    def getEventSource(self):
        return self._eventSource

    def getState(self):
        return self._state

    #game handlers
    def onNotInitialized(self, *data):
        self._state.setState(GameState.READY_TO_START)

    def onReadyToStart(self, *data):
        if self._timer:
            self._timer.cancel()
            self._timer = None

    def onGenerateTask(self, *data):
        self._context.send_msg("10,15Sledeća igra: 05,15\x02\x11" +
                               self._name)

    def onGameStarted(self, *data):
        self._timer = Timer(self._duration,
                            lambda: self._state.setState(GameState.TIMEOUT))
        self._timer.start()

    def __onTimeoutInternal(self, *data):
        self._context.send_msg("10,15Vreme je isteklo")
        self._context.send_notice(self._context.botNick, 'TIMEOUT')

    #external events
    def onMessageReceived(self, user, message):
        pass

    def onTimeout(self):
        pass
Example #19
0
class Wiring():
    def __init__(self,gps=False,servo_port=SERVO_PORT):
        # devices
        self._gps = gps
        self.windsensor = WindSensor(I2C(WINDSENSOR_I2C_ADDRESS))
        self.compass = Compass(I2C(COMPASS_I2C_ADDRESS),I2C(ACCELEROMETER_I2C_ADDRESS))
        self.red_led = GpioWriter(17,os)
        self.green_led = GpioWriter(18,os)

        # Navigation
        self.globe = Globe()
        self.timer = Timer()
        self.application_logger = self._rotating_logger(APPLICATION_NAME)
        self.position_logger = self._rotating_logger("position")
        self.exchange = Exchange(self.application_logger)
        self.timeshift = TimeShift(self.exchange,self.timer.time)
        self.event_source = EventSource(self.exchange,self.timer,self.application_logger,CONFIG['event source'])

        self.sensors = Sensors(self.gps,self.windsensor,self.compass,self.timer.time,self.exchange,self.position_logger,CONFIG['sensors'])
        self.gps_console_writer = GpsConsoleWriter(self.gps)
        self.rudder_servo = Servo(serial.Serial(servo_port),RUDDER_SERVO_CHANNEL,RUDDER_MIN_PULSE,RUDDER_MIN_ANGLE,RUDDER_MAX_PULSE,RUDDER_MAX_ANGLE)
        self.steerer = Steerer(self.rudder_servo,self.application_logger,CONFIG['steerer'])
        self.helm = Helm(self.exchange,self.sensors,self.steerer,self.application_logger,CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors,self.helm,self.timer,CONFIG['course steerer'])
        self.navigator = Navigator(self.sensors,self.globe,self.exchange,self.application_logger,CONFIG['navigator'])
        self.self_test = SelfTest(self.red_led,self.green_led,self.timer,self.rudder_servo,RUDDER_MIN_ANGLE,RUDDER_MAX_ANGLE)

        # Tracking
        self.tracking_logger = self._rotating_logger("track")
        self.tracking_sensors = Sensors(self.gps,self.windsensor,self.compass,self.timer.time,self.exchange,self.tracking_logger,CONFIG['sensors'])
        self.tracker = Tracker(self.tracking_logger,self.tracking_sensors,self.timer)

    def _rotating_logger(self,appname):
        logHandler = TimedRotatingFileHandler("/var/log/pi-nav/" + appname,when="midnight",backupCount=30)
        logHandler.setFormatter(logging.Formatter(LOGGING_FORMAT))
        logger = logging.getLogger(appname)
        logger.addHandler( logHandler )
        logger.setLevel( CONFIG['wiring']['logging level'])
        return logger

    @property
    def gps(self):
        if not self._gps:
            self._gps = GpsReader()
            self._gps.setDaemon(True)
            self._gps.start()
        return self._gps

    def showgps(self):
        try:
            self.timer.call(self.gps_console_writer.write).every(5)
        except (KeyboardInterrupt, SystemExit):
            self.gps.running = False
            self.gps.join()

    def follow(self,waypoints):
        self.application_logger.info('**************************************************************')
        self.application_logger.info('*** Pi-Nav starting navigation: ' + datetime.datetime.now().strftime("%Y-%m-%d"))
        self.application_logger.info('**************************************************************')
        self.self_test.run()
        self.rudder_servo.set_position(0)
        self.follower = Follower(self.exchange,waypoints,self.application_logger)
        self.event_source.start()

    def track(self):
        self.self_test.run()
        self.tracker.track(10)
Example #20
0
class Wiring():
    def __init__(self, gps=False, servo_port=SERVO_PORT):
        # devices
        self._gps = gps
        self.windsensor = WindSensor(I2C(WINDSENSOR_I2C_ADDRESS))
        self.compass = Compass(I2C(COMPASS_I2C_ADDRESS),
                               I2C(ACCELEROMETER_I2C_ADDRESS))
        self.red_led = GpioWriter(17, os)
        self.green_led = GpioWriter(18, os)

        # Navigation
        self.globe = Globe()
        self.timer = Timer()
        self.application_logger = self._rotating_logger(APPLICATION_NAME)
        self.position_logger = self._rotating_logger("position")
        self.exchange = Exchange(self.application_logger)
        self.timeshift = TimeShift(self.exchange, self.timer.time)
        self.event_source = EventSource(self.exchange, self.timer,
                                        self.application_logger,
                                        CONFIG['event source'])

        self.sensors = Sensors(self.gps, self.windsensor, self.compass,
                               self.timer.time, self.exchange,
                               self.position_logger, CONFIG['sensors'])
        self.gps_console_writer = GpsConsoleWriter(self.gps)
        self.rudder_servo = Servo(serial.Serial(servo_port),
                                  RUDDER_SERVO_CHANNEL, RUDDER_MIN_PULSE,
                                  RUDDER_MIN_ANGLE, RUDDER_MAX_PULSE,
                                  RUDDER_MAX_ANGLE)
        self.steerer = Steerer(self.rudder_servo, self.application_logger,
                               CONFIG['steerer'])
        self.helm = Helm(self.exchange, self.sensors, self.steerer,
                         self.application_logger, CONFIG['helm'])
        self.course_steerer = CourseSteerer(self.sensors, self.helm,
                                            self.timer,
                                            CONFIG['course steerer'])
        self.navigator = Navigator(self.sensors, self.globe, self.exchange,
                                   self.application_logger,
                                   CONFIG['navigator'])
        self.self_test = SelfTest(self.red_led, self.green_led, self.timer,
                                  self.rudder_servo, RUDDER_MIN_ANGLE,
                                  RUDDER_MAX_ANGLE)

        # Tracking
        self.tracking_logger = self._rotating_logger("track")
        self.tracking_sensors = Sensors(self.gps, self.windsensor,
                                        self.compass, self.timer.time,
                                        self.exchange, self.tracking_logger,
                                        CONFIG['sensors'])
        self.tracker = Tracker(self.tracking_logger, self.tracking_sensors,
                               self.timer)

    def _rotating_logger(self, appname):
        logHandler = TimedRotatingFileHandler("/var/log/pi-nav/" + appname,
                                              when="midnight",
                                              backupCount=30)
        logHandler.setFormatter(logging.Formatter(LOGGING_FORMAT))
        logger = logging.getLogger(appname)
        logger.addHandler(logHandler)
        logger.setLevel(CONFIG['wiring']['logging level'])
        return logger

    @property
    def gps(self):
        if not self._gps:
            self._gps = GpsReader()
            self._gps.setDaemon(True)
            self._gps.start()
        return self._gps

    def showgps(self):
        try:
            self.timer.call(self.gps_console_writer.write).every(5)
        except (KeyboardInterrupt, SystemExit):
            self.gps.running = False
            self.gps.join()

    def follow(self, waypoints):
        self.application_logger.info(
            '**************************************************************')
        self.application_logger.info(
            '*** Pi-Nav starting navigation: ' +
            datetime.datetime.now().strftime("%Y-%m-%d"))
        self.application_logger.info(
            '**************************************************************')
        self.self_test.run()
        self.rudder_servo.set_position(0)
        self.follower = Follower(self.exchange, waypoints,
                                 self.application_logger)
        self.event_source.start()

    def track(self):
        self.self_test.run()
        self.tracker.track(10)