/// <summary> /// Configures traffic light for and for all lane types at input segmentId, nodeId, and step. /// </summary> /// <param name="step"></param> /// <param name="nodeId"></param> /// <param name="segmentId"></param> /// <param name="m">Determines which directions are green</param> private static void SetupHelper(ITimedTrafficLightsStep step, ushort nodeId, ushort segmentId, GreenDir m) { bool startNode = (bool)netService.IsStartNode(segmentId, nodeId); //get step data for side seg ICustomSegmentLights liveSegmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode); //for each lane type foreach (ExtVehicleType vehicleType in liveSegmentLights.VehicleTypes) { //set light mode ICustomSegmentLight liveSegmentLight = liveSegmentLights.GetCustomLight(vehicleType); liveSegmentLight.CurrentMode = LightMode.All; TimedLight(nodeId).ChangeLightMode( segmentId, vehicleType, liveSegmentLight.CurrentMode); // set light states var green = RoadBaseAI.TrafficLightState.Green; var red = RoadBaseAI.TrafficLightState.Red; switch (m) { case GreenDir.AllRed: liveSegmentLight.SetStates(red, red, red); break; case GreenDir.AllGreen: liveSegmentLight.SetStates(green, green, green); break; case GreenDir.ShortOnly: { // calculate directions ref ExtSegmentEnd segEnd = ref segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, nodeId)]; ref NetNode node = ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]; segEndMan.CalculateOutgoingLeftStraightRightSegments(ref segEnd, ref node, out bool bLeft, out bool bForward, out bool bRight); bool bShort = RHT ? bRight : bLeft; bool bLong = RHT ? bLeft : bRight; if (bShort) { SetStates(liveSegmentLight, red, red, green); } else if (bLong) { // go forward instead of short SetStates(liveSegmentLight, green, red, red); } else { Debug.LogAssertion("Unreachable code."); liveSegmentLight.SetStates(green, green, green); } break; }
public void SetLights(ICustomSegmentLights otherLights) { foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e in otherLights.CustomLights) { ICustomSegmentLight ourLight = null; if (!CustomLights.TryGetValue(e.Key, out ourLight)) { continue; } ourLight.SetStates(e.Value.LightMain, e.Value.LightLeft, e.Value.LightRight, false); //ourLight.LightPedestrian = e.Value.LightPedestrian; } InternalPedestrianLightState = otherLights.InternalPedestrianLightState; manualPedestrianMode = otherLights.ManualPedestrianMode; AutoPedestrianLightState = otherLights.AutoPedestrianLightState; }
public bool LoadData(List <Configuration.TimedTrafficLights> data) { bool success = true; Log.Info($"Loading {data.Count} timed traffic lights (new method)"); TrafficLightManager tlm = TrafficLightManager.Instance; HashSet <ushort> nodesWithSimulation = new HashSet <ushort>(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { nodesWithSimulation.Add(cnfTimedLights.nodeId); } Dictionary <ushort, ushort> masterNodeIdBySlaveNodeId = new Dictionary <ushort, ushort>(); Dictionary <ushort, List <ushort> > nodeGroupByMasterNodeId = new Dictionary <ushort, List <ushort> >(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { // TODO most of this should not be necessary at all if the classes around TimedTrafficLights class were properly designed List <ushort> currentNodeGroup = cnfTimedLights.nodeGroup.Distinct().ToList(); // enforce uniqueness of node ids if (!currentNodeGroup.Contains(cnfTimedLights.nodeId)) { currentNodeGroup.Add(cnfTimedLights.nodeId); } // remove any nodes that are not configured to have a simulation currentNodeGroup = new List <ushort>(currentNodeGroup.Intersect(nodesWithSimulation)); // remove invalid nodes from the group; find if any of the nodes in the group is already a master node ushort masterNodeId = 0; int foundMasterNodes = 0; for (int i = 0; i < currentNodeGroup.Count;) { ushort nodeId = currentNodeGroup[i]; if (!Services.NetService.IsNodeValid(currentNodeGroup[i])) { currentNodeGroup.RemoveAt(i); continue; } else if (nodeGroupByMasterNodeId.ContainsKey(nodeId)) { // this is a known master node if (foundMasterNodes > 0) { // we already found another master node. ignore this node. currentNodeGroup.RemoveAt(i); continue; } // we found the first master node masterNodeId = nodeId; ++foundMasterNodes; } ++i; } if (masterNodeId == 0) { // no master node defined yet, set the first node as a master node masterNodeId = currentNodeGroup[0]; } // ensure the master node is the first node in the list (TimedTrafficLights depends on this at the moment...) currentNodeGroup.Remove(masterNodeId); currentNodeGroup.Insert(0, masterNodeId); // update the saved node group and master-slave info nodeGroupByMasterNodeId[masterNodeId] = currentNodeGroup; foreach (ushort nodeId in currentNodeGroup) { masterNodeIdBySlaveNodeId[nodeId] = masterNodeId; } } catch (Exception e) { Log.Warning($"Error building timed traffic light group for TimedNode {cnfTimedLights.nodeId} (NodeGroup: {string.Join(", ", cnfTimedLights.nodeGroup.Select(x => x.ToString()).ToArray())}): " + e.ToString()); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { if (!masterNodeIdBySlaveNodeId.ContainsKey(cnfTimedLights.nodeId)) { continue; } ushort masterNodeId = masterNodeIdBySlaveNodeId[cnfTimedLights.nodeId]; List <ushort> nodeGroup = nodeGroupByMasterNodeId[masterNodeId]; Log._Debug($"Adding timed light at node {cnfTimedLights.nodeId}. NodeGroup: {string.Join(", ", nodeGroup.Select(x => x.ToString()).ToArray())}"); ITrafficLightSimulation sim = AddNodeToSimulation(cnfTimedLights.nodeId); sim.SetupTimedTrafficLight(nodeGroup); var timedNode = sim.TimedLight; int j = 0; foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps) { Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}"); ITimedTrafficLightsStep step = timedNode.AddStep(cnfTimedStep.minTime, cnfTimedStep.maxTime, (TrafficLight.StepChangeMetric)cnfTimedStep.changeMetric, cnfTimedStep.waitFlowBalance); foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in cnfTimedStep.segmentLights) { if (!Services.NetService.IsSegmentValid(e.Key)) { continue; } e.Value.nodeId = cnfTimedLights.nodeId; Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}"); ICustomSegmentLights lights = null; if (!step.CustomSegmentLights.TryGetValue(e.Key, out lights)) { Log._Debug($"No segment lights found at timed step {j} for segment {e.Key}, node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLights cnfLights = e.Value; Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: {cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}"); lights.ManualPedestrianMode = cnfLights.manualPedestrianMode; lights.PedestrianLightState = cnfLights.pedestrianLightState; foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2 in cnfLights.customLights) { Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); ICustomSegmentLight light = null; if (!lights.CustomLights.TryGetValue(e2.Key, out light)) { Log._Debug($"No segment light found for timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLight cnfLight = e2.Value; light.InternalCurrentMode = (TrafficLight.LightMode)cnfLight.currentMode; // TODO improve & remove light.SetStates(cnfLight.mainLight, cnfLight.leftLight, cnfLight.rightLight, false); } } ++j; } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from TimedNode (new method): " + e.ToString()); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { ITrafficLightSimulation sim = GetNodeSimulation(cnfTimedLights.nodeId); if (sim == null || sim.TimedLight == null) { continue; } var timedNode = sim.TimedLight; timedNode.Housekeeping(); if (cnfTimedLights.started) { timedNode.Start(cnfTimedLights.currentStep); } } catch (Exception e) { Log.Warning($"Error starting timed light @ {cnfTimedLights.nodeId}: " + e.ToString()); success = false; } } return(success); }