@@ -3,6 +3,52 @@ import { Feature } from '@tak-ps/node-cot';
33import ETL , { Event , SchemaType , handler as internal , local , DataFlowType , InvocationType } from '@tak-ps/etl' ;
44import { fetch } from '@tak-ps/etl' ;
55
6+ /**
7+ * Calculate the bearing (azimuth) from point 1 to point 2.
8+ * @param lat1 - Latitude of starting point (degrees)
9+ * @param lon1 - Longitude of starting point (degrees)
10+ * @param lat2 - Latitude of destination point (degrees)
11+ * @param lon2 - Longitude of destination point (degrees)
12+ * @returns Bearing in degrees (0-360, where 0 is north)
13+ */
14+ function calculateBearing ( lat1 : number , lon1 : number , lat2 : number , lon2 : number ) : number {
15+ const lat1Rad = lat1 * Math . PI / 180 ;
16+ const lat2Rad = lat2 * Math . PI / 180 ;
17+ const deltaLon = ( lon2 - lon1 ) * Math . PI / 180 ;
18+
19+ const x = Math . sin ( deltaLon ) * Math . cos ( lat2Rad ) ;
20+ const y = Math . cos ( lat1Rad ) * Math . sin ( lat2Rad ) -
21+ Math . sin ( lat1Rad ) * Math . cos ( lat2Rad ) * Math . cos ( deltaLon ) ;
22+
23+ const bearing = Math . atan2 ( x , y ) * 180 / Math . PI ;
24+
25+ // Normalize to 0-360
26+ return ( bearing + 360 ) % 360 ;
27+ }
28+
29+ /**
30+ * Calculate the distance between two points using Haversine formula.
31+ * @param lat1 - Latitude of point 1 (degrees)
32+ * @param lon1 - Longitude of point 1 (degrees)
33+ * @param lat2 - Latitude of point 2 (degrees)
34+ * @param lon2 - Longitude of point 2 (degrees)
35+ * @returns Distance in meters
36+ */
37+ function calculateDistance ( lat1 : number , lon1 : number , lat2 : number , lon2 : number ) : number {
38+ const R = 6371000 ; // Earth's radius in meters
39+
40+ const lat1Rad = lat1 * Math . PI / 180 ;
41+ const lat2Rad = lat2 * Math . PI / 180 ;
42+ const deltaLat = ( lat2 - lat1 ) * Math . PI / 180 ;
43+ const deltaLon = ( lon2 - lon1 ) * Math . PI / 180 ;
44+
45+ const a = Math . sin ( deltaLat / 2 ) ** 2 +
46+ Math . cos ( lat1Rad ) * Math . cos ( lat2Rad ) * Math . sin ( deltaLon / 2 ) ** 2 ;
47+ const c = 2 * Math . atan2 ( Math . sqrt ( a ) , Math . sqrt ( 1 - a ) ) ;
48+
49+ return R * c ;
50+ }
51+
652const DroneSenseLocation = Type . Object ( {
753 id : Type . String ( ) ,
854 callSign : Type . String ( ) ,
@@ -130,6 +176,38 @@ export default class Task extends ETL {
130176 }
131177 }
132178
179+ // Add sensor FOV when SPOI (Sensor Point of Interest) data is available
180+ // SPOI indicates where the drone's camera is pointing
181+ if ( record . spoiLat !== 0 && record . spoiLng !== 0 ) {
182+ const azimuth = calculateBearing (
183+ record . latitude , record . longitude ,
184+ record . spoiLat , record . spoiLng
185+ ) ;
186+ const range = calculateDistance (
187+ record . latitude , record . longitude ,
188+ record . spoiLat , record . spoiLng
189+ ) ;
190+
191+ feat . properties . sensor = {
192+ azimuth : azimuth ,
193+ fov : 45 ,
194+ vfov : 45 ,
195+ range : range ,
196+ elevation : 0 ,
197+ roll : 0 ,
198+ displayMagneticReference : 0 ,
199+ strokeColor : - 16777216 ,
200+ strokeWeight : 0.5 ,
201+ fovRed : 1.0 ,
202+ fovGreen : 0.5 ,
203+ fovBlue : 0.0 ,
204+ fovAlpha : 0.3 ,
205+ rangeLines : 100 ,
206+ rangeLineStrokeColor : - 16777216 ,
207+ rangeLineStrokeWeight : 1.0
208+ } ;
209+ }
210+
133211 fc . features . push ( feat ) ;
134212 }
135213
0 commit comments