public static void RemoveNodeFromSimulation(ushort nodeId)
        {
            //lock (simLock) {
            if (!LightSimByNodeId.ContainsKey(nodeId))
            {
                return;
            }
            var nodeSim      = LightSimByNodeId[nodeId];
            var isTimedLight = nodeSim.TimedTrafficLights;
            TrafficLightsTimed timedLights = null;

            if (isTimedLight)
            {
                timedLights = TrafficLightsTimed.GetTimedLight(nodeId);
            }
            nodeSim.Destroy();
            if (isTimedLight && timedLights != null)
            {
                foreach (ushort otherNodeId in timedLights.NodeGroup)
                {
                    Log.Message($"Removing simulation @ node {otherNodeId} (group)");
                    LightSimByNodeId.Remove(otherNodeId);
                }
            }
            LightSimByNodeId.Remove(nodeId);
            //}
        }
Пример #2
0
        private bool invalid = false;         // TODO rework

        public TimedTrafficStep(int minTime, int maxTime, ushort nodeId, ushort masterNodeId, List <ushort> groupNodeIds)
        {
            this.nodeId    = nodeId;
            this.minTime   = minTime;
            this.maxTime   = maxTime;
            this.timedNode = TrafficLightsTimed.GetTimedLight(nodeId);

            if (nodeId == masterNodeId)
            {
                this.masterNodeId = null;
            }
            else
            {
                this.masterNodeId = masterNodeId;
            }
            this.groupNodeIds = groupNodeIds;

            var node = TrafficLightTool.GetNetNode(nodeId);

            minFlow = Single.NaN;
            maxWait = Single.NaN;

            endTransitionStart = -1;
            stepDone           = false;

            for (var s = 0; s < 8; s++)
            {
                var segmentId = node.GetSegment(s);
                if (segmentId <= 0)
                {
                    continue;
                }

                addSegment(segmentId);
            }
            rebuildSegmentIds();
        }
        public static void housekeeping()
        {
            try {
                // delete invalid segments
                List <ushort> segmentIdsToDelete = new List <ushort>();
                foreach (KeyValuePair <ushort, TrafficSegment> e in PrioritySegments)
                {
                    var segmentId = e.Key;
                    if (segmentId <= 0)
                    {
                        segmentIdsToDelete.Add(segmentId);
                        continue;
                    }

                    NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId];
                    if (segment.m_flags == NetSegment.Flags.None || (!priorityNodes.Contains(segment.m_startNode) && !priorityNodes.Contains(segment.m_endNode)))
                    {
                        segmentIdsToDelete.Add(segmentId);
                    }
                }

                foreach (var sId in segmentIdsToDelete)
                {
                    Log.Warning("Housekeeping: Deleting segment " + sId);
                    PrioritySegments.Remove(sId);
                    TrafficLightsManual.RemoveSegmentLight(sId);
                }

                // delete invalid nodes
                List <ushort> nodeIdsToDelete = new List <ushort>();
                foreach (ushort nodeId in priorityNodes)
                {
                    NodeValidityState nodeState = NodeValidityState.Valid;
                    if (!isValidPriorityNode(nodeId, out nodeState))
                    {
                        if (nodeState != NodeValidityState.SimWithoutLight)
                        {
                            nodeIdsToDelete.Add(nodeId);
                        }

                        switch (nodeState)
                        {
                        case NodeValidityState.SimWithoutLight:
                            Log.Warning("Housekeeping: Re-adding traffic light at node " + nodeId);
                            Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_flags |= NetNode.Flags.TrafficLights;
                            break;

                        case NodeValidityState.Unused:
                            // delete traffic light simulation
                            Log.Warning("Housekeeping: RemoveNodeFromSimulation " + nodeId);
                            RemoveNodeFromSimulation(nodeId);
                            break;

                        default:
                            break;
                        }
                    }
                }

                foreach (var nId in nodeIdsToDelete)
                {
                    Log.Warning("Housekeeping: Deleting node " + nId);
                    RemovePrioritySegments(nId);
                }

                // add newly created segments to timed traffic lights
                foreach (KeyValuePair <ushort, TrafficLightsTimed> e in TrafficLightsTimed.TimedScripts)
                {
                    TrafficLightsTimed timedLights = e.Value;
                    ushort             nodeId      = e.Key;

                    timedLights.handleNewSegments();
                }
            } catch (Exception e) {
                Log.Warning($"Housekeeping failed: {e.Message}");
            }
        }
        private static bool isValidPriorityNode(ushort nodeId, out NodeValidityState nodeState)
        {
            nodeState = NodeValidityState.Valid;

            if (nodeId <= 0)
            {
                nodeState = NodeValidityState.Invalid;
                return(false);
            }

            var node = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId];

            if (node.m_flags == NetNode.Flags.None)
            {
                nodeState = NodeValidityState.Unused;
                return(false);                // node is unused
            }

            var nodeSim = GetNodeSimulation(nodeId);

            if (nodeSim != null)
            {
                if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    // traffic light simulation is active but node does not have a traffic light
                    nodeState = NodeValidityState.SimWithoutLight;
                    return(false);
                }
                else
                {
                    // check if all timed step segments are valid
                    if (nodeSim.FlagTimedTrafficLights && nodeSim.TimedTrafficLightsActive)
                    {
                        TrafficLightsTimed timedLight = TrafficLightsTimed.GetTimedLight(nodeId);
                        if (timedLight == null || timedLight.Steps.Count <= 0)
                        {
                            Log.Warning("Housekeeping: Timed light is null or no steps!");
                            RemoveNodeFromSimulation(nodeId);
                            return(false);
                        }

                        /*foreach (var segmentId in timedLight.Steps[0].segmentIds) {
                         *      if (! IsPrioritySegment(nodeId, segmentId)) {
                         *              Log.Warning("Housekeeping: Timed light - Priority segment has gone away!");
                         *              RemoveNodeFromSimulation(nodeId);
                         *              return false;
                         *      }
                         * }*/
                    }
                    return(true);
                }
            }
            else
            {
                bool ok = false;
                for (var s = 0; s < 8; s++)
                {
                    var segmentId = node.GetSegment(s);
                    if (segmentId <= 0)
                    {
                        continue;
                    }
                    NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId];
                    if (segment.m_startNode != nodeId && segment.m_endNode != nodeId)
                    {
                        continue;
                    }

                    PrioritySegment prioritySegment = GetPrioritySegment(nodeId, segmentId);
                    if (prioritySegment == null)
                    {
                        continue;
                    }

                    // if node is a traffic light, it must not have priority signs
                    if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
                    {
                        prioritySegment.Type = PrioritySegment.PriorityType.None;
                    }

                    // if a priority sign is set, everything is ok
                    if (prioritySegment.Type != PrioritySegment.PriorityType.None)
                    {
                        ok = true;
                        break;
                    }
                }

                if (!ok)
                {
                    nodeState = NodeValidityState.NoValidSegments;
                }
                return(ok);
            }
        }
Пример #5
0
        public bool StepDone()
        {
            if (stepDone)
            {
                return(true);
            }

            if (startFrame + maxTime <= getCurrentFrame())
            {
                // maximum time reached. switch!
#if DEBUG
                //Log.Message("step finished @ " + nodeId);
#endif
                stepDone           = true;
                endTransitionStart = (int)getCurrentFrame();
                return(stepDone);
            }

            if (startFrame + minTime <= getCurrentFrame())
            {
                if (masterNodeId != null && TrafficLightsTimed.IsTimedLight((ushort)masterNodeId))
                {
                    TrafficLightsTimed masterTimedNode = TrafficLightsTimed.GetTimedLight((ushort)masterNodeId);
                    bool done = masterTimedNode.Steps[masterTimedNode.CurrentStep].StepDone();
#if DEBUG
                    //Log.Message("step finished (1) @ " + nodeId);
#endif
                    stepDone = done;
                    if (stepDone)
                    {
                        endTransitionStart = (int)getCurrentFrame();
                    }
                    return(stepDone);
                }
                else
                {
                    int   numFlows    = 0;
                    int   numWaits    = 0;
                    float curMeanFlow = 0;
                    float curMeanWait = 0;

                    // we are the master node. calculate traffic data
                    foreach (ushort timedNodeId in groupNodeIds)
                    {
                        if (!TrafficLightsTimed.IsTimedLight(timedNodeId))
                        {
                            continue;
                        }
                        TrafficLightsTimed slaveTimedNode = TrafficLightsTimed.GetTimedLight(timedNodeId);
                        TimedTrafficStep   slaveStep      = slaveTimedNode.Steps[timedNode.CurrentStep];

                        //List<int> segmentIdsToDelete = new List<int>();

                        // minimum time reached. check traffic!
                        foreach (KeyValuePair <ushort, ManualSegmentLight> e in slaveStep.segmentLightStates)
                        {
                            var   fromSegmentId = e.Key;
                            var   segLightState = e.Value;
                            float segmentWeight = Singleton <NetManager> .instance.m_segments.m_buffer[fromSegmentId].m_averageLength / maxSegmentLength;

                            // one of the traffic lights at this segment is green: count minimum traffic flowing through
                            PrioritySegment prioSeg = TrafficPriority.GetPrioritySegment(timedNodeId, fromSegmentId);
                            if (prioSeg == null)
                            {
                                //Log.Warning("stepDone(): prioSeg is null");
                                //segmentIdsToDelete.Add(fromSegmentId);
                                continue;                                 // skip invalid segment
                            }
                            foreach (KeyValuePair <ushort, int> f in prioSeg.numCarsGoingToSegmentId)
                            {
                                var toSegmentId = f.Key;
                                var numCars     = f.Value;

                                TrafficPriority.Direction dir = TrafficPriority.GetDirection(fromSegmentId, toSegmentId, timedNodeId);
                                bool addToFlow = false;
                                switch (dir)
                                {
                                case TrafficPriority.Direction.Left:
                                    if (segLightState.isLeftGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;

                                case TrafficPriority.Direction.Right:
                                    if (segLightState.isRightGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;

                                case TrafficPriority.Direction.Forward:
                                default:
                                    if (segLightState.isForwardGreen())
                                    {
                                        addToFlow = true;
                                    }
                                    break;
                                }

                                if (addToFlow)
                                {
                                    ++numFlows;
                                    curMeanFlow += (float)numCars * segmentWeight;
                                }
                                else
                                {
                                    ++numWaits;
                                    curMeanWait += (float)numCars * segmentWeight;
                                }
                            }
                        }

                        // delete invalid segments from step

                        /*foreach (int segmentId in segmentIdsToDelete) {
                         *      slaveStep.segmentLightStates.Remove(segmentId);
                         * }*/

                        if (slaveStep.segmentLightStates.Count <= 0)
                        {
                            invalid = true;
                            return(true);
                        }
                    }

                    if (numFlows > 0)
                    {
                        curMeanFlow /= (float)numFlows;
                    }
                    if (numWaits > 0)
                    {
                        curMeanWait /= (float)numWaits;
                    }

                    float decisionValue = 0.8f;                     // a value smaller than 1 rewards steady traffic currents
                    curMeanFlow /= decisionValue;

                    if (Single.IsNaN(minFlow))
                    {
                        minFlow = curMeanFlow;
                    }
                    else
                    {
                        minFlow = Math.Min(curMeanFlow, minFlow);
                    }

                    if (Single.IsNaN(maxWait))
                    {
                        maxWait = curMeanWait;
                    }
                    else
                    {
                        maxWait = Math.Max(curMeanWait, maxWait);
                    }

                    // if more cars are waiting than flowing, we change the step
                    bool done = maxWait > 0 && minFlow < maxWait;
#if DEBUG
                    //Log.Message("step finished (2) @ " + nodeId);
#endif
                    stepDone = done;
                    if (stepDone)
                    {
                        endTransitionStart = (int)getCurrentFrame();
                    }
                    return(stepDone);
                }
            }
            return(false);
        }