def __generate_heading_strip__(self, heading): things_to_render = [] for heading_strip in self.__heading_strip_offset__: to_the_left = (heading - heading_strip) to_the_right = (heading + heading_strip) displayed_left = utils.apply_declination(to_the_left) displayed_right = utils.apply_declination(to_the_right) if to_the_left < 0: to_the_left += 360 if to_the_right > 360: to_the_right -= 360 if (displayed_left == 0) or ((displayed_left % 90) == 0): line_x_left = self.__center_x__ - \ self.__heading_strip_offset__[heading_strip] things_to_render.append([line_x_left, to_the_left]) if to_the_left == to_the_right: continue if (displayed_right % 90) == 0: line_x_right = self.__center_x__ + \ self.__heading_strip_offset__[heading_strip] things_to_render.append([line_x_right, to_the_right]) return things_to_render
def render(self, framebuffer, orientation): """ Renders the current heading to the HUD. """ self.task_timer.start() # Render a crude compass # Render a heading strip along the top heading = orientation.get_onscreen_projection_heading() for heading_mark_to_render in self.__heading_strip__[heading]: self.__render_heading_mark__( framebuffer, heading_mark_to_render[0], heading_mark_to_render[1]) # Render the text that is showing our AHRS and GPS headings cover_old_rendering_spaces = " " heading_text = "{0}{1} | {2}{0}".format(cover_old_rendering_spaces, str(int(utils.apply_declination( orientation.get_onscreen_projection_display_heading()))).rjust(3), str(int(utils.apply_declination(orientation.gps_heading))).rjust(3)) rendered_text = self.__font__.render( heading_text, True, display.GREEN, display.BLACK) text_width, text_height = rendered_text.get_size() framebuffer.blit( rendered_text, (self.__center_x__ - (text_width >> 1), text_height << 1)) pygame.draw.lines(framebuffer, display.GREEN, True, self.__heading_text_box_lines__, 2) self.task_timer.stop()
def __render_heading_mark__(self, framebuffer, x_pos, heading): pygame.draw.line(framebuffer, display.GREEN, [x_pos, self.line_height], [x_pos, 0], 4) self.__render_heading_text__(framebuffer, utils.apply_declination(heading), x_pos, self.compass_text_y)
def __render_heading_mark__(self, framebuffer, x_pos, heading): pygame.draw.line(framebuffer, GREEN, [x_pos, self.__line_top__], [x_pos, self.__line_bottom__], self.__border_width__) self.__render_heading_text__(framebuffer, utils.apply_declination(heading), x_pos, self.compass_text_y)
def __get_padded_traffic_reports__(self, traffic_reports): max_identifier_length = 0 max_bearing_length = 0 max_altitude_length = 0 max_distance_length = 0 pre_padded_text = [] max_identifier_length, max_distance_length, max_altitude_length = self.__get_pre_padded_text_reports__( traffic_reports, max_identifier_length, max_bearing_length, max_altitude_length, max_distance_length, pre_padded_text) out_padded_reports = [] for report in pre_padded_text: identifier = report[0] bearing = str(utils.apply_declination(float(report[1]))) distance_text = report[2] altitude = report[3] icao = report[4] # if self.__show_list__: traffic_report = "{0} {1} {2} {3}".format( identifier.ljust(max_identifier_length), bearing.rjust(3), distance_text.rjust(max_distance_length), altitude.rjust(max_altitude_length)) out_padded_reports.append((icao, traffic_report)) return out_padded_reports
def __render_traffic_heading_bug__(self, traffic_report, heading, orientation, framebuffer): """ Render a single heading bug to the framebuffer. Arguments: traffic_report {Traffic} -- The traffic we want to render a bug for. heading {int} -- Our current heading. orientation {Orientation} -- Our plane's current orientation. framebuffer {Framebuffer} -- What we are going to draw to. """ heading_bug_x = get_heading_bug_x( heading, utils.apply_declination(traffic_report.bearing), self.__pixels_per_degree_x__) additional_info_text = self.__get_additional_target_text__( traffic_report, orientation) try: self.__render_info_card__(framebuffer, str(traffic_report.get_display_name()), additional_info_text, heading_bug_x, traffic_report.get_age()) except Exception as ex: print("EX:{}".format(ex)) pass
def __render_traffic_heading_bug__(self, traffic_report, heading, orientation, framebuffer): """ Render a single heading bug to the framebuffer. Arguments: traffic_report {Traffic} -- The traffic we want to render a bug for. heading {int} -- Our current heading. orientation {Orientation} -- Our plane's current orientation. framebuffer {Framebuffer} -- What we are going to draw to. """ # Render using the Above us bug # target_bug_scale = 0.04 target_bug_scale = get_reticle_size(traffic_report.distance) heading_bug_x = get_heading_bug_x( heading, utils.apply_declination(traffic_report.bearing), self.__pixels_per_degree_x__) try: is_below = (orientation.alt - 100) > traffic_report.altitude reticle, reticle_edge_positon_y = self.get_below_reticle( heading_bug_x, target_bug_scale) if is_below else self.get_above_reticle( heading_bug_x, target_bug_scale) bug_color = display.BLUE if traffic_report.is_on_ground( ) == True else display.RED pygame.draw.polygon(framebuffer, bug_color, reticle) except: pass
def _render_hallow_heading_box_(self, orientation, framebuffer, heading_y_pos): heading_text = "{0} | {1}".format( str( utils.apply_declination( orientation.get_onscreen_projection_display_heading())). rjust(3), str(utils.apply_declination( orientation.get_onscreen_gps_heading())).rjust(3)) rendered_text = self.__font__.render(heading_text, True, display.GREEN) text_width, text_height = rendered_text.get_size() framebuffer.blit(rendered_text, (self.__center_x__ - (text_width >> 1), heading_y_pos)) pygame.draw.lines(framebuffer, display.GREEN, True, self.__heading_text_box_lines__, 2)
def render(self, framebuffer, orientation): """ Renders the current heading to the HUD. """ self.task_timer.start() # Render a crude compass # Render a heading strip along the top heading = orientation.get_onscreen_projection_heading() if heading < 0: heading += 360 if heading > 360: heading -= 360 [ self.__render_heading_mark__(framebuffer, heading_mark_to_render[0], heading_mark_to_render[1]) for heading_mark_to_render in self.__heading_strip__[heading] ] # Render the text that is showing our AHRS and GPS headings heading_text = "{0} | {1}".format( utils.apply_declination( orientation.get_onscreen_projection_display_heading()), utils.apply_declination(orientation.gps_heading)) rendered_text = self.__font__.render(heading_text, True, BLACK, GREEN) text_width, text_height = rendered_text.get_size() pygame.draw.polygon(framebuffer, GREEN, self.__heading_text_box_lines__) framebuffer.blit(rendered_text, (self.__center_x__ - (text_width >> 1), self.compass_text_y)) self.task_timer.stop()
def __get_report_text__(self, traffic): identifier = str(traffic.get_display_name()) altitude_delta = int(traffic.altitude / 100.0) distance_text = self.__get_distance_string__(traffic.distance, True) delta_sign = '' if altitude_delta > 0: delta_sign = '+' altitude_text = "{0}{1}".format(delta_sign, altitude_delta) bearing_text = "{0:.0f}".format( utils.apply_declination(traffic.bearing)) return [identifier, bearing_text, distance_text, altitude_text, traffic.icao_address]
def render(self, framebuffer, orientation): # Render a heading strip along the top self.task_timer.start() heading = orientation.get_onscreen_projection_heading() # Get the traffic, and bail out of we have none if targets.TARGET_MANAGER is None or targets.TARGET_MANAGER.targets is None: return for target_position in targets.TARGET_MANAGER.targets: ground_speed_ms = units.get_meters_per_second_from_mph( orientation.groundspeed) distance_miles = norden.get_distance(orientation.position, target_position) distance_meters = units.get_meters_from_feet( units.get_feet_from_miles(distance_miles)) time_to_target = norden.get_time_to_distance( distance_meters, ground_speed_ms) # NOTE: # Remember that the altitude off the AHRS is # in terms of MSL. That means that we need to # subtract out the altitude of the target. delta_altitude = orientation.alt - target_position[2] time_to_impact = norden.get_time_to_impact( units.get_meters_from_feet(delta_altitude)) time_until_drop = time_to_target - time_to_impact # target_altitude_for_drop = units.get_feet_from_meters( # norden.get_altitude(time_to_target)) bearing_to_target = norden.get_bearing(target_position, orientation.position) # time_to_impact_from_ideal_current_altitude = norden.get_time_to_impact( # target_altitude_for_drop) # Render using the Above us bug # target_bug_scale = 0.04 # target_bug_scale = get_reticle_size(distance_miles) heading_bug_x = get_heading_bug_x(heading, bearing_to_target, self.__pixels_per_degree_x__) additional_info_text = self.__get_additional_target_text__( time_until_drop, delta_altitude, units.get_feet_from_miles(distance_miles)) self.__render_info_card__( framebuffer, "{0:.1f}".format(utils.apply_declination(bearing_to_target)), additional_info_text, heading_bug_x, False) self.task_timer.stop()
def __get_listing__(self, report, max_string_lengths): identifier = report[0] try: bearing = str(utils.apply_declination(float(report[1]))) except: bearing = str(report[1]) distance_text = report[2] altitude = report[3] icao = report[4] # if self.__show_list__: traffic_report = "{0} {1} {2} {3}".format( identifier.ljust(max_string_lengths[0]), bearing.rjust(max_string_lengths[1]), distance_text.rjust(max_string_lengths[2]), altitude.rjust(max_string_lengths[3])) return (icao, traffic_report)
def __get_additional_target_text__(self, traffic_report, orientation): """ Gets the additional text for a traffic report Arguments: traffic_report {[type]} -- [description] orientation {[type]} -- [description] Returns: [type] -- [description] """ altitude_delta = int( (traffic_report.altitude - orientation.alt) / 100.0) distance_text = self.__get_distance_string__(traffic_report.distance) delta_sign = '' if altitude_delta > 0: delta_sign = '+' altitude_text = "{0}{1}".format(delta_sign, altitude_delta) bearing_text = "{0}".format( int(utils.apply_declination(traffic_report.bearing))) return [bearing_text, distance_text, altitude_text]
def __get_traffic_projection__(self, orientation, traffic): """ Attempts to figure out where the traffic reticle should be rendered. Returns value within screen space """ # Assumes traffic.position_valid # TODO - Account for aircraft roll... altitude_delta = int(traffic.altitude - orientation.alt) slope = altitude_delta / traffic.distance vertical_degrees_to_target = math.degrees(math.atan(slope)) vertical_degrees_to_target -= orientation.pitch # TODO - Double check ALL of this math... compass = orientation.get_onscreen_projection_heading() horizontal_degrees_to_target = utils.apply_declination( traffic.bearing) - compass screen_y = -vertical_degrees_to_target * self.__pixels_per_degree_y__ screen_x = horizontal_degrees_to_target * self.__pixels_per_degree_y__ return self.__center__[0] + screen_x, self.__center__[1] + screen_y