def run(self, phased=False): counters = [ 'inst_retired.any', 'instructions', 'mem_inst_retired.all_loads', 'mem_inst_retired.all_stores', 'L1-dcache-loads', 'L1-dcache-stores', 'LLC-load-misses', 'LLC-store-misses', 'cycles', 'fp_arith_inst_retired.128b_packed_double', 'fp_arith_inst_retired.128b_packed_single', 'fp_arith_inst_retired.256b_packed_double', 'fp_arith_inst_retired.256b_packed_single' ] for prereq in self.prereqs: self.logger.info("Running prereq %s" % prereq) run_command(prereq.split(), self.logger) for task in self.commands: name = task["name"] command = task["command"] self.logger.info("Running command %s" % name) p = Perf() p.set_command(command) p.set_counters(counters) p.set_repeat_factor(1) if phased: result = p.run_phased() for res in result: res["name"] = name self.data.extend(result) else: result = p.run() if result is not None: result["name"] = name self.data.append(result)
def __init__(self, cols): self._rows = [] self.logger = logging.Logger.manager.getLogger(self.__class__.__name__) #self.prio_rows = {} self.cols = cols self._passes = 0 # perf counter to see how many tests we do on a given table self.perf = Perf(self.logger)
def reset(self, navdb): # This ensures that the traffic arrays (which size is dynamic) # are all reset as well, so all lat,lon,sdp etc but also objects adsb super(Traffic, self).reset() self.ntraf = 0 # Reset models self.wind.clear() # Build new modules for area and turbulence self.area = Area(self) self.Turbulence = Turbulence(self) # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) # Import navigation data base self.navdb = navdb # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) self.AMAN=AMAN(AllFlights,unique_runways) for rwy in unique_runways: self.AMAN.initial_schedule_popupflightsonly(intarrtime_AMAN_runway,rwy,simulation_start,unique_runways)
def reset(self): # This ensures that the traffic arrays (which size is dynamic) # are all reset as well, so all lat,lon,sdp etc but also objects adsb super(Traffic, self).reset() self.ntraf = 0 # Reset models self.wind.clear() # Build new modules for area and turbulence self.area = Area() self.Turbulence = Turbulence() # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf() self.trails.reset()
def reset(self, navdb): # model-specific parameters. # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) self.ntraf = 0 # Traffic list & arrays definition # !!!IMPORTANT NOTE!!! # Any variables added here should also be added in the Traffic # methods self.create() (append) and self.delete() (delete) # which can be found directly below __init__ # Traffic basic flight data # Traffic basic flight data self.id = [] # identifier (string) self.type = [] # aircaft type (string) self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.trk = np.array([]) # track angle [deg] self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.cas = np.array([]) # calibrated airspeed [m/s] self.M = np.array([]) # mach number self.alt = np.array([]) # altitude [m] self.fll = np.array([]) # flight level [ft/100] self.vs = np.array([]) # vertical speed [m/s] self.p = np.array([]) # atmospheric air pressure [N/m2] self.rho = np.array([]) # atmospheric air density [kg/m3] self.Temp = np.array([]) # atmospheric air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array([]) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.bphase = np.array([]) # standard bank angles per phase self.hdgsel = np.array([]) # determines whether aircraft is turning # Help variables to save computation time self.coslat = np.array([]) # Cosine of latitude for flat-earth aproximations # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # Traffic autopilot settings self.ahdg = [] # selected heading [deg] self.aspd = [] # selected spd(CAS) [m/s] self.aptas = [] # just for initializing self.ama = [] # selected spd above crossover altitude (Mach) [-] self.apalt = [] # selected alt[m] self.apfll = [] # selected fl [ft/100] self.avs = [] # selected vertical speed [m/s] # limit settings self.limspd = [] # limit speed self.limalt = [] # limit altitude self.limvs = [] # limit vertical speed due to thrust limitation # Traffic navigation information self.orig = [] # Four letter code of origin airport self.dest = [] # Four letter code of destination airport # LNAV route navigation self.swlnav = np.array([]) # Lateral (HDG) based on nav? self.swvnav = np.array([]) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.array([]) # Active WP latitude self.actwplon = np.array([]) # Active WP longitude self.actwpalt = np.array([]) # Active WP altitude to arrive at self.actwpspd = np.array([]) # Active WP speed self.actwpturn = np.array([]) # Distance when to turn to next waypoint self.actwpflyby = np.array([]) # Distance when to turn to next waypoint # VNAV variablescruise level self.crzalt = np.array([]) # Cruise altitude[m] self.dist2vs = np.array([]) # Distance to start V/S of VANAV self.actwpvs = np.array([]) # Actual V/S to use # Route info self.route = [] self.desalt = np.array([]) # desired altitude [m] self.deshdg = np.array([]) # desired heading self.desvs = np.array([]) # desired vertical speed [m/s] self.desspd = np.array([]) # desired speed [m/s] # Display information on label self.label = [] # Text and bitmap of traffic label self.trailcol = [] # Trail color: default 'Blue' # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.array([]) self.adsblat = np.array([]) self.adsblon = np.array([]) self.adsbalt = np.array([]) self.adsbtrk = np.array([]) self.adsbtas = np.array([]) self.adsbgs = np.array([]) self.adsbvs = np.array([]) #----------------------------------------------------------------------------- # Not per aircraft data # Scheduling of FMS and ASAS self.t0fms = -999. # last time fms was called self.dtfms = 1.01 # interval for fms # Flight performance scheduling self.perfdt = 0.1 # [s] update interval of performance limits self.perft0 = -self.perfdt # [s] last time checked (in terms of simt) self.warned2 = False # Flag: Did we warn for default engine parameters yet? # ADS-B transmission-receiver model self.adsb = ADSBModel(self) # Import navigation data base self.navdb = navdb # Traffic area: delete traffic when it leaves this area (so not when outside) self.swarea = False self.arealat0 = 0.0 # [deg] lower latitude defining area self.arealat1 = 0.0 # [deg] upper latitude defining area self.arealon0 = 0.0 # [deg] lower longitude defining area self.arealon1 = 0.0 # [deg] upper longitude defining area self.areafloor = -999999.0 # [m] Delete when descending through this h self.areadt = 5.0 # [s] frequency of area check (simtime) self.areat0 = -100. # last time checked self.arearadius = 100.0 # [NM] radius of experiment area if it is a circle self.inside = [] self.fir_circle_point = (0.0, 0.0) self.fir_circle_radius = 1.0 # Taxi switch self.swtaxi = False # Default OFF: delete traffic below 1500 ft # Research Area ("Square" for Square, "Circle" for Circle area) self.area = "" # Bread crumbs for trails self.lastlat = [] self.lastlon = [] self.lasttim = [] self.trails = Trails() self.swtrails = False # Default switched off # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) self.eps = np.array([]) self.asas.reset()
class Traffic: """ Traffic class definition : Traffic data Methods: Traffic() : constructor reset() : Reset traffic database w.r.t a/c data create(acid,actype,aclat,aclon,achdg,acalt,acspd) : create aircraft delete(acid) : delete an aircraft from traffic data deletall() : delete all traffic update(sim) : do a numerical integration step id2idx(name) : return index in traffic database of given call sign selhdg(i,hdg) : set autopilot heading and activate heading select mode selspd(i,spd) : set autopilot CAS/Mach and activate heading select mode engchange(i,engtype) : change engine type of an aircraft changeTrailColor(color,idx) : change colour of trail of aircraft idx setNoise(A) : Add turbulence Members: see create Created by : Jacco M. Hoekstra """ def __init__(self, navdb): # ASAS object self.asas = ASAS() # All traffic data is initialized in the reset function self.reset(navdb) def reset(self, navdb): # model-specific parameters. # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) self.ntraf = 0 # Traffic list & arrays definition # !!!IMPORTANT NOTE!!! # Any variables added here should also be added in the Traffic # methods self.create() (append) and self.delete() (delete) # which can be found directly below __init__ # Traffic basic flight data # Traffic basic flight data self.id = [] # identifier (string) self.type = [] # aircaft type (string) self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.trk = np.array([]) # track angle [deg] self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.cas = np.array([]) # calibrated airspeed [m/s] self.M = np.array([]) # mach number self.alt = np.array([]) # altitude [m] self.fll = np.array([]) # flight level [ft/100] self.vs = np.array([]) # vertical speed [m/s] self.p = np.array([]) # atmospheric air pressure [N/m2] self.rho = np.array([]) # atmospheric air density [kg/m3] self.Temp = np.array([]) # atmospheric air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array([]) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.bphase = np.array([]) # standard bank angles per phase self.hdgsel = np.array([]) # determines whether aircraft is turning # Help variables to save computation time self.coslat = np.array([]) # Cosine of latitude for flat-earth aproximations # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # Traffic autopilot settings self.ahdg = [] # selected heading [deg] self.aspd = [] # selected spd(CAS) [m/s] self.aptas = [] # just for initializing self.ama = [] # selected spd above crossover altitude (Mach) [-] self.apalt = [] # selected alt[m] self.apfll = [] # selected fl [ft/100] self.avs = [] # selected vertical speed [m/s] # limit settings self.limspd = [] # limit speed self.limalt = [] # limit altitude self.limvs = [] # limit vertical speed due to thrust limitation # Traffic navigation information self.orig = [] # Four letter code of origin airport self.dest = [] # Four letter code of destination airport # LNAV route navigation self.swlnav = np.array([]) # Lateral (HDG) based on nav? self.swvnav = np.array([]) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.array([]) # Active WP latitude self.actwplon = np.array([]) # Active WP longitude self.actwpalt = np.array([]) # Active WP altitude to arrive at self.actwpspd = np.array([]) # Active WP speed self.actwpturn = np.array([]) # Distance when to turn to next waypoint self.actwpflyby = np.array([]) # Distance when to turn to next waypoint # VNAV variablescruise level self.crzalt = np.array([]) # Cruise altitude[m] self.dist2vs = np.array([]) # Distance to start V/S of VANAV self.actwpvs = np.array([]) # Actual V/S to use # Route info self.route = [] self.desalt = np.array([]) # desired altitude [m] self.deshdg = np.array([]) # desired heading self.desvs = np.array([]) # desired vertical speed [m/s] self.desspd = np.array([]) # desired speed [m/s] # Display information on label self.label = [] # Text and bitmap of traffic label self.trailcol = [] # Trail color: default 'Blue' # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.array([]) self.adsblat = np.array([]) self.adsblon = np.array([]) self.adsbalt = np.array([]) self.adsbtrk = np.array([]) self.adsbtas = np.array([]) self.adsbgs = np.array([]) self.adsbvs = np.array([]) #----------------------------------------------------------------------------- # Not per aircraft data # Scheduling of FMS and ASAS self.t0fms = -999. # last time fms was called self.dtfms = 1.01 # interval for fms # Flight performance scheduling self.perfdt = 0.1 # [s] update interval of performance limits self.perft0 = -self.perfdt # [s] last time checked (in terms of simt) self.warned2 = False # Flag: Did we warn for default engine parameters yet? # ADS-B transmission-receiver model self.adsb = ADSBModel(self) # Import navigation data base self.navdb = navdb # Traffic area: delete traffic when it leaves this area (so not when outside) self.swarea = False self.arealat0 = 0.0 # [deg] lower latitude defining area self.arealat1 = 0.0 # [deg] upper latitude defining area self.arealon0 = 0.0 # [deg] lower longitude defining area self.arealon1 = 0.0 # [deg] upper longitude defining area self.areafloor = -999999.0 # [m] Delete when descending through this h self.areadt = 5.0 # [s] frequency of area check (simtime) self.areat0 = -100. # last time checked self.arearadius = 100.0 # [NM] radius of experiment area if it is a circle self.inside = [] self.fir_circle_point = (0.0, 0.0) self.fir_circle_radius = 1.0 # Taxi switch self.swtaxi = False # Default OFF: delete traffic below 1500 ft # Research Area ("Square" for Square, "Circle" for Circle area) self.area = "" # Bread crumbs for trails self.lastlat = [] self.lastlon = [] self.lasttim = [] self.trails = Trails() self.swtrails = False # Default switched off # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) self.eps = np.array([]) self.asas.reset() def mcreate(self, count, actype=None, alt=None, spd=None, dest=None, area=None): """ Create multiple random aircraft in a specified area """ idbase = chr(randint(65, 90)) + chr(randint(65, 90)) if actype is None: actype = 'B744' for i in xrange(count): acid = idbase + '%05d' % i aclat = random() * (area[1] - area[0]) + area[0] aclon = random() * (area[3] - area[2]) + area[2] achdg = float(randint(1, 360)) acalt = (randint(2000, 39000) * ft) if alt is None else alt acspd = (randint(250, 450) * kts) if spd is None else spd self.create(acid, actype, aclat, aclon, achdg, acalt, acspd) def create(self, acid, actype, aclat, aclon, achdg, acalt, casmach): """Create an aircraft""" # Check if not already exist if self.id.count(acid.upper()) > 0: return False, acid + " already exists." # already exists do nothing # Increase number of aircraft self.ntraf = self.ntraf + 1 # Convert speed if 0.1 < casmach < 1.0 : acspd = mach2tas(casmach, acalt) else: acspd = cas2tas(casmach, acalt) # Process input self.id.append(acid.upper()) self.type.append(actype) self.lat = np.append(self.lat, aclat) self.lon = np.append(self.lon, aclon) self.trk = np.append(self.trk, achdg) # TBD: add conversion hdg => trk self.alt = np.append(self.alt, acalt) self.fll = np.append(self.fll, (acalt) / (100 * ft)) self.vs = np.append(self.vs, 0.) c_temp, c_rho, c_p = vatmos(acalt) self.p = np.append(self.p, c_p) self.rho = np.append(self.rho, c_rho) self.Temp = np.append(self.Temp, c_temp) self.dtemp = np.append(self.dtemp, 0) # at the moment just ISA conditions self.tas = np.append(self.tas, acspd) self.gs = np.append(self.gs, acspd) self.cas = np.append(self.cas, tas2cas(acspd, acalt)) self.M = np.append(self.M, tas2mach(acspd, acalt)) # AC is initialized with neutral max bank angle self.bank = np.append(self.bank, radians(25.)) if self.ntraf < 2: self.bphase = np.deg2rad(np.array([15, 35, 35, 35, 15, 45])) self.hdgsel = np.append(self.hdgsel, False) #------------------------------Performance data-------------------------------- # Type specific data #(temporarily default values) self.avsdef = np.append(self.avsdef, 1500. * fpm) # default vertical speed of autopilot self.aphi = np.append(self.aphi, radians(25.)) # bank angle setting of autopilot self.ax = np.append(self.ax, kts) # absolute value of longitudinal accelleration # Crossover altitude self.abco = np.append(self.abco, 0) self.belco = np.append(self.belco, 1) # performance data self.perf.create(actype) # Traffic autopilot settings: hdg[deg], spd (CAS,m/s), alt[m], vspd[m/s] self.ahdg = np.append(self.ahdg, achdg) # selected heading [deg] self.aspd = np.append(self.aspd, tas2cas(acspd, acalt)) # selected spd(cas) [m/s] self.aptas = np.append(self.aptas, acspd) # [m/s] self.ama = np.append(self.ama, 0.) # selected spd above crossover (Mach) [-] self.apalt = np.append(self.apalt, acalt) # selected alt[m] self.apfll = np.append(self.apfll, (acalt / 100)) # selected fl[ft/100] self.avs = np.append(self.avs, 0.) # selected vertical speed [m/s] # limit settings: initialize with 0 self.limspd = np.append(self.limspd, 0.0) self.limalt = np.append(self.limalt, 0.0) self.limvs = np.append(self.limvs, 0.0) # Help variables to save computation time self.coslat = np.append(self.coslat, cos(radians(aclat))) # Cosine of latitude for flat-earth aproximations # Traffic navigation information self.dest.append("") self.orig.append("") # LNAV route navigation self.swlnav = np.append(self.swlnav, False) # Lateral (HDG) based on nav self.swvnav = np.append(self.swvnav, False) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.append(self.actwplat, 89.99) # Active WP latitude self.actwplon = np.append(self.actwplon, 0.0) # Active WP longitude self.actwpalt = np.append(self.actwpalt, 0.0) # Active WP altitude self.actwpspd = np.append(self.actwpspd, -999.) # Active WP speed self.actwpturn = np.append(self.actwpturn, 1.0) # Distance to active waypoint where to turn self.actwpflyby = np.append(self.actwpflyby, 1.0) # Flyby/fly-over switch # VNAV cruise level self.crzalt = np.append(self.crzalt, -999.) # Cruise altitude[m] <0=None self.dist2vs = np.append(self.dist2vs, -999.) # Distance to start V/S of VANAV self.actwpvs = np.append(self.actwpvs, 0.0) # Actual V/S to use then # Route info self.route.append(Route(self.navdb)) # create empty route connected with nav databse eas = tas2eas(acspd, acalt) self.desalt = np.append(self.desalt, acalt) self.desvs = np.append(self.desvs, 0.0) self.desspd = np.append(self.desspd, eas) self.deshdg = np.append(self.deshdg, achdg) # Area variable set to False to avoid deletion upon creation outside self.inside.append(False) # Display information on label self.label.append(['', '', '', 0]) # Bread crumbs for trails self.trailcol.append(self.trails.defcolor) self.lastlat = np.append(self.lastlat, aclat) self.lastlon = np.append(self.lastlon, aclon) self.lasttim = np.append(self.lasttim, 0.0) # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.append(self.adsbtime, np.random.rand(self.trunctime)) self.adsblat = np.append(self.adsblat, aclat) self.adsblon = np.append(self.adsblon, aclon) self.adsbalt = np.append(self.adsbalt, acalt) self.adsbtrk = np.append(self.adsbtrk, achdg) self.adsbtas = np.append(self.adsbtas, acspd) self.adsbgs = np.append(self.adsbgs, acspd) self.adsbvs = np.append(self.adsbvs, 0.) self.eps = np.append(self.eps, 0.01) self.asas.create(achdg, eas, acalt) return True def delete(self, acid): """Delete an aircraft""" # Look up index of aircraft idx = self.id2idx(acid) # Do nothing if not found if idx < 0: return False del self.id[idx] del self.type[idx] # Traffic basic data self.lat = np.delete(self.lat, idx) self.lon = np.delete(self.lon, idx) self.trk = np.delete(self.trk, idx) self.alt = np.delete(self.alt, idx) self.fll = np.delete(self.fll, idx) self.vs = np.delete(self.vs, idx) self.tas = np.delete(self.tas, idx) self.gs = np.delete(self.gs, idx) self.cas = np.delete(self.cas, idx) self.M = np.delete(self.M, idx) self.p = np.delete(self.p, idx) self.rho = np.delete(self.rho, idx) self.Temp = np.delete(self.Temp, idx) self.dtemp = np.delete(self.dtemp, idx) self.hdgsel = np.delete(self.hdgsel, idx) self.bank = np.delete(self.bank, idx) # Crossover altitude self.abco = np.delete(self.abco, idx) self.belco = np.delete(self.belco, idx) # Type specific data (temporarily default values) self.avsdef = np.delete(self.avsdef, idx) self.aphi = np.delete(self.aphi, idx) self.ax = np.delete(self.ax, idx) # performance data self.perf.delete(idx) # Traffic autopilot settings: hdg[deg], spd (CAS,m/s), alt[m], vspd[m/s] self.ahdg = np.delete(self.ahdg, idx) self.aspd = np.delete(self.aspd, idx) self.ama = np.delete(self.ama, idx) self.aptas = np.delete(self.aptas, idx) self.apalt = np.delete(self.apalt, idx) self.apfll = np.delete(self.apfll, idx) self.avs = np.delete(self.avs, idx) # limit settings self.limspd = np.delete(self.limspd, idx) self.limalt = np.delete(self.limalt, idx) self.limvs = np.delete(self.limvs, idx) # Help variables to save computation time self.coslat = np.delete(self.coslat, idx) # Cosine of latitude for flat-earth aproximations # Traffic navigation variables del self.dest[idx] del self.orig[idx] self.swlnav = np.delete(self.swlnav, idx) self.swvnav = np.delete(self.swvnav, idx) self.actwplat = np.delete(self.actwplat, idx) self.actwplon = np.delete(self.actwplon, idx) self.actwpalt = np.delete(self.actwpalt, idx) self.actwpspd = np.delete(self.actwpspd, idx) self.actwpturn = np.delete(self.actwpturn, idx) self.actwpflyby = np.delete(self.actwpflyby, idx) # VNAV cruise level self.crzalt = np.delete(self.crzalt, idx) self.dist2vs = np.delete(self.dist2vs, idx) # Distance to start V/S of VANAV self.actwpvs = np.delete(self.actwpvs, idx) # Actual V/S to use # Route info del self.route[idx] self.desalt = np.delete(self.desalt, idx) self.desvs = np.delete(self.desvs, idx) self.desspd = np.delete(self.desspd, idx) self.deshdg = np.delete(self.deshdg, idx) # Metrics, area del self.inside[idx] # Traffic display data: label del self.label[idx] # Delete bread crumb data self.lastlat = np.delete(self.lastlat, idx) self.lastlon = np.delete(self.lastlon, idx) self.lasttim = np.delete(self.lasttim, idx) del self.trailcol[idx] # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.delete(self.adsbtime, idx) self.adsblat = np.delete(self.adsblat, idx) self.adsblon = np.delete(self.adsblon, idx) self.adsbalt = np.delete(self.adsbalt, idx) self.adsbtrk = np.delete(self.adsbtrk, idx) self.adsbtas = np.delete(self.adsbtas, idx) self.adsbgs = np.delete(self.adsbgs, idx) self.adsbvs = np.delete(self.adsbvs, idx) # Decrease number fo aircraft self.ntraf = self.ntraf - 1 self.eps = np.delete(self.eps, idx) self.asas.delete(idx) return True def update(self, simt, simdt): # Update only necessary if there is traffic if self.ntraf == 0: return #---------------- Atmosphere ---------------- self.p, self.rho, self.Temp = vatmos(self.alt) ############################################################################### # Debugging: add 10000 random aircraft # if simt>1.0 and self.ntraf<1000: # for i in range(10000): # acid="KL"+str(i) # aclat = random.random()*180.-90. # aclon = random.random()*360.-180. # achdg = random.random()*360. # acalt = (random.random()*18000.+2000.)*0.3048 # self.create(acid,'B747',aclat,aclon,achdg,acalt,350.) # ################################################################################# #-------------------- ADSB update: -------------------- self.adsbtime = self.adsbtime + simdt if self.ADSBtrunc: ADSB_update = np.where(self.adsbtime > self.trunctime) else: ADSB_update = range(self.ntraf) for i in ADSB_update: self.adsbtime[i] = self.adsbtime[i] - self.trunctime self.adsblat[i] = self.lat[i] self.adsblon[i] = self.lon[i] self.adsbalt[i] = self.alt[i] self.adsbtrk[i] = self.trk[i] self.adsbtas[i] = self.tas[i] self.adsbgs[i] = self.gs[i] self.adsbvs[i] = self.vs[i] # New version ADSB Model self.adsb.update() #------------------- ASAS update: --------------------- # Reset label because of colour change # Save old result iconf0 = np.array(self.asas.iconf) self.asas.update(self, simt) # TODO: this doesn't work anymore when asas.iconf is a list of lists # chnged = np.where(iconf0 != np.array(self.asas.iconf))[0] if settings.gui=="pygame": for i in range(self.ntraf): if np.any(iconf0[i] != self.asas.iconf[i]): self.label[i] = [" ", " ", "", " "] #----------------- FMS GUIDANCE & NAVIGATION ------------------ # Scheduling: when dt has passed or restart: if self.t0fms + self.dtfms < simt or simt < self.t0fms: self.t0fms = simt # FMS LNAV mode: qdr, dist = geo.qdrdist(self.lat, self.lon, self.actwplat, self.actwplon) # [deg][nm]) # Check whether shift based dist [nm] is required, set closer than WP turn distance iwpclose = np.where(self.swlnav * (dist < self.actwpturn))[0] # Shift waypoints for aircraft i where necessary for i in iwpclose: # Get next wp (lnavon = False if no more waypoints) lat, lon, alt, spd, xtoalt, toalt, lnavon, flyby = \ self.route[i].getnextwp() # note: xtoalt,toalt in [m] # End of route/no more waypoints: switch off LNAV if not lnavon: self.swlnav[i] = False # Drop LNAV at end of route # In case of no LNAV, do not allow VNAV mode on it sown if not self.swlnav[i]: self.swvnav[i] = False self.actwplat[i] = lat self.actwplon[i] = lon self.actwpflyby[i] = int(flyby) # 1.0 in case of fly by, els fly over # User has entered an altitude for this waypoint if alt >= 0.: self.actwpalt[i] = alt # VNAV = FMS ALT/SPD mode # calculated altitude is available and active if toalt >= 0. and self.swvnav[i]: # somewhere there is an altitude constraint ahead # Descent VNAV mode (T/D logic) if self.alt[i] > toalt + 10. * ft: #Steepness dh/dx in [m/m], for now 1:3 rule of thumb steepness = 3000. * ft / (10. * nm) #Calculate max allowed altitude at next wp (above toalt) self.actwpalt[i] = toalt + xtoalt * steepness # Dist to waypoint where descent should start self.dist2vs[i] = (self.alt[i] - self.actwpalt[i]) / steepness # Flat earth distance to next wp dy = (lat - self.lat[i]) dx = (lon - self.lon[i]) * self.coslat[i] legdist = 60. * nm * sqrt(dx * dx + dy * dy) # If descent is urgent, descent with maximum steepness if legdist < self.dist2vs[i]: self.apalt[i] = self.actwpalt[i] # dial in altitude of next waypoint as calculated t2go = max(0.1, legdist) / max(0.01, self.gs[i]) self.actwpvs[i] = (self.actwpalt[i] - self.alt[i]) / t2go else: # normal case: still time till descent starts # Calculate V/s using steepness, # protect against zero/invalid ground speed value self.actwpvs[i] = -steepness*(self.gs[i] + \ (self.gs[i]<0.2*self.tas[i])*self.tas[i]) # Climb VNAV mode: climb as soon as possible (T/C logic) elif self.swvnav[i] and self.alt[i]<toalt-10.*ft: self.actwpalt[i] = toalt self.apalt[i] = self.actwpalt[i] # dial in altitude of next waypoint as calculated self.dist2vs[i] = 9999. # Level leg: never start V/S else: self.dist2vs[i] = -999. #No altirude defined: never start V/S else: self.dist2vs[i] = -999. # VNAV spd mode: use speed of this waypoint as commanded speed # while passing waypoint and save next speed for passing next wp if self.swvnav[i] and self.actwpspd[i]>0.0: # check mode and value # Select CAS or Mach command by checking value of actwpspd if self.actwpspd[i]<2.0: # Mach command self.aspd[i] = mach2cas(self.actwpspd[i],self.alt[i]) self.ama[i] = self.actwpspd[i] else: # CAS command self.aspd[i] = self.actwpspd[i] self.ama[i] = cas2tas(spd,self.alt[i]) if spd>0. and self.swlnav[i] and self.swvnav[i]: # Valid speed and LNAV and VNAV ap modes are on self.actwpspd[i] = spd else: self.actwpspd[i] = -999. # Calculate distance before waypoint where to start the turn # Turn radius: R = V2 tan phi / g # Distance to turn: wpturn = R * tan (1/2 delhdg) but max 4 times radius # using default bank angle per flight phase turnrad = self.tas[i]*self.tas[i]/tan(self.bank[i]) /g0 /nm # [nm] dy = (self.actwplat[i]-self.lat[i]) dx = (self.actwplon[i]-self.lon[i])*self.coslat[i] qdr[i] = degrees(atan2(dx,dy)) self.actwpturn[i] = self.actwpflyby[i]* \ max(3.,abs(turnrad*tan(radians(0.5*degto180(qdr[i]- \ self.route[i].wpdirfrom[self.route[i].iactwp]))))) # [nm] #=============== End of Waypoint switching loop =================== # VNAV Guidance # Do VNAV start of descent check dy = (self.actwplat-self.lat) dx = (self.actwplon-self.lon)*self.coslat dist2wp = 60.*nm*np.sqrt(dx*dx+dy*dy) steepness = 3000.*ft/(10.*nm) # VNAV AP LOGIC: descend as late as possible, climb as soon as possible # First term: descend when distance to next wp is descent distance # Second term: climb when still below altitude of next waypoint self.swvnavvs = self.swlnav*self.swvnav*((dist2wp<self.dist2vs) + \ (self.actwpalt>self.alt)) self.avs = (1-self.swvnavvs)*self.avs + self.swvnavvs*steepness*self.gs self.aalt = (1-self.swvnavvs)*self.apalt + self.swvnavvs*self.actwpalt # Set headings based on swlnav self.ahdg = np.where(self.swlnav, qdr, self.ahdg) #-------------END of FMS update ------------------- # NOISE: Turbulence if self.turbulence: timescale=np.sqrt(simdt) trkrad=np.radians(self.trk) #write turbulences in array turb=np.array(self.standardturbulence) turb=np.where(turb>1e-6,turb,1e-6) #horizontal flight direction turbhf=np.random.normal(0,turb[0]*timescale,self.ntraf) #[m] #horizontal wing direction turbhw=np.random.normal(0,turb[1]*timescale,self.ntraf) #[m] #vertical direction turbalt=np.random.normal(0,turb[2]*timescale,self.ntraf) #[m] #lateral, longitudinal direction turblat=np.cos(trkrad)*turbhf-np.sin(trkrad)*turbhw #[m] turblon=np.sin(trkrad)*turbhf+np.cos(trkrad)*turbhw #[m] else: turbalt=np.zeros(self.ntraf) #[m] turblat=np.zeros(self.ntraf) #[m] turblon=np.zeros(self.ntraf) #[m] # ASAS AP switches #--------- Input to Autopilot settings to follow: destination or ASAS ---------- # desired autopilot settings due to ASAS self.deshdg = self.asas.asasactive*self.asas.asashdg + (1-self.asas.asasactive)*self.ahdg self.desspd = self.asas.asasactive*self.asas.asasspd + (1-self.asas.asasactive)*self.aspd self.desalt = self.asas.asasactive*self.asas.asasalt + (1-self.asas.asasactive)*self.apalt self.desvs = self.asas.asasactive*self.asas.asasvsp + (1-self.asas.asasactive)*self.avs #-------------- Performance limits autopilot settings -------------- # Check difference with AP settings for trafperf and autopilot self.delalt = self.desalt - self.alt # [m] # below crossover altitude: CAS=const, above crossover altitude: Mach = const # aptas has to be calculated before delspd self.aptas = vcas2tas(self.desspd, self.alt) * self.belco + \ vmach2tas(self.ama, self.alt) * self.abco self.delspd = self.desspd - self.tas # check for the flight envelope self.perf.limits() # Update autopilot settings with values within the flight envelope # Autopilot selected speed setting [m/s] # To do: add const Mach const CAS mode self.aspd = (self.limspd ==0)*self.desspd + (self.limspd!=0)*self.limspd # Autopilot selected altitude [m] limited when necessary self.aalt = (self.limalt ==0)*self.desalt + (self.limalt!=0)*self.limalt # Autopilot selected heading self.ahdg = self.deshdg # Autopilot selected vertical speed (V/S) self.avs = (self.limvs==0)*self.desvs + (self.limvs!=0)*self.limvs # To be discussed: Following change in VNAV mode only? # below crossover altitude: CAS=const, above crossover altitude: MA = const #climb/descend above crossover: Ma = const, else CAS = const #ama is fixed when above crossover swma = np.where(self.abco*(self.ama == 0.)) # Above cross-over self.ama[swma] = vcas2mach(self.aspd[swma], self.alt[swma]) # ama is deleted when below crossover swma2 = np.where(self.belco*(self.ama!=0.)) # below corss-over self.ama[swma2] = 0. #---------- Basic Autopilot modes ---------- # SPD HOLD/SEL mode: aspd = autopilot selected speed (first only eas) # for information: # no more ? self.aptas = (self.actwpspd > 0.01)*self.actwpspd*self.swvnav + \ # np.logical_or((self.actwpspd <= 0.01),np.logical_not (self.swvnav))*self.aptas self.delspd = self.aptas - self.tas swspdsel = np.abs(self.delspd) > 0.4 # <1 kts = 0.514444 m/s ax = np.minimum(abs(self.delspd / max(1e-8,simdt)), self.ax) self.tas = swspdsel * (self.tas + ax * np.sign(self.delspd) * \ simdt) + (1. - swspdsel) * self.aptas # Speed conversions self.cas = vtas2cas(self.tas, self.alt) self.gs = self.tas self.M = vtas2mach(self.tas, self.alt) # Update performance every self.perfdt seconds if abs(simt - self.perft0) >= self.perfdt: self.perft0 = simt self.perf.perf() # Update aircraft altitude self.eps = np.array(self.ntraf * [0.01]) # almost zero for misc purposes swaltsel = np.abs(self.aalt-self.alt) > \ np.maximum(3.,np.abs(2. * simdt * np.abs(self.vs))) # 3.[m] = 10 [ft] eps alt self.vs = swaltsel*np.sign(self.aalt-self.alt)* \ ( (1-self.swvnav)*np.abs(1500./60.*ft) + \ self.swvnav*np.abs(self.avs) ) self.alt = swaltsel * (self.alt + self.vs * simdt) + \ (1. - swaltsel) * self.aalt + turbalt # HDG HOLD/SEL mode: ahdg = ap selected heading delhdg = (self.ahdg - self.trk + 180.) % 360 - 180. # [deg] # omega = np.degrees(g0 * np.tan(self.aphi) / \ # np.maximum(self.tas, self.eps)) # nominal bank angles per phase from BADA 3.12 omega = np.degrees(g0 * np.tan(self.bank) / \ np.maximum(self.tas, self.eps)) self.hdgsel = np.abs(delhdg) > np.abs(2. * simdt * omega) self.trk = (self.trk + simdt * omega * self.hdgsel * np.sign(delhdg)) % 360. #--------- Kinematics: update lat,lon,alt ---------- ds = simdt * self.gs self.lat = self.lat + \ np.degrees((ds * np.cos(np.radians(self.trk)) + turblat) \ / Rearth) self.coslat = np.cos(np.deg2rad(self.lat)) self.lon = self.lon + \ np.degrees((ds * np.sin(np.radians(self.trk)) + turblon) \ / self.coslat / Rearth) # Update trails when switched on if self.swtrails: self.trails.update(simt, self.lat, self.lon, self.lastlat, self.lastlon, self.lasttim, self.id, self.trailcol) else: self.lastlat = self.lat self.lastlon = self.lon self.lasttim[:] = simt # ----------------AREA check---------------- # Update area once per areadt seconds: if self.swarea and abs(simt - self.areat0) > self.areadt: # Update loop timer self.areat0 = simt # Check all aircraft i = 0 while (i < self.ntraf): # Current status if self.area == "Square": inside = self.arealat0 <= self.lat[i] <= self.arealat1 and \ self.arealon0 <= self.lon[i] <= self.arealon1 and \ self.alt[i] >= self.areafloor and \ (self.alt[i] >= 1500 or self.swtaxi) elif self.area == "Circle": # delete aircraft if it is too far from the center of the circular area, or if has decended below the minimum altitude distance = geo.kwikdist(self.arealat0, self.arealon0, self.lat[i], self.lon[i]) # [NM] inside = distance < self.arearadius and self.alt[i] >= self.areafloor # Compare with previous: when leaving area: delete command if self.inside[i] and not inside: self.delete(self.id[i]) else: # Update area status self.inside[i] = inside i = i + 1 return def id2idx(self, acid): """Find index of aircraft id""" try: return self.id.index(acid.upper()) except: return -1 def setTrails(self, *args): """ Set trails on/off, or change trail color of aircraft """ if type(args[0]) == bool: # Set trails on/off self.swtrails = args[0] if len(args) > 1: self.trails.dt = args[1] if not self.swtrails: self.trails.clear() else: # Change trail color if len(args) < 2 or args[2] not in ["BLUE", "RED", "YELLOW"]: return False, "Set aircraft trail color with: TRAIL acid BLUE/RED/YELLOW" self.changeTrailColor(args[1], args[0]) def changeTrailColor(self, color, idx): """Change color of aircraft trail""" self.trailcol[idx] = self.trails.colorList[color] return def setNoise(self, noiseflag=None): """Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect)""" if noiseflag is None: return True, "Noise is currently " + ("on" if self.noise else "off") self.noise = noiseflag # Noise/turbulence switch self.trunctime = 1 # seconds self.transerror = [1, 100, 100 * ft] # [degree,m,m] standard bearing, distance, altitude error self.standardturbulence = [0, 0.1, 0.1] # m/s standard turbulence (nonnegative) # in (horizontal flight direction, horizontal wing direction, vertical) self.turbulence = self.noise self.ADSBtransnoise = self.noise self.ADSBtrunc = self.noise return True def engchange(self, acid, engid): """Change of engines""" self.perf.engchange(acid, engid) return def selhdg(self, idx, hdg): # HDG command """ Select heading command: HDG acid, hdg """ # Give autopilot commands self.ahdg[idx] = float(hdg) self.swlnav[idx] = False # Everything went ok! return True def selspd(self, idx, casmach): # SPD command """ Select speed command: SPD acid, casmach (= CASkts/Mach) """ # When >=1.0 it is probably CASkts else it is Mach if 0.1 < casmach < 1.0: self.aspd[idx] = mach2cas(casmach, self.alt[idx]) # Convert Mach to CAS m/s self.ama[idx] = casmach else: self.aspd[idx] = casmach # CAS m/s self.ama[idx] = cas2mach(casmach, self.alt[idx]) # Switch off VNAV: SPD command overrides self.swvnav[idx] = False return True def move(self, idx, lat, lon, alt=None, hdg=None, casmach=None, vspd=None): self.lat[idx] = lat self.lon[idx] = lon if alt: self.alt[idx] = alt self.aalt[idx] = alt if hdg: self.trk[idx] = hdg self.ahdg[idx] = hdg if casmach: # Convert speed if 0.1 < casmach < 1.0: self.tas[idx] = mach2tas(casmach, alt) self.aspd[idx] = mach2cas(casmach, alt) else: self.tas[idx] = cas2tas(casmach, alt) self.aspd[idx] = casmach if vspd: self.vs[idx] = vspd self.swvnav[idx] = False def selalt(self, idx, alt, vspd=None): """ Select altitude command: ALT acid, alt, [vspd] """ self.apalt[idx] = alt self.apfll[idx] = alt / (100. * ft) self.swvnav[idx] = False # Check for optional VS argument if vspd: self.avs[idx] = vspd else: delalt = alt - self.alt[idx] # Check for VS with opposite sign => use default vs # by setting autopilot vs to zero if self.avs[idx] * delalt < 0. and abs(self.avs[idx]) > 0.01: self.avs[idx] = 0. def selvspd(self, idx, vspd): """ Vertical speed autopilot command: VS acid vspd """ self.avs[idx] = vspd # self.vs[idx] = vspd self.swvnav[idx] = False def nom(self, idx): """ Reset acceleration back to nominal (1 kt/s^2): NOM acid """ self.ax[idx] = kts def setTaxi(self, flag): """ Set taxi delete flag: OFF auto deletes traffic below 1500 ft """ self.swtaxi = flag def setLNAV(self, idx, flag=None): """ Set LNAV on or off for a specific or for all aircraft """ if idx is None: # All aircraft are targeted self.swlnav = np.array(self.ntraf*[flag]) elif flag is None: return True, (self.id[idx] + ": LNAV is " + "ON" if self.swlnav[idx] else "OFF") elif flag: route = self.route[idx] if route.nwp > 0: self.swlnav[idx] = True route.direct(self, idx, route.wpname[route.findact(self, idx)]) else: return False, ("LNAV " + self.id[idx] + ": no waypoints or destination specified") else: self.swlnav[idx] = False def setVNAV(self, idx, flag=None): """ Set VNAV on or off for a specific or for all aircraft """ if idx is None: # All aircraft are targeted self.swvnav = np.array(self.ntraf*[flag]) elif flag is None: return True, (self.id[idx] + ": VNAV is " + "ON" if self.swvnav[idx] else "OFF") elif flag: if not self.swlnav[idx]: return False, (self.id[idx] + ": VNAV ON requires LNAV to be ON") route = self.route[idx] if route.nwp > 0: self.swvnav[idx] = True route.direct(self, idx, route.wpname[route.findact(self, idx)]) else: return False, ("VNAV " + self.id[idx] + ": no waypoints or destination specified") else: self.swvnav[idx] = False def setDestOrig(self, cmd, idx, *args): if len(args) == 0: if cmd == 'DEST': return True, ('DEST ' + self.id[idx] + ': ' + self.dest[idx]) else: return True, ('ORIG ' + self.id[idx] + ': ' + self.orig[idx]) route = self.route[idx] if len(args) == 1: name = args[0] apidx = self.navdb.getapidx(name) if apidx < 0: return False, (cmd + ": Airport " + name + " not found.") lat = self.navdb.aplat[apidx] lon = self.navdb.aplon[apidx] else: name = self.id[idx] + cmd lat, lon = args if cmd == "DEST": self.dest[idx] = name iwp = route.addwpt(self, idx, self.dest[idx], route.dest, lat, lon, 0.0, self.cas[idx]) # If only waypoint: activate if (iwp == 0) or (self.orig[idx] != "" and route.nwp == 2): self.actwplat[idx] = route.wplat[iwp] self.actwplon[idx] = route.wplon[iwp] self.actwpalt[idx] = route.wpalt[iwp] self.actwpspd[idx] = route.wpspd[iwp] self.swlnav[idx] = True route.iactwp = iwp # If not found, say so elif iwp < 0: return False, (self.dest[idx] + " not found.") # Origin: bookkeeping only for now else: self.orig[idx] = name iwp = route.addwpt(self, idx, self.orig[idx], route.orig, self.lat[idx], self.lon[idx], 0.0, self.cas[idx]) if iwp < 0: return False, (self.orig[idx] + " not found.") def acinfo(self, acid): idx = self.id.index(acid) actype = self.type[idx] lat, lon = self.lat[idx], self.lon[idx] alt, hdg = self.alt[idx] / ft, self.trk[idx] cas = tas2cas(self.tas[idx], self.alt[idx]) / kts tas = self.tas[idx] / kts route = self.route[idx] line = "Info on %s %s index = %d\n" % (acid, actype, idx) \ + "Pos = %.2f, %.2f. Spd: %d kts CAS, %d kts TAS\n" % (lat, lon, cas, tas) \ + "Alt = %d ft, Hdg = %d\n" % (alt, hdg) if self.swlnav[idx] and route.nwp > 0 and route.iactwp >= 0: if self.swvnav[idx]: line += "VNAV, " line += "LNAV to " + route.wpname[route.iactwp] + "\n" if self.orig[idx] != "" or self.dest[idx] != "": line += "Flying" if self.orig[idx] != "": line += " from " + self.orig[idx] if self.dest[idx] != "": line += " to " + self.dest[idx] return line def setArea(self, scr, metric, *args): if args[0] == 'OFF': self.swarea = False self.area = "" scr.objappend(2, "AREA", None) # delete square areas scr.objappend(3, "AREA", None) # delete circle areas return True if type(args[0]) == float and len(args) >= 4: # This is a square area self.arealat0 = min(args[0], args[2]) self.arealat1 = max(args[0], args[2]) self.arealon0 = min(args[1], args[3]) self.arealon1 = max(args[1], args[3]) if len(args) == 5: self.areafloor = args[4] * ft else: self.areafloor = -9999999. self.area = "Square" self.swarea = True scr.objappend(2, "AREA", [args[0], args[1], args[2], args[3]]) # Avoid mass delete due to redefinition of area self.inside = self.ntraf * [False] return True elif args[0] == "FIR" and len(args) <= 3: for i in range(0, len(self.navdb.fir)): if args[1] == self.navdb.fir[i][0]: break if args[1] != self.navdb.fir[i][0]: return False, "Unknown FIR, try again" metric.fir_number = i metric.fir_circle_point = metric.metric_Area.FIR_circle(self.navdb, metric.fir_number) metric.fir_circle_radius = float(args[1]) if len(args) == 3: self.areafloor = args[2] * ft else: self.areafloor = -9999999. self.area = "Circle" self.swarea = True self.inside = self.ntraf * [False] scr.objappend(3, "AREA", [metric.fir_circle_point[0] , metric.fir_circle_point[1], metric.fir_circle_radius]) return True elif args[0] == "CIRCLE" and len(args) in [4, 5]: # draw circular experiment area self.arealat0 = args[1] # Latitude of circle center [deg] self.arealon0 = args[2] # Longitude of circle center [deg] self.arearadius = args[3] # Radius of circle Center [NM] # Deleting traffic flying out of experiment area self.area = "Circle" self.swarea = True if len(args) == 5: self.areafloor = args[4] * ft # [m] else: self.areafloor = -9999999. # [m] # draw the circular experiment area on the radar gui scr.objappend(3, "AREA", [self.arealat0, self.arealon0, self.arearadius]) # Avoid mass delete due to redefinition of area self.inside = self.ntraf * [False] return True return False
class Traffic: """ Traffic class definition : Traffic data Methods: Traffic() : constructor create(acid,actype,aclat,aclon,achdg,acalt,acspd) : create aircraft delete(acid) : delete an aircraft from traffic data update(sim) : do a numerical integration step trafperf () : calculate aircraft performance parameters Members: see create Created by : Jacco M. Hoekstra """ def __init__(self, navdb): self.reset(navdb) return def reset(self, navdb): self.dts = [] self.ntraf = 0 # model-specific parameters. # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) self.dts = [] self.ntraf = 0 # Create datalog instance self.log = Datalog() # Traffic list & arrays definition # !!!IMPORTANT NOTE!!! # Any variables added here should also be added in the Traffic # methods self.create() (append) and self.delete() (delete) # which can be found directly below __init__ # Traffic basic flight data # Traffic basic flight data self.id = [] # identifier (string) self.type = [] # aircaft type (string) self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.trk = np.array([]) # track angle [deg] self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.cas = np.array([]) # callibrated airspeed [m/s] self.M = np.array([]) # mach number self.alt = np.array([]) # altitude [m] self.fll = np.array([]) # flight level [ft/100] self.vs = np.array([]) # vertical speed [m/s] self.rho = np.array([]) # atmospheric air density [m/s] self.temp = np.array([]) # atmospheric air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array( []) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.bphase = np.array([]) # standard bank angles per phase self.hdgsel = np.array([]) # determines whether aircraft is turning # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # Traffic autopilot settings self.ahdg = [] # selected heading [deg] self.aspd = [] # selected spd(eas) [m/s] self.aptas = [] # just for initializing self.ama = [] # selected spd above crossover altitude (Mach) [-] self.aalt = [] # selected alt[m] self.afll = [] # selected fl [ft/100] self.avs = [] # selected vertical speed [m/s] # limit settings self.lspd = [] # limit speed self.lalt = [] # limit altitude self.lvs = [] # limit vertical speed due to thrust limitation # Traffic navigation information self.orig = [] # Four letter code of origin airport self.dest = [] # Four letter code of destination airport # LNAV route navigation self.swlnav = np.array([]) # Lateral (HDG) based on nav? self.swvnav = np.array( []) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.array([]) # Active WP latitude self.actwplon = np.array([]) # Active WP longitude self.actwpalt = np.array([]) # Active WP altitude to arrive at self.actwpspd = np.array([]) # Active WP speed self.actwpturn = np.array([]) # Distance when to turn to next waypoint # VNAV cruise level self.crzalt = np.array([]) # Cruise altitude[m] # Route info self.route = [] # ASAS info per aircraft: self.iconf = [] # index in 'conflicting' aircraft database self.asasactive = np.array( []) # whether the autopilot follows ASAS or not self.asashdg = np.array([]) # heading provided by the ASAS [deg] self.asasspd = np.array([]) # speed provided by the ASAS (eas) [m/s] self.asasalt = np.array([]) # speed alt by the ASAS [m] self.asasvsp = np.array([]) # speed vspeed by the ASAS [m/s] self.desalt = np.array([]) #desired altitude [m] self.deshdg = np.array([]) #desired heading self.desvs = np.array([]) #desired vertical speed [m/s] self.desspd = np.array([]) #desired speed [m/s] # Display information on label self.label = [] # Text and bitmap of traffic label self.trailcol = [] # Trail color: default 'Blue' # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.array([]) self.adsblat = np.array([]) self.adsblon = np.array([]) self.adsbalt = np.array([]) self.adsbtrk = np.array([]) self.adsbtas = np.array([]) self.adsbgs = np.array([]) self.adsbvs = np.array([]) self.inconflict = np.array([], dtype=bool) #----------------------------------------------------------------------------- # Not per aircraft data # Scheduling of FMS and ASAS self.t0fms = -999. # last time fms was called self.dtfms = 1.01 # interval for fms self.t0asas = -999. # last time ASAS was called self.dtasas = 1.00 # interval for ASAS # Flight performance scheduling self.perfdt = 0.1 # [s] update interval of performance limits self.perft0 = -self.perfdt # [s] last time checked (in terms of simt) self.warned2 = False # Flag: Did we warn for default engine parameters yet? # ADS-B transmission-receiver model self.adsb = ADSBModel(self) # ASAS objects: Conflict Database self.dbconf = Dbconf(self, 300., 5. * nm, 1000. * ft) # hard coded values to be replaced # Import navigation data base self.navdb = navdb # Traffic area: delete traffic when it leaves this area (so not when outside) self.swarea = False self.arealat0 = 0.0 # [deg] lower latitude defining area self.arealat1 = 0.0 # [deg] upper latitude defining area self.arealat0 = 0.0 # [deg] lower longitude defining area self.arealat1 = 0.0 # [deg] upper longitude defining area self.areafloor = -999999.0 # [m] Delete when descending through this h self.areadt = 5.0 # [s] frequency of area check (simtime) self.areat0 = -100. # last time checked self.inside = [] self.fir_circle_point = (0.0, 0.0) self.fir_circle_radius = 1.0 # Taxi switch self.swtaxi = False # Default OFF: delete traffic below 1500 ft # Research Area ("Square" for Square, "Circle" for Circle area) self.area = "" # Bread crumbs for trails self.lastlat = [] self.lastlon = [] self.lasttim = [] self.trails = Trails() self.swtrails = False # Default switched off # ADS-B Coverage area self.swAdsbCoverage = False # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) self.eps = np.array([]) return def create_ac(self, acid, actype, aclat, aclon, achdg, acalt, acspd): """Create an aircraft""" # Check if not already exist if self.id.count(acid.upper()) > 0: return False # already exists do nothing # Increase number of aircraft self.ntraf = self.ntraf + 1 # Process input self.id.append(acid.upper()) self.type.append(actype) self.lat = np.append(self.lat, aclat) self.lon = np.append(self.lon, aclon) self.trk = np.append(self.trk, achdg) # TBD: add conversion hdg => trk self.alt = np.append(self.alt, acalt) self.fll = np.append(self.fll, (acalt) / 100) self.vs = np.append(self.vs, 0.) self.rho = np.append(self.rho, density(acalt)) self.temp = np.append(self.temp, temp(acalt)) self.dtemp = np.append(self.dtemp, 0) # at the moment just ISA conditions self.tas = np.append(self.tas, acspd) self.gs = np.append(self.gs, acspd) self.cas = np.append(self.cas, tas2cas(acspd, acalt)) self.M = np.append(self.M, tas2mach(acspd, acalt)) # AC is initialized with neutral max bank angle self.bank = np.append(self.bank, 25.) if self.ntraf < 2: self.bphase = np.deg2rad(np.array([15, 35, 35, 35, 15, 45])) self.hdgsel = np.append(self.hdgsel, False) #------------------------------Performance data-------------------------------- # Type specific data #(temporarily default values) self.avsdef = np.append( self.avsdef, 1500. * fpm) # default vertical speed of autopilot self.aphi = np.append(self.aphi, radians(25.)) # bank angle setting of autopilot self.ax = np.append( self.ax, kts) # absolute value of longitudinal accelleration # Crossover altitude self.abco = np.append(self.abco, 0) self.belco = np.append(self.belco, 1) # performance data self.perf.create(actype) # Traffic autopilot settings: hdg[deg], spd (CAS,m/s), alt[m], vspd[m/s] self.ahdg = np.append(self.ahdg, achdg) # selected heading [deg] self.aspd = np.append(self.aspd, tas2eas(acspd, acalt)) # selected spd(eas) [m/s] self.aptas = np.append(self.aptas, vcas2tas(self.aspd, self.alt)) # [m/s] self.ama = np.append(self.ama, 0.) # selected spd above crossover (Mach) [-] self.aalt = np.append(self.aalt, acalt) # selected alt[m] self.afll = np.append(self.afll, (acalt / 100)) # selected fl[ft/100] self.avs = np.append(self.avs, 0.) # selected vertical speed [m/s] # limit settings: initialize with 0 self.lspd = np.append(self.lspd, 0.0) self.lalt = np.append(self.lalt, 0.0) self.lvs = np.append(self.lvs, 0.0) # Traffic navigation information self.dest.append("") self.orig.append("") # LNAV route navigation self.swlnav = np.append(self.swlnav, False) # Lateral (HDG) based on nav self.swvnav = np.append( self.swvnav, False) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.append(self.actwplat, 89.99) # Active WP latitude self.actwplon = np.append(self.actwplon, 0.0) # Active WP longitude self.actwpalt = np.append(self.actwpalt, 0.0) # Active WP altitude self.actwpspd = np.append(self.actwpspd, -999.) # Active WP speed self.actwpturn = np.append( self.actwpturn, 1.0) # Distance to active waypoint where to turn # VNAV cruise level self.crzalt = np.append(self.crzalt, -999.) # Cruise altitude[m] <0=None # Route info self.route.append(Route( self.navdb)) # create empty route connected with nav databse # ASAS info: no conflict => -1 self.iconf.append(-1) # index in 'conflicting' aircraft database self.asasactive = np.append(self.asasactive, False) self.asashdg = np.append(self.asashdg, achdg) self.asasspd = np.append(self.asasspd, tas2eas(acspd, acalt)) self.asasalt = np.append(self.asasalt, acalt) self.asasvsp = np.append(self.asasvsp, 0.) # Area variable set to False to avoid deletion upon creation outside self.inside.append(False) # Display information on label self.label.append(['', '', '', 0]) # Bread crumbs for trails self.trailcol.append(self.trails.defcolor) self.lastlat = np.append(self.lastlat, aclat) self.lastlon = np.append(self.lastlon, aclon) self.lasttim = np.append(self.lasttim, 0.0) # ADS-B Coverage area self.swAdsbCoverage = False # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.append(self.adsbtime, np.random.rand(self.trunctime)) self.adsblat = np.append(self.adsblat, aclat) self.adsblon = np.append(self.adsblon, aclon) self.adsbalt = np.append(self.adsbalt, acalt) self.adsbtrk = np.append(self.adsbtrk, achdg) self.adsbtas = np.append(self.adsbtas, acspd) self.adsbgs = np.append(self.adsbgs, acspd) self.adsbvs = np.append(self.adsbvs, 0.) self.inconflict = np.append(self.inconflict, False) self.eps = np.append(self.eps, 0.01) return True def delete(self, acid): """Delete an aircraft""" try: # prevent error due to not found idx = self.id.index(acid) except: return False del self.id[idx] del self.type[idx] # Traffic basic data self.lat = np.delete(self.lat, idx) self.lon = np.delete(self.lon, idx) self.trk = np.delete(self.trk, idx) self.alt = np.delete(self.alt, idx) self.fll = np.delete(self.fll, idx) self.vs = np.delete(self.vs, idx) self.tas = np.delete(self.tas, idx) self.gs = np.delete(self.gs, idx) self.cas = np.delete(self.cas, idx) self.M = np.delete(self.M, idx) self.T = np.delete(self.T, idx) self.p = np.delete(self.p, idx) self.rho = np.delete(self.rho, idx) self.temp = np.delete(self.temp, idx) self.dtemp = np.delete(self.dtemp, idx) self.hdgsel = np.delete(self.hdgsel, idx) self.bank = np.delete(self.bank, idx) # Crossover altitude self.abco = np.delete(self.abco, idx) self.belco = np.delete(self.belco, idx) # Type specific data (temporarily default values) self.avsdef = np.delete(self.avsdef, idx) self.aphi = np.delete(self.aphi, idx) self.ax = np.delete(self.ax, idx) # performance data self.perf.delete(idx) # Traffic autopilot settings: hdg[deg], spd (CAS,m/s), alt[m], vspd[m/s] self.ahdg = np.delete(self.ahdg, idx) self.aspd = np.delete(self.aspd, idx) self.ama = np.delete(self.ama, idx) self.aptas = np.delete(self.aptas, idx) self.aalt = np.delete(self.aalt, idx) self.afll = np.delete(self.afll, idx) self.avs = np.delete(self.avs, idx) # limit settings self.lspd = np.delete(self.lspd, idx) self.lalt = np.delete(self.lalt, idx) self.lvs = np.delete(self.lvs, idx) # Traffic navigation variables del self.dest[idx] del self.orig[idx] self.swlnav = np.delete(self.swlnav, idx) self.swvnav = np.delete(self.swvnav, idx) self.actwplat = np.delete(self.actwplat, idx) self.actwplon = np.delete(self.actwplon, idx) self.actwpalt = np.delete(self.actwpalt, idx) self.actwpspd = np.delete(self.actwpspd, idx) self.actwpturn = np.delete(self.actwpturn, idx) # VNAV cruise level self.crzalt = np.delete(self.crzalt, idx) # Route info del self.route[idx] # ASAS info del self.iconf[idx] self.asasactive = np.delete(self.asasactive, idx) self.asashdg = np.delete(self.asashdg, idx) self.asasspd = np.delete(self.asasspd, idx) self.asasalt = np.delete(self.asasalt, idx) self.asasvsp = np.delete(self.asasvsp, idx) self.desalt = np.delete(self.desalt, idx) self.desvs = np.delete(self.desvs, idx) self.desspd = np.delete(self.desspd, idx) self.deshdg = np.delete(self.deshdg, idx) # Metrics, area del self.inside[idx] # Traffic display data: label del self.label[idx] # Delete bread crumb data self.lastlat = np.delete(self.lastlat, idx) self.lastlon = np.delete(self.lastlon, idx) self.lasttim = np.delete(self.lasttim, idx) del self.trailcol[idx] # Transmitted data to other aircraft due to truncated effect self.adsbtime = np.delete(self.adsbtime, idx) self.adsblat = np.delete(self.adsblat, idx) self.adsblon = np.delete(self.adsblon, idx) self.adsbalt = np.delete(self.adsbalt, idx) self.adsbtrk = np.delete(self.adsbtrk, idx) self.adsbtas = np.delete(self.adsbtas, idx) self.adsbgs = np.delete(self.adsbgs, idx) self.adsbvs = np.delete(self.adsbvs, idx) self.inconflict = np.delete(self.inconflict, idx) # Decrease number fo aircraft self.ntraf = self.ntraf - 1 self.eps = np.delete(self.eps, idx) return True def deleteall(self): """Clear traffic buffer""" ndel = self.ntraf for i in range(ndel): self.delete(self.id[-1]) self.ntraf = 0 self.dbconf.reset() self.perf.reset() return def update(self, simt, simdt): # i = self.id2idx("TP233") # if i>=0: # print "LNAV TP233:",self.swlnav[i] # Update only necessary if there is traffic if self.ntraf == 0: return self.dts.append(simdt) #---------------- Atmosphere ---------------- self.T, self.rho, self.p = vatmos(self.alt) #-------------- Performance limits autopilot settings -------------- # Check difference with AP settings for trafperf and autopilot self.delalt = self.aalt - self.alt # [m] # below crossover altitude: CAS=const, above crossover altitude: MA = const # aptas hast to be calculated before delspd self.aptas = vcas2tas(self.aspd, self.alt) * self.belco + vmach2tas( self.ama, self.alt) * self.abco self.delspd = self.aptas - self.tas ############################################################################### # Debugging: add 10000 random aircraft # if simt>1.0 and self.ntraf<1000: # for i in range(10000): # acid="KL"+str(i) # aclat = random.random()*180.-90. # aclon = random.random()*360.-180. # achdg = random.random()*360. # acalt = (random.random()*18000.+2000.)*0.3048 # self.create(acid,'B747',aclat,aclon,achdg,acalt,350.) # ################################################################################# #-------------------- ADSB update: -------------------- self.adsbtime = self.adsbtime + simdt if self.ADSBtrunc: ADSB_update = np.where(self.adsbtime > self.trunctime) else: ADSB_update = range(self.ntraf) for i in ADSB_update: self.adsbtime[i] = self.adsbtime[i] - self.trunctime self.adsblat[i] = self.lat[i] self.adsblon[i] = self.lon[i] self.adsbalt[i] = self.alt[i] self.adsbtrk[i] = self.trk[i] self.adsbtas[i] = self.tas[i] self.adsbgs[i] = self.gs[i] self.adsbvs[i] = self.vs[i] # New version ADSB Model self.adsb.update() #------------------- ASAS update: --------------------- # Scheduling: when dt has passed or restart: if self.t0asas+self.dtasas<simt or simt<self.t0asas \ and self.dbconf.swasas: self.t0asas = simt # Save old result iconf0 = np.array(self.iconf) # Call with traffic database and sim data self.dbconf.detect() self.dbconf.conflictlist(simt) self.dbconf.APorASAS() self.dbconf.resolve() # Reset label because of colour change chnged = np.where(iconf0 != np.array(self.iconf))[0] for i in chnged: self.label[i] = [" ", " ", "", " "] #----------------- FMS GUIDANCE & NAVIGATION ------------------ # Scheduling: when dt has passed or restart: if self.t0fms + self.dtfms < simt or simt < self.t0fms: self.t0fms = simt # FMS LNAV mode: qdr, dist = qdrdist(self.lat, self.lon, self.actwplat, self.actwplon) #[deg][nm] # Check whether shift based dist [nm] is required, set closer than WP turn distance iwpclose = np.where(self.swlnav * (dist < self.actwpturn))[0] # Shift for aircraft i where necessary for i in iwpclose: # Get next wp (lnavon = False if no more waypoints) lat, lon, alt, spd, xtoalt, toalt, lnavon = \ self.route[i].getnextwp() # note: xtoalt,toalt in [m] # End of route/no more waypoints: switch off LNAV if not lnavon: self.swlnav[i] = False # Drop LNAV at end of route # In case of no LNAV, do not allow VNAV mode on it sown if not self.swlnav[i]: self.swvnav[i] = False self.actwplat[i] = lat self.actwplon[i] = lon # User entered altitude if alt >= 0.: self.actwpalt[i] = alt # VNAV calculated altitude is available and active if toalt >= 0. and self.swvnav[i]: # Descent VNAV mode (T/D logic) if self.alt[ i] > toalt + 10. * ft: # Descent part is in this range of waypoints: # Flat earth distance to next wp dy = (lat - self.lat[i]) dx = (lon - self.lon[i]) * cos(radians(lat)) dist2wp = 60. * nm * sqrt(dx * dx + dy * dy) steepness = 3000. * ft / ( 10. * nm) # 1:3 rule of thumb for now maxaltwp = toalt + xtoalt * steepness # max allowed altitude at next wp self.actwpalt[i] = min( self.alt[i], maxaltwp) #To descend now or descend later? if maxaltwp < self.alt[ i]: # if descent is necessary with maximum steepness self.aalt[i] = self.actwpalt[ i] # dial in altitude of next waypoint as calculated t2go = max(0.1, dist2wp) / max(0.01, self.gs[i]) self.avs[i] = ( self.actwpalt[i] - self.alt[i]) / t2go else: print "else 1" pass # TBD # Climb VNAV mode: climb as soon as possible (T/C logic) elif self.swvnav[i] and self.alt[i] < toalt - 10. * ft: # Flat earth distance to next wp dy = (lat - self.lat[i]) dx = (lon - self.lon[i]) * cos(radians(lat)) dist2wp = 60. * nm * sqrt(dx * dx + dy * dy) self.aalt[i] = self.actwpalt[ i] # dial in altitude of next waypoint as calculated t2go = max(0.1, dist2wp) / max(0.01, self.gs[i]) self.avs[i] = (self.actwpalt[i] - self.alt[i]) / t2go if spd > 0. and lnavon and self.swvnav[i]: if spd < 2.0: self.actwpspd[i] = mach2cas(spd, self.alt[i]) else: self.actwpspd[i] = cas2tas(spd, self.alt[i]) else: self.actwpspd[i] = -999. # Calculate distance before waypoint where to start the turn # Turn radius: R = V2 tan phi / g # Distance to turn: wpturn = R * tan (1/2 delhdg) but max 4 times radius turnrad = self.tas[i] * self.tas[i] / tan( self.bank[i] ) / g0 / nm # [nm] default bank angle per flight phase # print turnrad dy = (self.actwplat[i] - self.lat[i]) dx = (self.actwplon[i] - self.lon[i]) * cos( radians(self.lat[i])) qdr[i] = degrees(atan2(dx, dy)) self.actwpturn[i] = max(3.,abs(turnrad*tan(radians(0.5*degto180(qdr[i]- \ self.route[i].wpdirfrom[self.route[i].iactwp]))))) # [nm] # Set headings based on swlnav self.ahdg = np.where(self.swlnav, qdr, self.ahdg) # NOISE: Turbulence if self.turbulence: timescale = np.sqrt(simdt) trkrad = np.radians(self.trk) #write turbulences in array turb = np.array(self.standardturbulence) turb = np.where(turb > 1e-6, turb, 1e-6) #horizontal flight direction turbhf = np.random.normal(0, turb[0] * timescale, self.ntraf) #[m] #horizontal wing direction turbhw = np.random.normal(0, turb[1] * timescale, self.ntraf) #[m] #vertical direction turbalt = np.random.normal(0, turb[2] * timescale, self.ntraf) #[m] #latitudinal, longitudinal direction turblat = np.cos(trkrad) * turbhf - np.sin(trkrad) * turbhw #[m] turblon = np.sin(trkrad) * turbhf + np.cos(trkrad) * turbhw #[m] else: turbalt = np.zeros(self.ntraf) #[m] turblat = np.zeros(self.ntraf) #[m] turblon = np.zeros(self.ntraf) #[m] # ASAS AP switches #--------- Select Autopilot settings to follow: destination or ASAS ---------- # desired autopilot settings due to ASAS self.deshdg = self.asasactive * self.asashdg + ( 1 - self.asasactive) * self.ahdg self.desspd = self.asasactive * self.asasspd + ( 1 - self.asasactive) * self.aspd self.desalt = self.asasactive * self.asasalt + ( 1 - self.asasactive) * self.aalt self.desvs = self.asasactive * self.asasvsp + ( 1 - self.asasactive) * self.avs # check for the flight envelope self.perf.limits() # update autopilot settings with values within the flight envelope # speed self.aspd = (self.lspd == 0) * self.desspd + (self.lspd != 0) * self.lspd # altitude self.aalt = (self.lalt == 0) * self.desalt + (self.lalt != 0) * self.lalt # hdg self.ahdg = self.deshdg # vs self.avs = (self.lvs == 0) * self.desvs + (self.lvs != 0) * self.lvs # below crossover altitude: CAS=const, above crossover altitude: MA = const #climb/descend above crossover: Ma = const, else CAS = const #ama is fixed when above crossover check = self.abco * (self.ama == 0.) swma = np.where(check == True) self.ama[swma] = cas2mach(self.aspd[swma], self.alt[swma]) # ama is deleted when below crossover check2 = self.belco * (self.ama != 0.) swma2 = np.where(check2 == True) self.ama[swma2] = 0. #---------- Basic Autopilot modes ---------- # SPD HOLD/SEL mode: aspd = autopilot selected speed (first only eas) # for information: self.aptas = (self.actwpspd>0.)*self.actwpspd + \ (self.actwpspd<=0.)*self.aptas self.delspd = self.aptas - self.tas swspdsel = np.abs(self.delspd) > 0.4 # <1 kts = 0.514444 m/s ax = np.minimum(abs(self.delspd / max(1e-8, simdt)), self.ax) self.tas = swspdsel * (self.tas + ax * np.sign(self.delspd) * \ simdt) + (1. - swspdsel) * self.aptas # print "DELSPD", self.delspd/simdt, "AX", self.ax, "SELECTED", ax # without that part: non-accelerating ac would have TAS = 0 # print "1-sw", (1. - swspdsel) * self.aptas # print "NEW TAS", self.tas # Speed conversions self.cas = vtas2cas(self.tas, self.alt) self.gs = self.tas self.M = vtas2mach(self.tas, self.alt) # Update performance every self.perfdt seconds if abs(simt - self.perft0) >= self.perfdt: self.perft0 = simt self.perf.perf() # update altitude self.eps = np.array( self.ntraf * [0.01]) # almost zero for misc purposes swaltsel = np.abs(self.aalt-self.alt) > \ np.maximum(3.,np.abs(2. * simdt * np.abs(self.vs))) # 3.[m] = 10 [ft] eps alt # print swaltsel self.vs = swaltsel*np.sign(self.aalt-self.alt)* \ ( (1-self.swvnav)*np.abs(1500./60.*ft) + \ self.swvnav*np.abs(self.avs) ) self.alt = swaltsel * (self.alt + self.vs * simdt) + \ (1. - swaltsel) * self.aalt + turbalt # HDG HOLD/SEL mode: ahdg = ap selected heading delhdg = (self.ahdg - self.trk + 180.) % 360 - 180. #[deg] # print delhdg # omega = np.degrees(g0 * np.tan(self.aphi) / \ # np.maximum(self.tas, self.eps)) # nominal bank angles per phase from BADA 3.12 omega = np.degrees(g0 * np.tan(self.bank) / \ np.maximum(self.tas, self.eps)) self.hdgsel = np.abs(delhdg) > np.abs(2. * simdt * omega) self.trk = ( self.trk + simdt * omega * self.hdgsel * np.sign(delhdg)) % 360. #--------- Kinematics: update lat,lon,alt ---------- ds = simdt * self.gs self.lat = self.lat + np.degrees(ds * np.cos(np.radians(self.trk)+turblat) \ / Rearth) self.lon = self.lon + np.degrees(ds * np.sin(np.radians(self.trk)+turblon) \ / np.cos(np.radians(self.lat)) / Rearth) # Update trails when switched on if self.swtrails: self.trails.update(simt, self.lat, self.lon, self.lastlat, self.lastlon, self.lasttim, self.id, self.trailcol) else: self.lastlat = self.lat self.lastlon = self.lon self.lattime = simt # ----------------AREA check---------------- # Update area once per areadt seconds: if self.swarea and abs(simt - self.areat0) > self.areadt: # Update loop timer self.areat0 = simt # Check all aircraft i = 0 while (i < self.ntraf): # Current status if self.area == "Square": inside = self.arealat0 <= self.lat[i] <= self.arealat1 and \ self.arealon0 <= self.lon[i] <= self.arealon1 and \ self.alt[i] >= self.areafloor and \ (self.alt[i] >= 1500 or self.swtaxi) elif self.area == "Circle": pass ## Average of lat latavg = (radians(self.lat[i]) + radians( self.fir_circle_point[0])) / 2 cosdlat = (cos(latavg)) # Distance x to centroid dx = ( self.lon[i] - self.fir_circle_point[1]) * cosdlat * 60 dx2 = dx * dx # Distance y to centroid dy = self.lat[i] - self.fir_circle_point[0] dy2 = dy * dy * 3600 # Radius squared r2 = self.fir_circle_radius * self.fir_circle_radius # Inside if smaller inside = (dx2 + dy2) < r2 # Compare with previous: when leaving area: delete command if self.inside[i] and not inside: self.delete(self.id[i]) else: # Update area status self.inside[i] = inside i = i + 1 return def id2idx(self, acid): """Find index of aircraft id""" try: return self.id.index(acid.upper()) except: return -1 def changeTrailColor(self, color, idx): """Change color of aircraft trail""" # print color # print idx # print " " + str(self.trails.colorsOfAC[idx]) self.trailcol[idx] = self.trails.colorList[color] # print " " + str(self.trails.colorsOfAC[idx]) return def setNoise(self, A): """Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect)""" self.noise = A self.trunctime = 1 # seconds self.transerror = [ 1, 100, 100 * ft ] #[degree,m,m] standard bearing, distance, altitude error self.standardturbulence = [0, 0.1, 0.1 ] #m/s standard turbulence (nonnegative) # in (horizontal flight direction, horizontal wing direction, vertical) self.turbulence = self.noise self.ADSBtransnoise = self.noise self.ADSBtrunc = self.noise def engchange(self, acid, engid): """Change of engines""" self.perf.engchange(acid, engid) return def create(self, arglist): # CRE command if len(arglist) < 7: return False acid = arglist[0] if self.id.count(acid.upper()) > 0: return False, acid + " already exists" actype = arglist[1] aclat = arglist[2] aclon = arglist[3] achdg = arglist[4] acalt = arglist[5] # m cmdspd = arglist[6] # Mach/IAS kts (float if 0.1 < cmdspd < 1.0: acspd = mach2tas(cmdspd, acalt) else: acspd = cas2tas(cmdspd * kts, acalt) sw = self.create_ac(acid, actype, aclat, aclon, achdg, acalt, acspd) return sw def selhdg(self, arglist): # HDG command # Select heading command: HDG acid, hdg if len(arglist) < 2: return False #Error/Display helptext print "en voorbij de check" # unwrap arguments idx = arglist[0] # aircraft index hdg = arglist[1] # float # Give autopilot commands self.ahdg[idx] = hdg self.swlnav[idx] = False # Everything went ok! return True
class Traffic(DynamicArrays): """ Traffic class definition : Traffic data Methods: Traffic() : constructor reset() : Reset traffic database w.r.t a/c data create(acid,actype,aclat,aclon,achdg,acalt,acspd) : create aircraft delete(acid) : delete an aircraft from traffic data deletall() : delete all traffic update(sim) : do a numerical integration step id2idx(name) : return index in traffic database of given call sign engchange(i,engtype) : change engine type of an aircraft setNoise(A) : Add turbulence Members: see create Created by : Jacco M. Hoekstra """ def __init__(self, navdb): self.wind = WindSim() # Define the periodic loggers # ToDo: explain what these line sdo in comments (type of logs?) datalog.definePeriodicLogger('SNAPLOG', 'SNAPLOG logfile.', settings.snapdt) datalog.definePeriodicLogger('INSTLOG', 'INSTLOG logfile.', settings.instdt) datalog.definePeriodicLogger('SKYLOG', 'SKYLOG logfile.', settings.skydt) with RegisterElementParameters(self): # Register the following parameters for logging with datalog.registerLogParameters('SNAPLOG', self): # Aircraft Info self.id = [] # identifier (string) self.type = [] # aircaft type (string) # Positions self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.alt = np.array([]) # altitude [m] self.hdg = np.array([]) # traffic heading [deg] self.trk = np.array([]) # track angle [deg] # Velocities self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.gsnorth = np.array([]) # ground speed [m/s] self.gseast = np.array([]) # ground speed [m/s] self.cas = np.array([]) # calibrated airspeed [m/s] self.M = np.array([]) # mach number self.vs = np.array([]) # vertical speed [m/s] # Atmosphere self.p = np.array([]) # air pressure [N/m2] self.rho = np.array([]) # air density [kg/m3] self.Temp = np.array([]) # air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic autopilot settings self.aspd = np.array([]) # selected spd(CAS) [m/s] self.aptas = np.array([]) # just for initializing self.ama = np.array([]) # selected spd above crossover altitude (Mach) [-] self.apalt = np.array([]) # selected alt[m] self.avs = np.array([]) # selected vertical speed [m/s] # Speed offset self.spdoffset = np.array([]) # speed offset [kts] self.spdoffsetdev = np.array([]) # speed offset deviation [kts] self.spd_onoff = np.array([]) # speed offset on/off # Whether to perform LNAV and VNAV self.swlnav = np.array([], dtype=np.bool) self.swvnav = np.array([], dtype=np.bool) # Flight Models self.asas = ASAS(self) self.ap = Autopilot(self) self.pilot = Pilot(self) self.adsb = ADSB(self) self.trails = Trails(self) self.actwp = ActiveWaypoint(self) # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array([]) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.hdgsel = np.array([], dtype=np.bool) # determines whether aircraft is turning # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # limit settings self.limspd = np.array([]) # limit speed self.limspd_flag = np.array([], dtype=np.bool) # flag for limit spd - we have to test for max and min self.limalt = np.array([]) # limit altitude self.limvs = np.array([]) # limit vertical speed due to thrust limitation self.limvs_flag = np.array([]) # Display information on label self.label = [] # Text and bitmap of traffic label # Miscallaneous self.coslat = np.array([]) # Cosine of latitude for computations self.eps = np.array([]) # Small nonzero numbers # Default bank angles per flight phase self.bphase = np.deg2rad(np.array([15, 35, 35, 35, 15, 45])) self.reset(navdb) def reset(self, navdb): # This ensures that the traffic arrays (which size is dynamic) # are all reset as well, so all lat,lon,sdp etc but also objects adsb super(Traffic, self).reset() self.ntraf = 0 # Reset models self.wind.clear() # Build new modules for area and turbulence self.area = Area(self) self.Turbulence = Turbulence(self) # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) # Import navigation data base self.navdb = navdb # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) self.AMAN=AMAN(AllFlights,unique_runways) for rwy in unique_runways: self.AMAN.initial_schedule_popupflightsonly(intarrtime_AMAN_runway,rwy,simulation_start,unique_runways) def mcreate(self, count, actype=None, alt=None, spd=None, dest=None, area=None): """ Create multiple random aircraft in a specified area """ idbase = chr(randint(65, 90)) + chr(randint(65, 90)) if actype is None: actype = 'B744' for i in xrange(count): acid = idbase + '%05d' % i aclat = random() * (area[1] - area[0]) + area[0] aclon = random() * (area[3] - area[2]) + area[2] achdg = float(randint(1, 360)) acalt = (randint(2000, 39000) * ft) if alt is None else alt acspd = (randint(250, 450) * kts) if spd is None else spd self.create(acid, actype, aclat, aclon, achdg, acalt, acspd) def create(self, acid=None, actype="B744", aclat=None, aclon=None, achdg=None, acalt=None, casmach=None): """Create an aircraft""" # Check if not already exist if self.id.count(acid.upper()) > 0: return False, acid + " already exists." # already exists do nothing # Catch missing acid, replace by a default if acid == None or acid =="*": acid = "KL204" flno = 204 while self.id.count(acid)>0: flno = flno+1 acid ="KL"+str(flno) # Check for (other) missing arguments if actype == None or aclat == None or aclon == None or achdg == None \ or acalt == None or casmach == None: return False,"CRE: Missing one or more arguments:"\ "acid,actype,aclat,aclon,achdg,acalt,acspd" super(Traffic, self).create() # Increase number of aircraft self.ntraf = self.ntraf + 1 # Aircraft Info self.id[-1] = acid.upper() self.type[-1] = actype # Positions self.lat[-1] = aclat self.lon[-1] = aclon self.alt[-1] = acalt self.hdg[-1] = achdg self.trk[-1] = achdg # Velocities self.tas[-1], self.cas[-1], self.M[-1] = casormach(casmach, acalt) self.gs[-1] = self.tas[-1] self.gsnorth[-1] = self.tas[-1] * cos(radians(self.hdg[-1])) self.gseast[-1] = self.tas[-1] * sin(radians(self.hdg[-1])) # Speed offset self.spd_onoff[-1] = 0. # Speed offset = 0 (off) on default # Atmosphere self.Temp[-1], self.rho[-1], self.p[-1] = vatmos(acalt) # Wind if self.wind.winddim > 0: vnwnd, vewnd = self.wind.getdata(self.lat[-1], self.lon[-1], self.alt[-1]) self.gsnorth[-1] = self.gsnorth[-1] + vnwnd self.gseast[-1] = self.gseast[-1] + vewnd self.trk[-1] = np.degrees(np.arctan2(self.gseast[-1], self.gsnorth[-1])) self.gs[-1] = np.sqrt(self.gsnorth[-1]**2 + self.gseast[-1]**2) # Traffic performance data #(temporarily default values) self.avsdef[-1] = 1500. * fpm # default vertical speed of autopilot self.aphi[-1] = radians(25.) # bank angle setting of autopilot self.ax[-1] = kts # absolute value of longitudinal accelleration self.bank[-1] = radians(25.) # Crossover altitude self.abco[-1] = 0 # not necessary to overwrite 0 to 0, but leave for clarity self.belco[-1] = 1 # Traffic autopilot settings self.aspd[-1] = self.cas[-1] self.aptas[-1] = self.tas[-1] self.apalt[-1] = self.alt[-1] # Display information on label self.label[-1] = ['', '', '', 0] # Miscallaneous self.coslat[-1] = cos(radians(aclat)) # Cosine of latitude for flat-earth aproximations self.eps[-1] = 0.01 # ----- Submodules of Traffic ----- self.ap.create() self.actwp.create() self.pilot.create() self.adsb.create() self.area.create() self.asas.create() self.perf.create() self.trails.create() return True def delete(self, acid): """Delete an aircraft""" # Look up index of aircraft idx = self.id2idx(acid) # Do nothing if not found if idx < 0: return False # Decrease number of aircraft self.ntraf = self.ntraf - 1 # Delete all aircraft parameters super(Traffic, self).delete(idx) # ----- Submodules of Traffic ----- self.perf.delete(idx) self.area.delete(idx) return True def update(self, simt, simdt): # Update only if there is traffic --------------------- if self.ntraf == 0: return #---------- Atmosphere -------------------------------- self.p, self.rho, self.Temp = vatmos(self.alt) #---------- ADSB Update ------------------------------- self.adsb.update(simt) #---------- Fly the Aircraft -------------------------- self.ap.update(simt) self.asas.update(simt) self.pilot.FMSOrAsas() #---------- Limit Speeds ------------------------------ self.pilot.FlightEnvelope() #---------- Kinematics -------------------------------- self.UpdateAirSpeed(simdt, simt) self.UpdateGroundSpeed(simdt) self.UpdatePosition(simdt) #---------- Performance Update ------------------------ self.perf.perf(simt) #---------- Simulate Turbulence ----------------------- self.Turbulence.Woosh(simdt) #---------- Aftermath --------------------------------- self.trails.update(simt) self.area.check(simt) #---------- AMAN -------------------------------------- i=0 while(i<self.ntraf): temp1, temp2 = qdrdist(self.lat[i], self.lon[i], 52.309, 4.764) # Check distance towards EHAM if temp2<2. and self.alt[i]<1.: # If aircraft within 2 nm from airport and below 1 meter, delete it self.delete(self.id[i]) i=i+1 # Calculate energy cost per flight self.AMAN.calculate_energy_cost(self.id,self.vs,self.tas,CD_0,CD_2,self.rho,WingSurface,self.hdg,self.trk,mass_nominal,simdt) # Increase iteration counter self.AMAN.IterationCounter=self.AMAN.IterationCounter+1 # Update trajectory predictor, scheduler and SARA every five seconds if self.AMAN.IterationCounter%2==0: # Check for speed offset self.AMAN.speed_offset_switch(self.id,AMAN_horizon,self.spd_onoff) # Update Trajectory Predictions self.AMAN.update_TP(self.id,self.lat,self.lon,self.tas/kts,self.actwp.lat,self.actwp.lon,simt) # Update schedule per runway for rwy in unique_runways: if '--node' in sys.argv: if var_TP==str('ASAPBASIC'): self.AMAN.scheduler_ASAP_basic(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway,Freeze_horizon,unique_runways) elif var_TP==str('DYNAMIC'): self.AMAN.scheduler_dynamic(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway) elif var_TP==str('ASAPUPGRADE'): self.AMAN.scheduler_ASAP_upgrade(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway,Freeze_horizon,unique_runways) else: self.AMAN.scheduler_ASAP_basic(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway,Freeze_horizon,unique_runways) # #self.AMAN.scheduler_dynamic(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway) # #self.AMAN.scheduler_ASAP_upgrade(self.id,Take_into_account_schedule_horizon,rwy,intarrtime_AMAN_runway,Freeze_horizon,unique_runways) # Update SARA advisories self.AMAN.update_SARA(self.id,self.alt,self.ap.route,SARA_horizon,simt,approach_margin) # Save variables in logger self.AMAN.AMAN_LOG_arrtimes_and_energycost(self.id,simulation_start) self.AMAN.AMAN_LOG_STAhistory(self.id,simt) self.AMAN.AMAN_LOG_lowleveldelay(self.id,simt) self.AMAN.AMAN_LOG_seqhistory(self.id) self.AMAN.AMAN_LOG_CBAShistory(self.id,simulation_start) #self.AMAN.AMAN_LOG_ETA_CBAShistory(self.id,simt) self.AMAN.AMAN_LOG_traffic_bunches(self.id,approach_margin,simt) return def UpdateAirSpeed(self, simdt, simt): # Acceleration self.delspd = self.pilot.spd - self.tas swspdsel = np.abs(self.delspd) > 0.4 # <1 kts = 0.514444 m/s ax = self.perf.acceleration(simdt) # Update velocities self.tas = self.tas + swspdsel * ax * np.sign(self.delspd) * simdt self.cas = vtas2cas(self.tas, self.alt) self.M = vtas2mach(self.tas, self.alt) # Turning turnrate = np.degrees(g0 * np.tan(self.bank) / np.maximum(self.tas, self.eps)) delhdg = (self.pilot.hdg - self.hdg + 180.) % 360 - 180. # [deg] self.hdgsel = np.abs(delhdg) > np.abs(2. * simdt * turnrate) # Update heading self.hdg = (self.hdg + simdt * turnrate * self.hdgsel * np.sign(delhdg)) % 360. # Update vertical speed delalt = self.pilot.alt - self.alt self.swaltsel = np.abs(delalt) > np.maximum(10 * ft, np.abs(2 * simdt * np.abs(self.vs))) self.vs = self.swaltsel * np.sign(delalt) * self.pilot.vs def UpdateGroundSpeed(self, simdt): # Compute ground speed and track from heading, airspeed and wind spd_random = self.spdoffset * kts + np.random.randn(self.ntraf) * self.spdoffsetdev * kts #self.spd_onoff = array([0 0 0 0 0 0 1 0 0 0 etc.]) # Array whether speed offset + randomness is on/off per aircraft tasx = self.tas + spd_random * self.spd_onoff #print(tasx) #tasx = self.tas + self.spdoffset * kts # np.random.randn(self.ntraf) * self.spdoffsetdev * kts if self.wind.winddim == 0: # no wind self.gsnorth = tasx * np.cos(np.radians(self.hdg)) self.gseast = tasx * np.sin(np.radians(self.hdg)) self.gs = self.tas self.trk = self.hdg else: windnorth, windeast = self.wind.getdata(self.lat, self.lon, self.alt) self.gsnorth = tasx * np.cos(np.radians(self.hdg)) + windnorth self.gseast = tasx * np.sin(np.radians(self.hdg)) + windeast self.gs = np.sqrt(self.gsnorth**2 + self.gseast**2) self.trk = np.degrees(np.arctan2(self.gseast, self.gsnorth)) % 360. def UpdatePosition(self, simdt): # Update position self.alt = np.where(self.swaltsel, self.alt + self.vs * simdt, self.pilot.alt) self.lat = self.lat + np.degrees(simdt * self.gsnorth / Rearth) self.coslat = np.cos(np.deg2rad(self.lat)) self.lon = self.lon + np.degrees(simdt * self.gseast / self.coslat / Rearth) def id2idx(self, acid): """Find index of aircraft id""" try: return self.id.index(acid.upper()) except: return -1 def setNoise(self, noise=None): """Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect)""" if noise is None: return True, "Noise is currently " + ("on" if self.Turbulence.active else "off") self.Turbulence.SetNoise(noise) self.adsb.SetNoise(noise) return True def engchange(self, acid, engid): """Change of engines""" self.perf.engchange(acid, engid) return def move(self, idx, lat, lon, alt=None, hdg=None, casmach=None, vspd=None): self.lat[idx] = lat self.lon[idx] = lon if alt: self.alt[idx] = alt self.apalt[idx] = alt if hdg: self.hdg[idx] = hdg self.ap.trk[idx] = hdg if casmach: self.tas[idx], self.aspd[-1], dummy = casormach(casmach, alt) if vspd: self.vs[idx] = vspd self.swvnav[idx] = False def nom(self, idx): """ Reset acceleration back to nominal (1 kt/s^2): NOM acid """ self.ax[idx] = kts def setdeltaspeed(self, idx, offset=0.): self.spdoffset[idx] = offset def setdeltaspeeddev(self, idx, offset=0.): self.spdoffsetdev[idx] = offset def poscommand(self, scr, idxorwp):# Show info on aircraft(int) or waypoint or airport (str) """POS command: Show info or an aircraft, airport, waypoint or navaid""" # Aircraft index if type(idxorwp)==int and idxorwp >= 0: idx = idxorwp acid = self.id[idx] actype = self.type[idx] lat, lon = self.lat[idx], self.lon[idx] alt, hdg, trk = self.alt[idx] / ft, self.hdg[idx], round(self.trk[idx]) cas = self.cas[idx] / kts tas = self.tas[idx] / kts route = self.ap.route[idx] # Position report lines = "Info on %s %s index = %d\n" % (acid, actype, idx) \ + "Pos = %.2f, %.2f. Spd: %d kts CAS, %d kts TAS\n" % (lat, lon, cas, tas) \ + "Alt = %d ft, Hdg = %d, Trk = %d\n" % (alt, hdg, trk) # FMS AP modes if self.swlnav[idx] and route.nwp > 0 and route.iactwp >= 0: if self.swvnav[idx]: lines = lines + "VNAV, " lines += "LNAV to " + route.wpname[route.iactwp] + "\n" # Flight info: Destination and origin if self.ap.orig[idx] != "" or self.ap.dest[idx] != "": lines = lines + "Flying" if self.ap.orig[idx] != "": lines = lines + " from " + self.ap.orig[idx] if self.ap.dest[idx] != "": lines = lines + " to " + self.ap.dest[idx] # Show a/c info and highlight route of aircraft in radar window # and pan to a/c (to show route) return scr.showacinfo(acid,lines) # Waypoint: airport, navaid or fix else: wp = idxorwp.upper() # Reference position for finding nearest reflat = scr.ctrlat reflon = scr.ctrlon lines = "Info on "+wp+":\n" # First try airports (most used and shorter, hence faster list) iap = self.navdb.getaptidx(wp) if iap>=0: aptypes = ["large","medium","small"] lines = lines + self.navdb.aptname[iap]+"\n" \ + "is a "+ aptypes[max(-1,self.navdb.aptype[iap]-1)] \ +" airport at:\n" \ + latlon2txt(self.navdb.aptlat[iap], \ self.navdb.aptlon[iap]) + "\n" \ + "Elevation: " \ + str(int(round(self.navdb.aptelev[iap]/ft))) \ + " ft \n" # Show country name try: ico = self.navdb.cocode2.index(self.navdb.aptco[iap].upper()) lines = lines + "in "+self.navdb.coname[ico]+" ("+ \ self.navdb.aptco[iap]+")" except: ico = -1 lines = lines + "Country code: "+self.navdb.aptco[iap] try: rwytxt = str(self.navdb.rwythresholds[self.navdb.aptid[iap]].keys()) lines = lines + "\nRunways: " +rwytxt.strip("[]").replace("'","") except: pass # Not found as airport, try waypoints & navaids else: iwps = self.navdb.getwpindices(wp,reflat,reflon) if iwps[0]>=0: typetxt = "" desctxt = "" lastdesc = "XXXXXXXX" for i in iwps: # One line type text if typetxt == "": typetxt = typetxt+self.navdb.wptype[i] else: typetxt = typetxt+" and "+self.navdb.wptype[i] # Description: multi-line samedesc = self.navdb.wpdesc[i]==lastdesc if desctxt == "": desctxt = desctxt +self.navdb.wpdesc[i] lastdesc = self.navdb.wpdesc[i] elif not samedesc: desctxt = desctxt +"\n"+self.navdb.wpdesc[i] lastdesc = self.navdb.wpdesc[i] # Navaid: frequency if self.navdb.wptype[i] in ["VOR","DME","TACAN"] and not samedesc: desctxt = desctxt + " "+ str(self.navdb.wpfreq[i])+" MHz" elif self.navdb.wptype[i]=="NDB" and not samedesc: desctxt = desctxt+ " " + str(self.navdb.wpfreq[i])+" kHz" iwp = iwps[0] # Basic info lines = lines + wp +" is a "+ typetxt \ + " at\n"\ + latlon2txt(self.navdb.wplat[iwp], \ self.navdb.wplon[iwp]) # Navaids have description if len(desctxt)>0: lines = lines+ "\n" + desctxt # VOR give variation if self.navdb.wptype[iwp]=="VOR": lines = lines + "\nVariation: "+ \ str(self.navdb.wpvar[iwp])+" deg" # How many others? nother = self.navdb.wpid.count(wp)-len(iwps) if nother>0: verb = ["is ","are "][min(1,max(0,nother-1))] lines = lines +"\nThere "+verb + str(nother) +\ " other waypoint(s) also named " + wp else: return False,idxorwp+" not found as a/c, airport, navaid or waypoint" # Show what we found on airport and navaid/waypoint scr.echo(lines) return True
def __init__(self, tmx): self.tmx = tmx # tmx object contains sim, scr and other main objects self.dts = [] self.ntraf = 0 # model-specific parameters. # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 # Check for BADA OPF file path = os.path.dirname(__file__) + '/../../data/coefficients/BADA/' files = os.listdir(path) self.bada = False for f in files: if f.upper().find(".OPF")!=-1: self.bada=True break # Initialize correct performance models if self.bada: self.perf = PerfBADA(self) else: self.perf = Perf(self) self.dts = [] self.ntraf = 0 # Create datalog instance self.log = Datalog() # Traffic list & arrays definition # !!!IMPORTANT NOTE!!! # Anny variables added here should also be added in the Traffic # methods self.create() (append) and self.delete() (delete) # which can be found directly below __init__ # Traffic basic flight data # Traffic basic flight data self.id = [] # identifier (string) self.type = [] # aircaft type (string) self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.trk = np.array([]) # track angle [deg] self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.cas = np.array([]) # callibrated airspeed [m/s] self.M = np.array([]) # mach number self.alt = np.array([]) # altitude [m] self.fll = np.array([]) # flight level [ft/100] self.vs = np.array([]) # vertical speed [m/s] self.rho = np.array([]) # atmospheric air density [m/s] self.temp = np.array([]) # atmospheric air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array([]) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.bphase = np.array([]) # standard bank angles per phase self.hdgsel = np.array([]) # determines whether aircraft is turning # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # Traffic autopilot settings self.ahdg = [] # selected heading [deg] self.aspd = [] # selected spd(eas) [m/s] self.aptas = [] # just for initializing self.ama = [] # selected spd above crossover altitude (Mach) [-] self.aalt = [] # selected alt[m] self.afll = [] # selected fl [ft/100] self.avs = [] # selected vertical speed [m/s] # limit settings self.lspd = [] # limit speed self.lalt = [] # limit altitude self.lvs = [] # limit vertical speed due to thrust limitation # Traffic navigation information self.orig = [] # Four letter code of origin airport self.dest = [] # Four letter code of destination airport # LNAV route navigation self.swlnav = np.array([]) # Lateral (HDG) based on nav? self.swvnav = np.array([]) # Vertical/longitudinal (ALT+SPD) based on nav info self.actwplat = np.array([]) # Active WP latitude self.actwplon = np.array([]) # Active WP longitude self.actwpalt = np.array([]) # Active WP altitude to arrive at self.actwpspd = np.array([]) # Active WP speed self.actwpturn = np.array([]) # Distance when to turn to next waypoint # VNAV cruise level self.crzalt = np.array([]) # Cruise altitude[m] # Route info self.route = [] # ASAS info per aircraft: self.iconf = [] # index in 'conflicting' aircraft database self.asasactive = np.array([]) # whether the autopilot follows ASAS or not self.asashdg = np.array([]) # heading provided by the ASAS [deg] self.asasspd = np.array([]) # speed provided by the ASAS (eas) [m/s] self.asasalt = np.array([]) # speed alt by the ASAS [m] self.asasvsp = np.array([]) # speed vspeed by the ASAS [m/s] self.desalt = np.array([]) #desired altitude [m] self.deshdg =np.array([]) #desired heading self.desvs =np.array([]) #desired vertical speed [m/s] self.desspd =np.array([]) #desired speed [m/s] # Display information on label self.label = [] # Text and bitmap of traffic label self.trailcol = [] # Trail color: default 'Blue' # Area self.inside = [] # Transmitted data to other aircraft due to truncated effect self.adsbtime=np.array([]) self.adsblat=np.array([]) self.adsblon=np.array([]) self.adsbalt=np.array([]) self.adsbtrk=np.array([]) self.adsbtas=np.array([]) self.adsbgs=np.array([]) self.adsbvs=np.array([]) #----------------------------------------------------------------------------- # Not per aircraft data # Scheduling of FMS and ASAS self.t0fms = -999. # last time fms was called self.dtfms = 1.01 # interval for fms self.t0asas = -999. # last time ASAS was called self.dtasas = 1.00 # interval for ASAS # Flight performance scheduling self.perfdt = 0.1 # [s] update interval of performance limits self.perft0 = -self.perfdt # [s] last time checked (in terms of sim.t) self.warned2 = False # Flag: Did we warn for default engine parameters yet? # ASAS objects: Conflict Database self.dbconf = Dbconf(self,300., 5.*nm, 1000.*ft) # hard coded values to be replaced # Import navigation data base self.navdb = Navdatabase("global") # Read nav data from global folder # Traffic area: delete traffic when it leaves this area (so not when outside) self.swarea = False self.arealat0 = 0.0 # [deg] lower latitude defining area self.arealat1 = 0.0 # [deg] upper latitude defining area self.arealat0 = 0.0 # [deg] lower longitude defining area self.arealat1 = 0.0 # [deg] upper longitude defining area self.areafloor = -999999.0 # [m] Delete when descending through this h self.areadt = 5.0 # [s] frequency of area check (simtime) self.areat0 = -100. # last time checked # Taxi switch self.swtaxi = False # Default OFF: delete traffic below 1500 ft # Research Area ("Square" for Square, "Circle" for Circle area) self.area = "" # Metrics self.metricSwitch = 0 self.metric = Metric() # Bread crumbs for trails self.lastlat = [] self.lastlon = [] self.lasttim = [] self.trails = Trails() self.swtrails = False # Default switched off # ADS-B Coverage area self.swAdsbCoverage = False # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) self.eps = np.array([]) return
class Traffic(DynamicArrays): """ Traffic class definition : Traffic data Methods: Traffic() : constructor reset() : Reset traffic database w.r.t a/c data create(acid,actype,aclat,aclon,achdg,acalt,acspd) : create aircraft delete(acid) : delete an aircraft from traffic data deletall() : delete all traffic update(sim) : do a numerical integration step id2idx(name) : return index in traffic database of given call sign engchange(i,engtype) : change engine type of an aircraft setNoise(A) : Add turbulence Members: see create Created by : Jacco M. Hoekstra """ def __init__(self, navdb): self.wind = WindSim() # Define the periodic loggers # ToDo: explain what these line sdo in comments (type of logs?) datalog.definePeriodicLogger('SNAPLOG', 'SNAPLOG logfile.', settings.snapdt) datalog.definePeriodicLogger('INSTLOG', 'INSTLOG logfile.', settings.instdt) datalog.definePeriodicLogger('SKYLOG', 'SKYLOG logfile.', settings.skydt) with RegisterElementParameters(self): # Register the following parameters for logging with datalog.registerLogParameters('SNAPLOG', self): # Aircraft Info self.id = [] # identifier (string) self.type = [] # aircaft type (string) # Positions self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.alt = np.array([]) # altitude [m] self.hdg = np.array([]) # traffic heading [deg] self.trk = np.array([]) # track angle [deg] # Velocities self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.gsnorth = np.array([]) # ground speed [m/s] self.gseast = np.array([]) # ground speed [m/s] self.cas = np.array([]) # calibrated airspeed [m/s] self.M = np.array([]) # mach number self.vs = np.array([]) # vertical speed [m/s] # Atmosphere self.p = np.array([]) # air pressure [N/m2] self.rho = np.array([]) # air density [kg/m3] self.Temp = np.array([]) # air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic autopilot settings self.aspd = np.array([]) # selected spd(CAS) [m/s] self.aptas = np.array([]) # just for initializing self.ama = np.array( []) # selected spd above crossover altitude (Mach) [-] self.apalt = np.array([]) # selected alt[m] self.avs = np.array([]) # selected vertical speed [m/s] # Whether to perform LNAV and VNAV self.swlnav = np.array([], dtype=np.bool) self.swvnav = np.array([], dtype=np.bool) # Flight Models self.asas = ASAS(self) self.ap = Autopilot(self) self.pilot = Pilot(self) self.adsb = ADSB(self) self.trails = Trails(self) self.actwp = ActiveWaypoint(self) # Traffic performance data self.avsdef = np.array( []) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array( []) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.hdgsel = np.array( [], dtype=np.bool) # determines whether aircraft is turning # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # limit settings self.limspd = np.array([]) # limit speed self.limspd_flag = np.array( [], dtype=np.bool ) # flag for limit spd - we have to test for max and min self.limalt = np.array([]) # limit altitude self.limvs = np.array( []) # limit vertical speed due to thrust limitation self.limvs_flag = np.array([]) # Display information on label self.label = [] # Text and bitmap of traffic label # Miscallaneous self.coslat = np.array([]) # Cosine of latitude for computations self.eps = np.array([]) # Small nonzero numbers # Default bank angles per flight phase self.bphase = np.deg2rad(np.array([15, 35, 35, 35, 15, 45])) self.reset(navdb) def reset(self, navdb): # This ensures that the traffic arrays (which size is dynamic) # are all reset as well, so all lat,lon,sdp etc but also objects adsb super(Traffic, self).reset() self.ntraf = 0 # Reset models self.wind.clear() # Build new modules for area and turbulence self.area = Area(self) self.Turbulence = Turbulence(self) # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) # Import navigation data base self.navdb = navdb # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf(self) def mcreate(self, count, actype=None, alt=None, spd=None, dest=None, area=None): """ Create multiple random aircraft in a specified area """ idbase = chr(randint(65, 90)) + chr(randint(65, 90)) if actype is None: actype = 'B744' for i in xrange(count): acid = idbase + '%05d' % i aclat = random() * (area[1] - area[0]) + area[0] aclon = random() * (area[3] - area[2]) + area[2] achdg = float(randint(1, 360)) acalt = (randint(2000, 39000) * ft) if alt is None else alt acspd = (randint(250, 450) * kts) if spd is None else spd self.create(acid, actype, aclat, aclon, achdg, acalt, acspd) def create(self, acid=None, actype="B744", aclat=None, aclon=None, achdg=None, acalt=None, casmach=None): """Create an aircraft""" # Check if not already exist if self.id.count(acid.upper()) > 0: return False, acid + " already exists." # already exists do nothing # Catch missing acid, replace by a default if acid == None or acid == "*": acid = "KL204" flno = 204 while self.id.count(acid) > 0: flno = flno + 1 acid = "KL" + str(flno) # Check for (other) missing arguments if actype == None or aclat == None or aclon == None or achdg == None \ or acalt == None or casmach == None: return False,"CRE: Missing one or more arguments:"\ "acid,actype,aclat,aclon,achdg,acalt,acspd" super(Traffic, self).create() # Increase number of aircraft self.ntraf = self.ntraf + 1 # Aircraft Info self.id[-1] = acid.upper() self.type[-1] = actype # Positions self.lat[-1] = aclat self.lon[-1] = aclon self.alt[-1] = acalt self.hdg[-1] = achdg self.trk[-1] = achdg # Velocities self.tas[-1], self.cas[-1], self.M[-1] = casormach(casmach, acalt) self.gs[-1] = self.tas[-1] self.gsnorth[-1] = self.tas[-1] * cos(radians(self.hdg[-1])) self.gseast[-1] = self.tas[-1] * sin(radians(self.hdg[-1])) # Atmosphere self.Temp[-1], self.rho[-1], self.p[-1] = vatmos(acalt) # Wind if self.wind.winddim > 0: vnwnd, vewnd = self.wind.getdata(self.lat[-1], self.lon[-1], self.alt[-1]) self.gsnorth[-1] = self.gsnorth[-1] + vnwnd self.gseast[-1] = self.gseast[-1] + vewnd self.trk[-1] = np.degrees( np.arctan2(self.gseast[-1], self.gsnorth[-1])) self.gs[-1] = np.sqrt(self.gsnorth[-1]**2 + self.gseast[-1]**2) # Traffic performance data #(temporarily default values) self.avsdef[-1] = 1500. * fpm # default vertical speed of autopilot self.aphi[-1] = radians(25.) # bank angle setting of autopilot self.ax[-1] = kts # absolute value of longitudinal accelleration self.bank[-1] = radians(25.) # Crossover altitude self.abco[ -1] = 0 # not necessary to overwrite 0 to 0, but leave for clarity self.belco[-1] = 1 # Traffic autopilot settings self.aspd[-1] = self.cas[-1] self.aptas[-1] = self.tas[-1] self.apalt[-1] = self.alt[-1] # Display information on label self.label[-1] = ['', '', '', 0] # Miscallaneous self.coslat[-1] = cos( radians(aclat)) # Cosine of latitude for flat-earth aproximations self.eps[-1] = 0.01 # ----- Submodules of Traffic ----- self.ap.create() self.actwp.create() self.pilot.create() self.adsb.create() self.area.create() self.asas.create() self.perf.create() self.trails.create() return True def delete(self, acid): """Delete an aircraft""" # Look up index of aircraft idx = self.id2idx(acid) # Do nothing if not found if idx < 0: return False # Decrease number of aircraft self.ntraf = self.ntraf - 1 # Delete all aircraft parameters super(Traffic, self).delete(idx) # ----- Submodules of Traffic ----- self.perf.delete(idx) self.area.delete(idx) return True def update(self, simt, simdt): # Update only if there is traffic --------------------- if self.ntraf == 0: return #---------- Atmosphere -------------------------------- self.p, self.rho, self.Temp = vatmos(self.alt) #---------- ADSB Update ------------------------------- self.adsb.update(simt) #---------- Fly the Aircraft -------------------------- self.ap.update(simt) self.asas.update(simt) self.pilot.FMSOrAsas() #---------- Limit Speeds ------------------------------ self.pilot.FlightEnvelope() #---------- Kinematics -------------------------------- self.UpdateAirSpeed(simdt, simt) self.UpdateGroundSpeed(simdt) self.UpdatePosition(simdt) #---------- Performance Update ------------------------ self.perf.perf(simt) #---------- Simulate Turbulence ----------------------- self.Turbulence.Woosh(simdt) #---------- Aftermath --------------------------------- self.trails.update(simt) self.area.check(simt) return def UpdateAirSpeed(self, simdt, simt): # Acceleration self.delspd = self.pilot.spd - self.tas swspdsel = np.abs(self.delspd) > 0.4 # <1 kts = 0.514444 m/s ax = self.perf.acceleration(simdt) # Update velocities self.tas = self.tas + swspdsel * ax * np.sign(self.delspd) * simdt self.cas = vtas2cas(self.tas, self.alt) self.M = vtas2mach(self.tas, self.alt) # Turning turnrate = np.degrees(g0 * np.tan(self.bank) / np.maximum(self.tas, self.eps)) delhdg = (self.pilot.hdg - self.hdg + 180.) % 360 - 180. # [deg] self.hdgsel = np.abs(delhdg) > np.abs(2. * simdt * turnrate) # Update heading self.hdg = (self.hdg + simdt * turnrate * self.hdgsel * np.sign(delhdg)) % 360. # Update vertical speed delalt = self.pilot.alt - self.alt self.swaltsel = np.abs(delalt) > np.maximum( 10 * ft, np.abs(2 * simdt * np.abs(self.vs))) self.vs = self.swaltsel * np.sign(delalt) * self.pilot.vs def UpdateGroundSpeed(self, simdt): # Compute ground speed and track from heading, airspeed and wind if self.wind.winddim == 0: # no wind self.gsnorth = self.tas * np.cos(np.radians(self.hdg)) self.gseast = self.tas * np.sin(np.radians(self.hdg)) self.gs = self.tas self.trk = self.hdg else: windnorth, windeast = self.wind.getdata(self.lat, self.lon, self.alt) self.gsnorth = self.tas * np.cos(np.radians(self.hdg)) + windnorth self.gseast = self.tas * np.sin(np.radians(self.hdg)) + windeast self.gs = np.sqrt(self.gsnorth**2 + self.gseast**2) self.trk = np.degrees(np.arctan2(self.gseast, self.gsnorth)) % 360. def UpdatePosition(self, simdt): # Update position self.alt = np.where(self.swaltsel, self.alt + self.vs * simdt, self.pilot.alt) self.lat = self.lat + np.degrees(simdt * self.gsnorth / Rearth) self.coslat = np.cos(np.deg2rad(self.lat)) self.lon = self.lon + np.degrees( simdt * self.gseast / self.coslat / Rearth) def id2idx(self, acid): """Find index of aircraft id""" try: return self.id.index(acid.upper()) except: return -1 def setNoise(self, noise=None): """Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect)""" if noise is None: return True, "Noise is currently " + ( "on" if self.Turbulence.active else "off") self.Turbulence.SetNoise(noise) self.adsb.SetNoise(noise) return True def engchange(self, acid, engid): """Change of engines""" self.perf.engchange(acid, engid) return def move(self, idx, lat, lon, alt=None, hdg=None, casmach=None, vspd=None): self.lat[idx] = lat self.lon[idx] = lon if alt: self.alt[idx] = alt self.apalt[idx] = alt if hdg: self.hdg[idx] = hdg self.ap.trk[idx] = hdg if casmach: self.tas[idx], self.aspd[-1], dummy = casormach(casmach, alt) if vspd: self.vs[idx] = vspd self.swvnav[idx] = False def nom(self, idx): """ Reset acceleration back to nominal (1 kt/s^2): NOM acid """ self.ax[idx] = kts def acinfo(self, idx): acid = self.id[idx] actype = self.type[idx] lat, lon = self.lat[idx], self.lon[idx] alt, hdg, trk = self.alt[idx] / ft, self.hdg[idx], round(self.trk[idx]) cas = self.cas[idx] / kts tas = self.tas[idx] / kts route = self.ap.route[idx] line = "Info on %s %s index = %d\n" % (acid, actype, idx) \ + "Pos = %.2f, %.2f. Spd: %d kts CAS, %d kts TAS\n" % (lat, lon, cas, tas) \ + "Alt = %d ft, Hdg = %d, Trk = %d\n" % (alt, hdg, trk) if self.swlnav[idx] and route.nwp > 0 and route.iactwp >= 0: if self.swvnav[idx]: line += "VNAV, " line += "LNAV to " + route.wpname[route.iactwp] + "\n" if self.ap.orig[idx] != "" or self.ap.dest[idx] != "": line += "Flying" if self.ap.orig[idx] != "": line += " from " + self.ap.orig[idx] if self.ap.dest[idx] != "": line += " to " + self.ap.dest[idx] return acid, line
class MatchTable(object): """ """ def __init__(self, cols): self._rows = [] self.logger = logging.Logger.manager.getLogger(self.__class__.__name__) #self.prio_rows = {} self.cols = cols self._passes = 0 # perf counter to see how many tests we do on a given table self.perf = Perf(self.logger) def passes(self): return self._passes() def len(self): return len(self._rows) def add_row(self, row): self._add_match_row( MatchRow(row, cols=self.cols, ordinal=len(self._rows))) def _add_match_row(self, match_row, prio=0, colname=None): # storig these as tuples, in the initial load they are 0 because we don't ko wthe self._rows.append(match_row) #, prio, colname)) # gets a dict of key/value pairs for this row from the lookup def get_row(self, pos): return self._rows[pos].get_values() def match_table(self, record): """ search for all items im cols find the matching rows from dict params: cols: list of column names record: a splunk event to match to the table returns a single dict that was the best match for the input passed if nothing matches we return None """ # find the matching rows if self.logger.level == logging.DEBUG: self.logger.debug("match table {}".format(self.cols)) self.logger.debug("match table cols:{} record:{}".format( self.cols, record)) tbl = self try: for col in self.cols: tbl = tbl._match(col, record[col]) if tbl.len() == 0: # nothing left to do ... we didn't match self.logger.info("match table has no rows to return") return None except KeyError: # key doesn't exist in message is a failed match self.logger.warn( "Key(s) '{}' doesn't exist in input message {}".format( str(self.cols), record)) return None tbl.drop_low_prio_rows() self.logger.info("match_table Passes: {}".format(tbl._passes)) return tbl.get_first_row().get_values() def match_table_optimised(self, record): """ search for all items im cols find the matching rows from dict params: cols: list of column names record: a splunk event to match to the table returns a single dict that was the best match for the input passed if nothing matches we return None """ # find the matching rows info = self.logger.info self.logger.debug("match table {}".format(self.cols)) info("match table cols:{} record:{}".format(self.cols, record)) tbl = self try: for col in self.cols: tbl = tbl._match(col, record[col]) if tbl.len() == 0: # nothing left to do ... we didn't match info("match table has no rows to return") return None tbl.drop_low_prio_rows() if tbl.len() == 1: # nothing left to do ... we didn't match info("match table match 1 row found") break except KeyError: # key doesn't exist in message is a failed match self.logger.warn( "Key(s) '{}' doesn't exist in input message {}".format( str(self.cols), record)) return None #tbl.drop_low_prio_rows() self.logger.info("match_table_optimised Passes: {}".format( tbl._passes)) return tbl.get_first_row().get_values() def get_first_row(self): # if more than 1 remain take the one that was inserted first if self.len() > 1: self._rows.sort(key=lambda t: t.idx) elif self.len() == 0: self.logger.warn("match table is empty return empty dictionary") return {} return self._rows[0] def drop_low_prio_rows(self): # prune the rows down based on prioirty rules # for each column, in order, drop any rows that are not equal to the highest priority self.perf.start("drop_low_prio_rows") before = self.len() for col in self.cols: if self.len() == 1: # we are done when there is just 1 left self.logger.info("matched table 1 row remains") self.perf.end("drop_low_prio_rows", "before {}/ after 1".format(before)) return self.prune_rows(col) self.logger.info("before/after dropping low prio rows {}/{}".format( before, self.len())) self.perf.end("drop_low_prio_rows", "before: {}/ after: {}".format(before, self.len())) def prune_rows(self, colname): """ By this stage the table should contain just the rows that matched the input data Go through and discard and rows that have low match priority we do this by scoring rows using this - 10^(priority^2) * (length-1) * is always 1 """ rows = [] for row in self._rows: cell = row.get_value(colname) rows.append((row, pow(10, pow(cell.prio, 2)) * (cell.length - 1))) self.logger.info("prune rows, colname={}, row_count={}".format( colname, len(rows))) rows.sort(key=lambda t: t[1], reverse=True) # now max prio row is at the head of this list max = rows[0][1] self._rows = [] while len(rows) > 0 and rows[0][1] == max: row = rows.pop(0)[0] self.logger.info("prune is adding row {}".format(row.get_values())) self._add_match_row(row) def _match(self, colname, value): if 1 == 2: return self._match_fast(colname, value) else: return self._match_slow(colname, value) def _match_fast(self, colname, value): """ find all rows where the column matches and return a new table """ new_table = MatchTable(self.cols) self.logger.debug("Matching {} to {}".format(colname, value)) # ll stores matched rows based on priority (0 .. 3) and only takes the list with the highest priority # should help to reduce the number of iterations as wildcard matches are dropped earlier # I want to learn lists in python n0w ... ll = [[], [], [], []] for row in self._rows: matched = row.match_row(colname, value) if matched[0]: ll[matched[1]].append(row) #new_table._add_match_row(row) for p in reversed(ll): if len(p) > 0: new_table._rows = p break new_table._passes = self._passes + len(self._rows) return new_table def _match_slow(self, colname, value): """ find all rows where the column matches and return a new table """ new_table = MatchTable(self.cols) self.logger.debug("Matching {} to {}".format(colname, value)) for row in self._rows: matched = row.match_row(colname, value) if matched[0]: new_table._add_match_row(row) new_table._passes = self._passes + len(self._rows) return new_table
def optimize(self, nIter): if self._t is None: self._t0 = time.time() self._t = self._t0 pAsk = Perf() pTell = Perf() pPhi = MultiPerf() for _ in range(nIter): pAsk.start() ws = np.array(self._es.ask()) pAsk.stop() phis = self._phi(pPhi, ws) pTell.start() self._es.tell(phis) pTell.stop() self._iReport += 1 if self._iReport == self._nReport: t = time.time() print( "EVAL: iter = %d t = %.2f dt = %.4f phi = %.4e wmn = %.4f wmx = %.4f sigma = %.4e nEvalsPerW = %d" % (self._nIter, t - self._t0, t - self._t, phis.mean(), ws.mean(), np.abs(ws).max(), self._es.getSigma(), self._nEvalsThisTime)) self._phiLatest = phis.mean() perf = self._collectPerf() print("PERF: pA = %.3f pT = %.3f pP = %s %s" % (1000 * pAsk.mean(), 1000 * pTell.mean(), ' '.join( ["%.3f" % (1000 * p) for p in pPhi.means()]), perf)) self._t = t self._nIter += 1 self._trace.append(phis.mean()) self._iReport = 0 self._wfav = np.array(self._es.getXFavorite()) self._bbo.setParams(self._wfav)
class Traffic(DynamicArrays): """ Traffic class definition : Traffic data Methods: Traffic() : constructor reset() : Reset traffic database w.r.t a/c data create(acid,actype,aclat,aclon,achdg,acalt,acspd) : create aircraft delete(acid) : delete an aircraft from traffic data deletall() : delete all traffic update(sim) : do a numerical integration step id2idx(name) : return index in traffic database of given call sign engchange(i,engtype) : change engine type of an aircraft setNoise(A) : Add turbulence Members: see create Created by : Jacco M. Hoekstra """ def __init__(self): self.wind = WindSim() # Define the periodic loggers # ToDo: explain what these line sdo in comments (type of logs?) datalog.definePeriodicLogger('SNAPLOG', 'SNAPLOG logfile.', settings.snapdt) datalog.definePeriodicLogger('INSTLOG', 'INSTLOG logfile.', settings.instdt) datalog.definePeriodicLogger('SKYLOG', 'SKYLOG logfile.', settings.skydt) with RegisterElementParameters(self): # Register the following parameters for logging with datalog.registerLogParameters('SNAPLOG', self): # Aircraft Info self.id = [] # identifier (string) self.type = [] # aircaft type (string) # Positions self.lat = np.array([]) # latitude [deg] self.lon = np.array([]) # longitude [deg] self.alt = np.array([]) # altitude [m] self.hdg = np.array([]) # traffic heading [deg] self.trk = np.array([]) # track angle [deg] # Velocities self.tas = np.array([]) # true airspeed [m/s] self.gs = np.array([]) # ground speed [m/s] self.gsnorth = np.array([]) # ground speed [m/s] self.gseast = np.array([]) # ground speed [m/s] self.cas = np.array([]) # calibrated airspeed [m/s] self.M = np.array([]) # mach number self.vs = np.array([]) # vertical speed [m/s] # Atmosphere self.p = np.array([]) # air pressure [N/m2] self.rho = np.array([]) # air density [kg/m3] self.Temp = np.array([]) # air temperature [K] self.dtemp = np.array([]) # delta t for non-ISA conditions # Traffic autopilot settings self.aspd = np.array([]) # selected spd(CAS) [m/s] self.aptas = np.array([]) # just for initializing self.ama = np.array([]) # selected spd above crossover altitude (Mach) [-] self.apalt = np.array([]) # selected alt[m] self.avs = np.array([]) # selected vertical speed [m/s] # Whether to perform LNAV and VNAV self.swlnav = np.array([], dtype=np.bool) self.swvnav = np.array([], dtype=np.bool) # Flight Models self.asas = ASAS() self.ap = Autopilot() self.pilot = Pilot() self.adsb = ADSB() self.trails = Trails() self.actwp = ActiveWaypoint() # Traffic performance data self.avsdef = np.array([]) # [m/s]default vertical speed of autopilot self.aphi = np.array([]) # [rad] bank angle setting of autopilot self.ax = np.array([]) # [m/s2] absolute value of longitudinal accelleration self.bank = np.array([]) # nominal bank angle, [radian] self.hdgsel = np.array([], dtype=np.bool) # determines whether aircraft is turning # Crossover altitude self.abco = np.array([]) self.belco = np.array([]) # limit settings self.limspd = np.array([]) # limit speed self.limspd_flag = np.array([], dtype=np.bool) # flag for limit spd - we have to test for max and min self.limalt = np.array([]) # limit altitude self.limvs = np.array([]) # limit vertical speed due to thrust limitation self.limvs_flag = np.array([]) # Display information on label self.label = [] # Text and bitmap of traffic label # Miscallaneous self.coslat = np.array([]) # Cosine of latitude for computations self.eps = np.array([]) # Small nonzero numbers # Default bank angles per flight phase self.bphase = np.deg2rad(np.array([15, 35, 35, 35, 15, 45])) self.reset() def reset(self): # This ensures that the traffic arrays (which size is dynamic) # are all reset as well, so all lat,lon,sdp etc but also objects adsb super(Traffic, self).reset() self.ntraf = 0 # Reset models self.wind.clear() # Build new modules for area and turbulence self.area = Area() self.Turbulence = Turbulence() # Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect) self.setNoise(False) # Default: BlueSky internal performance model. # Insert your BADA files to the folder "BlueSky/data/coefficients/BADA" # for working with EUROCONTROL`s Base of Aircraft Data revision 3.12 self.perf = Perf() self.trails.reset() def mcreate(self, count, actype=None, alt=None, spd=None, dest=None): """ Create multiple random aircraft in a specified area """ area = bs.scr.getviewlatlon() idbase = chr(randint(65, 90)) + chr(randint(65, 90)) if actype is None: actype = 'B744' n = count super(Traffic, self).create(n) # Increase number of aircraft self.ntraf = self.ntraf + count acids = [] aclats = [] aclons = [] achdgs = [] acalts = [] acspds = [] for i in xrange(count): acids.append((idbase + '%05d' % i).upper()) aclats.append(random() * (area[1] - area[0]) + area[0]) aclons.append(random() * (area[3] - area[2]) + area[2]) achdgs.append(float(randint(1, 360))) acalts.append((randint(2000, 39000) * ft) if alt is None else alt) acspds.append((randint(250, 450) * kts) if spd is None else spd) # Aircraft Info self.id[-n:] = acids self.type[-n:] = [actype] * n # Positions self.lat[-n:] = aclats self.lon[-n:] = aclons self.alt[-n:] = acalts self.hdg[-n:] = achdgs self.trk[-n:] = achdgs # Velocities self.tas[-n:], self.cas[-n:], self.M[-n:] = vcasormach(acspds, acalts) self.gs[-n:] = self.tas[-n:] self.gsnorth[-n:] = self.tas[-n:] * np.cos(np.radians(self.hdg[-n:])) self.gseast[-n:] = self.tas[-n:] * np.sin(np.radians(self.hdg[-n:])) # Atmosphere self.p[-n:], self.rho[-n:], self.Temp[-n:] = vatmos(acalts) # Wind if self.wind.winddim > 0: vnwnd, vewnd = self.wind.getdata(self.lat[-n:], self.lon[-n:], self.alt[-n:]) self.gsnorth[-n:] = self.gsnorth[-n:] + vnwnd self.gseast[-n:] = self.gseast[-n:] + vewnd self.trk[-n:] = np.degrees(np.arctan2(self.gseast[-n:], self.gsnorth[-n:])) self.gs[-n:] = np.sqrt(self.gsnorth[-n:]**2 + self.gseast[-n:]**2) # Traffic performance data #(temporarily default values) self.avsdef[-n:] = 1500. * fpm # default vertical speed of autopilot self.aphi[-n:] = np.radians(25.) # bank angle setting of autopilot self.ax[-n:] = kts # absolute value of longitudinal accelleration self.bank[-n:] = np.radians(25.) # Crossover altitude self.abco[-n:] = 0 # not necessary to overwrite 0 to 0, but leave for clarity self.belco[-n:] = 1 # Traffic autopilot settings self.aspd[-n:] = self.cas[-n:] self.aptas[-n:] = self.tas[-n:] self.apalt[-n:] = self.alt[-n:] # Display information on label self.label[-n:] = ['', '', '', 0] # Miscallaneous self.coslat[-n:] = np.cos(np.radians(aclats)) # Cosine of latitude for flat-earth aproximations self.eps[-n:] = 0.01 # ----- Submodules of Traffic ----- self.ap.create(n) self.actwp.create(n) self.pilot.create(n) self.adsb.create(n) self.area.create(n) self.asas.create(n) self.perf.create(n) self.trails.create(n) def create(self, acid=None, actype="B744", aclat=None, aclon=None, achdg=None, acalt=None, casmach=None): """Create an aircraft""" # Check if not already exist if self.id.count(acid.upper()) > 0: return False, acid + " already exists." # already exists do nothing # Catch missing acid, replace by a default if acid is None or acid == "*": acid = "KL204" flno = 204 while self.id.count(acid) > 0: flno = flno + 1 acid = "KL" + str(flno) # Check for (other) missing arguments if actype is None or aclat is None or aclon is None or achdg is None \ or acalt is None or casmach is None: return False, "CRE: Missing one or more arguments:"\ "acid,actype,aclat,aclon,achdg,acalt,acspd" super(Traffic, self).create() # Increase number of aircraft self.ntraf = self.ntraf + 1 # Aircraft Info self.id[-1] = acid.upper() self.type[-1] = actype # Positions self.lat[-1] = aclat self.lon[-1] = aclon self.alt[-1] = acalt self.hdg[-1] = achdg self.trk[-1] = achdg # Velocities self.tas[-1], self.cas[-1], self.M[-1] = casormach(casmach, acalt) self.gs[-1] = self.tas[-1] self.gsnorth[-1] = self.tas[-1] * cos(radians(self.hdg[-1])) self.gseast[-1] = self.tas[-1] * sin(radians(self.hdg[-1])) # Atmosphere self.p[-1], self.rho[-1], self.Temp[-1] = vatmos(acalt) # Wind if self.wind.winddim > 0: vnwnd, vewnd = self.wind.getdata(self.lat[-1], self.lon[-1], self.alt[-1]) self.gsnorth[-1] = self.gsnorth[-1] + vnwnd self.gseast[-1] = self.gseast[-1] + vewnd self.trk[-1] = np.degrees(np.arctan2(self.gseast[-1], self.gsnorth[-1])) self.gs[-1] = np.sqrt(self.gsnorth[-1]**2 + self.gseast[-1]**2) # Traffic performance data #(temporarily default values) self.avsdef[-1] = 1500. * fpm # default vertical speed of autopilot self.aphi[-1] = radians(25.) # bank angle setting of autopilot self.ax[-1] = kts # absolute value of longitudinal accelleration self.bank[-1] = radians(25.) # Crossover altitude self.abco[-1] = 0 # not necessary to overwrite 0 to 0, but leave for clarity self.belco[-1] = 1 # Traffic autopilot settings self.aspd[-1] = self.cas[-1] self.aptas[-1] = self.tas[-1] self.apalt[-1] = self.alt[-1] # Display information on label self.label[-1] = ['', '', '', 0] # Miscallaneous self.coslat[-1] = cos(radians(aclat)) # Cosine of latitude for flat-earth aproximations self.eps[-1] = 0.01 # ----- Submodules of Traffic ----- self.ap.create() self.actwp.create() self.pilot.create() self.adsb.create() self.area.create() self.asas.create() self.perf.create() self.trails.create() return True def creconfs(self, acid, actype, targetidx, dpsi, cpa, tlosh, dH=None, tlosv=None, spd=None): latref = self.lat[targetidx] # deg lonref = self.lon[targetidx] # deg altref = self.alt[targetidx] # m trkref = radians(self.trk[targetidx]) gsref = self.gs[targetidx] # m/s vsref = self.vs[targetidx] # m/s cpa = cpa * nm pzr = settings.asas_pzr * nm pzh = settings.asas_pzh * ft trk = trkref + radians(dpsi) gs = gsref if spd is None else spd if dH is None: acalt = altref acvs = 0.0 else: acalt = altref + dH tlosv = tlosh if tlosv is None else tlosv acvs = vsref - np.sign(dH) * (abs(dH) - pzh) / tlosv # Horizontal relative velocity vector gsn, gse = gs * cos(trk), gs * sin(trk) vreln, vrele = gsref * cos(trkref) - gsn, gsref * sin(trkref) - gse # Relative velocity magnitude vrel = sqrt(vreln * vreln + vrele * vrele) # Relative travel distance to closest point of approach drelcpa = tlosh * vrel + (0 if cpa > pzr else sqrt(pzr * pzr - cpa * cpa)) # Initial intruder distance dist = sqrt(drelcpa * drelcpa + cpa * cpa) # Rotation matrix diagonal and cross elements for distance vector rd = drelcpa / dist rx = cpa / dist # Rotate relative velocity vector to obtain intruder bearing brn = degrees(atan2(-rx * vreln + rd * vrele, rd * vreln + rx * vrele)) # Calculate intruder lat/lon aclat, aclon = geo.qdrpos(latref, lonref, brn, dist / nm) # convert groundspeed to CAS, and track to heading wn, we = self.wind.getdata(aclat, aclon, acalt) tasn, tase = gsn - wn, gse - we acspd = vtas2cas(sqrt(tasn * tasn + tase * tase), acalt) achdg = degrees(atan2(tase, tasn)) # Create and, when necessary, set vertical speed self.create(acid, actype, aclat, aclon, achdg, acalt, acspd) self.ap.selalt(len(self.lat) - 1, altref, acvs) self.vs[-1] = acvs def delete(self, acid): """Delete an aircraft""" # Look up index of aircraft idx = self.id2idx(acid) # Do nothing if not found if idx < 0: return False # Decrease number of aircraft self.ntraf = self.ntraf - 1 # Delete all aircraft parameters super(Traffic, self).delete(idx) # ----- Submodules of Traffic ----- self.perf.delete(idx) self.area.delete(idx) return True def update(self, simt, simdt): # Update only if there is traffic --------------------- if self.ntraf == 0: return #---------- Atmosphere -------------------------------- self.p, self.rho, self.Temp = vatmos(self.alt) #---------- ADSB Update ------------------------------- self.adsb.update(simt) #---------- Fly the Aircraft -------------------------- self.ap.update(simt) self.asas.update(simt) self.pilot.FMSOrAsas() #---------- Limit Speeds ------------------------------ self.pilot.FlightEnvelope() #---------- Kinematics -------------------------------- self.UpdateAirSpeed(simdt, simt) self.UpdateGroundSpeed(simdt) self.UpdatePosition(simdt) #---------- Performance Update ------------------------ self.perf.perf(simt) #---------- Simulate Turbulence ----------------------- self.Turbulence.Woosh(simdt) #---------- Aftermath --------------------------------- self.trails.update(simt) self.area.check(simt) return def UpdateAirSpeed(self, simdt, simt): # Acceleration self.delspd = self.pilot.spd - self.tas swspdsel = np.abs(self.delspd) > 0.4 # <1 kts = 0.514444 m/s ax = self.perf.acceleration(simdt) # Update velocities self.tas = self.tas + swspdsel * ax * np.sign(self.delspd) * simdt self.cas = vtas2cas(self.tas, self.alt) self.M = vtas2mach(self.tas, self.alt) # Turning turnrate = np.degrees(g0 * np.tan(self.bank) / np.maximum(self.tas, self.eps)) delhdg = (self.pilot.hdg - self.hdg + 180.) % 360 - 180. # [deg] self.hdgsel = np.abs(delhdg) > np.abs(2. * simdt * turnrate) # Update heading self.hdg = (self.hdg + simdt * turnrate * self.hdgsel * np.sign(delhdg)) % 360. # Update vertical speed delalt = self.pilot.alt - self.alt self.swaltsel = np.abs(delalt) > np.maximum(10 * ft, np.abs(2. * simdt * np.abs(self.vs))) self.vs = self.swaltsel * np.sign(delalt) * np.abs(self.pilot.vs) def UpdateGroundSpeed(self, simdt): # Compute ground speed and track from heading, airspeed and wind if self.wind.winddim == 0: # no wind self.gsnorth = self.tas * np.cos(np.radians(self.hdg)) self.gseast = self.tas * np.sin(np.radians(self.hdg)) self.gs = self.tas self.trk = self.hdg else: windnorth, windeast = self.wind.getdata(self.lat, self.lon, self.alt) self.gsnorth = self.tas * np.cos(np.radians(self.hdg)) + windnorth self.gseast = self.tas * np.sin(np.radians(self.hdg)) + windeast self.gs = np.sqrt(self.gsnorth**2 + self.gseast**2) self.trk = np.degrees(np.arctan2(self.gseast, self.gsnorth)) % 360. def UpdatePosition(self, simdt): # Update position self.alt = np.where(self.swaltsel, self.alt + self.vs * simdt, self.pilot.alt) self.lat = self.lat + np.degrees(simdt * self.gsnorth / Rearth) self.coslat = np.cos(np.deg2rad(self.lat)) self.lon = self.lon + np.degrees(simdt * self.gseast / self.coslat / Rearth) def id2idx(self, acid): """Find index of aircraft id""" try: return self.id.index(acid.upper()) except: return -1 def setNoise(self, noise=None): """Noise (turbulence, ADBS-transmission noise, ADSB-truncated effect)""" if noise is None: return True, "Noise is currently " + ("on" if self.Turbulence.active else "off") self.Turbulence.SetNoise(noise) self.adsb.SetNoise(noise) return True def engchange(self, acid, engid): """Change of engines""" self.perf.engchange(acid, engid) return def move(self, idx, lat, lon, alt=None, hdg=None, casmach=None, vspd=None): self.lat[idx] = lat self.lon[idx] = lon if alt: self.alt[idx] = alt self.apalt[idx] = alt if hdg: self.hdg[idx] = hdg self.ap.trk[idx] = hdg if casmach: self.tas[idx], self.aspd[-1], dummy = casormach(casmach, alt) if vspd: self.vs[idx] = vspd self.swvnav[idx] = False def nom(self, idx): """ Reset acceleration back to nominal (1 kt/s^2): NOM acid """ self.ax[idx] = kts def poscommand(self, idxorwp):# Show info on aircraft(int) or waypoint or airport (str) """POS command: Show info or an aircraft, airport, waypoint or navaid""" # Aircraft index if type(idxorwp)==int and idxorwp >= 0: idx = idxorwp acid = self.id[idx] actype = self.type[idx] latlon = latlon2txt(self.lat[idx], self.lon[idx]) alt = round(self.alt[idx] / ft) hdg = round(self.hdg[idx]) trk = round(self.trk[idx]) cas = round(self.cas[idx] / kts) tas = round(self.tas[idx] / kts) gs = round(self.gs[idx]/kts) M = self.M[idx] VS = round(self.vs[idx]/ft*60.) route = self.ap.route[idx] # Position report lines = "Info on %s %s index = %d\n" %(acid, actype, idx) \ + "Pos: "+latlon+ "\n" \ + "Hdg: %03d Trk: %03d\n" %(hdg, trk) \ + "Alt: %d ft V/S: %d fpm\n" %(alt,VS) \ + "CAS/TAS/GS: %d/%d/%d kts M: %.3f\n"%(cas,tas,gs,M) # FMS AP modes if self.swlnav[idx] and route.nwp > 0 and route.iactwp >= 0: if self.swvnav[idx]: lines = lines + "VNAV, " lines += "LNAV to " + route.wpname[route.iactwp] + "\n" # Flight info: Destination and origin if self.ap.orig[idx] != "" or self.ap.dest[idx] != "": lines = lines + "Flying" if self.ap.orig[idx] != "": lines = lines + " from " + self.ap.orig[idx] if self.ap.dest[idx] != "": lines = lines + " to " + self.ap.dest[idx] # Show a/c info and highlight route of aircraft in radar window # and pan to a/c (to show route) return bs.scr.showacinfo(acid,lines) # Waypoint: airport, navaid or fix else: wp = idxorwp.upper() # Reference position for finding nearest reflat = bs.scr.ctrlat reflon = bs.scr.ctrlon lines = "Info on "+wp+":\n" # First try airports (most used and shorter, hence faster list) iap = bs.navdb.getaptidx(wp) if iap>=0: aptypes = ["large","medium","small"] lines = lines + bs.navdb.aptname[iap]+"\n" \ + "is a "+ aptypes[max(-1,bs.navdb.aptype[iap]-1)] \ +" airport at:\n" \ + latlon2txt(bs.navdb.aptlat[iap], \ bs.navdb.aptlon[iap]) + "\n" \ + "Elevation: " \ + str(int(round(bs.navdb.aptelev[iap]/ft))) \ + " ft \n" # Show country name try: ico = bs.navdb.cocode2.index(bs.navdb.aptco[iap].upper()) lines = lines + "in "+bs.navdb.coname[ico]+" ("+ \ bs.navdb.aptco[iap]+")" except: ico = -1 lines = lines + "Country code: "+bs.navdb.aptco[iap] try: rwytxt = str(bs.navdb.rwythresholds[bs.navdb.aptid[iap]].keys()) lines = lines + "\nRunways: " +rwytxt.strip("[]").replace("'","") except: pass # Not found as airport, try waypoints & navaids else: iwps = bs.navdb.getwpindices(wp,reflat,reflon) if iwps[0]>=0: typetxt = "" desctxt = "" lastdesc = "XXXXXXXX" for i in iwps: # One line type text if typetxt == "": typetxt = typetxt+bs.navdb.wptype[i] else: typetxt = typetxt+" and "+bs.navdb.wptype[i] # Description: multi-line samedesc = bs.navdb.wpdesc[i]==lastdesc if desctxt == "": desctxt = desctxt +bs.navdb.wpdesc[i] lastdesc = bs.navdb.wpdesc[i] elif not samedesc: desctxt = desctxt +"\n"+bs.navdb.wpdesc[i] lastdesc = bs.navdb.wpdesc[i] # Navaid: frequency if bs.navdb.wptype[i] in ["VOR","DME","TACAN"] and not samedesc: desctxt = desctxt + " "+ str(bs.navdb.wpfreq[i])+" MHz" elif bs.navdb.wptype[i]=="NDB" and not samedesc: desctxt = desctxt+ " " + str(bs.navdb.wpfreq[i])+" kHz" iwp = iwps[0] # Basic info lines = lines + wp +" is a "+ typetxt \ + " at\n"\ + latlon2txt(bs.navdb.wplat[iwp], \ bs.navdb.wplon[iwp]) # Navaids have description if len(desctxt)>0: lines = lines+ "\n" + desctxt # VOR give variation if bs.navdb.wptype[iwp]=="VOR": lines = lines + "\nVariation: "+ \ str(bs.navdb.wpvar[iwp])+" deg" # How many others? nother = bs.navdb.wpid.count(wp)-len(iwps) if nother>0: verb = ["is ","are "][min(1,max(0,nother-1))] lines = lines +"\nThere "+verb + str(nother) +\ " other waypoint(s) also named " + wp # In which airways? connect = bs.navdb.listconnections(wp, \ bs.navdb.wplat[iwp], bs.navdb.wplon[iwp]) if len(connect)>0: awset = set([]) for c in connect: awset.add(c[0]) lines = lines+"\nAirways: "+"-".join(awset) # Try airway id else: # airway awid = wp airway = bs.navdb.listairway(awid) if len(airway)>0: lines = "" for segment in airway: lines = lines+"Airway "+ awid + ": " + \ " - ".join(segment)+"\n" lines = lines[:-1] # cut off final newline else: return False,idxorwp+" not found as a/c, airport, navaid or waypoint" # Show what we found on airport and navaid/waypoint bs.scr.echo(lines) return True def airwaycmd(self,key=""): # Show conections of a waypoint reflat = bs.scr.ctrlat reflon = bs.scr.ctrlon if key=="": return False,'AIRWAY needs waypoint or airway' if bs.navdb.awid.count(key)>0: return self.poscommand(key.upper()) else: # Find connecting airway legs wpid = key.upper() iwp = bs.navdb.getwpidx(wpid,reflat,reflon) if iwp<0: return False,key + " not found." wplat = bs.navdb.wplat[iwp] wplon = bs.navdb.wplon[iwp] connect = bs.navdb.listconnections(key.upper(),wplat,wplon) if len(connect)>0: lines = "" for c in connect: if len(c)>=2: # Add airway, direction, waypoint lines = lines+ c[0]+": to "+c[1]+"\n" return True, lines[:-1] # exclude final newline else: return False,"No airway legs found for ",key
from logger import create_logger if __name__ == "__main__": logger = create_logger() cmd = "/home/prathyushpv/work/cpu2017/bin/runcpu --config=config1.cfg --threads 1 " benchmarks = [ '607.cactuBSSN_s' '619.lbm_s', '621.wrf_s', '627.cam4_s', '628.pop2_s', '638.imagick_s', '644.nab_s', '649.fotonik3d_s', '654.roms_s' ] counters = [ 'LLC-load-misses', 'LLC-store-misses', 'instructions', 'L1-dcache-loads', 'L1-dcache-stores' ] for benchmark in benchmarks: p = Perf(counters, cmd + benchmark) result = p.run_continuous() size = min([len(counter_values) for counter_values in result.values()]) y_mem = [(result["LLC-load-misses"][i] + result["LLC-store-misses"][i]) for i in range(size)] y_cpu = [(result["instructions"][i] - result["L1-dcache-loads"][i] - result["L1-dcache-stores"][i]) / 1000 for i in range(size)] x = range(size) print(y_mem) print(y_cpu) fig = plt.figure() ax = fig.add_subplot( 1, 1,