public void SetLights(bool noTransition) { try { bool atEndTransition = !noTransition && isInEndTransition(); // = yellow bool atStartTransition = !noTransition && !atEndTransition && isInStartTransition(); // = red + yellow TimedTrafficStep previousStep = timedNode.Steps[(timedNode.CurrentStep + timedNode.Steps.Count - 1) % timedNode.Steps.Count]; TimedTrafficStep nextStep = timedNode.Steps[(timedNode.CurrentStep + 1) % timedNode.Steps.Count]; foreach (KeyValuePair <ushort, ManualSegmentLight> e in segmentLightStates) { var segmentId = e.Key; var segLightState = e.Value; var prevLightState = previousStep.segmentLightStates[segmentId]; var nextLightState = nextStep.segmentLightStates[segmentId]; var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segmentId); if (segmentLight == null) { continue; } segmentLight.LightMain = calcLightState(prevLightState.LightMain, segLightState.LightMain, nextLightState.LightMain, atStartTransition, atEndTransition); segmentLight.LightLeft = calcLightState(prevLightState.LightLeft, segLightState.LightLeft, nextLightState.LightLeft, atStartTransition, atEndTransition); segmentLight.LightRight = calcLightState(prevLightState.LightRight, segLightState.LightRight, nextLightState.LightRight, atStartTransition, atEndTransition); segmentLight.LightPedestrian = calcLightState(prevLightState.LightPedestrian, segLightState.LightPedestrian, nextLightState.LightPedestrian, atStartTransition, atEndTransition); segmentLight.UpdateVisuals(); } } catch (Exception e) { Log.Error($"Exception in TimedTrafficStep.SetLights: {e.Message}"); invalid = true; } }
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); }