def drawdeprwy(apt,rwy,rwylat,rwylon,rwyhdg): # Draw approach ILS arrow Ldep = 5. # [nm] length of approach path drawn phi = 3. # [deg] angle of half the arrow # Calculate arrow (T = Threshold runway): # L (left) # / # D ------------------------------------- T (approach) # \ # R (right) # deplat,deplon = kwikpos(rwylat,rwylon,rwyhdg%360.,Ldep*1.1) rightlat,rightlon = kwikpos(rwylat,rwylon,(rwyhdg+phi)%360,Ldep) leftlat,leftlon = kwikpos(rwylat,rwylon,(rwyhdg-phi)%360,Ldep) # Make arguments for POLYLINE command T = str(rwylat)+","+str(rwylon) D = str(deplat)+","+str(deplon) L = str(leftlat)+","+str(leftlon) R = str(rightlat)+","+str(rightlon) stack.stack("POLYLINE " + apt + rwy + "-D," + ",".join([R,D,L,D,T])) return apt + rwy + "-D"
def drawapprwy(apt,rwy,rwylat,rwylon,rwyhdg): # Draw approach ILS arrow Lapp = 7. # [nm] length of approach path drawn phi = 5. # [deg] angle of half the arrow # Calculate arrow (T = Threshold runway): # /------------- L (left) # /-----------/ / # T -------------------------------------- A (approach) # \-----------\ \ # \--------------R (right) # applat,applon = kwikpos(rwylat,rwylon,(rwyhdg+180)%360.,Lapp) rightlat,rightlon = kwikpos(rwylat,rwylon,(rwyhdg+180-phi)%360,Lapp*1.1) leftlat,leftlon = kwikpos(rwylat,rwylon,(rwyhdg+180+phi)%360,Lapp*1.1) # Make arguments for POLYLINE command T = str(rwylat)+","+str(rwylon) A = str(applat)+","+str(applon) L = str(leftlat)+","+str(leftlon) R = str(rightlat)+","+str(rightlon) stack.stack("POLYLINE "+apt+rwy+"-A,"+",".join([T,A,L,T,R,A])) return apt+rwy+"-A"
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.kwikpos(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 = tas2cas(sqrt(tasn * tasn + tase * tase), acalt) achdg = degrees(atan2(tase, tasn)) # Create and, when necessary, set vertical speed self.create(1, actype, acalt, acspd, None, aclat, aclon, achdg, acid) self.ap.selaltcmd(len(self.lat) - 1, altref, acvs) self.vs[-1] = acvs
def getseg(txt): # Get a random position on the segment with the heading inward # SEGMnnn is segment in direction nnn degrees from center circle brg = float(txt[4:]) lat,lon = kwikpos(ctrlat,ctrlon,brg,radius) return lat,lon,brg
def detect_all(cls, traf, dtlookahead=None): #dtlookahead: lookahead time in s if dtlookahead is None: dtlookahead = settings.geofence_dtlookahead # Linearly extrapolate current state to prefict future position pred_lat, pred_lon = geo.kwikpos(traf.lat, traf.lon, traf.hdg, (dtlookahead * traf.gs) / aero.nm) pred_alt = traf.alt + dtlookahead * traf.vs # Check intersections with geofences for each aircraft separately hits_per_ac = [] for lat1, lon1, alt1, lat2, lon2, alt2 in zip(traf.lat, traf.lon, traf.alt, pred_lat, pred_lon, pred_alt): hits = [] # First a course detection based on geofence bounding boxes potential_hits = areafilter.get_intersecting( min(lat1, lat2), min(lon1, lon2), max(lat1, lat2), max(lon1, lon2)) # Create linearly extrapolated 2D flight path flightpath = Path([(lat1, lon1), (lat2, lon2)]) # Loop through all detected areas from the course detection for geofence in potential_hits: # Check if the area is a geofence if type(geofence) is Geofence: # Check if the 2D horizontal flight path intersects the geofence border if flightpath.intersects_path(geofence.border): # Check if the vertical flight path intersects simultaneously if geofence.bottom <= alt1 <= geofence.top and geofence.bottom <= alt2 <= geofence.top: hits.append( geofence ) # always a hit: entire vertical flight path lies inside else: # linearly extrapolate flightpath and check points separately lats = np.linspace( lat1, lat2, 100) # for now use 100 iterations lons = np.linspace(lon1, lon2, 100) alts = np.linspace(alt1, alt2, 100) hit_ver = geofence.checkInside(lats, lons, alts) if np.any(hit_ver): hits.append(geofence) # Finally append all geofence hits to the overall list hits_per_ac.append(hits) return hits_per_ac
def detect_all(cls, traf, dtlookahead=None): if dtlookahead is None: dtlookahead = settings.geofence_dtlookahead # Linearly extrapolate current state to prefict future position pred_lat, pred_lon = geo.kwikpos(traf.lat, traf.lon, traf.hdg, traf.gs / aero.nm) hits_per_ac = [] for idx, line in zip(traf.lat, traf.lon, pred_lat, pred_lon): hits = [] # First a course detection based on geofence bounding boxes potential_hits = areafilter.get_intersecting(*line) # Then a fine-grained intersection detection for geofence in potential_hits: if geofence.intersects(line): hits.append(geofence) hits_per_ac.append(hits) return hits_per_ac
def getLastPoint(self, last_node): # add last point to delete aircraft from map as fast as possible destination_side = cb.getCurrentBorder(last_node, cb.GRAPH) # 0 - north, 1-bottom, 2-east, 3-west heading_finalpoint = 0 # up alt_final = 2 if destination_side == 1: # bottom heading_finalpoint = 180 alt_final = 6 elif destination_side == 2: # east heading_finalpoint = 90 alt_final = 4 elif destination_side == 3: # left heading_finalpoint = 270 alt_final = 8 lat0, lon0 = cb.getLatLonnode(cb.GRAPH, last_node) lat_final, lon_final = geo.kwikpos(lat0, lon0, heading_finalpoint, 1000 / nm) return lat_final, lon_final, alt_final
def getNewNode(previous_node, step, edges): lat_node, lon_node = cb.getLatLonnode(cb.GRAPH, previous_node) possible_directions = [86.8, 176.8, 266.8, 356.8] distances = [94.4, 207.6, 94.4, 207.6] # meters lat0, lon0 = geo.kwikpos(lat_node, lon_node, possible_directions[step], distances[step] / nm) # check if we ended up in an existing node lat_nodes, lon_nodes, node_ids = cb.getLatLonAllNodes(cb.GRAPH) closest_node, dummy = cb.getclosestnode([lat0], [lon0], lat_nodes, lon_nodes, node_ids) lat_closest_node, lon_closest_node = cb.getLatLonnode( cb.GRAPH, closest_node) qdr, dist = geo.kwikqdrdist(lat0, lon0, lat_closest_node, lon_closest_node) if closest_node != previous_node and dist * nm < 15: # lets use this existent node lat0, lon0 = lat_closest_node, lon_closest_node edges[step] = (closest_node, qdr, dist * nm) cb.EDGES_PER_NODE[previous_node] = edges # create a new node else: existent_nodes = list(cb.NODES.keys()) # find the smallest positive number not in list new_nodes_key = next( filterfalse(set(existent_nodes).__contains__, count(1))) cb.addtoNodes(lat0, lon0, new_nodes_key, True) if edges[step] is None: edges[step] = (new_nodes_key, possible_directions[step], distances[step]) cb.EDGES_PER_NODE[previous_node] = edges # create edges for the new node, create only the ones that we are going to need new_nodes_edges = [None, None, None, None] opposite_step = getOppositeStep(step) new_nodes_edges[opposite_step] = (previous_node, possible_directions[opposite_step], distances[step]) cb.EDGES_PER_NODE[new_nodes_key] = new_nodes_edges closest_node = new_nodes_key return lat0, lon0, edges, closest_node
def update(self,gain): # Time step update of source # Get time step dt = sim.simt - self.tupdate self.tupdate = sim.simt # Time for a new aircraft? if dt>0.0: # Calculate probability of a geberate occurring with flow chances = 1.0-gain*self.flow*dt/3600. #flow is in a/c per hour=360 seconds if random.random() >= chances: # Runways defined? => use runway lines (queues) if len(self.runways)>0: # We do not yet need to create an aircraft gennow = False # Find shortest line and put it in isel = random.randint(0,len(self.runways)-1) self.rwyline[isel] = self.rwyline[isel] + 1 else: # Yes we do need to generate one now gennow = True else: gennow = False # Check for generating aircraft # First check runways for a/c already in line: txt = "" for i in range(len(self.runways)): # Runway vacated and there is one waiting? if sim.simt-self.rwytotime[i]>self.dtakeoff and self.rwyline[i]>0: #if self.name == "EHAM": # print(sim.simt, self.runways[i], self.rwytotime[i]) self.rwytotime[i] = sim.simt self.rwyline[i] = self.rwyline[i]-1 # Choose and aicraft type, check for distance if len(self.dest)>0: idest = int(random.random() * len(self.dest)) else: idest = -1 if idest>=0: acid = randacname(self.name,self.dest[idest]) if self.desttype[idest]=="seg" or self.dest[idest][:4]=="SEGM": lat,lon,hdg = getseg(self.dest[idest]) else: success,posobj = txt2pos(self.dest[idest],ctrlat,ctrlon) lat,lon = posobj.lat,posobj.lon distroute = latlondist(self.lat,self.lon,lat,lon)/nm else: acid = randacname(self.name, self.name) if self.destactypes[idest] == []: actype = random.choice(self.actypes) actype = checkactype(actype, distroute, self.actypes) else: actype = random.choice(self.destactypes[idest]) stack.stack("CRE "+",".join([acid, actype, str(self.rwylat[i]),str(self.rwylon[i]),str(self.rwyhdg[i]), "0.0","0.0"])) stack.stack(acid + " SPD 250") stack.stack(acid + " ALT FL100") stack.stack(acid + " HDG " + str(self.rwyhdg[i])) # TBD: Add waypoint for after take-off? if idest>=0: if self.dest[idest][:4] != "SEGM": stack.stack(acid + " DEST " + self.dest[idest]) else: stack.stack(acid + " DEST " + str(self.destlat[idest]) + " " + str(self.destlon[idest])) if self.name[:4] != "SEGM": stack.stack(acid + " ORIG " + self.name) else: stack.stack(acid + " ORIG " + str(self.lat) + " " + str(self.lon)) if idest>=0 and self.desttype[idest]=="seg": lat,lon,hdg = getseg(self.dest[idest]) brg,dist = kwikqdrdist(self.lat,self.lon,lat,lon) #stack.stack(acid+" HDG "+str(brg)) else: stack.stack(acid+" LNAV OFF") #stack.stack(acid+" VNAV ON") # Not runway, then define instantly at position with random heading or in case of segment inward heading if gennow: if not self.incircle: lat,lon = kwikpos(ctrlat,ctrlon,self.segdir,radius) hdg = self.segdir-180 elif self.type=="seg": lat,lon,brg = getseg(self.name) hdg = (brg+180)%360 elif self.type=="rwy": lat,lon = self.lat,self.lon hdg = self.hdg # Runway heading else: hdg = random.random()*360. if (self.type=="apt" or self.type=="rwy") and self.incircle: alttxt,spdtxt = str(0),str(0) else: alttxt,spdtxt = "FL"+str(random.randint(200,300)), str(random.randint(250,350)) # Add destination if len(self.dest)>0: idest = int(random.random() * len(self.dest)) acid = randacname(self.name,self.dest[idest]) else: acid = randacname(self.name,self.name) idest = -1 stack.stack("CRE " + ",".join([acid, random.choice(self.actypes), str(self.lat), str(self.lon), str(int(hdg%360)), alttxt,spdtxt])) if idest>=0: if self.dest[idest][:4] != "SEGM": stack.stack(acid + " DEST " + self.dest[idest]) else: stack.stack(acid + " DEST " + str(self.destlat[idest])+" "+str(self.destlon[idest])) if self.name[:4] != "SEGM": stack.stack(acid + " ORIG " + self.name) else: stack.stack(acid + " ORIG " + str(self.lat)+" "+str(self.lon)) if alttxt=="0" and spdtxt =="0": stack.stack(acid+" SPD 250") stack.stack(acid+" ALT FL100") else: if idest>=0: if self.desttype[idest] == "seg": lat, lon, hdg = getseg(self.dest[idest]) brg, dist = kwikdist(self.lat, self.lon, lat, lon) stack.stack(acid + " HDG " + str(brg)) else: stack.stack(acid + " LNAV ON")
def creconfs(self, acid, actype, targetidx, dpsi, dcpa, tlosh, dH=None, tlosv=None, spd=None): ''' Create an aircraft in conflict with target aircraft. Arguments: - acid: callsign of new aircraft - actype: aircraft type of new aircraft - targetidx: id (callsign) of target aircraft - dpsi: Conflict angle (angle between tracks of ownship and intruder) (deg) - cpa: Predicted distance at closest point of approach (NM) - tlosh: Horizontal time to loss of separation ((hh:mm:)sec) - dH: Vertical distance (ft) - tlosv: Vertical time to loss of separation - spd: Speed of new aircraft (CAS/Mach, kts/-) ''' 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 tasref = self.tas[targetidx] # m/s vsref = self.vs[targetidx] # m/s cpa = dcpa * nm pzr = bs.settings.asas_pzr * nm pzh = bs.settings.asas_pzh * ft trk = trkref + radians(dpsi) 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 if spd: # CAS or Mach provided: convert to groundspeed, assuming that # wind at intruder position is similar to wind at ownship position tas = tasref if spd is None else casormach2tas(spd, acalt) tasn, tase = tas * cos(trk), tas * sin(trk) wn, we = self.wind.getdata(latref, lonref, acalt) gsn, gse = tasn + wn, tase + we else: # Groundspeed is the same as ownship gsn, gse = gsref * cos(trk), gsref * sin(trk) # Horizontal relative velocity vector 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.kwikpos(latref, lonref, brn, dist / nm) # convert groundspeed to CAS, and track to heading using actual # intruder position wn, we = self.wind.getdata(aclat, aclon, acalt) tasn, tase = gsn - wn, gse - we acspd = tas2cas(sqrt(tasn * tasn + tase * tase), acalt) achdg = degrees(atan2(tase, tasn)) # Create and, when necessary, set vertical speed self.cre(acid, actype, aclat, aclon, achdg, acalt, acspd) self.ap.selaltcmd(len(self.lat) - 1, altref, acvs) self.vs[-1] = acvs
def update(self): """Draw a new frame""" # First check for keys & mouse self.keyb.update() # Navdisp mode: get center: if self.swnavdisp: i = bs.traf.id2idx(self.ndacid) if i >= 0: self.ndlat = bs.traf.lat[i] self.ndlon = bs.traf.lon[i] self.ndcrs = bs.traf.hdg[i] else: self.swnavdisp = False else: self.ndcrs = 0.0 # Radar window # --------------Background-------------- if self.redrawradbg or self.swnavdisp: if self.swnavdisp or not self.swsat: self.radbmp.fill(darkgrey) else: #--------------Satellite image-------------- navsel = (self.lat0, self.lat1, \ self.lon0, self.lon1) if not self.satsel == navsel: # Map cutting and scaling: normal case if self.lon1 > self.lon0: x0 = max(0, self.lon0 * self.mapax + self.mapbx) x1 = min(self.mapbmp.get_width() - 1, \ self.lon1 * self.mapax + self.mapbx) y1 = min(self.mapbmp.get_height() - 1, \ self.lat0 * self.mapay + self.mapby) y0 = max(0, self.lat1 * self.mapay + self.mapby) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (self.width, self.height)) self.radbmp.blit(self.submap, (0, 0)) else: # Wrap around case: clip two segments w0 = int(self.width * (180. - self.lon0) / \ (180.0 - self.lon0 + self.lon1 + 180.)) w1 = int(self.width - w0) # Left part x0 = max(0, self.lon0 * self.mapax + self.mapbx) x1 = self.mapbmp.get_width() - 1 y1 = min(self.mapbmp.get_height() - 1, \ self.lat0 * self.mapay + self.mapby) y0 = max(0, self.lat1 * self.mapay + self.mapby) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (w0, self.height)) self.radbmp.blit(self.submap, (0, 0)) # Right half x0 = 0 x1 = min(self.mapbmp.get_width() - 1, \ self.lon1 * self.mapax + self.mapbx) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (w1, self.height)) self.radbmp.blit(self.submap, (w0, 0)) self.submap = self.radbmp.copy() self.satsel = navsel else: # Map blit only self.radbmp.blit(self.submap, (0, 0)) if self.swgrid and not self.swnavdisp: # ------Draw lat/lon grid------ ngrad = int(self.lon1 - self.lon0) if ngrad >= 10: step = 10 i0 = step * int(self.lon0 / step) j0 = step * int(self.lat0 / step) else: step = 1 i0 = int(self.lon0) j0 = int(self.lon0) for i in range(i0, int(self.lon1 + 1.), step): x, y = self.ll2xy(self.ctrlat, i) pg.draw.line(self.radbmp, lightgreygreen, \ (x, 0), (x, self.height)) for j in range(j0, int(self.lat1 + 1.), step): x, y = self.ll2xy(j, self.ctrlon) pg.draw.line(self.radbmp, lightgreygreen, \ (0, y), (self.width, y)) #------ Draw coastlines ------ if self.swgeo: # cx,cy = -1,-1 geosel = (self.lat0, self.lon0, self.lat1, self.lon1) if self.geosel != geosel: self.geosel = geosel self.cstsel = np.where( self.onradar(self.coastlat0, self.coastlon0) + \ self.onradar(self.coastlat1, self.coastlon1)) # print len(self.cstsel[0])," coastlines" self.cx0, self.cy0 = self.ll2xy(self.coastlat0, self.coastlon0) self.cx1, self.cy1 = self.ll2xy(self.coastlat1, self.coastlon1) for i in list(self.cstsel[0]): pg.draw.line(self.radbmp, grey, (self.cx0[i], self.cy0[i]), \ (self.cx1[i], self.cy1[i])) #------ Draw FIRs ------ if self.swfir: self.firx0, self.firy0 = self.ll2xy(bs.navdb.firlat0, \ bs.navdb.firlon0) self.firx1, self.firy1 = self.ll2xy(bs.navdb.firlat1, \ bs.navdb.firlon1) for i in range(len(self.firx0)): pg.draw.line(self.radbmp, lightcyan, (self.firx0[i], self.firy0[i]), (self.firx1[i], self.firy1[i])) # -----------------Waypoint & airport symbols----------------- # Check whether we need to reselect waypoint set to be drawn navsel = (self.lat0, self.lat1, \ self.lon0, self.lon1) if self.navsel != navsel: self.navsel = navsel # Make list of indices of waypoints & airports on screen self.wpinside = list(np.where(self.onradar(bs.navdb.wplat, \ bs.navdb.wplon))[0]) self.wptsel = [] for i in self.wpinside: if self.wpsw == 3 or \ (self.wpsw == 1 and len(bs.navdb.wpid[i]) == 3) or \ (self.wpsw == 2 and bs.navdb.wpid[i].isalpha()): self.wptsel.append(i) self.wptx, self.wpty = self.ll2xy(bs.navdb.wplat, bs.navdb.wplon) self.apinside = list(np.where(self.onradar(bs.navdb.aptlat, \ bs.navdb.aptlon))[0]) self.aptsel = [] for i in self.apinside: if self.apsw == 2 or (self.apsw == 1 and \ bs.navdb.aptmaxrwy[i] > 1000.): self.aptsel.append(i) self.aptx, self.apty = self.ll2xy(bs.navdb.aptlat, bs.navdb.aptlon) #------- Draw waypoints ------- if self.wpsw > 0: # print len(self.wptsel)," waypoints" if len(self.wptsel) < self.maxnrwp: wptrect = self.wptsymbol.get_rect() for i in self.wptsel: # wptrect.center = self.ll2xy(bs.navdb.wplat[i], \ # bs.navdb.wplon[i]) wptrect.center = self.wptx[i], self.wpty[i] self.radbmp.blit(self.wptsymbol, wptrect) # If waypoint label bitmap does not yet exist, make it if not self.wpswbmp[i]: self.wplabel[i] = pg.Surface((80, 30), 0, self.win) self.fontnav.printat(self.wplabel[i], 0, 0, \ bs.navdb.wpid[i]) self.wpswbmp[i] = True # In any case, blit it xtxt = wptrect.right + 2 ytxt = wptrect.top self.radbmp.blit(self.wplabel[i], (xtxt, ytxt), \ None, pg.BLEND_ADD) if not self.wpswbmp[i]: xtxt = wptrect.right + 2 ytxt = wptrect.top # self.fontnav.printat(self.radbmp,xtxt,ytxt, \ # bs.navdb.wpid[i]) #------- Draw airports ------- if self.apsw > 0: # if len(self.aptsel)<800: aptrect = self.aptsymbol.get_rect() # print len(self.aptsel)," airports" for i in self.aptsel: # aptrect.center = self.ll2xy(bs.navdb.aptlat[i], \ # bs.navdb.aptlon[i]) aptrect.center = self.aptx[i], self.apty[i] self.radbmp.blit(self.aptsymbol, aptrect) # If airport label bitmap does not yet exist, make it if not self.apswbmp[i]: self.aplabel[i] = pg.Surface((50, 30), 0, self.win) self.fontnav.printat(self.aplabel[i], 0, 0, \ bs.navdb.aptid[i]) self.apswbmp[i] = True # In either case, blit it xtxt = aptrect.right + 2 ytxt = aptrect.top self.radbmp.blit(self.aplabel[i], (xtxt, ytxt), \ None, pg.BLEND_ADD) # self.fontnav.printat(self.radbmp,xtxt,ytxt, \ # bs.navdb.aptid[i]) #---------- Draw background trails ---------- if bs.traf.trails.active: bs.traf.trails.buffer() # move all new trails to background trlsel = list(np.where( self.onradar(bs.traf.trails.bglat0, bs.traf.trails.bglon0) + \ self.onradar(bs.traf.trails.bglat1, bs.traf.trails.bglon1))[0]) x0, y0 = self.ll2xy(bs.traf.trails.bglat0, bs.traf.trails.bglon0) x1, y1 = self.ll2xy(bs.traf.trails.bglat1, bs.traf.trails.bglon1) for i in trlsel: pg.draw.aaline(self.radbmp, bs.traf.trails.bgcol[i], \ (x0[i], y0[i]), (x1[i], y1[i])) #---------- Draw ADSB Coverage Area if self.swAdsbCoverage: # These points are based on the positions of the antennas with range = 200km adsbCoverageLat = [ 53.7863, 53.5362, 52.8604, 51.9538, 51.2285, 50.8249, 50.7382, 50.9701, 51.6096, 52.498, 53.4047, 53.6402 ] adsbCoverageLon = [ 4.3757, 5.8869, 6.9529, 7.2913, 6.9312, 6.251, 5.7218, 4.2955, 3.2162, 2.7701, 3.1117, 3.4891 ] for i in range(0, len(adsbCoverageLat)): if i == len(adsbCoverageLat) - 1: x0, y0 = self.ll2xy(adsbCoverageLat[i], adsbCoverageLon[i]) x1, y1 = self.ll2xy(adsbCoverageLat[0], adsbCoverageLon[0]) else: x0, y0 = self.ll2xy(adsbCoverageLat[i], adsbCoverageLon[i]) x1, y1 = self.ll2xy(adsbCoverageLat[i + 1], adsbCoverageLon[i + 1]) pg.draw.line(self.radbmp, red, (x0, y0), (x1, y1)) # User defined objects for i in range(len(self.objtype)): # Draw LINE or POLYGON with objdata = [lat0,lon,lat1,lon1,lat2,lon2,..] if self.objtype[i] == 'LINE' or self.objtype[i] == "POLY": npoints = len(self.objdata[i]) / 2 print(npoints) x0, y0 = self.ll2xy(self.objdata[i][0], self.objdata[i][1]) for j in range(1, npoints): x1, y1 = self.ll2xy(self.objdata[i][j * 2], self.objdata[i][j * 2 + 1]) pg.draw.line(self.radbmp, self.objcolor[i], (x0, y0), (x1, y1)) x0, y0 = x1, y1 if self.objtype[i] == "POLY": x1, y1 = self.ll2xy(self.objdata[i][0], self.objdata[i][1]) pg.draw.line(self.radbmp, self.objcolor[i], (x0, y0), (x1, y1)) # Draw bounding box of objdata = [lat0,lon0,lat1,lon1] elif self.objtype[i] == 'BOX': lat0 = min(self.objdata[i][0], self.objdata[i][2]) lon0 = min(self.objdata[i][1], self.objdata[i][3]) lat1 = max(self.objdata[i][0], self.objdata[i][2]) lon1 = max(self.objdata[i][1], self.objdata[i][3]) x0, y0 = self.ll2xy(lat1, lon0) x1, y1 = self.ll2xy(lat0, lon1) pg.draw.rect(self.radbmp, self.objcolor[i], pg.Rect(x0, y0, x1 - x0, y1 - y0), 1) # Draw circle with objdata = [latcenter,loncenter,radiusnm] elif self.objtype[i] == 'CIRCLE': pass xm, ym = self.ll2xy(self.objdata[i][0], self.objdata[i][1]) xtop, ytop = self.ll2xy( self.objdata[i][0] + self.objdata[i][2] / 60., self.objdata[i][1]) radius = int(round(abs(ytop - ym))) pg.draw.circle(self.radbmp, self.objcolor[i], (int(xm), int(ym)), radius, 1) # Reset background drawing switch self.redrawradbg = False ############################################################################## # END OF BACKGROUND DRAWING # ############################################################################## # Blit background self.win.blit(self.radbmp, (0, 0)) # Decide to redraw radar picture of a/c syst = pg.time.get_ticks() * 0.001 redrawrad = self.redrawradbg or abs(syst - self.radt0) >= self.radardt if redrawrad: self.radt0 = syst # Update lats drawing time of radar # Select which aircraft are within screen area trafsel = np.where((bs.traf.lat > self.lat0) * (bs.traf.lat < self.lat1) * \ (bs.traf.lon > self.lon0) * (bs.traf.lon < self.lon1))[0] # ------------------- Draw aircraft ------------------- # Convert lat,lon to x,y trafx, trafy = self.ll2xy(bs.traf.lat, bs.traf.lon) trafy -= bs.traf.alt * self.isoalt if bs.traf.trails.active: ltx, lty = self.ll2xy(bs.traf.trails.lastlat, bs.traf.trails.lastlon) # Find pixel size of horizontal separation on screen pixelrad = self.dtopix_eq(bs.traf.asas.R / 2) # Loop through all traffic indices which we found on screen for i in trafsel: # Get index of ac symbol, based on heading and its rect object isymb = int(round((bs.traf.hdg[i] - self.ndcrs) / 6.)) % 60 pos = self.acsymbol[isymb].get_rect() # Draw aircraft symbol pos.centerx = trafx[i] pos.centery = trafy[i] dy = self.fontrad.linedy * 7 / 6 # Draw aircraft altitude line if self.isoalt > 1e-7: pg.draw.line( self.win, white, (int(trafx[i]), int(trafy[i])), (int(trafx[i]), int(trafy[i] + bs.traf.alt[i] * self.isoalt))) # Normal symbol if no conflict else amber toosmall = self.lat1 - self.lat0 > 6 #don't draw circles if zoomed out too much if not bs.traf.asas.inconf[i]: self.win.blit(self.acsymbol[isymb], pos) if self.swsep and not toosmall: pg.draw.circle(self.win, green, (int(trafx[i]), int(trafy[i])), pixelrad, 1) else: self.win.blit(self.ambacsymbol[isymb], pos) if self.swsep and not toosmall: pg.draw.circle(self.win, amber, (int(trafx[i]), int(trafy[i])), pixelrad, 1) # Draw last trail part if bs.traf.trails.active: pg.draw.line(self.win, tuple(bs.traf.trails.accolor[i]), (ltx[i], lty[i]), (trafx[i], trafy[i])) # Label text label = [] if self.swlabel > 0: label.append(bs.traf.id[i]) # Line 1 of label: id else: label.append(" ") if self.swlabel > 1: if bs.traf.alt[i] > bs.traf.translvl: label.append( "FL" + str(int(round( bs.traf.alt[i] / (100. * ft))))) # Line 2 of label: altitude else: label.append(str(int( round(bs.traf.alt[i] / ft)))) # Line 2 of label: altitude else: label.append(" ") if self.swlabel > 2: cas = bs.traf.cas[i] / kts label.append(str(int( round(cas)))) # line 3 of label: speed else: label.append(" ") # Check for changes in traffic label text if not (type(bs.traf.label[i])==list) or \ not (type(bs.traf.label[i][3])==str) or \ not (label[:3] == bs.traf.label[i][:3]): bs.traf.label[i] = [] labelbmp = pg.Surface((100, 60), 0, self.win) if not bs.traf.asas.inconf[i]: acfont = self.fontrad else: acfont = self.fontamb acfont.printat(labelbmp, 0, 0, label[0]) acfont.printat(labelbmp, 0, dy, label[1]) acfont.printat(labelbmp, 0, 2 * dy, label[2]) bs.traf.label[i].append(label[0]) bs.traf.label[i].append(label[1]) bs.traf.label[i].append(label[2]) bs.traf.label[i].append(labelbmp) # Blit label dest = bs.traf.label[i][3].get_rect() dest.top = trafy[i] - 5 dest.left = trafx[i] + 15 self.win.blit(bs.traf.label[i][3], dest, None, pg.BLEND_ADD) # Draw aircraft speed vectors if self.swspd: # just a nominal length: a speed of 150 kts will be displayed # as an arrow of 30 pixels long on screen nomlength = 30 nomspeed = 150. vectorlength = float(nomlength) * bs.traf.tas[i] / nomspeed spdvcx = trafx[i] + np.sin(np.radians( bs.traf.trk[i])) * vectorlength spdvcy = trafy[i] - np.cos(np.radians(bs.traf.trk[i])) * vectorlength \ - bs.traf.vs[i]/nomspeed*nomlength*self.isoalt / \ self.dtopix_eq(1e5)*1e5 pg.draw.line(self.win, green, (trafx[i], trafy[i]), (spdvcx, spdvcy)) # ---- End of per aircraft i loop # Draw conflicts: line from a/c to closest point of approach nconf = len(bs.traf.asas.confpairs_unique) n2conf = len(bs.traf.asas.confpairs) if nconf > 0: for j in range(n2conf): i = bs.traf.id2idx(bs.traf.asas.confpairs[j][0]) if i >= 0 and i < bs.traf.ntraf and (i in trafsel): latcpa, loncpa = geo.kwikpos(bs.traf.lat[i], bs.traf.lon[i], \ bs.traf.trk[i], bs.traf.asas.tcpa[j] * bs.traf.gs[i] / nm) altcpa = bs.traf.lat[ i] + bs.traf.vs[i] * bs.traf.asas.tcpa[j] xc, yc = self.ll2xy(latcpa, loncpa) yc = yc - altcpa * self.isoalt pg.draw.line(self.win, amber, (xc, yc), (trafx[i], trafy[i])) # Draw selected route: if self.acidrte != "": i = bs.traf.id2idx(self.acidrte) if i >= 0: for j in range(0, bs.traf.ap.route[i].nwp): if j == 0: x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \ bs.traf.ap.route[i].wplon[j]) else: x0, y0 = x1, y1 x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \ bs.traf.ap.route[i].wplon[j]) pg.draw.line(self.win, magenta, (x0, y0), (x1, y1)) if j >= len(self.rtewpid) or not self.rtewpid[ j] == bs.traf.ap.route[i].wpname[j]: # Waypoint name labels # If waypoint label bitmap does not yet exist, make it # Waypoint name and constraint(s), if there are any txt = bs.traf.ap.route[i].wpname[j] alt = bs.traf.ap.route[i].wpalt[j] spd = bs.traf.ap.route[i].wpspd[j] if alt >= 0. or spd >= 0.: # Altitude if alt < 0: txt = txt + " -----/" elif alt > 4500 * ft: FL = int(round((alt / (100. * ft)))) txt = txt + " FL" + str(FL) + "/" else: txt = txt + " " + str(int(round( alt / ft))) + "/" # Speed if spd < 0: txt = txt + "---" else: txt = txt + str(int(round(spd / kts))) wplabel = pg.Surface((128, 32), 0, self.win) self.fontnav.printat(wplabel, 0, 0, \ txt) if j >= len(self.rtewpid): self.rtewpid.append(txt) self.rtewplabel.append(wplabel) else: self.rtewpid[j] = txt self.rtewplabel[j] = wplabel # In any case, blit the waypoint name xtxt = x1 + 7 ytxt = y1 - 3 self.radbmp.blit(self.rtewplabel[j], (xtxt, ytxt), \ None, pg.BLEND_ADD) # Line from aircraft to active waypoint if bs.traf.ap.route[i].iactwp == j: x0, y0 = self.ll2xy(bs.traf.lat[i], bs.traf.lon[i]) pg.draw.line(self.win, magenta, (x0, y0), (x1, y1)) # Draw aircraft trails which are on screen if bs.traf.trails.active: trlsel = list(np.where( self.onradar(bs.traf.trails.lat0, bs.traf.trails.lon0) + \ self.onradar(bs.traf.trails.lat1, bs.traf.trails.lon1))[0]) x0, y0 = self.ll2xy(bs.traf.trails.lat0, bs.traf.trails.lon0) x1, y1 = self.ll2xy(bs.traf.trails.lat1, bs.traf.trails.lon1) for i in trlsel: pg.draw.line(self.win, bs.traf.trails.col[i], \ (x0[i], y0[i]), (x1[i], y1[i])) # Redraw background => buffer ; if >1500 foreground linepieces on screen if len(trlsel) > 1500: self.redrawradbg = True # Draw edit window self.editwin.update() if self.redrawradbg or redrawrad or self.editwin.redraw: self.win.blit(self.menu.bmps[self.menu.ipage], \ (self.menu.x, self.menu.y)) self.win.blit(self.editwin.bmp, (self.editwin.winx, self.editwin.winy)) # Draw frames pg.draw.rect(self.win, white, self.editwin.rect, 1) pg.draw.rect(self.win, white, pg.Rect(1, 1, self.width - 1, self.height - 1), 1) # Add debug line self.fontsys.printat(self.win, 10, 2, str(bs.sim.utc.replace(microsecond=0))) self.fontsys.printat(self.win, 10, 18, tim2txt(bs.sim.simt)) self.fontsys.printat(self.win, 10+80, 2, \ "ntraf = " + str(bs.traf.ntraf)) self.fontsys.printat(self.win, 10+160, 2, \ "Freq=" + str(int(len(bs.sim.dts) / max(0.001, sum(bs.sim.dts))))) self.fontsys.printat(self.win, 10+240, 2, \ "#LOS = " + str(len(bs.traf.asas.lospairs_unique))) self.fontsys.printat(self.win, 10+240, 18, \ "Total LOS = " + str(len(bs.traf.asas.lospairs_all))) self.fontsys.printat(self.win, 10+240, 34, \ "#Con = " + str(len(bs.traf.asas.confpairs_unique))) self.fontsys.printat(self.win, 10+240, 50, \ "Total Con = " + str(len(bs.traf.asas.confpairs_all))) # Frame ready, flip to screen pg.display.flip() # If needed, take a screenshot if self.screenshot: pg.image.save(self.win, self.screenshotname) self.screenshot = False return
def update(self): """Draw a new frame""" # First check for keys & mouse self.keyb.update() # Navdisp mode: get center: if self.swnavdisp: i = bs.traf.id2idx(self.ndacid) if i >= 0: self.ndlat = bs.traf.lat[i] self.ndlon = bs.traf.lon[i] self.ndcrs = bs.traf.hdg[i] else: self.swnavdisp = False else: self.ndcrs = 0.0 # Radar window # --------------Background-------------- if self.redrawradbg or self.swnavdisp: if self.swnavdisp or not self.swsat: self.radbmp.fill(darkgrey) else: #--------------Satellite image-------------- navsel = (self.lat0, self.lat1, \ self.lon0, self.lon1) if not self.satsel == navsel: # Map cutting and scaling: normal case if self.lon1 > self.lon0: x0 = max(0, self.lon0 * self.mapax + self.mapbx) x1 = min(self.mapbmp.get_width() - 1, \ self.lon1 * self.mapax + self.mapbx) y1 = min(self.mapbmp.get_height() - 1, \ self.lat0 * self.mapay + self.mapby) y0 = max(0, self.lat1 * self.mapay + self.mapby) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (self.width, self.height)) self.radbmp.blit(self.submap, (0, 0)) else: # Wrap around case: clip two segments w0 = int(self.width * (180. - self.lon0) / \ (180.0 - self.lon0 + self.lon1 + 180.)) w1 = int(self.width - w0) # Left part x0 = max(0, self.lon0 * self.mapax + self.mapbx) x1 = self.mapbmp.get_width() - 1 y1 = min(self.mapbmp.get_height() - 1, \ self.lat0 * self.mapay + self.mapby) y0 = max(0, self.lat1 * self.mapay + self.mapby) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (w0, self.height)) self.radbmp.blit(self.submap, (0, 0)) # Right half x0 = 0 x1 = min(self.mapbmp.get_width() - 1, \ self.lon1 * self.mapax + self.mapbx) selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0)) mapsel = self.mapbmp.subsurface(selrect) self.submap = pg.transform.scale(mapsel, \ (w1, self.height)) self.radbmp.blit(self.submap, (w0, 0)) self.submap = self.radbmp.copy() self.satsel = navsel else: # Map blit only self.radbmp.blit(self.submap, (0, 0)) if self.swgrid and not self.swnavdisp: # ------Draw lat/lon grid------ ngrad = int(self.lon1 - self.lon0) if ngrad >= 10: step = 10 i0 = step * int(self.lon0 / step) j0 = step * int(self.lat0 / step) else: step = 1 i0 = int(self.lon0) j0 = int(self.lon0) for i in range(i0, int(self.lon1 + 1.), step): x, y = self.ll2xy(self.ctrlat, i) pg.draw.line(self.radbmp, lightgreygreen, \ (x, 0), (x, self.height)) for j in range(j0, int(self.lat1 + 1.), step): x, y = self.ll2xy(j, self.ctrlon) pg.draw.line(self.radbmp, lightgreygreen, \ (0, y), (self.width, y)) #------ Draw coastlines ------ if self.swgeo: # cx,cy = -1,-1 geosel = (self.lat0, self.lon0, self.lat1, self.lon1) if self.geosel != geosel: self.geosel = geosel self.cstsel = np.where( self.onradar(self.coastlat0, self.coastlon0) + \ self.onradar(self.coastlat1, self.coastlon1)) # print len(self.cstsel[0])," coastlines" self.cx0, self.cy0 = self.ll2xy(self.coastlat0, self.coastlon0) self.cx1, self.cy1 = self.ll2xy(self.coastlat1, self.coastlon1) for i in list(self.cstsel[0]): pg.draw.line(self.radbmp, grey, (self.cx0[i], self.cy0[i]), \ (self.cx1[i], self.cy1[i])) #------ Draw FIRs ------ if self.swfir: self.firx0, self.firy0 = self.ll2xy(bs.navdb.firlat0, \ bs.navdb.firlon0) self.firx1, self.firy1 = self.ll2xy(bs.navdb.firlat1, \ bs.navdb.firlon1) for i in range(len(self.firx0)): pg.draw.line(self.radbmp, lightcyan, (self.firx0[i], self.firy0[i]), (self.firx1[i], self.firy1[i])) # -----------------Waypoint & airport symbols----------------- # Check whether we need to reselect waypoint set to be drawn navsel = (self.lat0, self.lat1, \ self.lon0, self.lon1) if self.navsel != navsel: self.navsel = navsel # Make list of indices of waypoints & airports on screen self.wpinside = list(np.where(self.onradar(bs.navdb.wplat, \ bs.navdb.wplon))[0]) self.wptsel = [] for i in self.wpinside: if self.wpsw == 3 or \ (self.wpsw == 1 and len(bs.navdb.wpid[i]) == 3) or \ (self.wpsw == 2 and bs.navdb.wpid[i].isalpha()): self.wptsel.append(i) self.wptx, self.wpty = self.ll2xy(bs.navdb.wplat, bs.navdb.wplon) self.apinside = list(np.where(self.onradar(bs.navdb.aptlat, \ bs.navdb.aptlon))[0]) self.aptsel = [] for i in self.apinside: if self.apsw == 2 or (self.apsw == 1 and \ bs.navdb.aptmaxrwy[i] > 1000.): self.aptsel.append(i) self.aptx, self.apty = self.ll2xy(bs.navdb.aptlat, bs.navdb.aptlon) #------- Draw waypoints ------- if self.wpsw > 0: # print len(self.wptsel)," waypoints" if len(self.wptsel) < self.maxnrwp: wptrect = self.wptsymbol.get_rect() for i in self.wptsel: # wptrect.center = self.ll2xy(bs.navdb.wplat[i], \ # bs.navdb.wplon[i]) wptrect.center = self.wptx[i], self.wpty[i] self.radbmp.blit(self.wptsymbol, wptrect) # If waypoint label bitmap does not yet exist, make it if not self.wpswbmp[i]: self.wplabel[i] = pg.Surface((80, 30), 0, self.win) self.fontnav.printat(self.wplabel[i], 0, 0, \ bs.navdb.wpid[i]) self.wpswbmp[i] = True # In any case, blit it xtxt = wptrect.right + 2 ytxt = wptrect.top self.radbmp.blit(self.wplabel[i], (xtxt, ytxt), \ None, pg.BLEND_ADD) if not self.wpswbmp[i]: xtxt = wptrect.right + 2 ytxt = wptrect.top # self.fontnav.printat(self.radbmp,xtxt,ytxt, \ # bs.navdb.wpid[i]) #------- Draw airports ------- if self.apsw > 0: # if len(self.aptsel)<800: aptrect = self.aptsymbol.get_rect() # print len(self.aptsel)," airports" for i in self.aptsel: # aptrect.center = self.ll2xy(bs.navdb.aptlat[i], \ # bs.navdb.aptlon[i]) aptrect.center = self.aptx[i], self.apty[i] self.radbmp.blit(self.aptsymbol, aptrect) # If airport label bitmap does not yet exist, make it if not self.apswbmp[i]: self.aplabel[i] = pg.Surface((50, 30), 0, self.win) self.fontnav.printat(self.aplabel[i], 0, 0, \ bs.navdb.aptid[i]) self.apswbmp[i] = True # In either case, blit it xtxt = aptrect.right + 2 ytxt = aptrect.top self.radbmp.blit(self.aplabel[i], (xtxt, ytxt), \ None, pg.BLEND_ADD) # self.fontnav.printat(self.radbmp,xtxt,ytxt, \ # bs.navdb.aptid[i]) #---------- Draw background trails ---------- if bs.traf.trails.active: bs.traf.trails.buffer() # move all new trails to background trlsel = list(np.where( self.onradar(bs.traf.trails.bglat0, bs.traf.trails.bglon0) + \ self.onradar(bs.traf.trails.bglat1, bs.traf.trails.bglon1))[0]) x0, y0 = self.ll2xy(bs.traf.trails.bglat0, bs.traf.trails.bglon0) x1, y1 = self.ll2xy(bs.traf.trails.bglat1, bs.traf.trails.bglon1) for i in trlsel: pg.draw.aaline(self.radbmp, bs.traf.trails.bgcol[i], \ (x0[i], y0[i]), (x1[i], y1[i])) #---------- Draw ADSB Coverage Area if self.swAdsbCoverage: # These points are based on the positions of the antennas with range = 200km adsbCoverageLat = [53.7863,53.5362,52.8604,51.9538,51.2285,50.8249,50.7382, 50.9701,51.6096,52.498,53.4047,53.6402] adsbCoverageLon = [4.3757,5.8869,6.9529,7.2913,6.9312,6.251,5.7218,4.2955, 3.2162,2.7701,3.1117,3.4891] for i in range(0,len(adsbCoverageLat)): if i == len(adsbCoverageLat)-1: x0, y0 = self.ll2xy(adsbCoverageLat[i],adsbCoverageLon[i]) x1, y1 = self.ll2xy(adsbCoverageLat[0],adsbCoverageLon[0]) else: x0, y0 = self.ll2xy(adsbCoverageLat[i],adsbCoverageLon[i]) x1, y1 = self.ll2xy(adsbCoverageLat[i+1],adsbCoverageLon[i+1]) pg.draw.line(self.radbmp, red,(x0, y0), (x1, y1)) # User defined objects for i in range(len(self.objtype)): # Draw LINE or POLYGON with objdata = [lat0,lon,lat1,lon1,lat2,lon2,..] if self.objtype[i]=='LINE' or self.objtype[i]=="POLY" or self.objtype[i]=="POLYLINE": npoints = int(len(self.objdata[i])/2) print(npoints) x0,y0 = self.ll2xy(self.objdata[i][0],self.objdata[i][1]) for j in range(1,npoints): x1,y1 = self.ll2xy(self.objdata[i][j*2],self.objdata[i][j*2+1]) pg.draw.line(self.radbmp,self.objcolor[i],(x0, y0), (x1, y1)) x0,y0 = x1,y1 if self.objtype[i]=="POLY": x1,y1 = self.ll2xy(self.objdata[i][0],self.objdata[i][1]) pg.draw.line(self.radbmp,self.objcolor[i],(x0, y0), (x1, y1)) # Draw bounding box of objdata = [lat0,lon0,lat1,lon1] elif self.objtype[i]=='BOX': lat0 = min(self.objdata[i][0],self.objdata[i][2]) lon0 = min(self.objdata[i][1],self.objdata[i][3]) lat1 = max(self.objdata[i][0],self.objdata[i][2]) lon1 = max(self.objdata[i][1],self.objdata[i][3]) x0,y0 = self.ll2xy(lat1,lon0) x1,y1 = self.ll2xy(lat0,lon1) pg.draw.rect(self.radbmp,self.objcolor[i],pg.Rect(x0, y0, x1-x0, y1-y0),1) # Draw circle with objdata = [latcenter,loncenter,radiusnm] elif self.objtype[i]=='CIRCLE': pass xm,ym = self.ll2xy(self.objdata[i][0],self.objdata[i][1]) xtop,ytop = self.ll2xy(self.objdata[i][0]+self.objdata[i][2]/60.,self.objdata[i][1]) radius = int(round(abs(ytop-ym))) pg.draw.circle(self.radbmp, self.objcolor[i], (int(xm),int(ym)), radius, 1) # Reset background drawing switch self.redrawradbg = False ############################################################################## # END OF BACKGROUND DRAWING # ############################################################################## # Blit background self.win.blit(self.radbmp, (0, 0)) # Decide to redraw radar picture of a/c syst = pg.time.get_ticks() * 0.001 redrawrad = self.redrawradbg or abs(syst - self.radt0) >= self.radardt if redrawrad: self.radt0 = syst # Update lats drawing time of radar # Select which aircraft are within screen area trafsel = np.where((bs.traf.lat > self.lat0) * (bs.traf.lat < self.lat1) * \ (bs.traf.lon > self.lon0) * (bs.traf.lon < self.lon1))[0] # ------------------- Draw aircraft ------------------- # Convert lat,lon to x,y trafx, trafy = self.ll2xy(bs.traf.lat, bs.traf.lon) trafy -= bs.traf.alt*self.isoalt if bs.traf.trails.active: ltx, lty = self.ll2xy(bs.traf.trails.lastlat, bs.traf.trails.lastlon) # Find pixel size of horizontal separation on screen pixelrad=self.dtopix_eq(bs.traf.asas.R/2) # Loop through all traffic indices which we found on screen for i in trafsel: # Get index of ac symbol, based on heading and its rect object isymb = int(round((bs.traf.hdg[i] - self.ndcrs) / 6.)) % 60 pos = self.acsymbol[isymb].get_rect() # Draw aircraft symbol pos.centerx = trafx[i] pos.centery = trafy[i] dy = int(self.fontrad.linedy * 7 / 6) # Draw aircraft altitude line if self.isoalt>1e-7: pg.draw.line(self.win,white,(int(trafx[i]),int(trafy[i])),(int(trafx[i]),int(trafy[i]+bs.traf.alt[i]*self.isoalt))) # Normal symbol if no conflict else amber toosmall=self.lat1-self.lat0>6 #don't draw circles if zoomed out too much if not bs.traf.asas.inconf[i]: self.win.blit(self.acsymbol[isymb], pos) if self.swsep and not toosmall: pg.draw.circle(self.win,green,(int(trafx[i]),int(trafy[i])),pixelrad,1) else: self.win.blit(self.ambacsymbol[isymb], pos) if self.swsep and not toosmall: pg.draw.circle(self.win,amber,(int(trafx[i]),int(trafy[i])),pixelrad,1) # Draw last trail part if bs.traf.trails.active: pg.draw.line(self.win, tuple(bs.traf.trails.accolor[i]), (ltx[i], lty[i]), (trafx[i], trafy[i])) # Label text label = [] if self.swlabel > 0: label.append(bs.traf.id[i]) # Line 1 of label: id else: label.append(" ") if self.swlabel > 1: if bs.traf.alt[i]>bs.traf.translvl: label.append("FL"+str(int(round(bs.traf.alt[i] / (100.*ft))))) # Line 2 of label: altitude else: label.append(str(int(round(bs.traf.alt[i] / ft)))) # Line 2 of label: altitude else: label.append(" ") if self.swlabel > 2: cas = bs.traf.cas[i] / kts label.append(str(int(round(cas)))) # line 3 of label: speed else: label.append(" ") # Check for changes in traffic label text if not (type(bs.traf.label[i])==list) or \ not (type(bs.traf.label[i][3])==str) or \ not (label[:3] == bs.traf.label[i][:3]): bs.traf.label[i] = [] labelbmp = pg.Surface((100, 60), 0, self.win) if not bs.traf.asas.inconf[i]: acfont = self.fontrad else: acfont = self.fontamb acfont.printat(labelbmp, 0, 0, label[0]) acfont.printat(labelbmp, 0, dy, label[1]) acfont.printat(labelbmp, 0, 2 * dy, label[2]) bs.traf.label[i].append(label[0]) bs.traf.label[i].append(label[1]) bs.traf.label[i].append(label[2]) bs.traf.label[i].append(labelbmp) # Blit label dest = bs.traf.label[i][3].get_rect() dest.top = trafy[i] - 5 dest.left = trafx[i] + 15 self.win.blit(bs.traf.label[i][3], dest, None, pg.BLEND_ADD) # Draw aircraft speed vectors if self.swspd: # just a nominal length: a speed of 150 kts will be displayed # as an arrow of 30 pixels long on screen nomlength = 30 nomspeed = 150. vectorlength = float(nomlength)*bs.traf.tas[i]/nomspeed spdvcx = trafx[i] + np.sin(np.radians(bs.traf.trk[i])) * vectorlength spdvcy = trafy[i] - np.cos(np.radians(bs.traf.trk[i])) * vectorlength \ - bs.traf.vs[i]/nomspeed*nomlength*self.isoalt / \ self.dtopix_eq(1e5)*1e5 pg.draw.line(self.win,green,(trafx[i],trafy[i]),(spdvcx,spdvcy)) # ---- End of per aircraft i loop # Draw conflicts: line from a/c to closest point of approach nconf = len(bs.traf.asas.confpairs_unique) n2conf = len(bs.traf.asas.confpairs) if nconf>0: for j in range(n2conf): i = bs.traf.id2idx(bs.traf.asas.confpairs[j][0]) if i>=0 and i<bs.traf.ntraf and (i in trafsel): latcpa, loncpa = geo.kwikpos(bs.traf.lat[i], bs.traf.lon[i], \ bs.traf.trk[i], bs.traf.asas.tcpa[j] * bs.traf.gs[i] / nm) altcpa = bs.traf.lat[i] + bs.traf.vs[i]*bs.traf.asas.tcpa[j] xc, yc = self.ll2xy(latcpa,loncpa) yc = yc - altcpa * self.isoalt pg.draw.line(self.win,amber,(xc,yc),(trafx[i],trafy[i])) # Draw selected route: if self.acidrte != "": i = bs.traf.id2idx(self.acidrte) if i >= 0: for j in range(0,bs.traf.ap.route[i].nwp): if j==0: x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \ bs.traf.ap.route[i].wplon[j]) else: x0,y0 = x1,y1 x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \ bs.traf.ap.route[i].wplon[j]) pg.draw.line(self.win, magenta,(x0,y0),(x1,y1)) if j>=len(self.rtewpid) or not self.rtewpid[j]== bs.traf.ap.route[i].wpname[j]: # Waypoint name labels # If waypoint label bitmap does not yet exist, make it # Waypoint name and constraint(s), if there are any txt = bs.traf.ap.route[i].wpname[j] alt = bs.traf.ap.route[i].wpalt[j] spd = bs.traf.ap.route[i].wpspd[j] if alt>=0. or spd >=0.: # Altitude if alt < 0: txt = txt + " -----/" elif alt > 4500 * ft: FL = int(round((alt/(100.*ft)))) txt = txt+" FL"+str(FL)+"/" else: txt = txt+" "+str(int(round(alt / ft))) + "/" # Speed if spd < 0: txt = txt+"---" else: txt = txt+str(int(round(spd / kts))) wplabel = pg.Surface((128, 32), 0, self.win) self.fontnav.printat(wplabel, 0, 0, \ txt) if j>=len(self.rtewpid): self.rtewpid.append(txt) self.rtewplabel.append(wplabel) else: self.rtewpid[j] = txt self.rtewplabel[j] = wplabel # In any case, blit the waypoint name xtxt = x1 + 7 ytxt = y1 - 3 self.radbmp.blit(self.rtewplabel[j], (xtxt, ytxt), \ None, pg.BLEND_ADD) # Line from aircraft to active waypoint if bs.traf.ap.route[i].iactwp == j: x0,y0 = self.ll2xy(bs.traf.lat[i],bs.traf.lon[i]) pg.draw.line(self.win, magenta,(x0,y0),(x1,y1)) # Draw aircraft trails which are on screen if bs.traf.trails.active: trlsel = list(np.where( self.onradar(bs.traf.trails.lat0, bs.traf.trails.lon0) + \ self.onradar(bs.traf.trails.lat1, bs.traf.trails.lon1))[0]) x0, y0 = self.ll2xy(bs.traf.trails.lat0, bs.traf.trails.lon0) x1, y1 = self.ll2xy(bs.traf.trails.lat1, bs.traf.trails.lon1) for i in trlsel: pg.draw.line(self.win, bs.traf.trails.col[i], \ (x0[i], y0[i]), (x1[i], y1[i])) # Redraw background => buffer ; if >1500 foreground linepieces on screen if len(trlsel) > 1500: self.redrawradbg = True # Draw edit window self.editwin.update() if self.redrawradbg or redrawrad or self.editwin.redraw: self.win.blit(self.menu.bmps[self.menu.ipage], \ (self.menu.x, self.menu.y)) self.win.blit(self.editwin.bmp, (self.editwin.winx, self.editwin.winy)) # Draw frames pg.draw.rect(self.win, white, self.editwin.rect, 1) pg.draw.rect(self.win, white, pg.Rect(1, 1, self.width - 1, self.height - 1), 1) # Add debug line self.fontsys.printat(self.win, 10, 2, str(bs.sim.utc.replace(microsecond=0))) self.fontsys.printat(self.win, 10, 18, tim2txt(bs.sim.simt)) self.fontsys.printat(self.win, 10+80, 2, \ "ntraf = " + str(bs.traf.ntraf)) self.fontsys.printat(self.win, 10+160, 2, \ "Freq=" + str(int(len(bs.sim.dts) / max(0.001, sum(bs.sim.dts))))) self.fontsys.printat(self.win, 10+240, 2, \ "#LOS = " + str(len(bs.traf.asas.lospairs_unique))) self.fontsys.printat(self.win, 10+240, 18, \ "Total LOS = " + str(len(bs.traf.asas.lospairs_all))) self.fontsys.printat(self.win, 10+240, 34, \ "#Con = " + str(len(bs.traf.asas.confpairs_unique))) self.fontsys.printat(self.win, 10+240, 50, \ "Total Con = " + str(len(bs.traf.asas.confpairs_all))) # Frame ready, flip to screen pg.display.flip() # If needed, take a screenshot if self.screenshot: pg.image.save(self.win,self.screenshotname) self.screenshot=False return
def update(self,gain): # Time step update of drain # Get time step dt = sim.simt - self.tupdate self.tupdate = sim.simt # Time for a new aircraft? if dt>0.0: # Calculate probability of a geberate occurring with flow chances = 1.0-gain*self.flow*dt/3600. #flow is in a/c per hour=360 seconds if random.random() >= chances: # Calculate starting position using origin if len(self.orig)>0: # Add origin iorig = int(random.random() * len(self.orig)) else: iorig = -1 if iorig>=0: incirc = self.origincirc[iorig] lat,lon = self.origlat[iorig],self.origlon[iorig] hdg,dist = qdrdist(lat,lon,self.lat,self.lon) else: print("Warning update drain",self.name,"called with no origins present!") hdg = random.random()*360. print("using random segment",int(hdg+180)%360) incirc = False if not incirc: lat,lon = kwikpos(ctrlat,ctrlon,(hdg+180)%360,radius) elif self.origtype=="seg": lat,lon,brg = getseg(self.name) hdg = (brg+180)%360 else: hdg = random.random()*360. if incirc and (self.origtype[iorig]=="apt" or self.origtype[iorig]=="rwy"): alttxt,spdtxt = str(0),str(0) else: if self.startaltmin and self.startaltmax: alt = random.randint(int(self.startaltmin), int(self.startaltmax)) else: alt = random.randint(200,300)*100*ft if self.startspdmin and self.startspdmax: spd = random.randint(int(self.startspdmin), int(self.startspdmax)) else: spd = random.randint(250,350) alttxt,spdtxt = "FL"+str(int(round(alt/(100*ft)))), str(spd) if iorig>=0: acid = randacname(self.orig[iorig], self.name) else: acid = randacname("LFPG", self.name) if len(self.origactypes)>0: actype = random.choice(self.origactypes[iorig]) else: actype = random.choice(self.actypes) stack.stack("CRE " + ",".join([acid,actype,str(lat), str(lon), str(int(hdg%360)),alttxt,spdtxt])) if iorig>=0: if self.orig[iorig][:4]!="SEGM": stack.stack(acid + " ORIG " + self.orig[iorig]) else: stack.stack(acid + " ORIG " + str(self.origlat[iorig]) + " " +\ str(self.origlon[iorig])) if not (self.name[:4]=="SEGM"): stack.stack(acid + " DEST " + self.name) else: stack.stack(acid + " ADDWPT " + str(self.lat) + " " + str(self.lon)) if alttxt=="0" and spdtxt =="0": stack.stack(acid+" SPD 250") stack.stack(acid+" ALT FL100") #stack.stack(acid+" LNAV ON") else: stack.stack(acid + " LNAV ON")
def update(self,gain): # Time step update of source # Get time step dt = sim.simt - self.tupdate self.tupdate = sim.simt # Time for a new aircraft? if dt>0.0: # Calculate probability of a geberate occurring with flow chances = 1.0-gain*self.flow*dt/3600. #flow is in a/c per hour=360 seconds if random.random() >= chances: # Runways defined? => use runway lines (queues) if len(self.runways)>0: # We do not yet need to create an aircraft gennow = False # Find shortest line and put it in isel = random.randint(0,len(self.runways)-1) self.rwyline[isel] = self.rwyline[isel] + 1 else: # Yes we do need to generate one now gennow = True else: gennow = False # Check for generating aircraft # First check runways for a/c already in line: txt = "" for i in range(len(self.runways)): # Runway vacated and there is one waiting? if sim.simt-self.rwytotime[i]>self.dtakeoff and self.rwyline[i]>0: #if self.name == "EHAM": # print(sim.simt, self.runways[i], self.rwytotime[i]) self.rwytotime[i] = sim.simt self.rwyline[i] = self.rwyline[i]-1 # Choose and aicraft type, check for distance if len(self.dest)>0: idest = int(random.random() * len(self.dest)) else: idest = -1 if idest>=0: acid = randacname(self.name,self.dest[idest]) if self.desttype[idest]=="seg" or self.dest[idest][:4]=="SEGM": lat,lon,hdg = getseg(self.dest[idest]) else: success,posobj = txt2pos(self.dest[idest],ctrlat,ctrlon) lat,lon = posobj.lat,posobj.lon distroute = latlondist(self.lat,self.lon,lat,lon)/nm else: acid = randacname(self.name, self.name) if self.destactypes[idest] == []: actype = random.choice(self.actypes) actype = checkactype(actype, distroute, self.actypes) else: actype = random.choice(self.destactypes[idest]) stack.stack("CRE "+",".join([acid, actype, str(self.rwylat[i]),str(self.rwylon[i]),str(self.rwyhdg[i]), "0.0","0.0"])) #wplat,wplon = kwikpos(self.rwylat[i],self.rwylon[i],self.rwyhdg[i],5.0*nm) #stack.stack(acid + " ADDWPT ",wplat," ",wplon) #stack.stack(acid+"LNAV ON") if idest>=0: if self.dest[idest][:4] != "SEGM": stack.stack(acid + " DEST " + self.dest[idest]) else: stack.stack(acid + " DEST " + str(self.destlat[idest]) + " " + str(self.destlon[idest])) if self.name[:4] != "SEGM": stack.stack(acid + " ORIG " + self.name) else: stack.stack(acid + " ORIG " + str(self.lat) + " " + str(self.lon)) stack.stack(acid + " SPD 250") stack.stack(acid + " ALT FL100") stack.stack(acid + " HDG " + str(self.rwyhdg[i])) stack.stack(acid+" LNAV OFF") # Not runway, then define instantly at position with random heading or in case of segment inward heading if gennow: if not self.incircle: lat,lon = kwikpos(ctrlat,ctrlon,self.segdir,radius) hdg = self.segdir-180 elif self.type=="seg": lat,lon,brg = getseg(self.name) hdg = (brg+180)%360 elif self.type=="rwy": lat,lon = self.lat,self.lon hdg = self.hdg # Runway heading else: hdg = random.random()*360. if self.startaltmin and self.startaltmax: alt = random.randint(int(self.startaltmin), int(self.startaltmax)) else: alt = random.randint(200, 300) * 100 * ft if self.startspdmin and self.startspdmax: spd = random.randint(int(self.startspdmin), int(self.startspdmax)) else: spd = random.randint(250, 350) alttxt, spdtxt = "FL" + str(int(round(alt / (100 * ft)))), str(spd) # Add destination if len(self.dest)>0: idest = int(random.random() * len(self.dest)) acid = randacname(self.name,self.dest[idest]) else: acid = randacname(self.name,self.name) idest = -1 stack.stack("CRE " + ",".join([acid, random.choice(self.actypes), str(self.lat), str(self.lon), str(int(hdg%360)), alttxt,spdtxt])) if idest>=0: if self.dest[idest][:4] != "SEGM": stack.stack(acid + " DEST " + self.dest[idest]) else: stack.stack(acid + " DEST " + str(self.destlat[idest])+" "+str(self.destlon[idest])) if self.name[:4] != "SEGM": stack.stack(acid + " ORIG " + self.name) else: stack.stack(acid + " ORIG " + str(self.lat)+" "+str(self.lon)) if alttxt=="0" and spdtxt =="0": stack.stack(acid+" SPD 250") stack.stack(acid+" ALT FL100") else: if idest>=0: if self.desttype[idest] == "seg": lat, lon, hdg = getseg(self.dest[idest]) brg, dist = kwikqdrdist(self.lat, self.lon, lat, lon) stack.stack(acid + " HDG " + str(brg)) else: stack.stack(acid + " LNAV ON")
def update(self,gain): # Time step update of drain # Get time step dt = sim.simt - self.tupdate self.tupdate = sim.simt # Time for a new aircraft? if dt>0.0: # Calculate probability of a geberate occurring with flow chances = 1.0-gain*self.flow*dt/3600. #flow is in a/c per hour=360 seconds if random.random() >= chances: # Calculate starting position using origin if len(self.orig)>0: # Add origin iorig = int(random.random() * len(self.orig)) else: iorig = -1 if iorig>=0: incirc = self.origincirc[iorig] lat,lon = self.origlat[iorig],self.origlon[iorig] hdg,dist = qdrdist(lat,lon,self.lat,self.lon) else: print("Warning update drain",self.name,"called with no origins present!") hdg = random.random()*360. print("using random segment",int(hdg+180)%360) incirc = False if not incirc: lat,lon = kwikpos(ctrlat,ctrlon,(hdg+180)%360,radius) elif self.origtype=="seg": lat,lon,brg = getseg(self.name) hdg = (brg+180)%360 else: hdg = random.random()*360. if incirc and (self.origtype[iorig]=="apt" or self.origtype[iorig]=="rwy"): alttxt,spdtxt = str(0),str(0) else: alttxt,spdtxt = "FL"+str(random.randint(200,300)), str(random.randint(250,350)) if iorig>=0: acid = randacname(self.orig[iorig], self.name) else: acid = randacname("LFPG", self.name) if len(self.origactypes)>0: actype = random.choice(self.origactypes[iorig]) else: actype = random.choice(self.actypes) stack.stack("CRE " + ",".join([acid,actype,str(lat), str(lon), str(int(hdg%360)),alttxt,spdtxt])) if iorig>=0: if self.orig[iorig][:4]!="SEGM": stack.stack(acid + " ORIG " + self.orig[iorig]) else: stack.stack(acid + " ORIG " + str(self.origlat[iorig]) + " " +\ str(self.origlat[iorig])) if not (self.name[:4]=="SEGM"): stack.stack(acid + " DEST " + self.name) else: stack.stack(acid + " ADDWPT " + str(self.lat) + " " + str(self.lon)) if alttxt=="0" and spdtxt =="0": stack.stack(acid+" SPD 250") stack.stack(acid+" ALT FL100") #stack.stack(acid+" LNAV ON") else: stack.stack(acid + " LNAV ON")
def trafgencmd(cmdline): global ctrlat,ctrlon,radius,dtsegment,drains,sources,rwsdep,rwsarr,globalgain cmd,args = splitline(cmdline) #print("TRAFGEN: cmd,args=",cmd,args) if cmd=="CIRCLE" or cmd=="CIRC": # Draw circle try: swcircle = True ctrlat = float(args[0]) ctrlon = float(args[1]) radius = float(args[2]) setcircle(ctrlat, ctrlon, radius) except: return False,'TRAFGEN ERROR while reading CIRCLE command arguments (lat,lon,radius):'+str(args) stack.stack("DEL SPAWN") stack.stack("CIRCLE SPAWN," + str(ctrlat) + "," + str(ctrlon) + "," + str(radius)) elif cmd=="GAIN" or cmd=="FACTOR": # Set global gain on traffic density try: globalgain = float(args[0]) except: return False, "TRAFGEN GAIN error: invalid value "+args[0] elif cmd=="SRC" or cmd == "SOURCE": # Define streams by source, give destinations name = args[0].upper() cmd = args[1].upper() cmdargs = args[2:] if name not in sources: if not name[:4] == "SEGM": success,posobj = txt2pos(name,ctrlat,ctrlon) if success: aptlat, aptlon = posobj.lat, posobj.lon sources[name] = Source(name,cmd,cmdargs) if posobj.type == "rwy" and name.count("/")==1: aptname, rwyname = name.split('/') sources[name].polys += drawrwy(aptname,[rwyname],posobj.lat,posobj.lon,drawdeprwy) else: try: brg = int(name[4:]) aptlat,aptlon = kwikpos(ctrlat,ctrlon,brg,radius) sources[name] = Source(name, cmd, cmdargs) success = True except: success = False else: aptlat,aptlon = sources[name].lat,sources[name].lat success = True if success: if cmd[:6]=="RUNWAY" or cmd=="RWY": sources[name].setrunways(cmdargs) for polyname in sources[name].polys: stack.stack("DEL "+polyname) sources[name].polys += drawrwy(name,cmdargs,aptlat,aptlon,drawdeprwy) elif cmd=="DEST": success = sources[name].adddest(cmdargs) elif cmd=="FLOW": success = sources[name].setflow(cmdargs[0]) elif cmd=="TYPES" or cmd=="TYPE": sources[name].addactypes(cmdargs) elif cmd=="ALT": # Set fixed alt or interval sources[name].setalt(cmdargs) elif cmd=="SPD": sources[name].setspd(cmdargs) elif cmd=="HDG": sources[name].sethdg(cmdargs) if not success: return False, "TRAFGEN SRC ERROR"+cmd+" ".join(cmdargs) else: return False,"TRAFGEN SRC ERROR "+name+" NOT FOUND" elif cmd=="DRN" or cmd=="DRAIN": name = args[0].upper() cmd = args[1].upper() cmdargs = args[2:] if name in drains: aptlat, aptlon = drains[name].lat, drains[name].lat success = True else: # name not in drains: New drain defined if not name[:4]=="SEGM": success, posobj = txt2pos(name, ctrlat, ctrlon) if success: drains[name] = Drain(name, cmd, cmdargs) if posobj.type == "rwy" and name.count("/") == 1: aptname, rwyname = name.split('/') drains[name].polys += drawrwy(aptname, [rwyname], posobj.lat, posobj.lon, drawapprwy) else: try: brg = int(name[:4]) drains[name] = Drain(name, cmd, cmdargs) success = True except: success = False if success: if cmd[:6] == "RUNWAY" or cmd == "RWY": # Delete old runways for polyname in drains[name].polys: stack.stack("DEL "+polyname) aptlat, aptlon = drains[name].lat,drains[name].lon drains[name].setrunways(cmdargs) drains[name].polys += drawrwy(name,cmdargs,aptlat,aptlon,drawapprwy) elif cmd=="ORIG": success = drains[name].addorig(cmdargs) elif cmd=="FLOW": sucess = drains[name].setflow(cmdargs[0]) elif cmd=="TYPES" or cmd=="TYPE": drains[name].addactypes(cmdargs) elif cmd == "ALT": # Set fixed alt or interval drains[name].setalt(cmdargs) elif cmd == "SPD": drains[name].setspd(cmdargs) elif cmd == "HDG": drains[name].sethdg(cmdargs) if not success: return False, "TRAFGEN SRC ERROR"+cmd+" ".join(cmdargs) else: return False, "TRAFGEN DRN ERROR " + name + " NOT FOUND" return True