def __init__(self, parent=None): QWidget.__init__(self, parent) self.setupUi(self) if env.airport_data != None: self.runway_select.addItems( [r.name for r in env.airport_data.allRunways(sortByName=True)]) self.setEnabled(False) self.target_acft = None self.tracker = TelnetSessionThreader( self, self.lookAtTargetAircraft_commands, loopInterval=tracker_interval) signals.towerViewProcessToggled.connect(self.setEnabled) signals.towerViewProcessToggled.connect(self.tracker.stop) signals.sessionEnded.connect(self.tracker.stop) signals.mainWindowClosing.connect(self.tracker.stop) self.lookAtAircraft_OK_button.clicked.connect( self.lookAtSelectedAircraft) self.lookAtRunway_OK_button.clicked.connect(self.lookAtRunway) self.lookNorth_button.clicked.connect( lambda: self.lookInDirection(Heading(360, true_panel_directions))) self.lookSouth_button.clicked.connect( lambda: self.lookInDirection(Heading(180, true_panel_directions))) self.lookEast_button.clicked.connect( lambda: self.lookInDirection(Heading(90, true_panel_directions))) self.lookWest_button.clicked.connect( lambda: self.lookInDirection(Heading(270, true_panel_directions))) self.useBinoculars_button.clicked.connect(lambda: self.setFOV( initial_FOV / self.binocularsFactor_edit.value())) self.dropBinoculars_button.clicked.connect( lambda: self.setFOV(initial_FOV))
def windVariability(self): ''' returns wind variability (Heading, Heading) if present, None otherwise ''' match = wind_hdgvrb_regexp.search(self.METAR_string) if match: return Heading(int(match.group(1)), False), Heading(int(match.group(2)), False) return None
def spawnNewUncontrolledAircraft(self): rndpos = env.radarPos().moved(Heading(randint(1, 360), True), uniform(10, .8 * settings.radar_range)) rndalt = StdPressureAlt(randint(1, 10) * 1000) if self.airbornePositionFullySeparated(rndpos, rndalt): acft_type = choice(self.uncontrolled_aircraft_types) params = SoloParams(Status(Status.AIRBORNE), rndpos, rndalt, Heading(randint(1, 360), True), cruise_speed(acft_type)) params.XPDR_code = settings.uncontrolled_VFR_XPDR_code new_acft = self.mkAiAcft(acft_type, params, goal=None) if new_acft != None: self.uncontrolled_traffic.append(new_acft)
def mainWind(self): ''' Returns a (heading, speed, gusts, unit) tuple, where: - heading & speed values are: - None, 0: wind is calm - None, int: wind is VRB - Heading, int: wind has dominant direction - and: - gusts is None or int speed - unit is either 'kt' or 'm/s', following that used in the METAR ''' match = wind_regexp.search(self.METAR_string) if match: if match.group('gusts') == None: gusts = None else: gusts = int(match.group('gusts')) unit = {'KT': 'kt', 'MPS': 'm/s'}[match.group('unit')] if match.group('speed_vrb') == None: # got dominant direction wind_speed = int(match.group('speed_nrm')) return (Heading(int(match.group('hdg')), True) if wind_speed != 0 else None), wind_speed, gusts, unit else: # wind is VRB return None, int(match.group('speed_vrb')), gusts, unit return None
def str2detail(dstr, vstr): try: d = int( dstr ) # CAUTION this assumes there is no str detail key that looks like an int except ValueError: d = dstr if d in [FPL.CALLSIGN, FPL.ACFT_TYPE, FPL.WTC, FPL.ICAO_DEP, FPL.ICAO_ARR, FPL.ICAO_ALT, \ FPL.CRUISE_ALT, FPL.ROUTE, FPL.COMMENTS, FPL.FLIGHT_RULES, assigned_altitude_detail]: # str v = vstr elif d in [FPL.SOULS, assigned_SQ_detail]: # int v = int(vstr) elif d in [FPL.TAS, assigned_speed_detail]: # Speed v = Speed(int(vstr)) elif d == FPL.TIME_OF_DEP: # datetime year, month, day, hour, minute = vstr.split() v = datetime(year=int(year), month=int(month), day=int(day), hour=int(hour), minute=int(minute), tzinfo=timezone.utc) elif d == FPL.EET: # timedelta v = timedelta(seconds=int(vstr)) elif d == assigned_heading_detail: # Heading v = Heading(int(vstr), False) else: raise ValueError('Unknown key for detail conversion: %s' % dstr) return d, v
def headingTo(self, other): ''' this gives the heading of route from self to other, using cartesian approx. of both radar coords ''' dx = other.x() - self.x() dy = other.y() - self.y() theta = atan2(dx, dy) return Heading(degrees(pi - theta), True)
def start(self, traffic_count): # overrides (but calls) parent's p = lambda d: env.radarPos().moved(Heading(d, True), 1.5 * settings. map_range) env.ATCs.updateATC('N', p(360), 'North', None) env.ATCs.updateATC('S', p(180), 'South', None) env.ATCs.updateATC('E', p(90), 'East', None) env.ATCs.updateATC('W', p(270), 'West', None) SoloSessionManager.start(self, traffic_count)
def get_airport_data(icao): result = AirportData() result.navpoint = world_navpoint_db.findAirfield(icao) # START WITH SIMPLE ONE-LINERS with open_airport_file(icao) as f: for line in f: row_type = line_code(line) if is_xplane_airport_header(line): # HEADER LINE; get elevation tokens = line.split(maxsplit=2) result.field_elevation = float(tokens[1]) elif row_type == 100: # RUNWAY tokens = line.split() width = float(tokens[1]) surface = int(tokens[2]) name, lat, lon, disp_thr = tokens[8:12] rwy1 = DirRunway(name, EarthCoords(float(lat), float(lon)), float(disp_thr)) name, lat, lon, disp_thr = tokens[17:21] rwy2 = DirRunway(name, EarthCoords(float(lat), float(lon)), float(disp_thr)) result.addPhysicalRunway(width, surface, rwy1, rwy2) elif row_type == 102: # HELIPAD tokens = line.split() row_code, name, lat, lon, ori, l, w, surface = tokens[:8] centre = EarthCoords(float(lat), float(lon)) result.helipads.append( Helipad(name, centre, int(surface), float(l), float(w), Heading(float(ori), True))) elif row_type == 14: # VIEWPOINT (NOTE: ATC-pie allows for more than one, though X-plane specifies one or zero) row_code, lat, lon, height, ignore, name = line.split( maxsplit=5) result.viewpoints.append( (EarthCoords(float(lat), float(lon)), float(height), name.strip())) elif row_type == 19: # WINDSOCK row_code, lat, lon, ignore_rest_of_line = line.split( maxsplit=3) result.windsocks.append(EarthCoords(float(lat), float(lon))) elif row_type == 1302: # METADATA RECORD tokens = line.split() if len(tokens) == 3 and tokens[1] == 'transition_alt': result.transition_altitude = int(tokens[2]) # NOW COMPLEX MULTI-LINE READS result.ground_net = get_ground_network(icao) return result
def headingTo(self, other): ''' this gives the initial heading of route from self to other that follows the shortest path (on great circle, i.e. as the crow flies) ''' lat1 = radians(self.lat) lat2 = radians(other.lat) dlon = radians(other.lon - self.lon) theta = atan2( sin(dlon) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)) return Heading(degrees(theta), True)
def import_ILS_capabilities(airport_data): with open_data_file_fallback(custom_navaid_file, fallback_navaid_file) as f: for line in f: # all lines with ILS codes [4..9] have similar structure: tokens = line.split(maxsplit=10) if not (len(tokens) == 11 and tokens[0] in '456789'): continue row_code, lat, lon, elev, frq, rng, qdm, ignore, ad, rwy, last_to_strip = tokens if ad == airport_data.navpoint.code: try: drwy = airport_data.runway(rwy) coords = EarthCoords(float(lat), float(lon)) except KeyError: # unknown RWY print('Unknown RWY %s or bad LOC spec' % rwy) else: # we are interested in the line spec if row_code in ['4', '5']: # LOC drwy.ILS_cat = last_to_strip.strip() drwy.LOC_freq = '%s.%s' % (frq[:3], frq[3:]) drwy.LOC_bearing = Heading(float(qdm), True) drwy.LOC_range = drwy.threshold(dthr=True).distanceTo( coords.moved(drwy.LOC_bearing.opposite(), float(rng))) elif row_code == '6': # GS (angle prefixes the bearing) try: iqdm = qdm.index('.') - 3 except ValueError: iqdm = len(qdm) - 3 fpa_degrees = int(qdm[:iqdm]) / 100 drwy.param_FPA = 100 * tan(radians(fpa_degrees)) drwy.GS_range = drwy.threshold(dthr=True).distanceTo( coords.moved( Heading(float(qdm[iqdm:]), True).opposite(), float(rng))) elif row_code == '7': # OM drwy.OM_pos = coords elif row_code == '8': # MM drwy.MM_pos = coords elif row_code == '9': # IM drwy.IM_pos = coords
def open_ad_positions_file(): try: return open(custom_ad_pos_file, encoding='utf8') except FileNotFoundError: # No custom airfield position file found; fall back on extracted X-plane inventory. try: return open(extracted_ad_pos_file, encoding='utf8') except FileNotFoundError: # Airport positions not extracted yet; build file from packaged X-plane world file. with open(fallback_world_apt_dat_file, encoding='iso-8859-15' ) as f: # WARNING: X-plane data encoded in ISO-8859-15 with open(extracted_ad_pos_file, 'w', encoding='utf8') as exf: line = f.readline() ad_count = 0 while line != '': # not EOF if is_xplane_airport_header(line): row_code, ignore1, ignore2, ignore3, icao_code, long_name = line.split( maxsplit=5) if icao_code.isalpha( ): # Ignoring airports with numbers in them---to many of them, hardly ever useful # we are inside the airport section looking for its coordinates coords = None line = f.readline() while line != '' and not is_xplane_airport_header( line): if line_code( line ) == 14: # X-plane viewpoint, unconditionally used as coords row_code, lat, lon, ignore_rest_of_line = line.split( maxsplit=3) coords = EarthCoords( float(lat), float(lon)) elif coords == None and line_code( line ) == 100: # falls back near a RWY end if no viewpoint for AD tokens = line.split() coords = EarthCoords( float(tokens[9]), float(tokens[10])).moved( Heading(360, True), .15) line = f.readline() if coords != None: # Airfields with unknown world coordinates are ignored exf.write('%s %s %s\n' % (icao_code, coords.toString(), long_name.strip())) ad_count += 1 else: line = f.readline() else: line = f.readline() # Terminate with the footer to mark a finished process exf.write('%d\n' % ad_count) # Now file should exist return open(extracted_ad_pos_file, encoding='utf8')
def new_arrival_APP(self, entry_point): type_choice = self.parkable_aircraft_types if self.parkable_aircraft_types != [] else self.playable_aircraft_types # must be landable too rwy_choice = [ rwy for rwy in env.airport_data.allRunways() if rwy.use_for_arrivals ] if rwy_choice == []: rwy_choice = env.airport_data.allRunways() pop_all( type_choice, lambda t: all(not rwy.acceptsAcftType(t) for rwy in rwy_choice)) if type_choice == []: return None acft_type = choice(type_choice) ils = any(rwy.hasILS() for rwy in rwy_choice) and random() >= settings.solo_ILSvsVisual_balance if entry_point == None: hdg = Heading(randint(1, 360), True) pos = env.radarPos().moved( hdg.opposite(), uniform(.33 * settings.radar_range, .75 * settings.radar_range)) else: pos = entry_point.coordinates hdg = pos.headingTo(env.radarPos()) alt = StdPressureAlt.fromFL( 10 * randint(settings.solo_APP_ceiling_FL_min // 10, settings.solo_APP_ceiling_FL_max // 10)) if not self.airbornePositionFullySeparated(pos, alt): return None ias = restrict_speed_under_ceiling( cruise_speed(acft_type), alt, StdPressureAlt.fromFL(150)) # 5000-ft anticipation params = SoloParams(Status(Status.AIRBORNE), pos, alt, hdg, ias) params.XPDR_code = env.nextSquawkCodeAssignment(XPDR_range_IFR_ARR) return self.mkAiAcft(acft_type, params, ils)
def get_ground_network(icao): with open_airport_file(icao) as f: ground_net = GroundNetwork() source_edges = [ ] # GroundNetwork pretty labelling breaks if we add duplicate edges line = f.readline() line_number = 1 while line != '': # not EOF if line_code(line) == 1201: # TWY node tokens = line.strip().split(maxsplit=5) lat, lon, ignore, nid = tokens[1:5] ground_net.addNode(nid, EarthCoords(float(lat), float(lon))) elif line_code(line) == 1202: # TWY edge tokens = line.strip().split(maxsplit=5) v1, v2 = tokens[1:3] twy_name = rwy_spec = None if len(tokens) == 6: if tokens[4] == 'runway': rwy_spec = tokens[5].rstrip() elif tokens[4].startswith( 'taxiway' ): # can be suffixed with "_X" to specify wing span twy_name = tokens[5].rstrip() if {v1, v2} in source_edges: print( 'WARNING: Ignoring duplicate ground route edge (%s, %s) in airport data file.' % (v1, v2)) else: source_edges.append({v1, v2}) try: ground_net.addEdge(v1, v2, rwy_spec, twy_name) except KeyError: print('Line %d: Invalid node for taxiway edge spec' % line_number) elif line_code(line) == 1300: # parking_position tokens = line.strip().split(maxsplit=6) if len(tokens) == 7: lat, lon, hdg, typ, who, pkid = tokens[1:7] if typ in ['gate', 'hangar', 'tie-down']: pos = EarthCoords(float(lat), float(lon)) cats = [] if who == 'all' else who.split('|') ground_net.addParkingPosition( pkid, pos, Heading(float(hdg), True), typ, cats) else: print('Line %d: Invalid parking position spec' % line_number) line = f.readline() # for new loop (more TWYs) line_number += 1 return ground_net
def rnd_rwy(choose_from, condition): ''' Picks a runway from the first arg list (or any by wind if empty), satisfying the given condition. ''' if choose_from == []: # Choose any from current wind w = env.primaryWeather() main_wind = w.mainWind() if w != None else None main_wind_hdg = main_wind[0] if main_wind != None else Heading( 360, True) choose_from = [ rwy for rwy in env.airport_data.allRunways() if abs(main_wind_hdg.diff(rwy.orientation())) <= 90 ] choose_from = [rwy for rwy in choose_from if condition(rwy)] return None if choose_from == [] else choice(choose_from)
def saveChangesAndClose(self): SharedDetailSheet.saveChangesAndClose(self) ## Assigned stuff # Squawk code if self.assignSquawkCode.isChecked(): self.set_detail(assigned_SQ_detail, self.xpdrCode_select.getSQ()) else: self.set_detail(assigned_SQ_detail, None) # Heading if self.assignHeading.isChecked(): self.set_detail(assigned_heading_detail, Heading(self.assignedHeading_edit.value(), False)) else: self.set_detail(assigned_heading_detail, None) # Altitude/FL if self.assignAltitude.isChecked(): reading = self.assignedAltitude_edit.text() try: # try reformating self.set_detail(assigned_altitude_detail, StdPressureAlt.reformatReading(reading)) except ValueError: self.set_detail(assigned_altitude_detail, reading) else: self.set_detail(assigned_altitude_detail, None) # Speed if self.assignSpeed.isChecked(): self.set_detail(assigned_speed_detail, Speed(self.assignedSpeed_edit.value())) else: self.set_detail(assigned_speed_detail, None) # DONE with details if self.strip.linkedFPL() == None: if self.linkFPL_tickBox.isChecked(): if self.FPL_link_on_save == None: signals.newLinkedFPLrequest.emit(self.strip) else: self.strip.linkFPL(self.FPL_link_on_save) else: # a flight plan is already linked if self.pushToFPL_tickBox.isChecked(): self.strip.pushToFPL() self.accept()
def read_point_spec(specstr, db): mvlst = specstr.split('>') pbase = mvlst.pop(0) try: if ',' in pbase and '~' not in pbase: result = EarthCoords.fromString(pbase) else: result = navpointFromSpec(pbase, db).coordinates except NavpointError: raise ValueError( 'No navpoint for "%s" or navpoint not unique (consider using `~\' operator)' % pbase) else: while mvlst != []: mv = mvlst.pop(0).split(',') if len(mv) == 2: radial = Heading(float(mv[0]), True) distance = float(mv[1]) result = result.moved(radial, distance) else: raise ValueError('Bad use of `>\' in point spec "%s"' % specstr) return result
def interpret_string(string): tokens = string.split() named_runways = pop_named_runways(tokens) rwy_to_expect = ' '.join(named_runways) ## Callsign recognition ialnum, alnumtk = find_tokens(is_alphanum_token, tokens, 0, False) addressee_tokens = [] for i in range(ialnum + len(alnumtk)): addressee_tokens.append(tokens.pop(0)) ## Instruction list recognised_instructions = [] # Instruction.CANCEL_APP try: try: i = tokens.index('go-around') j = i + 1 except ValueError: i = tokens.index('cancel') # cf. "cancel approach" j = i + 2 except ValueError: pass else: SR_log('RECOGNISED: cancel app', tokens) recognised_instructions.append( Instruction(Instruction.CANCEL_APP, voiceData={})) del tokens[i:j] # Instruction.EXPECT_RWY try: i = tokens.index('expect') except ValueError: pass else: # 'j' below is last index to remove once instr is recognised; runway tokens are already removed j_max = min(len(tokens), i + 3) j = next((j for j in range(i + 1, j_max) if tokens[j] not in ['ils', 'visual', 'approach']), j_max) app = next((b for t, b in [('ils', True), ('visual', False)] if t in tokens[i + 1:j + 1]), None) SR_log('RECOGNISED: rwy/app', rwy_to_expect, app, tokens) recognised_instructions.append( Instruction(Instruction.EXPECT_RWY, arg=rwy_to_expect, voiceData={'app': app})) del tokens[i:j + 1] # Instruction.VECTOR_HDG try: try: i = tokens.index('turn') except ValueError: i = tokens.index('heading') except ValueError: pass else: try: ni, ntk = find_num_tokens(tokens, i + 1) hdg = convert_num_tokens(ntk) except ValueError as err: SR_log('Please report bug with heading instruction: %s' % err, tokens) else: SR_log('RECOGNISED: hdg', hdg, tokens) recognised_instructions.append( Instruction(Instruction.VECTOR_HDG, arg=Heading(hdg, False), voiceData={})) del tokens[i:ni + len(ntk)] # Instruction.VECTOR_ALT try: ifl = tokens.index('flight-level') # "flight level" except ValueError: # try altitude th = hu = None try: ith = tokens.index('thousand') nith, thtk = find_num_tokens(tokens, ith - 1, bwd=True) del tokens[nith:ith + 1] SR_log('Tokens left after "thousand":', tokens) th = convert_num_tokens(thtk) # STYLE catch a fail here? except ValueError: pass try: ihu = tokens.index('hundred') nihu, hutk = find_num_tokens(tokens, ihu - 1, bwd=True) del tokens[nihu:ihu + 1] SR_log('Tokens left after "hundred":', tokens) hu = convert_num_tokens(hutk) # STYLE catch a fail here? except ValueError: pass if th != None or hu != None: # got altitude alt = 1000 * some(th, 0) + 100 * some(hu, 0) SR_log('RECOGNISED: alt', alt) recognised_instructions.append( Instruction(Instruction.VECTOR_ALT, arg=('%d ft' % alt), voiceData={})) else: # got FL try: nifl, fltk = find_num_tokens(tokens, ifl + 1) fl = convert_num_tokens(fltk) except ValueError as err: SR_log('Please report bug with FL instruction: %s' % err, tokens) else: SR_log('RECOGNISED: FL', fl, tokens) recognised_instructions.append( Instruction(Instruction.VECTOR_ALT, arg=('FL%03d' % fl), voiceData={})) del tokens[ifl:nifl + len(fltk)] # Instruction.VECTOR_SPD try: i = tokens.index('speed') except ValueError: pass else: if tokens[i + 1:i + 3] == ['your', 'discretion']: SR_log('RECOGNISED: cancel spd') recognised_instructions.append( Instruction(Instruction.CANCEL_VECTOR_SPD, voiceData={})) del tokens[i:i + 3] else: try: ni, ntk = find_num_tokens(tokens, i + 1) spd = convert_num_tokens(ntk) except ValueError as err: SR_log('Please report bug with speed instruction: %s' % err, tokens) else: SR_log('RECOGNISED: spd', spd, tokens) recognised_instructions.append( Instruction(Instruction.VECTOR_SPD, arg=Speed(spd), voiceData={})) del tokens[i:ni + len(ntk)] # Instruction.SQUAWK try: i = tokens.index('squawk') except ValueError: pass else: sq = [digit_tokens[tokens[k]] for k in range(i + 1, i + 5)] sq_code = 8 * 8 * 8 * sq[0] + 8 * 8 * sq[1] + 8 * sq[2] + sq[3] SR_log('RECOGNISED: sq', sq_code, tokens) recognised_instructions.append( Instruction(Instruction.SQUAWK, arg=sq_code, voiceData={})) del tokens[i:i + 5] # Instruction.HAND_OVER try: i = tokens.index('contact') except ValueError: pass else: try: atc = atc_tokens[tokens[i + 1]] except (KeyError, IndexError) as err: SR_log('Please report bug with h/o instruction: %s' % err, tokens) else: SR_log('RECOGNISED: handover', tokens) recognised_instructions.append( Instruction(Instruction.HAND_OVER, arg=(atc, None), voiceData={})) del tokens[i:i + 2] # Instruction.INTERCEPT_LOC try: iloc = tokens.index('localiser') i, tk = find_tokens('intercept'.__eq__, tokens, iloc - 1, True) except ValueError: pass else: SR_log('RECOGNISED: loc', tokens) recognised_instructions.append( Instruction(Instruction.INTERCEPT_LOC, voiceData={'rwy': rwy_to_expect})) del tokens[i:iloc + 1] # Instruction.CLEARED_APP try: try: iapp = tokens.index( 'approach' ) # WARNING "approach" also appears in CANCEL_APP, EXPECT_RWY and HAND_OVER, but should be removed by now except ValueError: iapp = tokens.index( 'ils' ) # WARNING "ils" also appears in EXPECT_RWY, but should be removed by now i, tk1_ignore = find_tokens('cleared'.__eq__, tokens, iapp - 1, True) except ValueError: pass else: app = next((b for t, b in [('ils', True), ('visual', False)] if t in tokens[i + 1:iapp + 1]), None) SR_log('RECOGNISED: app', app, tokens) recognised_instructions.append( Instruction(Instruction.CLEARED_APP, voiceData={ 'rwy': rwy_to_expect, 'app': app })) del tokens[i:iapp + 1] # Instruction.LINE_UP try: i = tokens.index('wait') except ValueError: pass else: SR_log('RECOGNISED: luw', tokens) recognised_instructions.append( Instruction(Instruction.LINE_UP, voiceData={'rwy': rwy_to_expect})) del tokens[i - 2:i + 1] # Instruction.CLEARED_TKOF try: i = tokens.index('take-off') except ValueError: pass else: SR_log('RECOGNISED: cto', tokens) recognised_instructions.append( Instruction(Instruction.CLEARED_TKOF, voiceData={'rwy': rwy_to_expect})) del tokens[i - 2:i + 1] # Instruction.CLEARED_TO_LAND try: i = tokens.index('land') except ValueError: pass else: SR_log('RECOGNISED: ctl', tokens) recognised_instructions.append( Instruction(Instruction.CLEARED_TO_LAND, voiceData={'rwy': rwy_to_expect})) del tokens[i - 2:i + 1] # Instruction.SAY_INTENTIONS try: i = tokens.index('intentions') except ValueError: pass else: SR_log('RECOGNISED: intentions?', tokens) recognised_instructions.append( Instruction(Instruction.SAY_INTENTIONS, voiceData={})) del tokens[i - 1:i + 1] # Instruction.VECTOR_DCT try: i = tokens.index('proceed') except ValueError: pass else: try: pi, ptk = find_tokens(is_navpoint_token, tokens, i + 1, False) point = convert_navpoint_tokens(ptk) except ValueError as err: SR_log('Please report bug with DCT instruction: %s' % err, tokens) else: SR_log('RECOGNISED: dct', point, tokens) recognised_instructions.append( Instruction(Instruction.VECTOR_DCT, arg=point, voiceData={})) del tokens[i:pi + len(ptk)] # Instruction.HOLD, Instruction.HOLD_POSITION try: i = tokens.index('hold') except ValueError: pass else: if i + 1 < len(tokens) and tokens[i + 1] == 'position': SR_log('RECOGNISED: hold-position', tokens) recognised_instructions.append( Instruction(Instruction.HOLD_POSITION, voiceData={})) del tokens[i:i + 2] else: try: pi, ptk = find_tokens(is_navpoint_token, tokens, i + 1, False) point = convert_navpoint_tokens(ptk) except ValueError as err: SR_log('Please report bug with hold instruction: %s' % err, tokens) else: j = pi + len(ptk) if j < len(tokens) and tokens[j] in ['left', 'right']: turns = tokens[j] == 'right' j += 2 else: turns = True SR_log('RECOGNISED: hold', point, tokens) recognised_instructions.append( Instruction(Instruction.HOLD, arg=(point, turns), voiceData={})) del tokens[i:j] return addressee_tokens, recognised_instructions
def sendInstruction_interceptNav(self): heading = Heading(self.intercept_heading_edit.value(), False) self.sendInstruction(Instruction(Instruction.INTERCEPT_NAV, arg=(self.navpoint_edit.text(), heading)))
def generateAircraftAndStrip(self): start_angle = uniform(0, 360) start_pos = env.radarPos().moved(Heading(start_angle, True), settings.solo_CTR_range_dist) end_pos = env.radarPos().moved( Heading(start_angle + 90 + uniform(1, 179), True), settings.solo_CTR_range_dist) transit_hdg = start_pos.headingTo(end_pos) dep_ad = world_navpoint_db.findClosest(env.radarPos().moved(transit_hdg.opposite(), \ uniform(1.2 * settings.map_range, 5000)), types=[Navpoint.AD]) dest_ad = world_navpoint_db.findClosest(env.radarPos().moved(transit_hdg, \ uniform(1.2 * settings.map_range, 5000)), types=[Navpoint.AD]) if env.pointOnMap(dep_ad.coordinates) or env.pointOnMap( dest_ad.coordinates): return None, None candidate_midpoints = [p for code in settings.solo_CTR_routing_points \ for p in env.navpoints.findAll(code, types=[Navpoint.NDB, Navpoint.VOR, Navpoint.FIX]) \ if start_pos.distanceTo(p.coordinates) < start_pos.distanceTo(end_pos)] midpoint = None if candidate_midpoints == [] else choice( candidate_midpoints) FLd10 = randint(settings.solo_CTR_floor_FL // 10, settings.solo_CTR_ceiling_FL // 10) if settings.solo_CTR_semi_circular_rule == SemiCircRule.E_W and (FLd10 % 2 == 0) != (transit_hdg.magneticAngle() >= 180) \ or settings.solo_CTR_semi_circular_rule == SemiCircRule.N_S and (FLd10 % 2 == 1) != (90 <= transit_hdg.magneticAngle() < 270): FLd10 += 1 if 10 * FLd10 > settings.solo_CTR_ceiling_FL: return None, None p_alt = StdPressureAlt.fromFL(10 * FLd10) if not self.airbornePositionFullySeparated(start_pos, p_alt): return None, None acft_type = choice(self.playable_aircraft_types) hdg = start_pos.headingTo(some(midpoint, dest_ad).coordinates) params = SoloParams(Status(Status.AIRBORNE), start_pos, p_alt, hdg, cruise_speed(acft_type)) params.XPDR_code = env.nextSquawkCodeAssignment(XPDR_range_IFR_transit) new_acft = self.mkAiAcft(acft_type, params, dest_ad) dist_key = lambda atc: env.ATCs.getATC(atc).position.distanceTo( start_pos) received_from = min(env.ATCs.knownATCs(), key=dist_key) strip = Strip() strip.writeDetail(FPL.CALLSIGN, new_acft.identifier) strip.writeDetail(FPL.ACFT_TYPE, new_acft.aircraft_type) strip.writeDetail(FPL.WTC, wake_turb_cat(new_acft.aircraft_type)) strip.writeDetail(FPL.FLIGHT_RULES, 'IFR') strip.writeDetail(FPL.ICAO_DEP, dep_ad.code) strip.writeDetail(FPL.ICAO_ARR, dest_ad.code) strip.writeDetail(FPL.CRUISE_ALT, env.readStdAlt(new_acft.params.altitude)) strip.writeDetail(assigned_altitude_detail, strip.lookup(FPL.CRUISE_ALT)) strip.writeDetail(assigned_SQ_detail, new_acft.params.XPDR_code) strip.writeDetail(received_from_detail, received_from) if midpoint != None: strip.insertRouteWaypoint(midpoint) new_acft.instructions.append( Instruction(Instruction.FOLLOW_ROUTE, arg=strip.lookup(parsed_route_detail).dup())) return new_acft, strip