Example #1
0
        private static void CreateTrackingInfo(Trolley trolley)
        {
            var newTrackingInfo = new TrolleyTrackingInfo(trolley);

            if (activeRoutes.Count == 1)
            {
                // For a single active route, all trolleys follow that route
                newTrackingInfo.CurrentRoute = activeRoutes.First().Value;
            }
            trolleyTrackingInfo.Add(trolley.ID, newTrackingInfo);
        }
Example #2
0
        private static void UpdateStopTime(TrolleyTrackingInfo trackingInfo)
        {
            // See if trolley has moved far enough to justify a full stop distance check
            var currentLocation = new Coordinate((double)trackingInfo.CurrentTrolley.CurrentLat, (double)trackingInfo.CurrentTrolley.CurrentLon);

            if (currentLocation.Distance(trackingInfo.LastReportedLocation) > MinMoveDistance)
            {
                // Heading will be integer 0..359
                trackingInfo.CurrentHeading = ((int)(trackingInfo.LastReportedLocation.DirectionToward(currentLocation) + 0.5)) % 360;
                CheckForStopInRange(trackingInfo, currentLocation);
                trackingInfo.LastReportedLocation = currentLocation;
            }
        }
Example #3
0
        /// <summary>
        /// Find stop index in the ordered stop list
        /// </summary>
        /// <param name="trackingInfo"></param>
        /// <param name="stopID"></param>
        /// <returns>Stop index or -1 if not found</returns>
        private static int FindRouteStopIndex(TrolleyTrackingInfo trackingInfo, int stopID)
        {
            var stopIndex = -1;

            for (int i = 0; i < trackingInfo.CurrentRoute.RouteStops.Count; i++)
            {
                if (trackingInfo.CurrentRoute.RouteStops[i].StopID == stopID)
                {
                    stopIndex = i;
                    break;
                }
            }
            return(stopIndex);
        }
Example #4
0
        /// <summary>
        /// Test that route path next to this stop is heading in the same direction as trolley,
        /// and not the return path
        /// </summary>
        /// <param name="trackingInfo">Tracking info - CurrentRouteStop and PreviousRouteStop will be assigned here</param>
        /// <param name="currentLocation"></param>
        /// <param name="stopSummary"></param>
        /// <returns></returns>
        private static bool StopIsOnRight(TrolleyTrackingInfo trackingInfo, Coordinate currentLocation, StopSummary stopSummary)
        {
            // Find route direction at our current location (stop)
            var routeStopIndex = FindRouteStopIndex(trackingInfo, stopSummary.ID);

            if (routeStopIndex < 0)
            {
                Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Route Stop Index not found");
                return(false);
            }
            var routeStop = trackingInfo.CurrentRoute.RouteStops[routeStopIndex];
            var numStops  = trackingInfo.CurrentRoute.RouteStops.Count;

            trackingInfo.PreviousRouteStop     = trackingInfo.CurrentRoute.RouteStops[(routeStopIndex + numStops - 1) % numStops];
            trackingInfo.CurrentRouteStop      = routeStop;
            trackingInfo.CurrentRouteStopIndex = routeStopIndex;
            var routeSegmentIndex = routeStop.RouteSegmentIndex;

            if (routeSegmentIndex < 0)
            {
                Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Route Stop Index not set");
                return(false);
            }

            var segmentCount      = trackingInfo.CurrentRoute.Shapes.Count;
            var segmentEnd        = trackingInfo.CurrentRoute.Shapes[routeSegmentIndex];
            var segmentStart      = trackingInfo.CurrentRoute.Shapes[(routeSegmentIndex + segmentCount - 1) % segmentCount];
            var routeSegmentStart = new Coordinate(segmentStart.Lat, segmentStart.Lon);
            var routeSegmentEnd   = new Coordinate(segmentEnd.Lat, segmentEnd.Lon);
            var routeDirection    = routeSegmentStart.DirectionToward(routeSegmentEnd);
            var trolleyDirection  = trackingInfo.CurrentHeading;

            // Convert directions from 0..360 to +/-180 for comparison
            if (routeDirection > 180)
            {
                routeDirection = routeDirection - 360;
            }
            if (trolleyDirection > 180)
            {
                trolleyDirection = trolleyDirection - 360;
            }


            Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Route direction: {routeDirection}, trolley heading: {trolleyDirection}");
            if (Math.Abs((int)routeDirection - trolleyDirection) < 130)
            {
                return(true);
            }
            return(false);
        }
Example #5
0
        /// <summary>
        /// Calculate and update travel time from previous to current stop
        /// </summary>
        /// <param name="trackingInfo"></param>
        private static void UpdateTravelTime(TrolleyTrackingInfo trackingInfo)
        {
            var routeStop = trackingInfo.CurrentRouteStop;

            if (routeStop == null)
            {
                return;
            }
            var lastRouteStop = trackingInfo.PreviousRouteStop;

            if (!lastRouteStop.LastTimeAtStop.HasValue)
            {
                return;
            }
            var elapsedSeconds = (routeStop.LastTimeAtStop - lastRouteStop.LastTimeAtStop).Value.TotalSeconds;

            if (elapsedSeconds > MaxTimeBetweenStops)
            {
                // Invalid time - likely from a long break or first stop of the day
                return;
            }

            var newTravelTime = (int)elapsedSeconds;

            if (routeStop.AverageTravelTimeToNextStop != 0)
            {
                // Average is approximted by a weighted moving average instead of true moving average
                int percentWeight = 50;
                var adjustment    = (newTravelTime - routeStop.AverageTravelTimeToNextStop) * percentWeight / 100;

                // Avoid having a single anomaly create a large swing
                if (Math.Abs(adjustment) > (routeStop.AverageTravelTimeToNextStop / 2))
                {
                    adjustment = (routeStop.AverageTravelTimeToNextStop / 2) * Math.Sign(adjustment);
                }

                newTravelTime = routeStop.AverageTravelTimeToNextStop + adjustment;

                if (newTravelTime < MinTimeBetweenStops)
                {
                    newTravelTime = MinTimeBetweenStops;
                }
            }
            routeStop.AverageTravelTimeToNextStop = newTravelTime;

            UpdateTravelTimeInDB(routeStop);
        }
Example #6
0
        /// <summary>
        /// Check for stop proximity - try to minimize number of polled stops
        ///   - First preference is the previous stop
        ///    Then loop through all stops
        /// </summary>
        /// <param name="trackingInfo"></param>
        /// <param name="currentLocation"></param>
        private static void CheckForStopInRange(TrolleyTrackingInfo trackingInfo, Coordinate currentLocation)
        {
            if (stopSummaries.ContainsKey(trackingInfo.LastStopID))
            {
                // Test if Still within stop zone
                var stopSummary = stopSummaries[trackingInfo.LastStopID];
                if (currentLocation.Distance(new Coordinate(stopSummary.Lat, stopSummary.Lon)) < StopRadiusCheck)
                {
                    return;
                }
                Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Left stop zone {stopSummary.Name}");
            }

            if (trackingInfo.CurrentRoute == null)
            {
                return;                                     // No route found to assign to trolley
            }
            foreach (var routeStop in trackingInfo.CurrentRoute.RouteStops)
            {
                var stopID      = routeStop.StopID;
                var stopSummary = stopSummaries[stopID];
                if (currentLocation.Distance(new Coordinate(stopSummary.Lat, stopSummary.Lon)) < StopRadiusCheck)
                {
                    Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Entered stop zone {stopSummary.Name}");
                    // Found new stop zone; validate that it's an upcoming stop on right side and not on the left side
                    // (which would be on the return trip)
                    if (StopIsOnRight(trackingInfo, currentLocation, stopSummary))
                    {
                        UpdateStopArrivalTime(trackingInfo.CurrentRouteStop);
                        UpdateTravelTime(trackingInfo);

                        PredictStopArrivalTimes(trackingInfo);

                        trackingInfo.LastStopID = stopSummary.ID;
                        Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Stop was on right {stopSummary.Name}");
                        return;
                    }
                    else
                    {
                        Debug.WriteLine($"Trolley {trackingInfo.CurrentTrolley.Number} Stop not on right {stopSummary.Name}");
                    }
                }
            }

            // Not currently in any stop zone
            trackingInfo.LastStopID = -1;
        }
Example #7
0
        /// <summary>
        /// Set or refresh stop arrival times for all stops on this route based on just arriving at current stop
        /// </summary>
        /// <param name="trackingInfo"></param>
        /// <param name="currentLocation"></param>
        /// <param name="stopSummary"></param>
        private static void PredictStopArrivalTimes(TrolleyTrackingInfo trackingInfo)
        {
            var trolleyNumber = trackingInfo.CurrentTrolley.Number;

            var now           = UTCToLocalTime.LocalTimeFromUTC(DateTime.UtcNow);
            var stopsCount    = trackingInfo.CurrentRoute.RouteStops.Count;
            int travelSeconds = 0;  // Total travel time from current stop

            for (var i = 0; i <= stopsCount; i++)
            {
                var stopIndex = (trackingInfo.CurrentRouteStopIndex + i) % stopsCount;
                var routeStop = trackingInfo.CurrentRoute.RouteStops[stopIndex];
                if (routeStop.LastTimeAtStop.HasValue)
                {
                    var timeAtStop        = now.AddSeconds(travelSeconds);
                    var previousRouteStop = trackingInfo.CurrentRoute.RouteStops[(stopIndex + stopsCount - 1) % stopsCount];
                    var previousSummary   = stopSummaries[previousRouteStop.StopID];
                    SetArrivalTime(trolleyNumber, previousSummary, timeAtStop);
                    travelSeconds += routeStop.AverageTravelTimeToNextStop;
                }
            }
        }