diff --git a/python/PiFinder/calc_utils.py b/python/PiFinder/calc_utils.py index 767c4357..a3451226 100644 --- a/python/PiFinder/calc_utils.py +++ b/python/PiFinder/calc_utils.py @@ -48,7 +48,9 @@ def radec_to_altaz(self, ra, dec, alt_only=False) -> Tuple[float, Optional[float self.lat * math.pi / 180 ) + math.cos(dec * math.pi / 180) * math.cos( self.lat * math.pi / 180 - ) * math.cos(hour_angle * math.pi / 180) + ) * math.cos( + hour_angle * math.pi / 180 + ) alt = math.asin(_alt) * 180 / math.pi if alt_only: @@ -227,7 +229,7 @@ def hadec_to_roll(ha_deg, dec_deg, lat_deg): The roll or the field rotation angle, as returned by the Tetra3 solver, describes how much the source (S) is rotated on the sky as seen by and the observer. The roll measures the same angle as the parallactic but - measured with a different orientation. See ha_dec2pa() for explanation of + measured with a different orientation. See hadec_to_pa() for explanation of the parallactic angle. The roll is positive for anti-clockwise rotation of ZS to PS when looking out towards the sky. diff --git a/python/PiFinder/integrator.py b/python/PiFinder/integrator.py index eb162f74..ac651c6a 100644 --- a/python/PiFinder/integrator.py +++ b/python/PiFinder/integrator.py @@ -52,6 +52,11 @@ def integrator(shared_state, solver_queue, console_queue, log_queue, is_debug=Fa solved = { "RA": None, "Dec": None, + "Roll": None, + "RA_camera": None, + "Dec_camera": None, + "Roll_camera": None, + "Roll_offset": 0, # May/may not be needed - for experimentation "imu_pos": None, "Alt": None, "Az": None, @@ -109,6 +114,20 @@ def integrator(shared_state, solver_queue, console_queue, log_queue, is_debug=Fa solved["Alt"] = alt solved["Az"] = az + # Experimental: For monitoring roll offset + # Estimate the roll offset due misalignment of the + # camera sensor with the Pole-to-Source great circle. + solved["Roll_offset"] = estimate_roll_offset(solved, dt) + # Find the roll at the target RA/Dec. Note that this doesn't include the + # roll offset so it's not the roll that the PiFinder camear sees but the + # roll relative to the celestial pole + roll_target_calculated = calc_utils.sf_utils.radec_to_roll( + solved["RA"], solved["Dec"], dt + ) + # Compensate for the roll offset. This gives the roll at the target + # as seen by the camera. + solved["Roll"] = roll_target_calculated + solved["Roll_offset"] + last_image_solve = copy.copy(solved) solved["solve_source"] = "CAM" @@ -148,9 +167,12 @@ def integrator(shared_state, solver_queue, console_queue, log_queue, is_debug=Fa solved["Alt"], solved["Az"], dt ) - # Find the roll from the RA/Dec and time - solved["Roll"] = calc_utils.sf_utils.radec_to_roll( - solved["RA"], solved["Dec"], dt + # Calculate the roll at the target RA/Dec and compensate for the offset. + solved["Roll"] = ( + calc_utils.sf_utils.radec_to_roll( + solved["RA"], solved["Dec"], dt + ) + + solved["Roll_offset"] ) solved["solve_time"] = time.time() @@ -169,3 +191,21 @@ def integrator(shared_state, solver_queue, console_queue, log_queue, is_debug=Fa shared_state.set_solve_state(True) except EOFError: logger.error("Main no longer running for integrator") + + +def estimate_roll_offset(solved, dt): + """ + Estimate the roll offset due to misalignment of the camera sensor with + the mount/scope's coordinate system. The offset is calculated at the + center of the camera's FoV. + + To calculate the roll with offset: roll = calculated_roll + roll_offset + """ + # Calculate the expected roll at the camera center given the RA/Dec of + # of the camera center. + roll_camera_calculated = calc_utils.sf_utils.radec_to_roll( + solved["RA_camera"], solved["Dec_camera"], dt + ) + roll_offset = solved["Roll_camera"] - roll_camera_calculated + + return roll_offset diff --git a/python/PiFinder/solver.py b/python/PiFinder/solver.py index 195d1af8..fdb2ed72 100644 --- a/python/PiFinder/solver.py +++ b/python/PiFinder/solver.py @@ -35,8 +35,14 @@ def solver( ) last_solve_time = 0 solved = { + # RA, Dec, Roll solved at the center of the camera FoV: + "RA_camera": None, + "Dec_camera": None, + "Roll_camera": None, + # RA, Dec, Roll at the target pixel "RA": None, "Dec": None, + "Roll": None, "imu_pos": None, "solve_time": None, "cam_solve_time": 0, @@ -119,9 +125,14 @@ def solver( logger.warn("Long solver time: %i", total_tetra_time) if solved["RA"] is not None: - # map the RA/DEC to the target pixel RA/DEC + # RA, Dec, Roll at the center of the camera's FoV: + solved["RA_camera"] = solved["RA"] + solved["Dec_camera"] = solved["Dec"] + solved["Roll_camera"] = solved["Roll"] + # RA, Dec, Roll at the target pixel: solved["RA"] = solved["RA_target"] solved["Dec"] = solved["Dec_target"] + solved["Roll"] = None # To be calculated in integrator.py if last_image_metadata["imu"]: solved["imu_pos"] = last_image_metadata["imu"]["pos"] solved["imu_quat"] = last_image_metadata["imu"]["quat"]