def star_coord(x, y): mag, ang = comutils.vector_between([0, 0], [x, y]) while ang < 0: ang += 360.0 mag /= PIXELS_PER_DEGREE mag = 90.0 - mag ang /= 360.0 ang *= 24.0 return ang, mag
def get_span_between(self, p0, point_list=None): if point_list is None: point_list = self.points max_mag = 0 i = 0 while i < len(point_list): p = point_list[i] mag = comutils.vector_between(p, p0, mag_only=True) if mag > max_mag: max_mag = mag i += 1 return max_mag
def _eval(self): # we want the star to be not too close to the edge if self.cx < SENSOR_WIDTH / 3: return 0 if self.cx > (SENSOR_WIDTH * 2) / 3: return 0 if self.cy < SENSOR_HEIGHT / 3: return 0 if self.cy > (SENSOR_HEIGHT * 2) / 3: return 0 # we want the star to be bright enough # but saturating is bad score_maxbrite = 0 best_maxbrite = 256 - 16 if self.maxbrite == best_maxbrite: score_maxbrite = 100 elif self.maxbrite < best_maxbrite: score_maxbrite = map_val(self.maxbrite, 64, best_maxbrite, 0, 100) elif self.maxbrite > best_maxbrite: score_maxbrite = 100 - map_val(self.maxbrite, best_maxbrite, 255, 0, 25) # fully saturated stars are bad for tracking because it's harder to find the center score_saturation = 100 - self.saturation # closer to center of screen is better center_x = SENSOR_WIDTH / 2 center_y = SENSOR_HEIGHT / 2 mag = comutils.vector_between([center_x, center_y], [self.cx, self.cy], mag_only=True) score_centerdist = 100 - map_val(mag, 0, SENSOR_HEIGHT / 6, 0, 100) # place weights on each item return (score_maxbrite * 0.9) + (score_saturation * 0.9) + (score_centerdist * 0.5)
def set_ref_star(self, ref_star): self.ref_star = ref_star mag, ang = comutils.vector_between([self.cx, self.cy], [ref_star.cx, ref_star.cy]) self.ref_star_dist = mag self.ref_star_angle = ang
def analyze(self): i = 0 min_mag = 10000 max_mag = 0 mag_sum = 0 all_mags = [] # this first loop simply figures out the farthest distance between any two consecutive points while i < len(self.points) - 1: p1 = self.points[i] p2 = self.points[i + 1] mag = comutils.vector_between(p1, p2, mag_only=True) if mag > max_mag: max_mag = mag if mag < min_mag: min_mag = mag all_mags.append(mag) i += 1 # now we figure out which moves were inhibited by backlash d_mag = max_mag - min_mag mag_limit = min_mag + (d_mag / 4) mag_sum = 0 mag_sum_cnt = 0 for i in all_mags: # only count the ones that are not affected by backlash if i >= mag_limit: mag_sum += i mag_sum_cnt += 1 # we can figure out the pixels per millisec, and millisec per pixel self.avg_step_mag = mag_sum / mag_sum_cnt self.pix_per_ms = self.avg_step_mag / self.pulse_width self.ms_per_pix = self.pulse_width / self.avg_step_mag i = 1 self.accepted_points = [] farthest_point = None farthest = 0 pstart = self.points[0] # now we go through the points again, find the ones not affected by backlash # these "good" points will be used to calculate a line-of-best-fit while i < len(self.points) - 1: p0 = self.points[i - 1] p1 = self.points[i] p2 = self.points[i + 1] mag1 = comutils.vector_between(p0, p1, mag_only=True) mag2 = comutils.vector_between(p1, p2, mag_only=True) mag_start = comutils.vector_between(pstart, p2, mag_only=True) if mag1 >= mag_limit and mag2 >= mag_limit: # "good" point self.accepted_points.append(p1) if i == 0 and mag1 >= mag_limit: # "good" point self.accepted_points.append(p0) if i == len(self.points) - 2 and mag2 >= mag_limit: # "good" point self.accepted_points.append(p2) if mag_start > farthest: farthest = mag_start farthest_point = p2 i += 1 self.line_est_center, self.angle = line_est(self.accepted_points) # we have a line-of-best-fit but there are two possible directions # use the start point and the farthest point to see if the direction needs to be flipped mag, ang = comutils.vector_between(pstart, farthest_point) dang = comutils.angle_diff(ang, self.angle) if abs(dang) > 90: # direction needs flipping self.angle += 180.0 self.angle = comutils.ang_normalize(self.angle) self.farthest = farthest if len(self.accepted_points ) < MINIMUM_REQUIRED_POINTS or farthest < 100: self.success = "failed" return False else: self.has_cal = True self.success = "done" return True