@@ -594,172 +594,179 @@ def _track_object(self, time_since_last_update: float) -> None:
594
594
595
595
start_time = time ()
596
596
597
+ try :
597
598
598
- if self .use_camera :
599
- # Get camera pan and tilt
600
- self .rho_c , self .tau_c , _zoom , _focus = self .camera .get_ptz ()
601
- # logging.info(
602
- # f"Camera pan, tilt, zoom, and focus: {self.rho_c} [deg], {self.tau_c} [deg], {_zoom}, {_focus}"
603
- # )
604
- else :
605
- logging .debug (f"Controller pan and tilt: { self .rho_c } , { self .tau_c } [deg]" )
599
+ if self .use_camera :
600
+ # Get camera pan and tilt
601
+ self .rho_c , self .tau_c , _zoom , _focus = self .camera .get_ptz ()
602
+ # logging.info(
603
+ # f"Camera pan, tilt, zoom, and focus: {self.rho_c} [deg], {self.tau_c} [deg], {_zoom}, {_focus}"
604
+ # )
605
+ else :
606
+ logging .debug (f"Controller pan and tilt: { self .rho_c } , { self .tau_c } [deg]" )
606
607
607
608
608
- if self .object is None :
609
- logging .error (f"Not sure why it is None here, but not earlier" )
610
- return
609
+ if self .object is None :
610
+ logging .error (f"Not sure why it is None here, but not earlier" )
611
+ return
611
612
612
- # recompute the object's current location
613
- # we want to do this after getting the camera's current location because that is a network call
614
- # and it there is latency and jitter in how long it takes.
615
- self .object .recompute_location ()
613
+ # recompute the object's current location
614
+ # we want to do this after getting the camera's current location because that is a network call
615
+ # and it there is latency and jitter in how long it takes.
616
+ self .object .recompute_location ()
616
617
617
- # Compute angle delta between camera and object pan and tilt
618
- self .delta_rho = axis_ptz_utilities .compute_angle_delta (
619
- self .camera .rho , self .object .rho
620
- )
621
- self .delta_tau = axis_ptz_utilities .compute_angle_delta (
622
- self .camera .tau , self .object .tau
623
- )
618
+ # Compute angle delta between camera and object pan and tilt
619
+ self .delta_rho = axis_ptz_utilities .compute_angle_delta (
620
+ self .camera .rho , self .object .rho
621
+ )
622
+ self .delta_tau = axis_ptz_utilities .compute_angle_delta (
623
+ self .camera .tau , self .object .tau
624
+ )
625
+
626
+ # Compute slew rate differences
627
+
628
+ # tracking the rate of change for the object's pan and tilt allows us to amplify the gain
629
+ # when the object is moving quickly past the camera
630
+ object_rho_derivative = abs (self .object .rho_derivative )
631
+ object_tau_derivative = abs (self .object .tau_derivative )
632
+
633
+ # we want to make sure the object derivative does not have a dampening effect on the gain
634
+ if object_rho_derivative < 1 :
635
+ object_rho_derivative = 1
636
+ if object_tau_derivative < 1 :
637
+ object_tau_derivative = 1
638
+ if object_rho_derivative > self .pan_derivative_gain_max :
639
+ object_rho_derivative = self .pan_derivative_gain_max
640
+ if object_tau_derivative > self .tilt_derivative_gain_max :
641
+ object_tau_derivative = self .tilt_derivative_gain_max
642
+
643
+ self .rho_c_gain = self .pan_gain * self .delta_rho * object_rho_derivative
644
+ self .tau_c_gain = self .tilt_gain * self .delta_tau * object_tau_derivative
645
+
646
+ # Compute position and velocity in the camera fixed (rst)
647
+ # coordinate system of the object relative to the tripod at
648
+ # time zero after pointing the camera at the object
649
+
650
+ # Update camera pan and tilt rate
651
+ self .rho_dot_c = self .object .rho_rate + self .rho_c_gain #- (self.object.rho_derivative ** 2)
652
+ self .tau_dot_c = self .object .tau_rate + self .tau_c_gain #- (self.object.tau_derivative ** 2)
624
653
625
- # Compute slew rate differences
626
-
627
- # tracking the rate of change for the object's pan and tilt allows us to amplify the gain
628
- # when the object is moving quickly past the camera
629
- object_rho_derivative = abs (self .object .rho_derivative )
630
- object_tau_derivative = abs (self .object .tau_derivative )
631
-
632
- # we want to make sure the object derivative does not have a dampening effect on the gain
633
- if object_rho_derivative < 1 :
634
- object_rho_derivative = 1
635
- if object_tau_derivative < 1 :
636
- object_tau_derivative = 1
637
- if object_rho_derivative > self .pan_derivative_gain_max :
638
- object_rho_derivative = self .pan_derivative_gain_max
639
- if object_tau_derivative > self .tilt_derivative_gain_max :
640
- object_tau_derivative = self .tilt_derivative_gain_max
641
-
642
- self .rho_c_gain = self .pan_gain * self .delta_rho * object_rho_derivative
643
- self .tau_c_gain = self .tilt_gain * self .delta_tau * object_tau_derivative
644
-
645
- # Compute position and velocity in the camera fixed (rst)
646
- # coordinate system of the object relative to the tripod at
647
- # time zero after pointing the camera at the object
648
-
649
- # Update camera pan and tilt rate
650
- self .rho_dot_c = self .object .rho_rate + self .rho_c_gain #- (self.object.rho_derivative ** 2)
651
- self .tau_dot_c = self .object .tau_rate + self .tau_c_gain #- (self.object.tau_derivative ** 2)
652
-
653
- # Get, or compute and set focus, command camera pan and tilt
654
- # rates, and begin capturing images, if needed
655
- if self .use_camera :
656
- # Note that focus cannot be negative, since distance_to_tripod3d
657
- # is non-negative
658
- self .camera .update_focus (self .object .distance_to_tripod3d )
659
- self .camera .update_pan_tilt_rates (self .rho_dot_c , self .tau_dot_c )
654
+ # Get, or compute and set focus, command camera pan and tilt
655
+ # rates, and begin capturing images, if needed
656
+ if self .use_camera :
657
+ # Note that focus cannot be negative, since distance_to_tripod3d
658
+ # is non-negative
659
+ self .camera .update_focus (self .object .distance_to_tripod3d )
660
+ self .camera .update_pan_tilt_rates (self .rho_dot_c , self .tau_dot_c )
661
+
662
+ if self .object is None :
663
+ logging .error (f"REALLY not sure why it is None here, but not earlier" )
664
+ return
665
+ if not self .do_capture and self .object is not None :
666
+ logging .info (
667
+ f"Starting image capture of object: { self .object .object_id } "
668
+ )
669
+ self .do_capture = True
670
+ self .capture_time = time ()
660
671
672
+ if self .do_capture and time () - self .capture_time > self .capture_interval :
673
+ capture_thread = threading .Thread (target = self ._capture_image )
674
+ capture_thread .daemon = True
675
+ capture_thread .start ()
676
+
677
+ elapsed_time = time () - start_time
678
+ # logging.info(
679
+ # f"\t⏱️\t {round(elapsed_time,3)}s RATES - 🎥 Pan: {self.rho_dot_c}\tTilt: {self.tau_dot_c}\t🛩️ Pan: {self.object.rho_rate}\tTilt: {self.object.tau_rate} ANGLES: 🎥 Pan: {self.rho_c}\tTilt: {self.tau_c}\t🛩️ Pan: {self.object.rho}\tTilt: {self.object.tau} "
680
+ # )
681
+
682
+ # Compute position of aircraft relative to tripod in ENz, then XYZ,
683
+ # then uvw coordinates
661
684
if self .object is None :
662
- logging .error (f"REALLY not sure why it is None here, but not earlier " )
685
+ logging .error (f"Object is None, not tracking " )
663
686
return
664
- if not self .do_capture and self .object is not None :
665
- logging .info (
666
- f"Starting image capture of object: { self .object .object_id } "
667
- )
668
- self .do_capture = True
669
- self .capture_time = time ()
670
-
671
- if self .do_capture and time () - self .capture_time > self .capture_interval :
672
- capture_thread = threading .Thread (target = self ._capture_image )
673
- capture_thread .daemon = True
674
- capture_thread .start ()
675
-
676
- elapsed_time = time () - start_time
677
- # logging.info(
678
- # f"\t⏱️\t {round(elapsed_time,3)}s RATES - 🎥 Pan: {self.rho_dot_c}\tTilt: {self.tau_dot_c}\t🛩️ Pan: {self.object.rho_rate}\tTilt: {self.object.tau_rate} ANGLES: 🎥 Pan: {self.rho_c}\tTilt: {self.tau_c}\t🛩️ Pan: {self.object.rho}\tTilt: {self.object.tau} "
679
- # )
680
-
681
- # Compute position of aircraft relative to tripod in ENz, then XYZ,
682
- # then uvw coordinates
683
- r_ENz_a_t = np .array (
684
- [
685
- math .sin (math .radians (self .object .rho )) * math .cos (math .radians (self .object .tau )),
686
- math .cos (math .radians (self .object .rho )) * math .cos (math .radians (self .object .tau )),
687
- math .sin (math .radians (self .object .tau )),
688
- ]
689
- )
690
- r_XYZ_a_t = np .matmul (self .camera .get_xyz_to_enz_transformation_matrix ().transpose (), r_ENz_a_t )
691
- r_uvw_a_t = np .matmul (self .camera .get_xyz_to_uvw_transformation_matrix (), r_XYZ_a_t )
692
-
693
- # Compute pan an tilt
694
- self .camera_pan = math .degrees (math .atan2 (r_uvw_a_t [0 ], r_uvw_a_t [1 ])) # [deg]
695
- self .camera_tilt = math .degrees (
696
- math .atan2 (r_uvw_a_t [2 ], axis_ptz_utilities .norm (r_uvw_a_t [0 :2 ]))
697
- ) # [deg]
698
-
699
-
700
- # Log camera pointing using MQTT
701
- if self .log_to_mqtt :
702
- logger_msg = self .generate_payload_json (
703
- push_timestamp = int (datetime .utcnow ().timestamp ()),
704
- device_type = os .environ .get ("DEVICE_TYPE" , "Collector" ),
705
- id_ = self .hostname ,
706
- deployment_id = os .environ .get (
707
- "DEPLOYMENT_ID" , f"Unknown-Location-{ self .hostname } "
708
- ),
709
- current_location = os .environ .get (
710
- "CURRENT_LOCATION" ,
711
- f"{ self .camera .tripod_latitude } , { self .camera .tripod_longitude } " ,
712
- ),
713
- status = "Debug" ,
714
- message_type = "Event" ,
715
- model_version = "null" ,
716
- firmware_version = "v0.0.0" ,
717
- data_payload_type = "Logger" ,
718
- data_payload = json .dumps (
719
- {
720
- "camera-pointing" : {
721
- "timestamp_c" : self .timestamp_c ,
722
- "rho_o" : self .object .rho ,
723
- "tau_o" : self .object .tau ,
724
- "rho_camera_o" : self .camera_pan ,
725
- "tau_camera_o" : self .camera_tilt ,
726
- "corrected_rho_delta" : self .object .rho - self .camera_pan ,
727
- "corrected_tau_delta" : self .object .tau - self .camera_tilt ,
728
- "rho_dot_o" : self .object .rho_rate ,
729
- "tau_dot_o" : self .object .tau_rate ,
730
- "rho_c" : self .camera .rho ,
731
- "tau_c" : self .camera .tau ,
732
- "rho_dot_c" : self .rho_dot_c ,
733
- "tau_dot_c" : self .tau_dot_c ,
734
- "rho_c_gain" : self .rho_c_gain ,
735
- "tau_c_gain" : self .tau_c_gain ,
736
- "rst_vel_o_0" : self .object .rst_velocity_msg_relative_to_tripod [0 ],
737
- "rst_vel_o_1" : self .object .rst_velocity_msg_relative_to_tripod [1 ],
738
- "rst_vel_o_2" : self .object .rst_velocity_msg_relative_to_tripod [2 ],
739
- "rst_point_o_0" : self .object .rst_point_msg_relative_to_tripod [0 ],
740
- "rst_point_o_1" : self .object .rst_point_msg_relative_to_tripod [1 ],
741
- "rst_point_o_2" : self .object .rst_point_msg_relative_to_tripod [2 ],
742
- "distance" : self .object .distance_to_tripod3d ,
743
- "focus" : _focus ,
744
- "zoom" : _zoom ,
745
- "object_location_update_period" : self .object .location_update_period ,
746
- "rho_derivative" : self .object .rho_derivative ,
747
- "tau_derivative" : self .object .tau_derivative ,
748
- "pan_rate_index" : self .camera .pan_rate_index ,
749
- "tilt_rate_index" : self .camera .tilt_rate_index ,
750
- "delta_rho_dot_c" : self .delta_rho_dot_c ,
751
- "delta_tau_dot_c" : self .delta_tau_dot_c ,
752
- "delta_rho" : self .delta_rho ,
753
- "delta_tau" : self .delta_tau ,
754
- "tracking_loop_time" : elapsed_time ,
755
- "time_since_last_update" : time_since_last_update ,
756
- "object_id" : self .object .object_id ,
757
- }
758
- }
759
- ),
687
+
688
+ r_ENz_a_t = np .array (
689
+ [
690
+ math .sin (math .radians (self .object .rho )) * math .cos (math .radians (self .object .tau )),
691
+ math .cos (math .radians (self .object .rho )) * math .cos (math .radians (self .object .tau )),
692
+ math .sin (math .radians (self .object .tau )),
693
+ ]
760
694
)
761
- self .publish_to_topic (self .logger_topic , logger_msg )
762
-
695
+ r_XYZ_a_t = np .matmul (self .camera .get_xyz_to_enz_transformation_matrix ().transpose (), r_ENz_a_t )
696
+ r_uvw_a_t = np .matmul (self .camera .get_xyz_to_uvw_transformation_matrix (), r_XYZ_a_t )
697
+
698
+ # Compute pan an tilt
699
+ self .camera_pan = math .degrees (math .atan2 (r_uvw_a_t [0 ], r_uvw_a_t [1 ])) # [deg]
700
+ self .camera_tilt = math .degrees (
701
+ math .atan2 (r_uvw_a_t [2 ], axis_ptz_utilities .norm (r_uvw_a_t [0 :2 ]))
702
+ ) # [deg]
703
+
704
+
705
+ # Log camera pointing using MQTT
706
+ if self .log_to_mqtt :
707
+ logger_msg = self .generate_payload_json (
708
+ push_timestamp = int (datetime .utcnow ().timestamp ()),
709
+ device_type = os .environ .get ("DEVICE_TYPE" , "Collector" ),
710
+ id_ = self .hostname ,
711
+ deployment_id = os .environ .get (
712
+ "DEPLOYMENT_ID" , f"Unknown-Location-{ self .hostname } "
713
+ ),
714
+ current_location = os .environ .get (
715
+ "CURRENT_LOCATION" ,
716
+ f"{ self .camera .tripod_latitude } , { self .camera .tripod_longitude } " ,
717
+ ),
718
+ status = "Debug" ,
719
+ message_type = "Event" ,
720
+ model_version = "null" ,
721
+ firmware_version = "v0.0.0" ,
722
+ data_payload_type = "Logger" ,
723
+ data_payload = json .dumps (
724
+ {
725
+ "camera-pointing" : {
726
+ "timestamp_c" : self .timestamp_c ,
727
+ "rho_o" : self .object .rho ,
728
+ "tau_o" : self .object .tau ,
729
+ "rho_camera_o" : self .camera_pan ,
730
+ "tau_camera_o" : self .camera_tilt ,
731
+ "corrected_rho_delta" : self .object .rho - self .camera_pan ,
732
+ "corrected_tau_delta" : self .object .tau - self .camera_tilt ,
733
+ "rho_dot_o" : self .object .rho_rate ,
734
+ "tau_dot_o" : self .object .tau_rate ,
735
+ "rho_c" : self .camera .rho ,
736
+ "tau_c" : self .camera .tau ,
737
+ "rho_dot_c" : self .rho_dot_c ,
738
+ "tau_dot_c" : self .tau_dot_c ,
739
+ "rho_c_gain" : self .rho_c_gain ,
740
+ "tau_c_gain" : self .tau_c_gain ,
741
+ "rst_vel_o_0" : self .object .rst_velocity_msg_relative_to_tripod [0 ],
742
+ "rst_vel_o_1" : self .object .rst_velocity_msg_relative_to_tripod [1 ],
743
+ "rst_vel_o_2" : self .object .rst_velocity_msg_relative_to_tripod [2 ],
744
+ "rst_point_o_0" : self .object .rst_point_msg_relative_to_tripod [0 ],
745
+ "rst_point_o_1" : self .object .rst_point_msg_relative_to_tripod [1 ],
746
+ "rst_point_o_2" : self .object .rst_point_msg_relative_to_tripod [2 ],
747
+ "distance" : self .object .distance_to_tripod3d ,
748
+ "focus" : _focus ,
749
+ "zoom" : _zoom ,
750
+ "object_location_update_period" : self .object .location_update_period ,
751
+ "rho_derivative" : self .object .rho_derivative ,
752
+ "tau_derivative" : self .object .tau_derivative ,
753
+ "pan_rate_index" : self .camera .pan_rate_index ,
754
+ "tilt_rate_index" : self .camera .tilt_rate_index ,
755
+ "delta_rho_dot_c" : self .delta_rho_dot_c ,
756
+ "delta_tau_dot_c" : self .delta_tau_dot_c ,
757
+ "delta_rho" : self .delta_rho ,
758
+ "delta_tau" : self .delta_tau ,
759
+ "tracking_loop_time" : elapsed_time ,
760
+ "time_since_last_update" : time_since_last_update ,
761
+ "object_id" : self .object .object_id ,
762
+ }
763
+ }
764
+ ),
765
+ )
766
+ self .publish_to_topic (self .logger_topic , logger_msg )
767
+ except Exception as e :
768
+ logging .error (f"Error in tracking object: { e } " )
769
+ logging .error (traceback .format_exc ())
763
770
764
771
def _slew_camera (self , rho_target : float , tau_target : float ) -> None :
765
772
if self .status == Status .SLEWING :
@@ -840,7 +847,9 @@ def _object_callback(
840
847
"vertical_velocity" ,
841
848
]
842
849
) <= set (data .keys ()):
843
- logging .info (f"Required keys missing from object message data: { data } " )
850
+ #logging.info(f"Required keys missing from object message data: {data}")
851
+ self .do_capture = False
852
+ self .status = Status .SLEEPING
844
853
self .object = None
845
854
return
846
855
logging .info (
0 commit comments