Example #1
0
 def get_course_towards(self, point):
     '''
     Get the heading of a direct vector towards a given point.
     '''
     assert isinstance(point, Vector3)
     delta = point - self.plane.position
     return U.v3_to_heading(delta)
Example #2
0
 def testVector2Heading(self):
     '''
     v3_to_heading - heading of a vector
     '''
     TOTEST = [((0, 1, -27),    0),
               ((0, -1, +0.57), 180),
               ((1, 1, 0),      45),
               ((-10, 10, 0),   315),
               ]
     for vector, result in TOTEST:
         vector = Vector3(*vector)
         self.assertEqual(U.v3_to_heading(vector), result)
Example #3
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     pl = self.plane
     aspace = pl.aerospace
     r_name = commands['TAKEOFF'][0][0]
     port = aspace.airports[pl.origin]
     runway = port.runways[r_name]
     twin = port.runways[runway['twin']]
     start_point = runway['location'] + port.location
     vector = Vector3(*(-twin['ils']).normalized().xy)
     self.end_of_runway = twin['location'] + port.location
     # SAVE PROCEDURE' PERSISTENT DATA
     h = commands['HEADING'][0][0] if 'HEADING' in commands \
                             else U.v3_to_heading(vector)
     a = commands['ALTITUDE'][0][0] if 'ALTITUDE' in commands \
                             else pl.max_altitude
     self.target_heading = h
     self.target_altitude = a
     self.timer = S.RUNWAY_BUSY_TIME
     # LET'S ROLL!!
     pl.position = start_point.copy()
     aspace.runways_manager.use_runway(port, twin, pl)
     pl.flags.locked = True
     # Give 1 m/s speed and update target to set the heading/sprite icon
     pl.velocity = vector.copy()
     self.pilot.set_target_conf_to_current()
     # Set max acceleration
     self.pilot.target_conf.speed = \
         commands['SPEED'][0][0] if 'SPEED' in commands else pl.max_speed
     self.phase = self.ACCELERATING
     # LOG
     log.info('%s is taking off from %s %s' %
                                 (pl.icao, pl.origin, runway['name']))
     if self._check_expedite(commands):
         self.pilot.status['haste'] = 'expedite'
Example #4
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     pl = self.plane
     pi = self.pilot
     port_name, rnwy_name = commands['LAND'][0]
     self.lander = Lander(self.pilot, port_name, rnwy_name)
     l = self.lander
     # EARLY RETURN - Maximum incidence angle into the ILS is 60°
     ils_heading = U.v3_to_heading(l.ils)
     boundaries = [(ils_heading - S.ILS_TOLERANCE)%360,
                   (ils_heading + S.ILS_TOLERANCE)%360]
     if not U.heading_in_between(boundaries, pl.heading):
         msg = 'ILS heading must be within %s degrees ' \
               'from current heading' % S.ILS_TOLERANCE
         return self._abort_landing(msg)
     # EARLY RETURN - No possible intersection (the RADAR_RANGE*3
     # ensures that the segments to test for intersection are long enough.
     if not l.set_intersection_point():
         msg = 'The ILS does not intersect the plane current heading'
         return self._abort_landing(msg)
     # EARLY RETURN - Although the intersection is ahead of the plane,
     # it's too late to merge into the ILS vector
     type_ = pi.status['haste']
     if l.set_merge_point(pi.navigator.get_veering_radius(type_)) < 0:
         msg = 'We are too close to the ILS to merge into it'
         return self._abort_landing(msg)
     # LANDING IS NOT EXCLUDED A PRIORI...
     log.info('%s started landing procedure, destination: %s %s' %
                             (self.plane.icao, port_name, rnwy_name))
     # SETTING PERSISTENT DATA
     if self._check_expedite(commands):
         pi.status['haste'] = 'expedite'
     self.phase = self.INTERCEPTING
     self.lander = l
Example #5
0
 def set_merge_point(self, radius):
     '''
     Set and return self.mp, the 2D point where the plane should begin
     merging into the ILS vector.
     '''
     # From the geometrical construction it is possible to observe that the
     # correct distance from the intersection point with a course for
     # merging into it is the cathetus of a triangle whose other cathetus is
     # the veering radius and whose adiacent angle is (180°-head_diff)/2, in
     # which head_diff is the difference between the current heading and the
     # target one. Since tan(angle) = opposite/adjacent the we solve for
     # adjacent with = adjacent = opposite/tan(angle)
     h1 = self.plane.heading
     h2 = U.v3_to_heading(self.ils)
     a1 = abs((h1-h2)%360)
     a2 = abs((h2-h1)%360)
     angle = min(a1, a2)
     angle = radians((180 - angle) / 2.0)
     dist_from_ip = radius/tan(angle)
     dist_from_plane = abs(self.ip-self.plane.position)-dist_from_ip
     self.mp = self.pilot.navigator.get_point_ahead(dist_from_plane)
     if self.pilot.navigator.check_overshot(self.mp) == True:
         self.mp = None
     return self.mp
Example #6
0
 def heading(self):
     '''Current heading [CW degrees from North]'''
     return U.v3_to_heading(self.velocity)