Skip to content

Commit 9228c73

Browse files
committed
SIYI: added FOV map display
1 parent e1d989d commit 9228c73

File tree

1 file changed

+105
-7
lines changed

1 file changed

+105
-7
lines changed

MAVProxy/modules/mavproxy_SIYI/__init__.py

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,22 @@ def check_events(self):
212212
if event.x < xres and event.y < yres and event.x >= 0 and event.y >= 0:
213213
self.siyi.spot_temp = self.get_pixel_temp(event.x, event.y)
214214
self.update_title()
215+
x = (2*event.x/float(xres))-1.0
216+
y = (2*event.y/float(yres))-1.0
217+
aspect_ratio = float(xres)/yres
218+
slant_range = self.siyi.get_slantrange(x,y,self.siyi.siyi_settings.thermal_fov,aspect_ratio)
219+
if slant_range is None:
220+
return
221+
latlonalt = self.siyi.get_latlonalt(slant_range, x, y,
222+
self.siyi.siyi_settings.thermal_fov,
223+
aspect_ratio)
224+
if latlonalt is None:
225+
return
226+
latlon = (latlonalt[0],latlonalt[1])
227+
self.siyi.mpstate.map.add_object(mp_slipmap.SlipIcon('SIYIClick', latlon,
228+
self.siyi.click_icon, layer='SIYI', rotation=0, follow=False))
229+
230+
215231

216232

217233
class SIYIModule(mp_module.MPModule):
@@ -249,6 +265,7 @@ def __init__(self, mpstate):
249265
('temp_hz', float, 5),
250266
('thermal_port', int, 7002),
251267
('logfile', str, 'SIYI_log.bin'),
268+
('thermal_fov', float, 18),
252269
])
253270
self.add_completion_function('(SIYISETTING)',
254271
self.siyi_settings.completion)
@@ -279,6 +296,7 @@ def __init__(self, mpstate):
279296
self.target_pos = None
280297
self.last_map_ROI = None
281298
self.icon = self.mpstate.map.icon('camera-small-red.png')
299+
self.click_icon = self.mpstate.map.icon('flag.png')
282300
self.last_target_send = time.time()
283301
self.last_rate_display = time.time()
284302
self.yaw_controller = PI_controller(self.siyi_settings, 'yaw_gain_P', 'yaw_gain_I', 'yaw_gain_IMAX')
@@ -684,7 +702,7 @@ def update_title(self):
684702
def update_status(self):
685703
if self.attitude is None:
686704
return
687-
self.console.set_status('SIYI', 'SIYI (%.1f,%.1f,%.1f) rf=%.1f' % (
705+
self.console.set_status('SIYI', 'SIYI (%.1f,%.1f,%.1f) SR=%.1f' % (
688706
self.attitude[0], self.attitude[1], self.attitude[2],
689707
self.rf_dist), row=6)
690708
if self.tmin is not None:
@@ -733,18 +751,81 @@ def get_gimbal_attitude(self):
733751
roll = self.attitude[0]
734752
return yaw, pitch, roll
735753

736-
def get_latlon(self, slant_range):
737-
'''get lat/lon given vehicle orientation, camera orientation and slant range'''
754+
def get_slantrange(self,x,y,FOV,aspect_ratio):
755+
'''
756+
get range to ground
757+
x and y are from -1 to 1, relative to center of camera view
758+
'''
759+
if self.rf_dist > 0:
760+
# use rangefinder if possible
761+
return self.rf_dist
762+
gpi = self.master.messages.get('GLOBAL_POSITION_INT',None)
763+
if not gpi:
764+
return None
765+
(lat,lon,alt) = gpi.lat*1.0e-7,gpi.lon*1.0e-7,gpi.alt*1.0e-3
766+
ground_alt = self.module('terrain').ElevationModel.GetElevation(lat, lon)
767+
if alt <= ground_alt:
768+
return None
769+
if self.attitude is None:
770+
return None
771+
pitch = self.attitude[1]
772+
if pitch >= 0:
773+
return None
774+
pitch -= y*FOV*0.5/aspect_ratio
775+
pitch = min(pitch, -1)
776+
777+
# start with flat earth
778+
sin_pitch = math.sin(abs(math.radians(pitch)))
779+
sr = (alt-ground_alt) / sin_pitch
780+
781+
# iterate to make more accurate
782+
for i in range(3):
783+
(lat2,lon2,alt2) = self.get_latlonalt(sr,x,y,FOV,aspect_ratio)
784+
ground_alt2 = self.module('terrain').ElevationModel.GetElevation(lat2, lon2)
785+
# adjust for height at this point
786+
sr += (alt2 - ground_alt2) / sin_pitch
787+
return sr
788+
789+
790+
791+
def get_view_vector(self, x, y, FOV, aspect_ratio):
792+
'''
793+
get ground lat/lon given vehicle orientation, camera orientation and slant range
794+
x and y are from -1 to 1, relative to center of camera view
795+
positive x is to the right
796+
positive y is down
797+
'''
738798
att = self.master.messages.get('ATTITUDE',None)
739799
if att is None:
740800
return None
801+
v = Vector3(1, 0, 0)
802+
m = Matrix3()
803+
(roll,pitch,yaw) = (math.radians(self.attitude[0]),math.radians(self.attitude[1]),math.radians(self.attitude[2]))
804+
yaw += att.yaw
805+
FOV_half = math.radians(0.5*FOV)
806+
yaw += FOV_half*x
807+
pitch -= y*FOV_half/aspect_ratio
808+
m.from_euler(roll, pitch, yaw)
809+
v = m * v
810+
return v
811+
812+
def get_latlonalt(self, slant_range, x, y, FOV, aspect_ratio):
813+
'''
814+
get ground lat/lon given vehicle orientation, camera orientation and slant range
815+
x and y are from -1 to 1, relative to center of camera view
816+
'''
817+
if slant_range is None:
818+
return None
819+
v = self.get_view_vector(x,y,FOV,aspect_ratio)
820+
if v is None:
821+
return None
741822
gpi = self.master.messages.get('GLOBAL_POSITION_INT',None)
742823
if gpi is None:
743824
return None
744-
cam_att = self.attitude
745-
v = Vector3(slant_range, 0, 0)
746-
m = Matrix3()
747-
m.from_euler()
825+
v *= slant_range
826+
(lat,lon,alt) = (gpi.lat*1.0e-7,gpi.lon*1.0e-7,gpi.alt*1.0e-3)
827+
(lat,lon) = mp_util.gps_offset(lat,lon,v.y,v.x)
828+
return (lat,lon,alt-v.z)
748829

749830
def update_target(self):
750831
'''update position targetting'''
@@ -823,6 +904,21 @@ def get_gps_time(self, tnow):
823904
week_ms = (epoch_seconds % SEC_PER_WEEK) * 1000 + ((t_ms//200) * 200)
824905
return week, week_ms
825906

907+
def show_thermal_fov(self):
908+
'''show thermal FOV polygon'''
909+
points = []
910+
FOV = self.siyi_settings.thermal_fov
911+
aspect_ratio = 640.0/512.0
912+
for (x,y) in [(-1,-1),(1,-1),(1,1),(-1,1),(-1,-1)]:
913+
latlonalt = self.get_latlonalt(self.get_slantrange(x,y,FOV,aspect_ratio),x,y,FOV,aspect_ratio)
914+
if latlonalt is None:
915+
return
916+
(lat,lon) = (latlonalt[0],latlonalt[1])
917+
points.append((lat,lon))
918+
self.mpstate.map.add_object(mp_slipmap.SlipPolygon('SIYIThermalFOV', points, layer='SIYI',
919+
linewidth=2, colour=(0,0,120)))
920+
921+
826922
def mavlink_packet(self, m):
827923
'''process a mavlink message'''
828924
mtype = m.get_type()
@@ -836,6 +932,8 @@ def mavlink_packet(self, m):
836932
self.micros64(),
837933
math.degrees(m.roll), math.degrees(m.pitch), math.degrees(m.yaw),
838934
math.degrees(m.rollspeed), math.degrees(m.pitchspeed), math.degrees(m.yawspeed))
935+
if mtype == 'GLOBAL_POSITION_INT':
936+
self.show_thermal_fov()
839937

840938

841939
def idle_task(self):

0 commit comments

Comments
 (0)