/*public VehiclePosition GetCurrentPosition() {
         *      LinkedListNode<VehiclePosition> firstNode = CurrentPosition;
         *      if (firstNode == null)
         *              return null;
         *      return firstNode.Value;
         * }*/

        internal void UpdatePosition(ref Vehicle vehicleData, ref PathUnit.Position curPos, ref PathUnit.Position nextPos, bool skipCheck = false)
        {
            if (!skipCheck && !CheckValidity(ref vehicleData))
            {
                return;
            }

            LastPositionUpdate = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            SegmentEnd end = TrafficPriority.GetPrioritySegment(GetTransitNodeId(ref curPos, ref nextPos), curPos.m_segment);

            if (CurrentSegmentEnd != end)
            {
                if (CurrentSegmentEnd != null)
                {
                    Unlink();
                }

                WaitTime = 0;
                if (end != null)
                {
                    Link(end);
                    JunctionTransitState = VehicleJunctionTransitState.Enter;
                }
                else
                {
                    JunctionTransitState = VehicleJunctionTransitState.None;
                }
            }
        }
 internal void Housekeeping()
 {
     if (TrafficManagerTool.GetToolMode() != ToolMode.AddPrioritySigns && TrafficLightSimulation.GetNodeSimulation(NodeId) == null && Type == PriorityType.None)
     {
         TrafficPriority.RemovePrioritySegments(NodeId);
     }
 }
 public void AddVehicle(ushort vehicleId, VehiclePosition carPos)
 {
     if (carPos.ToNode != NodeId || carPos.FromSegment != SegmentId)
     {
         Log.Warning($"Refusing to add vehicle {vehicleId} to PrioritySegment {SegmentId} @ {NodeId} (given: {carPos.FromSegment} @ {carPos.ToNode}).");
         return;
     }
     Vehicles[vehicleId] = carPos;
     TrafficPriority.MarkVehicleInSegment(vehicleId, SegmentId);
 }
        /// <summary>
        /// Determines the allowed vehicle types that may approach the given node from the given segment (lane-wise).
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        internal static Dictionary <byte, ExtVehicleType> GetAllowedVehicleTypesAsDict(ushort segmentId, ushort nodeId)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
            Dictionary <byte, ExtVehicleType> ret = new Dictionary <byte, ExtVehicleType>();

            NetManager netManager = Singleton <NetManager> .instance;
            if (segmentId == 0 || (netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None ||
                nodeId == 0 || (netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
            {
#if TRACE
                Singleton <CodeProfiler> .instance.Stop("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
                return(ret);
            }

            var dir  = NetInfo.Direction.Forward;
            var dir2 = ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir);
            var dir3 = TrafficPriority.IsLeftHandDrive() ? NetInfo.InvertDirection(dir2) : dir2;

            NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
            uint    curLaneId   = netManager.m_segments.m_buffer[segmentId].m_lanes;
            int     numLanes    = segmentInfo.m_lanes.Length;
            uint    laneIndex   = 0;
            while (laneIndex < numLanes && curLaneId != 0u)
            {
                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                ushort       toNodeId = (laneInfo.m_direction == dir3) ? netManager.m_segments.m_buffer[segmentId].m_endNode : netManager.m_segments.m_buffer[segmentId].m_startNode;

                if (toNodeId == nodeId)
                {
                    ExtVehicleType vehicleTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo);
                    if (vehicleTypes != ExtVehicleType.None)
                    {
                        ret[(byte)laneIndex] = vehicleTypes;
                    }
                }
                curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                ++laneIndex;
            }

#if TRACE
            Singleton <CodeProfiler> .instance.Stop("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
            return(ret);
        }
        public void OnUpdate(SegmentGeometry geometry)
        {
            if (!geometry.IsValid())
            {
                TrafficPriority.RemovePrioritySegment(NodeId, SegmentId);
                return;
            }

            StartNode = Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].m_startNode == NodeId;
            numLanes  = Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].Info.m_lanes.Length;
            numVehiclesFlowingToSegmentId = new Dictionary <ushort, uint>(7);
            numVehiclesGoingToSegmentId   = new Dictionary <ushort, uint>(7);
            //frontVehicleIds = new ushort[numLanes];
            ushort[] outgoingSegmentIds = geometry.GetOutgoingSegments(StartNode);
            foreach (ushort otherSegmentId in outgoingSegmentIds)
            {
                numVehiclesFlowingToSegmentId[otherSegmentId] = 0;
                numVehiclesGoingToSegmentId[otherSegmentId]   = 0;
            }
        }
コード例 #6
0
        /// <summary>
        /// Determines the allowed vehicle types that may approach the given node from the given segment.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        internal static HashSet <ExtVehicleType> GetAllowedVehicleTypesAsSet(ushort segmentId, ushort nodeId)
        {
            HashSet <ExtVehicleType> ret = new HashSet <ExtVehicleType>();

            NetManager netManager = Singleton <NetManager> .instance;

            if (segmentId == 0 || (netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None ||
                nodeId == 0 || (netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
            {
                return(ret);
            }

            var dir  = NetInfo.Direction.Forward;
            var dir2 = ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir);
            var dir3 = TrafficPriority.IsLeftHandDrive() ? NetInfo.InvertDirection(dir2) : dir2;

            NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
            uint    curLaneId   = netManager.m_segments.m_buffer[segmentId].m_lanes;
            int     numLanes    = segmentInfo.m_lanes.Length;
            uint    laneIndex   = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                ushort       toNodeId = (laneInfo.m_direction == dir3) ? netManager.m_segments.m_buffer[segmentId].m_endNode : netManager.m_segments.m_buffer[segmentId].m_startNode;

                if (toNodeId == nodeId)
                {
                    ret.Add(GetAllowedVehicleTypes(segmentId, laneIndex, curLaneId, laneInfo));
                }
                curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                ++laneIndex;
            }

            return(ret);
        }
        /// <summary>
        /// Calculates for each segment the number of cars going to this segment.
        /// We use integer arithmetic for better performance.
        /// </summary>
        public Dictionary <ushort, uint> GetVehicleMetricGoingToSegment(float?minSpeed, ExtVehicleType?vehicleTypes = null, ExtVehicleType separateVehicleTypes = ExtVehicleType.None, bool debug = false)
        {
            Dictionary <ushort, uint> numCarsGoingToSegmentId = new Dictionary <ushort, uint>();
            VehicleManager            vehicleManager          = Singleton <VehicleManager> .instance;
            NetManager netManager = Singleton <NetManager> .instance;

            for (var s = 0; s < 8; s++)
            {
                var segmentId = netManager.m_nodes.m_buffer[NodeId].GetSegment(s);

                if (segmentId == 0 || segmentId == SegmentId)
                {
                    continue;
                }

                if (CustomRoadAI.GetSegmentGeometry(segmentId).IsIncomingOneWay(NodeId))
                {
                    continue;
                }

                numCarsGoingToSegmentId[segmentId] = 0;
            }

            List <ushort> vehicleIdsToReHandle = new List <ushort>();

            foreach (KeyValuePair <ushort, VehiclePosition> e in Vehicles)
            {
                var vehicleId = e.Key;
                var carPos    = e.Value;

                if (vehicleId <= 0 || carPos.ToSegment <= 0)
                {
                    continue;
                }
                if ((vehicleManager.m_vehicles.m_buffer[vehicleId].m_flags & Vehicle.Flags.Created) == Vehicle.Flags.None)
                {
                    vehicleIdsToReHandle.Add(vehicleId);
                    continue;
                }
                if (minSpeed != null && vehicleManager.m_vehicles.m_buffer[vehicleId].GetLastFrameVelocity().magnitude < minSpeed)
                {
                    continue;
                }
                VehiclePosition globalPos = TrafficPriority.GetVehiclePosition(vehicleId);
                if (globalPos == null || !globalPos.Valid || globalPos.LastFrame >> 7 < Singleton <SimulationManager> .instance.m_currentFrameIndex >> 7)                 // ~64 sec.
                {
                    vehicleIdsToReHandle.Add(vehicleId);
                    continue;
                }
                if (vehicleTypes != null)
                {
                    if (vehicleTypes == ExtVehicleType.None)
                    {
                        if ((globalPos.VehicleType & separateVehicleTypes) != ExtVehicleType.None)
                        {
                            // we want all vehicles that do not have separate traffic lights
                            continue;
                        }
                    }
                    else
                    {
                        if ((globalPos.VehicleType & vehicleTypes) == ExtVehicleType.None)
                        {
                            continue;
                        }
                    }
                }

                //debug = vehicleManager.m_vehicles.m_buffer[vehicleId].Info.m_vehicleType == VehicleInfo.VehicleType.Tram;
#if DEBUG
                /*if (debug) {
                 *      Log._Debug($"getNumCarsGoingToSegment: Handling vehicle {vehicleId} going from {carPos.FromSegment}/{SegmentId} to {carPos.ToSegment}. carState={globalPos.CarState}. lastUpdate={globalPos.LastCarStateUpdate}");
                 * }*/
#endif

                uint avgSegmentLength = (uint)Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].m_averageLength;
                uint normLength       = (uint)(vehicleManager.m_vehicles.m_buffer[vehicleId].CalculateTotalLength(vehicleId) * 100u) / avgSegmentLength;

#if DEBUG
                /*if (debug) {
                 *      Log._Debug($"getNumCarsGoingToSegment: NormLength of vehicle {vehicleId} going to {carPos.ToSegment}: {avgSegmentLength} -> {normLength}");
                 * }*/
#endif

                if (numCarsGoingToSegmentId.ContainsKey(carPos.ToSegment))
                {
                    /*if (carPos.OnEmergency)
                     *      numCarsGoingToSegmentId[carPos.ToSegment] += 10000f;
                     * else*/
                    numCarsGoingToSegmentId[carPos.ToSegment] += normLength;
                }
                // "else" must not happen (incoming one-way)
            }

            foreach (ushort vehicleId in vehicleIdsToReHandle)
            {
                CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], false, false);
            }
            return(numCarsGoingToSegmentId);
        }
 public bool RemoveVehicle(ushort vehicleId)
 {
     Vehicles.Remove(vehicleId);
     TrafficPriority.UnmarkVehicleInSegment(vehicleId, SegmentId);
     return(true);
 }
コード例 #9
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);
        }
コード例 #10
0
        internal void Recalculate()
        {
#if DEBUGGEO
            Log._Debug($"NodeGeometry: Recalculate @ {NodeId}");
#endif

            Cleanup();

            Flags.applyNodeTrafficLightFlag(NodeId);

            // check if node is valid
            if (!IsValid())
            {
                for (int i = 0; i < 8; ++i)
                {
                    SegmentEndGeometries[i] = null;
                }
                TrafficLightSimulation.RemoveNodeFromSimulation(NodeId, false, true);
                Flags.setNodeTrafficLight(NodeId, false);
            }
            else
            {
                NetManager netManager      = Singleton <NetManager> .instance;
                bool       hasTrafficLight = (netManager.m_nodes.m_buffer[NodeId].m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
                var        nodeSim         = TrafficLightSimulation.GetNodeSimulation(NodeId);
                if (nodeSim == null)
                {
                    byte numSegmentsWithSigns = 0;
                    for (var s = 0; s < 8; s++)
                    {
                        var segmentId = netManager.m_nodes.m_buffer[NodeId].GetSegment(s);
                        if (segmentId <= 0)
                        {
                            continue;
                        }

#if DEBUGx
                        Log._Debug($"NodeGeometry.Recalculate: Housekeeping segment {segmentId}");
#endif

                        SegmentEnd prioritySegment = TrafficPriority.GetPrioritySegment(NodeId, segmentId);
                        if (prioritySegment == null)
                        {
                            continue;
                        }

                        // if node is a traffic light, it must not have priority signs
                        if (hasTrafficLight && prioritySegment.Type != SegmentEnd.PriorityType.None)
                        {
                            Log.Warning($"Housekeeping: Node {NodeId}, Segment {segmentId} is a priority sign but node has a traffic light!");
                            prioritySegment.Type = SegmentEnd.PriorityType.None;
                        }

                        // if a priority sign is set, everything is ok
                        if (prioritySegment.Type != SegmentEnd.PriorityType.None)
                        {
                            ++numSegmentsWithSigns;
                        }
                    }

                    if (numSegmentsWithSigns > 0)
                    {
                        // add priority segments for newly created segments
                        numSegmentsWithSigns += TrafficPriority.AddPriorityNode(NodeId);
                    }
                }

                // calculate node properties
                byte incomingSegments = 0;
                byte outgoingSegments = 0;
                for (int i = 0; i < 8; ++i)
                {
                    if (SegmentEndGeometries[i] == null)
                    {
                        continue;
                    }
#if DEBUGGEO
                    Log._Debug($"NodeGeometry.Recalculate: Iterating over segment end {SegmentEndGeometries[i].SegmentId} @ node {NodeId}");
#endif

                    bool startNode = SegmentEndGeometries[i].StartNode;
                    if (SegmentEndGeometries[i].GetSegmentGeometry().IsIncoming(startNode))
                    {
                        ++incomingSegments;
                    }
                    if (SegmentEndGeometries[i].GetSegmentGeometry().IsOutgoing(startNode))
                    {
                        ++outgoingSegments;
                    }
                }

                IsSimpleJunction = incomingSegments == 1 || outgoingSegments == 1;
#if DEBUGGEO
                Log._Debug($"NodeGeometry.Recalculate: Node {NodeId} has {incomingSegments} incoming and {outgoingSegments} outgoing segments.");
#endif
            }

            NotifyObservers();
        }