def testHeadingLongFlag(self): ''' Test that the plane execute veering in the right direction. ''' self.plane.velocity = U.heading_to_v3(90).normalized() * 300 / 3.6 self.pilot.do([('HEADING', [180], ['LONG'])]) self.plane.update(5) self.assertFalse(U.heading_in_between([90,180], self.plane.heading))
def __get_crossed_gates(self, plane): ''' Return the list of gates (if any) that a given point of the edge on the aerospace corresponds to. ''' crossed = [] origin = Vector3(S.RADAR_RANGE, S.RADAR_RANGE) point = Vector3(*plane.position.xy) for gate in self.gates.values(): vector = U.heading_to_v3(gate.radial) dist = U.distance_point_line(point, origin, vector) boundaries = ((plane.heading - S.GATE_TOLERANCE) % 360, (plane.heading + S.GATE_TOLERANCE) % 360) if dist <= gate.width / 2 and \ U.heading_in_between(boundaries, gate.radial) and \ gate.bottom <= plane.altitude <= gate.top: crossed.append(gate) return crossed
def _dampen(self, previous_conf): ''' Prevent the aeroplane to "overshoot" its target configuration. ''' pl = self.plane p_alt = previous_conf['altitude'] p_head = previous_conf['heading'] p_speed = previous_conf['speed'] # Heading dampener (act on velocity vector) t_head = self.target_conf.heading if U.heading_in_between((p_head, pl.heading), t_head): mag = abs(Vector2(*pl.velocity.xy)) theta = radians(90-t_head) pl.velocity.x = cos(theta)*mag pl.velocity.y = sin(theta)*mag self.target_conf.heading = pl.heading #Fixes decimal approx. # Speed dampener (act on velocity vector) t_speed = self.target_conf.speed if U.in_between((p_speed, pl.speed), t_speed) and pl.fuel: mag = t_speed # this is ground speed, so we want to normalise that without # affecting the z component... saved_z = pl.velocity.z pl.velocity = Vector3(*pl.velocity.xy).normalized() * t_speed pl.velocity.z = saved_z self.target_conf.speed = pl.speed #Fixes decimal approx. # Update onboard instruments, as the following dampener will modify # the data they would access pl.update_instruments() # Altitude dampener (act on position vector) t_alt = self.target_conf.altitude if U.in_between((p_alt, pl.altitude), t_alt) and pl.fuel: pl.position.z = t_alt pl.velocity.z = 0 # Actions to be performed if all orders have been executed if self.target_conf.is_reached() and not self.status['procedure']: pl.flags.busy = False self.order_being_processed = '' self._reset_status()
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
def testHeadingInBetween(self): ''' U.heading_in_between - heading in the shortest arc between other two ''' # Normalised values self.assertTrue(U.heading_in_between((0, 90), 45)) self.assertTrue(U.heading_in_between((350, 10), 5)) self.assertTrue(U.heading_in_between((10, 350), 5)) self.assertTrue(U.heading_in_between((350, 10), -5)) self.assertTrue(U.heading_in_between((10, 350), -5)) self.assertFalse(U.heading_in_between((270, 0), 45)) # Non-normalised values self.assertTrue(U.heading_in_between((-60, 60), -1)) self.assertTrue(U.heading_in_between((-60, 60), -0)) self.assertTrue(U.heading_in_between((-60, 60), 1)) self.assertTrue(U.heading_in_between((60, -60), -1)) self.assertTrue(U.heading_in_between((60, -60), -0)) self.assertTrue(U.heading_in_between((60, -60), 1)) self.assertFalse(U.heading_in_between((-60, 60), -179)) self.assertFalse(U.heading_in_between((-60, 60), -180)) self.assertFalse(U.heading_in_between((-60, 60), 180)) self.assertFalse(U.heading_in_between((-60, 60), 179)) self.assertFalse(U.heading_in_between((60, -60), -179)) self.assertFalse(U.heading_in_between((60, -60), -180)) self.assertFalse(U.heading_in_between((60, -60), 180)) self.assertFalse(U.heading_in_between((60, -60), 179)) # Tricky cases self.assertTrue(U.heading_in_between((-90, 90), 0)) self.assertTrue(U.heading_in_between((-90, 90), 180)) # Cases discovered through bugs self.assertTrue(U.heading_in_between((300, 60), 350))