Exemplo n.º 1
0
    def __init__(self):
        # Screen state defaults
        self.def_pan = (0.0, 0.0)
        self.def_zoom = 1.0
        # Screen state overrides per client
        self.client_pan = dict()
        self.client_zoom = dict()
        self.client_ar = dict()

        self.route_acid = None

        # Timing bookkeeping counters
        self.prevtime = 0.0
        self.samplecount = 0
        self.prevcount = 0

        # Output event timers
        self.slow_timer = Timer()
        self.slow_timer.timeout.connect(self.send_siminfo)
        self.slow_timer.timeout.connect(self.send_route_data)
        self.slow_timer.start(int(1000 / self.siminfo_rate))

        self.fast_timer = Timer()
        self.fast_timer.timeout.connect(self.send_aircraft_data)
        self.fast_timer.start(int(1000 / self.acupdate_rate))
Exemplo n.º 2
0
    def __init__(self):
        # Screen state defaults
        self.def_pan     = (0.0, 0.0)
        self.def_zoom    = 1.0
        # Screen state overrides per client
        self.client_pan  = dict()
        self.client_zoom = dict()
        self.client_ar   = dict()

        self.route_acid  = None

        # Timing bookkeeping counters
        self.prevtime    = 0.0
        self.samplecount = 0
        self.prevcount   = 0

        # Output event timers
        self.slow_timer = Timer()
        self.slow_timer.timeout.connect(self.send_siminfo)
        self.slow_timer.timeout.connect(self.send_route_data)
        self.slow_timer.start(int(1000 / self.siminfo_rate))

        self.fast_timer = Timer()
        self.fast_timer.timeout.connect(self.send_aircraft_data)
        self.fast_timer.start(int(1000 / self.acupdate_rate))
Exemplo n.º 3
0
    def run(self):
        ''' Start the main loop of this node. '''

        hex_id = get_hexid(self.node_id)

        try:
            while self.running:
                # Get new events from the I/O thread
                # while self.event_io.poll(0):
                if self.event_io.getsockopt(zmq.EVENTS) & zmq.POLLIN:
                    msg = self.event_io.recv_multipart()
                    route, eventname, data = msg[:-2], msg[-2], msg[-1]
                    # route back to sender is acquired by reversing the incoming route
                    route.reverse()
                    if eventname == b'QUIT':
                        print(f'# Node({hex_id}): Quitting (Received QUIT from server)')
                        self.quit()
                    else:
                        pydata = msgpack.unpackb(data, object_hook=decode_ndarray, raw=False)
                        self.event(eventname, pydata, route)

                # Perform a simulation step
                self.step()

                # Process timers
                Timer.update_timers()
        except KeyboardInterrupt:
            print(f'# Node({hex_id}): Quitting (KeyboardInterrupt)')
            self.quit()
Exemplo n.º 4
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 5
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 6
0
 def step(self):
     ''' Perform one iteration step. Reimplemented in Simulation. '''
     # Process timers
     Timer.update_timers()
     # Get new events from the I/O thread
     # while self.event_io.poll(0):
     if self.event_io.getsockopt(zmq.EVENTS) & zmq.POLLIN:
         msg = self.event_io.recv_multipart()
         route, eventname, data = msg[:-2], msg[-2], msg[-1]
         # route back to sender is acquired by reversing the incoming route
         route.reverse()
         if eventname == b'QUIT':
             self.quit()
         else:
             pydata = msgpack.unpackb(
                 data, object_hook=decode_ndarray, raw=False)
             bs.sim.event(eventname, pydata, route)
Exemplo n.º 7
0
 def step(self):
     ''' Perform one iteration step. Reimplemented in Simulation. '''
     # Process timers
     Timer.update_timers()
     # Get new events from the I/O thread
     # while self.event_io.poll(0):
     if self.event_io.getsockopt(zmq.EVENTS) & zmq.POLLIN:
         msg = self.event_io.recv_multipart()
         route, eventname, data = msg[:-2], msg[-2], msg[-1]
         # route back to sender is acquired by reversing the incoming route
         route.reverse()
         if eventname == b'QUIT':
             self.quit()
         else:
             pydata = msgpack.unpackb(
                 data, object_hook=decode_ndarray, encoding='utf-8')
             self.event(eventname, pydata, route)
Exemplo n.º 8
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Get new events from the I/O thread
            while self.poll():
                res = self.event_io.recv_multipart()
                sender_id = res[0]
                name = res[1]
                if name == b'QUIT':
                    self.quit()
                else:
                    data = msgpack.unpackb(res[2], object_hook=decode_ndarray, encoding='utf-8')
                    self.event(name, data, sender_id)
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 9
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Get new events from the I/O thread
            # while self.event_io.poll(0):
            if self.event_io.getsockopt(zmq.EVENTS) & zmq.POLLIN:
                msg = self.event_io.recv_multipart()
                route, eventname, data = msg[:-2], msg[-2], msg[-1]
                # route back to sender is acquired by reversing the incoming route
                route.reverse()
                if eventname == b'QUIT':
                    self.quit()
                else:
                    pydata = msgpack.unpackb(data, object_hook=decode_ndarray, encoding='utf-8')
                    self.event(eventname, pydata, route)
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 10
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Get new events from the I/O thread
            while self.poll():
                res = self.event_io.recv_multipart()
                sender_id = res[0]
                name = res[1]
                if name == b'QUIT':
                    self.quit()
                else:
                    data = msgpack.unpackb(res[2],
                                           object_hook=decode_ndarray,
                                           encoding='utf-8')
                    self.event(name, data, sender_id)
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 11
0
    def run(self):
        ''' Start the main loop of this node. '''
        while self.running:
            # Get new events from the I/O thread
            # while self.event_io.poll(0):
            if self.event_io.getsockopt(zmq.EVENTS) & zmq.POLLIN:
                msg = self.event_io.recv_multipart()
                route, eventname, data = msg[:-2], msg[-2], msg[-1]
                # route back to sender is acquired by reversing the incoming route
                route.reverse()
                if eventname == b'QUIT':
                    self.quit()
                else:
                    pydata = msgpack.unpackb(data, object_hook=decode_ndarray, encoding='utf-8')
                    self.event(eventname, pydata, route)
            # Perform a simulation step
            self.step()

            # Process timers
            Timer.update_timers()
Exemplo n.º 12
0
class ScreenIO(object):
    """Class within sim task which sends/receives data to/from GUI task"""

    # =========================================================================
    # Settings
    # =========================================================================
    # Update rate of simulation info messages [Hz]
    siminfo_rate = 1

    # Update rate of aircraft update messages [Hz]
    acupdate_rate = 5

    # =========================================================================
    # Functions
    # =========================================================================
    def __init__(self):
        # Screen state defaults
        self.def_pan = (0.0, 0.0)
        self.def_zoom = 1.0
        # Screen state overrides per client
        self.client_pan = dict()
        self.client_zoom = dict()
        self.client_ar = dict()

        self.route_acid = None

        # Timing bookkeeping counters
        self.prevtime = 0.0
        self.samplecount = 0
        self.prevcount = 0

        # Output event timers
        self.slow_timer = Timer()
        self.slow_timer.timeout.connect(self.send_siminfo)
        self.slow_timer.timeout.connect(self.send_route_data)
        self.slow_timer.start(int(1000 / self.siminfo_rate))

        self.fast_timer = Timer()
        self.fast_timer.timeout.connect(self.send_aircraft_data)
        self.fast_timer.start(int(1000 / self.acupdate_rate))

    def update(self):
        if bs.sim.state == bs.OP:
            self.samplecount += 1

    def reset(self):
        self.samplecount = 0
        self.prevcount = 0
        self.prevtime = 0.0

        # Communicate reset to gui
        bs.sim.send_event(b'RESET', b'ALL')

    def echo(self, text='', flags=0):
        bs.sim.send_event(b'ECHO', dict(text=text, flags=flags))

    def cmdline(self, text):
        bs.sim.send_event(b'CMDLINE', text)

    def getviewctr(self):
        return self.client_pan.get(stack.sender()) or self.def_pan

    def getviewbounds(self):
        # Get appropriate lat/lon/zoom/aspect ratio
        sender = stack.sender()
        lat, lon = self.client_pan.get(sender) or self.def_pan
        zoom = self.client_zoom.get(sender) or self.def_zoom
        ar = self.client_ar.get(sender) or 1.0

        lat0 = lat - 1.0 / (zoom * ar)
        lat1 = lat + 1.0 / (zoom * ar)
        lon0 = lon - 1.0 / (zoom * np.cos(np.radians(lat)))
        lon1 = lon + 1.0 / (zoom * np.cos(np.radians(lat)))
        return lat0, lat1, lon0, lon1

    def zoom(self, zoom, absolute=True):
        sender = stack.sender()
        if sender:
            if absolute:
                self.client_zoom[sender] = zoom
            else:
                self.client_zoom[sender] = zoom * self.client_zoom.get(
                    sender, self.def_zoom)
        else:
            self.def_zoom = zoom * (1.0 if absolute else self.def_zoom)
            self.client_zoom.clear()

        bs.sim.send_event(b'PANZOOM', dict(zoom=zoom, absolute=absolute))

    def pan(self, *args):
        ''' Move center of display, relative of to absolute position lat,lon '''
        lat, lon = 0, 0
        absolute = False
        if args[0] == "LEFT":
            lon = -0.5
        elif args[0] == "RIGHT":
            lon = 0.5
        elif args[0] == "UP":
            lat = 0.5
        elif args[0] == "DOWN":
            lat = -0.5
        else:
            absolute = True
            lat, lon = args

        sender = stack.sender()
        if sender:
            if absolute:
                self.client_pan[sender] = (lat, lon)
            else:
                ll = self.client_pan.get(sender) or self.def_pan
                self.client_pan[sender] = (lat + ll[0], lon + ll[1])
        else:
            self.def_pan = (lat, lon) if absolute else (lat + self.def_pan[0],
                                                        lon + self.def_pan[1])
            self.client_pan.clear()

        bs.sim.send_event(b'PANZOOM', dict(pan=(lat, lon), absolute=absolute))

    def shownd(self, acid):
        bs.sim.send_event(b'SHOWND', acid)

    def symbol(self):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='SYM'))

    def feature(self, switch, argument=None):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag=switch, args=argument))

    def trails(self, sw):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='TRAIL', args=sw))

    def showroute(self, acid):
        ''' Toggle show route for this aircraft '''
        self.route_acid = acid
        return True

    def addnavwpt(self, name, lat, lon):
        ''' Add custom waypoint to visualization '''
        bs.sim.send_event(b'DEFWPT', dict(name=name, lat=lat, lon=lon))
        return True

    def show_file_dialog(self):
        bs.sim.send_event(b'SHOWDIALOG', dict(dialog='OPENFILE'))
        return ''

    def show_cmd_doc(self, cmd=''):
        bs.sim.send_event(b'SHOWDIALOG', dict(dialog='DOC', args=cmd))

    def filteralt(self, *args):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='FILTERALT', args=args))

    def objappend(self, objtype, objname, data):
        """Add a drawing object to the radar screen using the following inputs:
           objtype: "LINE"/"POLY" /"BOX"/"CIRCLE" = string with type of object
           objname: string with a name as key for reference
           objdata: lat,lon data, depending on type:
                    POLY/LINE: lat0,lon0,lat1,lon1,lat2,lon2,....
                    BOX : lat0,lon0,lat1,lon1   (bounding box coordinates)
                    CIRCLE: latctr,lonctr,radiusnm  (circle parameters)
        """
        bs.sim.send_event(b'SHAPE',
                          dict(name=objname, shape=objtype, coordinates=data))

    def event(self, eventname, eventdata, sender_rte):
        if eventname == b'PANZOOM':
            self.client_pan[sender_rte[-1]] = eventdata['pan']
            self.client_zoom[sender_rte[-1]] = eventdata['zoom']
            self.client_ar[sender_rte[-1]] = eventdata['ar']
            return True

        return False

    # =========================================================================
    # Slots
    # =========================================================================
    def send_siminfo(self):
        t = time.time()
        dt = np.maximum(t - self.prevtime, 0.00001)  # avoid divide by 0
        speed = (self.samplecount - self.prevcount) / dt * bs.sim.simdt
        bs.sim.send_stream(b'SIMINFO',
                           (speed, bs.sim.simdt, bs.sim.simt,
                            str(bs.sim.utc.replace(microsecond=0)),
                            bs.traf.ntraf, bs.sim.state, stack.get_scenname()))
        self.prevtime = t
        self.prevcount = self.samplecount

    def send_aircraft_data(self):
        data = dict()
        data['simt'] = bs.sim.simt
        data['id'] = bs.traf.id
        data['lat'] = bs.traf.lat
        data['lon'] = bs.traf.lon
        data['alt'] = bs.traf.alt
        data['tas'] = bs.traf.tas
        data['cas'] = bs.traf.cas
        data['gs'] = bs.traf.gs
        data['inconf'] = bs.traf.asas.inconf
        data['tcpamax'] = bs.traf.asas.tcpamax
        data['nconf_cur'] = len(bs.traf.asas.confpairs_unique)
        data['nconf_tot'] = len(bs.traf.asas.confpairs_all)
        data['nlos_cur'] = len(bs.traf.asas.lospairs_unique)
        data['nlos_tot'] = len(bs.traf.asas.lospairs_all)
        data['trk'] = bs.traf.trk
        data['vs'] = bs.traf.vs
        data['vmin'] = bs.traf.asas.vmin
        data['vmax'] = bs.traf.asas.vmax

        # Trails, send only new line segments to be added
        data['swtrails'] = bs.traf.trails.active
        data['traillat0'] = bs.traf.trails.newlat0
        data['traillon0'] = bs.traf.trails.newlon0
        data['traillat1'] = bs.traf.trails.newlat1
        data['traillon1'] = bs.traf.trails.newlon1
        bs.traf.trails.clearnew()

        # Last segment which is being built per aircraft
        data['traillastlat'] = bs.traf.trails.lastlat
        data['traillastlon'] = bs.traf.trails.lastlon

        # Transition level as defined in traf
        data['translvl'] = bs.traf.translvl

        # ASAS resolutions for visualization. Only send when evaluated
        if bs.traf.asas.asaseval:
            data['asasn'] = bs.traf.asas.asasn
            data['asase'] = bs.traf.asas.asase
        else:
            data['asasn'] = np.zeros(bs.traf.ntraf, dtype=np.float32)
            data['asase'] = np.zeros(bs.traf.ntraf, dtype=np.float32)

        bs.sim.send_stream(b'ACDATA', data)

    def send_route_data(self):
        if self.route_acid:
            data = dict()
            data['acid'] = self.route_acid
            idx = bs.traf.id2idx(self.route_acid)
            if idx >= 0:
                route = bs.traf.ap.route[idx]
                data['iactwp'] = route.iactwp

                # We also need the corresponding aircraft position
                data['aclat'] = bs.traf.lat[idx]
                data['aclon'] = bs.traf.lon[idx]

                data['wplat'] = route.wplat
                data['wplon'] = route.wplon

                data['wpalt'] = route.wpalt
                data['wpspd'] = route.wpspd

                data['wpname'] = route.wpname

            bs.sim.send_stream(b'ROUTEDATA', data)  # Send route data to GUI
Exemplo n.º 13
0
 def step(self):
     ''' Perform one iteration step. Reimplemented in Simulation. '''
     # Process timers
     Timer.update_timers()
Exemplo n.º 14
0
class ScreenIO(object):
    """Class within sim task which sends/receives data to/from GUI task"""

    # =========================================================================
    # Settings
    # =========================================================================
    # Update rate of simulation info messages [Hz]
    siminfo_rate = 1

    # Update rate of aircraft update messages [Hz]
    acupdate_rate = 5

    # =========================================================================
    # Functions
    # =========================================================================
    def __init__(self):
        # Screen state defaults
        self.def_pan     = (0.0, 0.0)
        self.def_zoom    = 1.0
        # Screen state overrides per client
        self.client_pan  = dict()
        self.client_zoom = dict()
        self.client_ar   = dict()

        self.route_acid  = None

        # Timing bookkeeping counters
        self.prevtime    = 0.0
        self.samplecount = 0
        self.prevcount   = 0

        # Output event timers
        self.slow_timer = Timer()
        self.slow_timer.timeout.connect(self.send_siminfo)
        self.slow_timer.timeout.connect(self.send_route_data)
        self.slow_timer.start(int(1000 / self.siminfo_rate))

        self.fast_timer = Timer()
        self.fast_timer.timeout.connect(self.send_aircraft_data)
        self.fast_timer.start(int(1000 / self.acupdate_rate))

    def update(self):
        if bs.sim.state == bs.OP:
            self.samplecount += 1

    def reset(self):
        self.samplecount = 0
        self.prevcount   = 0
        self.prevtime    = 0.0

        # Communicate reset to gui
        bs.sim.send_event(b'RESET', b'ALL')


    def echo(self, text='', flags=0):
        bs.sim.send_event(b'ECHO', dict(text=text, flags=flags))

    def cmdline(self, text):
        bs.sim.send_event(b'CMDLINE', text)

    def getviewctr(self):
        return self.client_pan.get(stack.sender()) or self.def_pan

    def getviewbounds(self):
        # Get appropriate lat/lon/zoom/aspect ratio
        sender   = stack.sender()
        lat, lon = self.client_pan.get(sender) or self.def_pan
        zoom     = self.client_zoom.get(sender) or self.def_zoom
        ar       = self.client_ar.get(sender) or 1.0

        lat0 = lat - 1.0 / (zoom * ar)
        lat1 = lat + 1.0 / (zoom * ar)
        lon0 = lon - 1.0 / (zoom * np.cos(np.radians(lat)))
        lon1 = lon + 1.0 / (zoom * np.cos(np.radians(lat)))
        return lat0, lat1, lon0, lon1

    def zoom(self, zoom, absolute=True):
        sender    = stack.sender()
        if sender:
            if absolute:
                self.client_zoom[sender] = zoom
            else:
                self.client_zoom[sender] = zoom * self.client_zoom.get(sender, self.def_zoom)
        else:
            self.def_zoom = zoom * (1.0 if absolute else self.def_zoom)
            self.client_zoom.clear()

        bs.sim.send_event(b'PANZOOM', dict(zoom=zoom, absolute=absolute))

    def pan(self, *args):
        ''' Move center of display, relative of to absolute position lat,lon '''
        lat, lon = 0, 0
        absolute = False
        if args[0] == "LEFT":
            lon = -0.5
        elif args[0] == "RIGHT":
            lon = 0.5
        elif args[0] == "UP":
            lat = 0.5
        elif args[0] == "DOWN":
            lat = -0.5
        else:
            absolute = True
            lat, lon = args

        sender    = stack.sender()
        if sender:
            if absolute:
                self.client_pan[sender] = (lat, lon)
            else:
                ll = self.client_pan.get(sender) or self.def_pan
                self.client_pan[sender] = (lat + ll[0], lon + ll[1])
        else:
            self.def_pan = (lat,lon) if absolute else (lat + self.def_pan[0],
                                                       lon + self.def_pan[1])
            self.client_pan.clear()

        bs.sim.send_event(b'PANZOOM', dict(pan=(lat,lon), absolute=absolute))

    def shownd(self, acid):
        bs.sim.send_event(b'SHOWND', acid)

    def symbol(self):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='SYM'))

    def feature(self, switch, argument=None):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag=switch, args=argument))

    def trails(self,sw):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='TRAIL', args=sw))

    def showroute(self, acid):
        ''' Toggle show route for this aircraft '''
        self.route_acid = acid
        return True

    def addnavwpt(self, name, lat, lon):
        ''' Add custom waypoint to visualization '''
        bs.sim.send_event(b'DEFWPT', dict(name=name, lat=lat, lon=lon))
        return True

    def show_file_dialog(self):
        bs.sim.send_event(b'SHOWDIALOG', dict(dialog='OPENFILE'))
        return ''

    def show_cmd_doc(self, cmd=''):
        bs.sim.send_event(b'SHOWDIALOG', dict(dialog='DOC', args=cmd))

    def filteralt(self, *args):
        bs.sim.send_event(b'DISPLAYFLAG', dict(flag='FILTERALT', args=args))

    def objappend(self, objtype, objname, data):
        """Add a drawing object to the radar screen using the following inputs:
           objtype: "LINE"/"POLY" /"BOX"/"CIRCLE" = string with type of object
           objname: string with a name as key for reference
           objdata: lat,lon data, depending on type:
                    POLY/LINE: lat0,lon0,lat1,lon1,lat2,lon2,....
                    BOX : lat0,lon0,lat1,lon1   (bounding box coordinates)
                    CIRCLE: latctr,lonctr,radiusnm  (circle parameters)
        """
        bs.sim.send_event(b'SHAPE', dict(name=objname, shape=objtype, coordinates=data))

    def event(self, eventname, eventdata, sender_rte):
        if eventname == b'PANZOOM':
            self.client_pan[sender_rte[-1]]  = eventdata['pan']
            self.client_zoom[sender_rte[-1]] = eventdata['zoom']
            self.client_ar[sender_rte[-1]]   = eventdata['ar']
            return True

        return False

    # =========================================================================
    # Slots
    # =========================================================================
    def send_siminfo(self):
        t  = time.time()
        dt = np.maximum(t - self.prevtime, 0.00001)  # avoid divide by 0
        speed = (self.samplecount - self.prevcount) / dt * bs.sim.simdt
        bs.sim.send_stream(b'SIMINFO', (speed, bs.sim.simdt, bs.sim.simt,
            bs.sim.simtclock, bs.traf.ntraf, bs.sim.state, stack.get_scenname()))
        self.prevtime  = t
        self.prevcount = self.samplecount

    def send_aircraft_data(self):
        data               = dict()
        data['simt']       = bs.sim.simt
        data['id']         = bs.traf.id
        data['lat']        = bs.traf.lat
        data['lon']        = bs.traf.lon
        data['alt']        = bs.traf.alt
        data['tas']        = bs.traf.tas
        data['cas']        = bs.traf.cas
        data['iconf']      = bs.traf.asas.iconf
        data['confcpalat'] = bs.traf.asas.latowncpa
        data['confcpalon'] = bs.traf.asas.lonowncpa
        data['trk']        = bs.traf.hdg
        data['vs']         = bs.traf.vs
        data['vmin']       = bs.traf.asas.vmin
        data['vmax']       = bs.traf.asas.vmax

        # Trails, send only new line segments to be added
        data['swtrails']  = bs.traf.trails.active
        data['traillat0'] = bs.traf.trails.newlat0
        data['traillon0'] = bs.traf.trails.newlon0
        data['traillat1'] = bs.traf.trails.newlat1
        data['traillon1'] = bs.traf.trails.newlon1
        bs.traf.trails.clearnew()

        # Last segment which is being built per aircraft
        data['traillastlat']   = bs.traf.trails.lastlat
        data['traillastlon']   = bs.traf.trails.lastlon

        # Conflict statistics
        data['nconf_tot']  = len(bs.traf.asas.conflist_all)
        data['nlos_tot']   = len(bs.traf.asas.LOSlist_all)
        data['nconf_exp']  = len(bs.traf.asas.conflist_exp)
        data['nlos_exp']   = len(bs.traf.asas.LOSlist_exp)
        data['nconf_cur']  = len(bs.traf.asas.conflist_now)
        data['nlos_cur']   = len(bs.traf.asas.LOSlist_now)

        # Transition level as defined in traf
        data['translvl']   = bs.traf.translvl

        # ASAS resolutions for visualization. Only send when evaluated
        if bs.traf.asas.asaseval:
            data['asasn']  = bs.traf.asas.asasn
            data['asase']  = bs.traf.asas.asase
        else:
            data['asasn']  = np.zeros(bs.traf.ntraf, dtype=np.float32)
            data['asase']  = np.zeros(bs.traf.ntraf, dtype=np.float32)

        bs.sim.send_stream(b'ACDATA', data)

    def send_route_data(self):
        if self.route_acid:
            data               = dict()
            data['acid']       = self.route_acid
            idx   = bs.traf.id2idx(self.route_acid)
            if idx >= 0:
                route          = bs.traf.ap.route[idx]
                data['iactwp'] = route.iactwp

                # We also need the corresponding aircraft position
                data['aclat']  = bs.traf.lat[idx]
                data['aclon']  = bs.traf.lon[idx]

                data['wplat']  = route.wplat
                data['wplon']  = route.wplon

                data['wpalt']  = route.wpalt
                data['wpspd']  = route.wpspd

                data['wpname'] = route.wpname

            bs.sim.send_stream(b'ROUTEDATA', data)  # Send route data to GUI