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 CustomCheckTrafficLights(ushort node, ushort segment) { var nodeSimulation = TrafficPriority.GetNodeSimulation(node); var instance = Singleton <NetManager> .instance; var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num = (uint)((node << 8) / 32768); var num2 = currentFrameIndex - num & 255u; RoadBaseAI.TrafficLightState pedestrianLightState; ManualSegmentLight light = TrafficLightsManual.GetSegmentLight(node, segment); if (light == null || nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive)) { RoadBaseAI.TrafficLightState vehicleLightState; bool vehicles; bool pedestrians; RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && num2 >= 196u) { RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true); return(true); } } else { pedestrianLightState = light.GetLightPedestrian(); } switch (pedestrianLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num2 < 60u) { return(false); } break; case RoadBaseAI.TrafficLightState.Red: case RoadBaseAI.TrafficLightState.GreenToRed: return(false); } return(true); }
/// <summary> /// Updates timed segment lights according to "real-world" traffic light states /// </summary> public void UpdateLights() { foreach (KeyValuePair <ushort, ManualSegmentLight> e in segmentLightStates) { var segmentId = e.Key; var segLightState = e.Value; //if (segment == 0) continue; var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segmentId); if (segmentLight == null) { continue; } segLightState.LightMain = segmentLight.LightMain; segLightState.LightLeft = segmentLight.LightLeft; segLightState.LightRight = segmentLight.LightRight; segLightState.LightPedestrian = segmentLight.LightPedestrian; } }
public void TmCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed) { var netManager = Singleton <NetManager> .instance; //var vehicleManager = Singleton<VehicleManager>.instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir); var lastFrameData = vehicleData.GetLastFrameData(); var lastFrameVehiclePos = lastFrameData.m_position; if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { // add vehicle to our vehicle list if (!TrafficPriority.VehicleList.ContainsKey(vehicleId)) { TrafficPriority.VehicleList.Add(vehicleId, new PriorityCar()); } } HandleVehicle(vehicleId, ref vehicleData); // I think this is supposed to be the lane position? // [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane. // This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position. var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f); //ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment; ushort destinationNodeId; ushort sourceNodeId; if (offset < position.m_offset) { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; } else { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; } var interestingNodeId = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode; // this seems to be like the required braking force in order to stop the vehicle within its half length. var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f; // Essentially, this is true if the car has enough time and space to brake (e.g. for a red traffic light) if (destinationNodeId == interestingNodeId) { if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) { var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num5 = (uint)((interestingNodeId << 8) / 32768); var num6 = currentFrameIndex - num5 & 255u; var nodeFlags = netManager.m_nodes.m_buffer[destinationNodeId].m_flags; var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags; var hasTrafficLight = (nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; var hasCrossing = (nodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None; var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None; if ((nodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && netManager.m_nodes.m_buffer[destinationNodeId].CountSegments() != 2) { var len = vehicleData.CalculateTotalLength(vehicleId) + 2f; if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) { var sufficientSpace = false; if (nextPosition.m_segment != 0 && netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) { var flags3 = netManager.m_nodes.m_buffer[sourceNodeId].m_flags; if ((flags3 & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || netManager.m_nodes.m_buffer[sourceNodeId].CountSegments() == 2) { var laneId2 = PathManager.GetLaneID(nextPosition); if (laneId2 != 0u) { sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId2)].CheckSpace(len); } } } if (!sufficientSpace) { maxSpeed = 0f; return; } } } if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { if (hasTrafficLight && (!isJoinedJunction || hasCrossing)) { var nodeSimulation = TrafficPriority.GetNodeSimulation(interestingNodeId); var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info; RoadBaseAI.TrafficLightState vehicleLightState; ManualSegmentLight light = TrafficLightsManual.GetSegmentLight(interestingNodeId, prevPos.m_segment); // TODO rework if (light == null || nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive)) { RoadBaseAI.TrafficLightState pedestrianLightState; bool flag5; bool pedestrians; RoadBaseAI.GetTrafficLightState(interestingNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5, out pedestrians); if (!flag5 && num6 >= 196u) { flag5 = true; RoadBaseAI.SetTrafficLightState(interestingNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, flag5, pedestrians); } if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None || destinationInfo.m_class.m_service != ItemClass.Service.Road) { switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num6 < 60u) { maxSpeed = 0f; return; } break; case RoadBaseAI.TrafficLightState.Red: maxSpeed = 0f; return; case RoadBaseAI.TrafficLightState.GreenToRed: if (num6 >= 30u) { maxSpeed = 0f; return; } break; } } } else { // traffic light simulation is active var stopCar = false; // determine responsible traffic light (left, right or main) if (TrafficPriority.IsLeftSegment(prevPos.m_segment, position.m_segment, destinationNodeId)) { vehicleLightState = light.GetLightLeft(); } else if (TrafficPriority.IsRightSegment(prevPos.m_segment, position.m_segment, destinationNodeId)) { vehicleLightState = light.GetLightRight(); } else { vehicleLightState = light.GetLightMain(); } if (vehicleLightState == RoadBaseAI.TrafficLightState.Green) { var hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId); if (hasIncomingCars) { // green light but other cars are incoming: slow approach maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f) * 0.01f; //stopCar = true; } } if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None || destinationInfo.m_class.m_service != ItemClass.Service.Road) { switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num6 < 60u) { stopCar = true; } break; case RoadBaseAI.TrafficLightState.Red: stopCar = true; break; case RoadBaseAI.TrafficLightState.GreenToRed: if (num6 >= 30u) { stopCar = true; } break; } } if (stopCar) { maxSpeed = 0f; return; } } } else { if (TrafficPriority.VehicleList.ContainsKey(vehicleId) && TrafficPriority.IsPrioritySegment(destinationNodeId, prevPos.m_segment)) { var currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex; var frame = currentFrameIndex2 >> 4; var prioritySegment = TrafficPriority.GetPrioritySegment(destinationNodeId, prevPos.m_segment); if (TrafficPriority.VehicleList[vehicleId].CarState == CarState.None) { TrafficPriority.VehicleList[vehicleId].CarState = CarState.Enter; } if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None && TrafficPriority.VehicleList[vehicleId].CarState != CarState.Leave) { bool hasIncomingCars; switch (prioritySegment.Type) { case PrioritySegment.PriorityType.Stop: if (TrafficPriority.VehicleList[vehicleId].WaitTime < 75) { TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop; if (lastFrameData.m_velocity.sqrMagnitude < 0.1f || TrafficPriority.VehicleList[vehicleId].Stopped) { TrafficPriority.VehicleList[vehicleId].Stopped = true; TrafficPriority.VehicleList[vehicleId].WaitTime++; if (TrafficPriority.VehicleList[vehicleId].WaitTime > 2) { hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId); if (hasIncomingCars) { maxSpeed = 0f; return; } TrafficPriority.VehicleList[vehicleId].CarState = CarState.Leave; } else { maxSpeed = 0f; return; } } else { maxSpeed = 0f; return; } } else { TrafficPriority.VehicleList[vehicleId].CarState = CarState.Leave; } break; case PrioritySegment.PriorityType.Yield: if (TrafficPriority.VehicleList[vehicleId].WaitTime < 75) { TrafficPriority.VehicleList[vehicleId].WaitTime++; TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop; maxSpeed = 0f; if (lastFrameData.m_velocity.sqrMagnitude < TrafficPriority.VehicleList[vehicleId].ReduceSpeedByValueToYield) { hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId); if (hasIncomingCars) { return; } } else { maxSpeed = lastFrameData.m_velocity.sqrMagnitude - TrafficPriority.VehicleList[vehicleId] .ReduceSpeedByValueToYield; return; } } else { TrafficPriority.VehicleList[vehicleId].CarState = CarState.Leave; } break; case PrioritySegment.PriorityType.Main: TrafficPriority.VehicleList[vehicleId].WaitTime++; TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop; maxSpeed = 0f; hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId); if (hasIncomingCars) { TrafficPriority.VehicleList[vehicleId].Stopped = true; return; } TrafficPriority.VehicleList[vehicleId].Stopped = false; var info3 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane) { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, info3.m_lanes[position.m_lane].m_speedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve) * 0.8f; } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f) * 0.8f; } return; } } else { TrafficPriority.VehicleList[vehicleId].CarState = CarState.Transit; } } } } } } var info2 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) { var laneSpeedLimit = info2.m_lanes[position.m_lane].m_speedLimit; if (TrafficRoadRestrictions.IsSegment(position.m_segment)) { var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment); if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f) { laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane]; } } maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } }
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}"); } }
public static bool HasIncomingVehicles(ushort targetCar, ushort nodeId) { var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var frame = currentFrameIndex >> 4; var node = TrafficLightTool.GetNetNode(nodeId); var fromPrioritySegment = GetPrioritySegment(nodeId, VehicleList[targetCar].FromSegment); if (fromPrioritySegment == null) { return(false); } var removeCarList = new List <ushort>(); var numCars = 0; // get all cars for (var s = 0; s < 8; s++) { var segment = node.GetSegment(s); if (segment == 0 || segment == VehicleList[targetCar].FromSegment) { continue; } if (!IsPrioritySegment(nodeId, segment)) { continue; } var prioritySegment = GetPrioritySegment(nodeId, segment); if (prioritySegment == null) { continue; // should not happen } // select outdated cars removeCarList.AddRange(from car in prioritySegment.Cars where VehicleList[car].LastFrame < frame - 32u select car); // remove outdated cars foreach (var rcar in removeCarList) { VehicleList[rcar].ResetCar(); //Log.Message("Removing *OUTDATED* vehicle " + rcar + " from segment " + segment + " @ node " + nodeId); prioritySegment.RemoveCar(rcar); CustomCarAI.watchedVehicleIds.Remove(rcar); } removeCarList.Clear(); if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { if (fromPrioritySegment.Type == PrioritySegment.PriorityType.Main) { if (prioritySegment.Type != PrioritySegment.PriorityType.Main) { continue; } numCars += prioritySegment.NumCars; foreach (var car in prioritySegment.Cars) { if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 0.1f) { numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId) ? numCars - 1 : numCars; } else { numCars--; } } } else { numCars += prioritySegment.NumCars; foreach (var car in prioritySegment.Cars) { if (prioritySegment.Type == PrioritySegment.PriorityType.Main) { if (!VehicleList[car].Stopped) { numCars = CheckPriorityRoadIncomingCar(targetCar, car, nodeId) ? numCars - 1 : numCars; } else { numCars--; } } else { if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 0.1f) { numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId) ? numCars - 1 : numCars; } else { numCars--; } } } } } else { if (!TrafficLightsManual.IsSegmentLight(nodeId, segment)) { continue; } var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segment); if (segmentLight.GetLightMain() != RoadBaseAI.TrafficLightState.Green) { continue; } numCars += prioritySegment.NumCars; foreach (var car in prioritySegment.Cars) { if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 1f) { numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId) ? numCars - 1 : numCars; } else { numCars--; } } } } return(numCars > 0); }
/// <summary> /// Adds a new segment to this step. After adding all steps the method `rebuildSegmentIds` must be called. /// </summary> /// <param name="segmentId"></param> internal void addSegment(ushort segmentId) { segmentLightStates.Add(segmentId, (ManualSegmentLight)TrafficLightsManual.GetOrLiveSegmentLight(nodeId, segmentId).Clone()); segmentLightStates[segmentId].makeRedOrGreen(); segmentIds.Add(segmentId); }