def calculate_local_north_and_up_in_celestial_coords(self, force_update): current_time = self.get_time_in_millis() diff = math.fabs(current_time - self.celestial_coords_last_updated) if (not force_update) and diff < self.MINIMUM_TIME_BETWEEN_CELESTIAL_COORD_UPDATES_MILLIS: return self.celestial_coords_last_updated = current_time self.update_magnetic_correction() up_ra, up_dec = Geometry.calculate_RADec_of_zenith(self.get_time(), self.location) self.up_celestial = get_instance(up_ra, up_dec) z = self.AXIS_OF_EARTHS_ROTATION z_dotu = Geometry.scalar_product(self.up_celestial, z) self.true_north_celestial = \ Geometry.add_vectors(z, Geometry.scale_vector(self.up_celestial, -z_dotu)) self.true_north_celestial.normalize() self.true_east_celestial = Geometry.vector_product(self.true_north_celestial, \ self.up_celestial) # Apply magnetic correction. Rather than correct the phone's axes for # the magnetic declination, it's more efficient to rotate the # celestial axes by the same amount in the opposite direction. declination = self.magnetic_declination_calc.get_declination() rotation_matrix = Geometry.calculate_rotation_matrix(declination, self.up_celestial) magnetic_north_celestial = Geometry.matrix_vector_multiply(rotation_matrix, \ self.true_north_celestial) magnetic_east_celestial = Geometry.vector_product(magnetic_north_celestial, \ self.up_celestial) self.axes_magnetic_celestial_matrix = get_colmatrix_from_vectors(magnetic_north_celestial, \ self.up_celestial, \ magnetic_east_celestial)
def change_up_down(self, radians): ''' Moves the astronomer's pointing up or down. @param radians the angular change in the pointing in radians (only accurate in the limit as radians tends to 0.) ''' if not self.enabled: return pointing = self.model.pointing pointing_xyz = pointing.get_line_of_sight() top_xyz = pointing.get_perpendicular() delta_xyz = Geometry.scale_vector(top_xyz, -radians) new_pointing_xyz = Geometry.add_vectors(pointing_xyz, delta_xyz) new_pointing_xyz.normalize() delta_up_xyz = Geometry.scale_vector(pointing_xyz, radians) new_up_xyz = Geometry.add_vectors(top_xyz, delta_up_xyz) new_up_xyz.normalize() self.model.set_pointing(new_pointing_xyz, new_up_xyz)
def change_right_left(self, radians): ''' Moves the astronomer's pointing right or left @param radians the angular change in the pointing in radians (only accurate in the limit as radians tends to 0.) ''' if not self.enabled: return pointing = self.model.pointing pointing_xyz = pointing.get_line_of_sight() top_xyz = pointing.get_perpendicular() horizontal_xyz = Geometry.vector_product(pointing_xyz, top_xyz) delta_xyz = Geometry.scale_vector(horizontal_xyz, radians) new_pointing_xyz = Geometry.add_vectors(pointing_xyz, delta_xyz) new_pointing_xyz.normalize() self.model.set_pointing(new_pointing_xyz, top_xyz)
def calculate_local_north_and_up_in_phone_coords(self): down = self.acceleration.copy() down.normalize() # Magnetic field goes *from* North to South, so reverse it. magnetic_field_to_north = self.magnetic_field.copy() magnetic_field_to_north.scale(-1) magnetic_field_to_north.normalize() # This is the vector to magnetic North *along the ground*. v2 = Geometry.scale_vector(down, -Geometry.scalar_product(magnetic_field_to_north, \ down)) magnetic_north_phone = Geometry.add_vectors(magnetic_field_to_north, v2) magnetic_north_phone.normalize() up_phone = Geometry.scale_vector(down, -1) magnetic_east_phone = Geometry.vector_product(magnetic_north_phone, up_phone) # The matrix is orthogonal, so transpose it to find its inverse. # Easiest way to do that is to construct it from row vectors instead # of column vectors. self.axes_phone_inverse_matrix = \ get_rowmatrix_from_vectors(magnetic_north_phone, up_phone, magnetic_east_phone)