def __init__(self): super(Autopilot, self).__init__() # setup all processes to exit on any signal self.childpids = [] def cleanup(signal_number, frame=None): print('got signal', signal_number, 'cleaning up') while self.childpids: pid = self.childpids.pop() #print('kill child', pid) os.kill(pid, signal.SIGTERM) # get backtrace sys.stdout.flush() if signal_number != 'atexit': raise KeyboardInterrupt # to get backtrace on all processes # unfortunately we occasionally get this signal, # some sort of timing issue where python doesn't realize the pipe # is broken yet, so doesn't raise an exception def printpipewarning(signal_number, frame): print('got SIGPIPE, ignoring') import signal for s in range(1, 16): if s == 13: signal.signal(s, printpipewarning) elif s != 9: signal.signal(s, cleanup) # self.server = SignalKServer() self.server = SignalKPipeServer() self.boatimu = BoatIMU(self.server) self.sensors = Sensors(self.server) self.servo = servo.Servo(self.server, self.sensors) self.version = self.Register(Value, 'version', 'pypilot' + ' ' + strversion) self.heading_command = self.Register(HeadingProperty, 'heading_command', 0) self.enabled = self.Register(BooleanProperty, 'enabled', False) self.lastenabled = False self.lost_mode = self.Register(BooleanValue, 'lost_mode', False) self.mode = self.Register(ModeProperty, 'mode') self.mode.ap = self self.lastmode = False self.last_heading = False self.last_heading_off = self.boatimu.heading_off.value self.pilots = [] for pilot_type in pilots.default: self.pilots.append(pilot_type(self)) self.pilot = self.Register(EnumProperty, 'pilot', 'basic', ['simple', 'basic', 'learning', 'wind'], persistent=True) timestamp = self.server.TimeStamp('ap') self.heading = self.Register(SensorValue, 'heading', timestamp, directional=True) self.heading_error = self.Register(SensorValue, 'heading_error', timestamp) self.heading_error_int = self.Register(SensorValue, 'heading_error_int', timestamp) self.heading_error_int_time = time.time() self.tack = tacking.Tack(self) self.gps_compass_offset = HeadingOffset() self.gps_speed = self.Register(SensorValue, 'gps_speed', timestamp) self.wind_compass_offset = HeadingOffset() self.true_wind_compass_offset = HeadingOffset() self.wind_direction = self.Register(SensorValue, 'wind_direction', timestamp, directional=True) self.wind_speed = self.Register(SensorValue, 'wind_speed', timestamp) self.runtime = self.Register(TimeValue, 'runtime') #, persistent=True) device = '/dev/watchdog0' self.watchdog_device = False try: self.watchdog_device = open(device, 'w') except: print('warning: failed to open special file', device, 'for writing') print(' cannot stroke the watchdog') if os.system('sudo chrt -pf 1 %d 2>&1 > /dev/null' % os.getpid()): print('warning, failed to make autopilot process realtime') self.starttime = time.time() self.times = 4 * [0] self.childpids = [ self.boatimu.imu_process.pid, self.boatimu.auto_cal.process.pid, self.server.process.pid, self.sensors.nmea.process.pid, self.sensors.gps.process.pid ] signal.signal(signal.SIGCHLD, cleanup) import atexit atexit.register(lambda: cleanup('atexit')) self.lastdata = False self.lasttime = time.time()
def __init__(self): super(Autopilot, self).__init__() self.watchdog_device = False self.server = pypilotServer() self.client = pypilotClient(self.server) self.boatimu = BoatIMU(self.client) self.sensors = Sensors(self.client) self.servo = servo.Servo(self.client, self.sensors) self.version = self.register(Value, 'version', 'pypilot' + ' ' + strversion) self.timestamp = self.client.register(SensorValue('timestamp', 0)) self.starttime = time.monotonic() self.mode = self.register(ModeProperty, 'mode') self.preferred_mode = self.register(Value, 'preferred_mode', 'compass') self.lastmode = False self.mode.ap = self self.heading_command = self.register(HeadingProperty, 'heading_command', self.mode) self.enabled = self.register(BooleanProperty, 'enabled', False) self.lastenabled = False self.last_heading = False self.last_heading_off = self.boatimu.heading_off.value self.pilots = {} for pilot_type in pilots.default: try: pilot = pilot_type(self) self.pilots[pilot.name] = pilot except Exception as e: print('failed to load pilot', pilot_type, e) pilot_names = list(self.pilots) print('Loaded Pilots:', pilot_names) self.pilot = self.register(EnumProperty, 'pilot', 'basic', pilot_names, persistent=True) self.heading = self.register(SensorValue, 'heading', directional=True) self.heading_error = self.register(SensorValue, 'heading_error') self.heading_error_int = self.register(SensorValue, 'heading_error_int') self.heading_error_int_time = time.monotonic() self.tack = tacking.Tack(self) self.gps_compass_offset = HeadingOffset() self.gps_speed = 0 self.wind_compass_offset = HeadingOffset() self.true_wind_compass_offset = HeadingOffset() self.wind_direction = self.register(SensorValue, 'wind_direction', directional=True) self.wind_speed = 0 self.runtime = self.register(TimeValue, 'runtime') #, persistent=True) self.timings = self.register(SensorValue, 'timings', False) device = '/dev/watchdog0' try: self.watchdog_device = open(device, 'w') except: print('warning: failed to open special file', device, 'for writing') print(' cannot stroke the watchdog') self.server.poll() # setup process before we switch main process to realtime if os.system('sudo chrt -pf 1 %d 2>&1 > /dev/null' % os.getpid()): print('warning, failed to make autopilot process realtime') self.lasttime = time.monotonic() # setup all processes to exit on any signal self.childprocesses = [self.boatimu.imu, self.boatimu.auto_cal, self.sensors.nmea, self.sensors.gpsd, self.sensors.signalk, self.server] def cleanup(signal_number, frame=None): #print('got signal', signal_number, 'cleaning up') if signal_number == signal.SIGCHLD: pid = os.waitpid(-1, os.WNOHANG) #print('sigchld waitpid', pid) if signal_number != 'atexit': # don't get this signal again signal.signal(signal_number, signal.SIG_IGN) while self.childprocesses: process = self.childprocesses.pop().process if process: pid = process.pid #print('kill', pid, process) try: os.kill(pid, signal.SIGTERM) # get backtrace except Exception as e: pass #print('kill failed', e) sys.stdout.flush() if signal_number != 'atexit': raise KeyboardInterrupt # to get backtrace on all processes # unfortunately we occasionally get this signal, # some sort of timing issue where python doesn't realize the pipe # is broken yet, so doesn't raise an exception def printpipewarning(signal_number, frame): print('got SIGPIPE, ignoring') import signal for s in range(1, 16): if s == 13: signal.signal(s, printpipewarning) elif s != 9: signal.signal(s, cleanup) signal.signal(signal.SIGCHLD, cleanup) import atexit atexit.register(lambda : cleanup('atexit'))