@@ -416,14 +416,24 @@ def _r_guess(self) -> Optional[np.ndarray]:
416
416
Should be roughly same as rotation matrix stored in :py:attr:`._pose_guess`, even though it is derived via
417
417
a different route. If gimbal is not stabilized to its set position, the rotation matrix will be different.
418
418
"""
419
+ static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
419
420
if self ._bridge .gimbal_set_attitude is None :
420
- self .get_logger ().warn ('Gimbal set attitude not available, will not provide pose guess.' )
421
- return None
422
-
423
- assert_type (self ._bridge .gimbal_set_attitude , Attitude )
424
- gimbal_set_attitude = self ._bridge .gimbal_set_attitude .to_esd () # Need coordinates in image frame, not NED
425
-
426
- return gimbal_set_attitude .r
421
+ if not static_camera :
422
+ self .get_logger ().warn ('Gimbal set attitude not available, will not provide pose guess.' )
423
+ return None
424
+ else :
425
+ if self ._bridge .attitude is not None :
426
+ attitude = self ._bridge .attitude .as_rotation ()
427
+ attitude *= Rotation .from_euler ('XYZ' , [0 , - np .pi / 2 , 0 ])
428
+ return Attitude (attitude .as_quat ()).to_esd ().r
429
+ else :
430
+ self .get_logger ().warn ('Vehicle attitude not available, will not provide pose guess for static '
431
+ 'camera.' )
432
+ return None
433
+ else :
434
+ assert_type (self ._bridge .gimbal_set_attitude , Attitude )
435
+ gimbal_set_attitude = self ._bridge .gimbal_set_attitude .to_esd () # Need coordinates in image frame, not NED
436
+ return gimbal_set_attitude .r
427
437
428
438
@property
429
439
def _wms_results_pending (self ) -> bool :
@@ -524,8 +534,10 @@ def _estimation_inputs(self) -> Optional[Tuple[InputData, ContextualMapData]]:
524
534
ground_elevation_ellipsoid = self ._bridge .ground_elevation_ellipsoid ,
525
535
)
526
536
537
+ static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
538
+
527
539
# Get cropped and rotated map
528
- if self ._bridge .gimbal_set_attitude is not None :
540
+ if self ._bridge .gimbal_set_attitude is not None and not static_camera :
529
541
camera_yaw = self ._bridge .gimbal_set_attitude .yaw
530
542
assert_type (camera_yaw , float )
531
543
assert - np .pi <= camera_yaw <= np .pi , f'Unexpected gimbal yaw value: { camera_yaw } ([-pi, pi] expected).'
@@ -772,12 +784,26 @@ def _guess_fov_center(self, origin: Position) -> Optional[GeoPoint]:
772
784
:param origin: Camera position
773
785
:return: Center of the projected FOV, or None if not available
774
786
"""
787
+ static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
788
+
775
789
if self ._bridge .gimbal_set_attitude is None :
776
- self .get_logger ().warn ('Gimbal set attitude not available, cannot project gimbal FOV.' )
777
- return None
790
+ if not static_camera :
791
+ self .get_logger ().warn ('Gimbal set attitude not available, cannot project gimbal FOV.' )
792
+ return None
793
+ else :
794
+ if self ._bridge .attitude is not None :
795
+ attitude = self ._bridge .attitude .as_rotation ()
796
+ attitude *= Rotation .from_euler ('XYZ' , [0 , - np .pi / 2 , 0 ])
797
+ gimbal_set_attitude = Attitude (attitude .as_quat ()).to_esd ().r
798
+ else :
799
+ self .get_logger ().warn ('Vehicle attitude not available, will not provide pose guess for static '
800
+ 'camera.' )
801
+ return None
802
+ else :
803
+ assert_type (self ._bridge .gimbal_set_attitude , Attitude )
804
+ gimbal_set_attitude = self ._bridge .gimbal_set_attitude .to_esd () # Need coordinates in image frame, not NED
778
805
779
- assert_type (self ._bridge .gimbal_set_attitude , Attitude )
780
- gimbal_set_attitude = self ._bridge .gimbal_set_attitude .to_esd () # Need coordinates in image frame, not NED
806
+ assert gimbal_set_attitude is not None
781
807
782
808
if self ._bridge .camera_data is None :
783
809
self .get_logger ().warn ('Camera data not available, could not create a mock pose to generate a FOV guess.' )
@@ -1132,7 +1158,7 @@ def _is_valid_estimate(self, fixed_camera: FixedCamera, input_data: InputData) -
1132
1158
"""
1133
1159
static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
1134
1160
if static_camera :
1135
- # TODO add vehicle body roll & pitch
1161
+ # TODO add vehicle body roll & pitch from input data
1136
1162
r_guess = Attitude (Rotation .from_rotvec ([0 , - np .pi / 2 , 0 ]).as_quat ()).to_esd ().as_rotation ()
1137
1163
1138
1164
if input_data .r_guess is None and not static_camera :
@@ -1176,21 +1202,33 @@ def _camera_pitch_too_high(self, max_pitch: Union[int, float]) -> bool:
1176
1202
Used to determine whether camera pitch setting is too high up from nadir to make matching against a map
1177
1203
not worthwhile.
1178
1204
1205
+ .. note::
1206
+ Uses actual vehicle attitude (instead of gimbal set attitude) if static_camera ROS param is True
1207
+
1179
1208
:param max_pitch: The limit for the pitch in degrees from nadir over which it will be considered too high
1180
1209
:return: True if pitch is too high
1181
1210
"""
1182
1211
assert_type (max_pitch , get_args (Union [int , float ]))
1183
- if self ._bridge .gimbal_set_attitude is not None :
1212
+ static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
1213
+ pitch = None
1214
+ if self ._bridge .gimbal_set_attitude is not None and not static_camera :
1184
1215
# +90 degrees to re-center from FRD frame to nadir-facing camera as origin for max pitch comparison
1185
1216
pitch = np .degrees (self ._bridge .gimbal_set_attitude .pitch ) + 90
1186
- if pitch > max_pitch :
1187
- self .get_logger ().warn (f'Camera pitch { pitch } is above limit { max_pitch } .' )
1188
- return True
1189
1217
else :
1190
- static_camera = self .get_parameter ('misc.static_camera' ).get_parameter_value ().bool_value
1191
1218
if not static_camera :
1192
1219
self .get_logger ().warn ('Gimbal attitude was not available, assuming camera pitch too high.' )
1193
1220
return True
1221
+ else :
1222
+ if self ._bridge .attitude is None :
1223
+ self .get_logger ().warn ('Vehicle attitude was not available, assuming static camera pitch too high.' )
1224
+ return True
1225
+ else :
1226
+ pitch = self ._bridge .attitude .pitch
1227
+
1228
+ assert pitch is not None
1229
+ if pitch > max_pitch :
1230
+ self .get_logger ().warn (f'Camera pitch { pitch } is above limit { max_pitch } .' )
1231
+ return True
1194
1232
1195
1233
return False
1196
1234
0 commit comments