public static int DistanceToGeoPositionMeters(this IGeographicPosition pos1, IGeographicPosition pos2) { var dLat = deg2rad(pos2.PositionLatDegrees - pos1.PositionLatDegrees); var dLon = deg2rad(pos2.PositionLonDegrees - pos1.PositionLonDegrees); var lat1 = deg2rad(pos1.PositionLatDegrees); var lat2 = deg2rad(pos2.PositionLatDegrees); var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2); var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return (int) Math.Round(meanEarthRadius * c * 1000); }
/// <summary> /// Subscribe an observation point (lat / lon / elevation) and attach a callback for detected events. /// </summary> /// <param name="airfieldKey">a definable key</param> /// <param name="airfieldPosition">position and elevation of the observation point (usually an airfield)</param> /// <param name="eventDetectedCallback">callback on event detected</param> public void SubscribeAirfieldForMovmentEvents(string airfieldKey, IGeographicPosition airfieldPosition, Action<AircraftTrackEvent> eventDetectedCallback = null) { if(airfieldSubscriptions.ContainsKey(airfieldKey)) { if(eventDetectedCallback != null) airfieldSubscriptions[airfieldKey].EventDetected += eventDetectedCallback; return; } var subscription = new AirfieldSubscription { AirfieldKey = airfieldKey, AirfieldPosition = airfieldPosition }; if (eventDetectedCallback != null) subscription.EventDetected += eventDetectedCallback; airfieldSubscriptions.Add(airfieldKey, subscription); }
public static float InitialBearingToGeoPositionDegrees(this IGeographicPosition pos1, IGeographicPosition pos2) { var lat1 = deg2rad(pos1.PositionLatDegrees); // φ1 var lat2 = deg2rad(pos2.PositionLatDegrees); // φ2 var lon1 = deg2rad(pos1.PositionLonDegrees); // λ1 var lon2 = deg2rad(pos2.PositionLonDegrees); // λ2 var dLat = deg2rad(pos2.PositionLatDegrees - pos1.PositionLatDegrees); // Δφ var dLon = deg2rad(pos2.PositionLonDegrees - pos1.PositionLonDegrees); // Δλ var y = Math.Sin(dLon) * Math.Cos(lat2); var x = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLon); var bearing = rad2deg(Math.Atan2(y, x)); if (bearing < 0d) bearing += 360d; return (float) Math.Round(bearing, 1); }
public static IEnumerable<AircraftTrackEvent> DetectTrackEvents(this CircularFifoBuffer<AircraftBeaconSpeedAndTrack> fifoBuffer, DateTime evalDateTimeUtc, TimeSpan maxTimeSpan, IGeographicPosition eventTargetCenter) { var events = new List<AircraftTrackEvent>(); List<AircraftBeaconSpeedAndTrack> evalWindow = fifoBuffer.extractAndReverseBufferForEvalWindow(evalDateTimeUtc, maxTimeSpan, getAlreadyAnalysed: true); // we need 4 beacons to detect - two one state - two other state if (evalWindow.Count < 4) return events; int i = 0; while(++i <= evalWindow.Count - 4) { var subWindow = evalWindow.Skip(i).Take(4).ToArray(); // accuracy check if (subWindow[3].PositionTimeUTC.Subtract(subWindow[0].PositionTimeUTC).TotalSeconds > accuracyCheck4BeaconsMaxTimeSpanSeconds) continue; bool landing = subWindow[0].isMoving() && subWindow[1].isMoving() && subWindow[2].isStoppedOnGround(eventTargetCenter.PositionAltitudeMeters) && subWindow[2].isWithinRefPositionRange(eventTargetCenter) && subWindow[3].isStoppedOnGround(eventTargetCenter.PositionAltitudeMeters) && subWindow[3].isWithinRefPositionRange(eventTargetCenter); if (landing) events.Add(new AircraftTrackEvent { EventType = AircraftTrackEventTypes.Landing, EventDateTimeUTC = subWindow[2].PositionTimeUTC, ReferenceBeacon = subWindow[2] }); bool takeOff = subWindow[0].isStoppedOnGround(eventTargetCenter.PositionAltitudeMeters) && subWindow[0].isWithinRefPositionRange(eventTargetCenter) && subWindow[1].isStoppedOnGround(eventTargetCenter.PositionAltitudeMeters) && subWindow[1].isWithinRefPositionRange(eventTargetCenter) && subWindow[2].isMoving() && subWindow[3].isMoving(); if (takeOff) events.Add(new AircraftTrackEvent { EventType = AircraftTrackEventTypes.TakeOff, EventDateTimeUTC = subWindow[1].PositionTimeUTC, ReferenceBeacon = subWindow[2] }); } return events.Distinct(new AircraftTrackEventComparer()); }
private static bool isWithinRefPositionRange(this AircraftBeaconSpeedAndTrack beacon, IGeographicPosition refPos) => beacon.DistanceToGeoPositionMeters(refPos) <= airportRangeRadiusMeters;