Beispiel #1
0
 public async Task SaveVehicleStateAsync(VehicleState vehicleState)
 {
     await _daprClient.SaveStateAsync <VehicleState>(
         DAPR_STORE_NAME, vehicleState.LicenseNumber, vehicleState);
 }
        /// <summary>
        /// Plans what maneuer we should take next
        /// </summary>
        /// <param name="planningState"></param>
        /// <param name="navigationalPlan"></param>
        /// <param name="vehicleState"></param>
        /// <param name="vehicles"></param>
        /// <param name="obstacles"></param>
        /// <param name="blockage"></param>
        /// <returns></returns>
        public Maneuver Plan(IState planningState, RoadPlan navigationalPlan, VehicleState vehicleState,
                             SceneEstimatorTrackedClusterCollection vehicles, SceneEstimatorUntrackedClusterCollection obstacles,
                             List <ITacticalBlockage> blockages, double vehicleSpeed)
        {
            // assign vehicles to their lanes
            this.roadMonitor.Assign(vehicles);

            // navigation tasks
            this.taskReasoning.navigationPlan = navigationalPlan;

            #region Stay in lane

            // maneuver given we are in a lane
            if (planningState is StayInLaneState)
            {
                // get state
                StayInLaneState sils = (StayInLaneState)planningState;

                // check reasoning if needs to be different
                if (this.forwardReasoning == null || !this.forwardReasoning.Lane.Equals(sils.Lane))
                {
                    if (sils.Lane.LaneOnLeft == null)
                    {
                        this.leftLateralReasoning = new LateralReasoning(null, SideObstacleSide.Driver);
                    }
                    else if (sils.Lane.LaneOnLeft.Way.Equals(sils.Lane.Way))
                    {
                        this.leftLateralReasoning = new LateralReasoning(sils.Lane.LaneOnLeft, SideObstacleSide.Driver);
                    }
                    else
                    {
                        this.leftLateralReasoning = new OpposingLateralReasoning(sils.Lane.LaneOnLeft, SideObstacleSide.Driver);
                    }

                    if (sils.Lane.LaneOnRight == null)
                    {
                        this.rightLateralReasoning = new LateralReasoning(null, SideObstacleSide.Passenger);
                    }
                    else if (sils.Lane.LaneOnRight.Way.Equals(sils.Lane.Way))
                    {
                        this.rightLateralReasoning = new LateralReasoning(sils.Lane.LaneOnRight, SideObstacleSide.Passenger);
                    }
                    else
                    {
                        this.rightLateralReasoning = new OpposingLateralReasoning(sils.Lane.LaneOnRight, SideObstacleSide.Passenger);
                    }

                    this.forwardReasoning = new ForwardReasoning(this.leftLateralReasoning, this.rightLateralReasoning, sils.Lane);
                }

                // populate navigation with road plan
                taskReasoning.SetRoadPlan(navigationalPlan, sils.Lane);

                // as penalties for lane changes already taken into account, can just look at
                // best lane plan to figure out what to do
                TypeOfTasks bestTask = taskReasoning.Best;

                // get the forward lane plan
                Maneuver forwardManeuver = forwardReasoning.ForwardManeuver(sils.Lane, vehicleState, navigationalPlan, blockages, sils.WaypointsToIgnore);

                // get the secondary
                Maneuver?secondaryManeuver = forwardReasoning.AdvancedSecondary(sils.Lane, vehicleState, navigationalPlan, blockages, sils.WaypointsToIgnore, bestTask);                   //forwardReasoning.SecondaryManeuver(sils.Lane, vehicleState, navigationalPlan, blockages, sils.WaypointsToIgnore, bestTask);

                // check behavior type for uturn
                if (secondaryManeuver.HasValue && secondaryManeuver.Value.PrimaryBehavior is UTurnBehavior)
                {
                    return(secondaryManeuver.Value);
                }

                // check if we wish to change lanes here
                if (bestTask != TypeOfTasks.Straight)
                {
                    // parameters
                    LaneChangeParameters parameters;
                    secondaryManeuver = this.forwardReasoning.AdvancedDesiredLaneChangeManeuver(sils.Lane, bestTask == TypeOfTasks.Left ? true : false, navigationalPlan.BestPlan.laneWaypointOfInterest.PointOfInterest,
                                                                                                navigationalPlan, vehicleState, blockages, sils.WaypointsToIgnore, new LaneChangeInformation(LaneChangeReason.Navigation, this.forwardReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle), secondaryManeuver, out parameters);
                }

                // final maneuver
                Maneuver finalManeuver = secondaryManeuver.HasValue ? secondaryManeuver.Value : forwardManeuver;

                // set opposing vehicle flag
                if (false && this.leftLateralReasoning != null && this.leftLateralReasoning is OpposingLateralReasoning && finalManeuver.PrimaryBehavior is StayInLaneBehavior)
                {
                    StayInLaneBehavior       silb = (StayInLaneBehavior)finalManeuver.PrimaryBehavior;
                    OpposingLateralReasoning olr  = (OpposingLateralReasoning)this.leftLateralReasoning;
                    olr.ForwardMonitor.ForwardVehicle.Update(olr.lane, vehicleState);
                    if (olr.ForwardMonitor.ForwardVehicle.CurrentVehicle != null)
                    {
                        ForwardVehicleTrackingControl fvtc = olr.ForwardMonitor.ForwardVehicle.GetControl(olr.lane, vehicleState);
                        BehaviorDecorator[]           bds  = new BehaviorDecorator[finalManeuver.PrimaryBehavior.Decorators.Count];
                        finalManeuver.PrimaryBehavior.Decorators.CopyTo(bds);
                        finalManeuver.PrimaryBehavior.Decorators = new List <BehaviorDecorator>(bds);
                        silb.Decorators.Add(new OpposingLaneDecorator(fvtc.xSeparation, olr.ForwardMonitor.ForwardVehicle.CurrentVehicle.Speed));
                        ArbiterOutput.Output("Added Opposing Lane Decorator: " + fvtc.xSeparation.ToString("F2") + "m, " + olr.ForwardMonitor.ForwardVehicle.CurrentVehicle.Speed.ToString("f2") + "m/s");
                    }
                    finalManeuver.PrimaryBehavior = silb;
                }

                // return the final
                return(finalManeuver);
            }

            #endregion

            #region Stay in supra lane

            else if (CoreCommon.CorePlanningState is StayInSupraLaneState)
            {
                // get state
                StayInSupraLaneState sisls = (StayInSupraLaneState)planningState;

                // check reasoning
                if (this.forwardReasoning == null || !this.forwardReasoning.Lane.Equals(sisls.Lane))
                {
                    if (sisls.Lane.Initial.LaneOnLeft == null)
                    {
                        this.leftLateralReasoning = new LateralReasoning(null, SideObstacleSide.Driver);
                    }
                    else if (sisls.Lane.Initial.LaneOnLeft.Way.Equals(sisls.Lane.Initial.Way))
                    {
                        this.leftLateralReasoning = new LateralReasoning(sisls.Lane.Initial.LaneOnLeft, SideObstacleSide.Driver);
                    }
                    else
                    {
                        this.leftLateralReasoning = new OpposingLateralReasoning(sisls.Lane.Initial.LaneOnLeft, SideObstacleSide.Driver);
                    }

                    if (sisls.Lane.Initial.LaneOnRight == null)
                    {
                        this.rightLateralReasoning = new LateralReasoning(null, SideObstacleSide.Passenger);
                    }
                    else if (sisls.Lane.Initial.LaneOnRight.Way.Equals(sisls.Lane.Initial.Way))
                    {
                        this.rightLateralReasoning = new LateralReasoning(sisls.Lane.Initial.LaneOnRight, SideObstacleSide.Passenger);
                    }
                    else
                    {
                        this.rightLateralReasoning = new OpposingLateralReasoning(sisls.Lane.Initial.LaneOnRight, SideObstacleSide.Passenger);
                    }

                    this.forwardReasoning = new ForwardReasoning(this.leftLateralReasoning, this.rightLateralReasoning, sisls.Lane);
                }

                // populate navigation with road plan
                taskReasoning.SetSupraRoadPlan(navigationalPlan, sisls.Lane);

                // as penalties for lane changes already taken into account, can just look at
                // best lane plan to figure out what to do
                // TODO: NOTE THAT THIS BEST TASK SHOULD BE IN THE SUPRA LANE!! (DO WE NEED THIS)
                TypeOfTasks bestTask = taskReasoning.Best;

                // get the forward lane plan
                Maneuver forwardManeuver = forwardReasoning.ForwardManeuver(sisls.Lane, vehicleState, navigationalPlan, blockages, sisls.WaypointsToIgnore);

                // get hte secondary
                Maneuver?secondaryManeuver = forwardReasoning.AdvancedSecondary(sisls.Lane, vehicleState, navigationalPlan, blockages, new List <ArbiterWaypoint>(), bestTask);                //forwardReasoning.SecondaryManeuver(sisls.Lane, vehicleState, navigationalPlan, blockages, sisls.WaypointsToIgnore, bestTask);

                // final maneuver
                Maneuver finalManeuver = secondaryManeuver.HasValue ? secondaryManeuver.Value : forwardManeuver;

                // check if stay in lane
                if (false && this.leftLateralReasoning != null && this.leftLateralReasoning is OpposingLateralReasoning && finalManeuver.PrimaryBehavior is SupraLaneBehavior)
                {
                    SupraLaneBehavior        silb = (SupraLaneBehavior)finalManeuver.PrimaryBehavior;
                    OpposingLateralReasoning olr  = (OpposingLateralReasoning)this.leftLateralReasoning;
                    olr.ForwardMonitor.ForwardVehicle.Update(olr.lane, vehicleState);
                    if (olr.ForwardMonitor.ForwardVehicle.CurrentVehicle != null)
                    {
                        ForwardVehicleTrackingControl fvtc = olr.ForwardMonitor.ForwardVehicle.GetControl(olr.lane, vehicleState);
                        BehaviorDecorator[]           bds  = new BehaviorDecorator[finalManeuver.PrimaryBehavior.Decorators.Count];
                        finalManeuver.PrimaryBehavior.Decorators.CopyTo(bds);
                        finalManeuver.PrimaryBehavior.Decorators = new List <BehaviorDecorator>(bds);
                        silb.Decorators.Add(new OpposingLaneDecorator(fvtc.xSeparation, olr.ForwardMonitor.ForwardVehicle.CurrentVehicle.Speed));
                        ArbiterOutput.Output("Added Opposing Lane Decorator: " + fvtc.xSeparation.ToString("F2") + "m, " + olr.ForwardMonitor.ForwardVehicle.CurrentVehicle.Speed.ToString("f2") + "m/s");
                    }
                    finalManeuver.PrimaryBehavior = silb;
                }

                // return the final
                return(finalManeuver);

                // notify

                /*if (secondaryManeuver.HasValue)
                 *      ArbiterOutput.Output("Secondary Maneuver");
                 *
                 * // check for forward's secondary maneuver for desired behavior other than going straight
                 * if (secondaryManeuver.HasValue)
                 * {
                 *      // return the secondary maneuver
                 *      return secondaryManeuver.Value;
                 * }
                 * // otherwise our default behavior and posibly desired is going straight
                 * else
                 * {
                 *      // return default forward maneuver
                 *      return forwardManeuver;
                 * }*/
            }

            #endregion

            #region Change Lanes State

            // maneuver given we are changing lanes
            else if (planningState is ChangeLanesState)
            {
                // get state
                ChangeLanesState    cls   = (ChangeLanesState)planningState;
                LaneChangeReasoning lcr   = new LaneChangeReasoning();
                Maneuver            final = lcr.PlanLaneChange(cls, vehicleState, navigationalPlan, blockages, new List <ArbiterWaypoint>());

                                #warning need to filter through waypoints to ignore so don't get stuck by a stop line
                //Maneuver final = new Maneuver(cls.Resume(vehicleState, vehicleSpeed), cls, cls.DefaultStateDecorators, vehicleState.Timestamp);

                // return the final planned maneuver
                return(final);

                /*if (!cls.parameters..TargetIsOnComing)
                 * {
                 *      // check reasoning
                 *      if (this.forwardReasoning == null || !this.forwardReasoning.Lane.Equals(cls.TargetLane))
                 *      {
                 *              if (cls.TargetLane.LaneOnLeft.Way.Equals(cls.TargetLane.Way))
                 *                      this.leftLateralReasoning = new LateralReasoning(cls.TargetLane.LaneOnLeft);
                 *              else
                 *                      this.leftLateralReasoning = new OpposingLateralReasoning(cls.TargetLane.LaneOnLeft);
                 *
                 *              if (cls.TargetLane.LaneOnRight.Way.Equals(cls.TargetLane.Way))
                 *                      this.rightLateralReasoning = new LateralReasoning(cls.TargetLane.LaneOnRight);
                 *              else
                 *                      this.rightLateralReasoning = new OpposingLateralReasoning(cls.TargetLane.LaneOnRight);
                 *
                 *              this.forwardReasoning = new ForwardReasoning(this.leftLateralReasoning, this.rightLateralReasoning, cls.TargetLane);
                 *      }
                 *
                 *
                 *      // get speed command
                 *      double speed;
                 *      double distance;
                 *      this.forwardReasoning.ForwardMonitor.StoppingParams(new ArbiterWaypoint(cls.TargetUpperBound.pt, null), cls.TargetLane, vehicleState.Front, vehicleState.ENCovariance, out speed, out distance);
                 *      SpeedCommand sc = new ScalarSpeedCommand(Math.Max(speed, 0.0));
                 *      cls.distanceLeft = distance;
                 *
                 *      // get behavior
                 *      ChangeLaneBehavior clb = new ChangeLaneBehavior(cls.InitialLane.LaneId, cls.TargetLane.LaneId, cls.InitialLane.LaneOnLeft != null && cls.InitialLane.LaneOnLeft.Equals(cls.TargetLane),
                 *              distance, sc, new List<int>(), cls.InitialLane.PartitionPath, cls.TargetLane.PartitionPath, cls.InitialLane.Width, cls.TargetLane.Width);
                 *
                 *      // plan over the target lane
                 *      //Maneuver targetManeuver = forwardReasoning.ForwardManeuver(cls.TargetLane, vehicleState, !cls.TargetIsOnComing, blockage, cls.InitialLaneState.IgnorableWaypoints);
                 *
                 *      // plan over the initial lane
                 *      //Maneuver initialManeuver = forwardReasoning.ForwardManeuver(cls.InitialLane, vehicleState, !cls.InitialIsOncoming, blockage, cls.InitialLaneState.IgnorableWaypoints);
                 *
                 *      // generate the change lanes command
                 *      //Maneuver final = laneChangeReasoning.PlanLaneChange(cls, initialManeuver, targetManeuver);
                 *
                 * }
                 * else
                 * {
                 *      throw new Exception("Change lanes into oncoming not supported yet by road tactical");
                 * }*/
            }

            #endregion

            #region Opposing Lanes State

            // maneuver given we are in an opposing lane
            else if (planningState is OpposingLanesState)
            {
                // get state
                OpposingLanesState ols         = (OpposingLanesState)planningState;
                ArbiterWayId       opposingWay = ols.OpposingWay;

                ols.SetClosestGood(vehicleState);
                ols.ResetLaneAgent = false;

                // check reasoning
                if (this.opposingReasoning == null || !this.opposingReasoning.Lane.Equals(ols.OpposingLane))
                {
                    if (ols.OpposingLane.LaneOnRight == null)
                    {
                        this.leftLateralReasoning = new LateralReasoning(null, SideObstacleSide.Driver);
                    }
                    else if (!ols.OpposingLane.LaneOnRight.Way.Equals(ols.OpposingLane.Way))
                    {
                        this.leftLateralReasoning = new LateralReasoning(ols.OpposingLane.LaneOnRight, SideObstacleSide.Driver);
                    }
                    else
                    {
                        this.leftLateralReasoning = new OpposingLateralReasoning(ols.OpposingLane.LaneOnRight, SideObstacleSide.Driver);
                    }

                    if (ols.OpposingLane.LaneOnLeft == null)
                    {
                        this.rightLateralReasoning = new LateralReasoning(null, SideObstacleSide.Passenger);
                    }
                    else if (!ols.OpposingLane.LaneOnLeft.Way.Equals(ols.OpposingLane.Way))
                    {
                        this.rightLateralReasoning = new LateralReasoning(ols.OpposingLane.LaneOnLeft, SideObstacleSide.Passenger);
                    }
                    else
                    {
                        this.rightLateralReasoning = new OpposingLateralReasoning(ols.OpposingLane.LaneOnLeft, SideObstacleSide.Passenger);
                    }

                    this.opposingReasoning = new OpposingReasoning(this.leftLateralReasoning, this.rightLateralReasoning, ols.OpposingLane);
                }

                // get the forward lane plan
                Maneuver forwardManeuver = this.opposingReasoning.ForwardManeuver(ols.OpposingLane, ols.ClosestGoodLane, vehicleState, navigationalPlan, blockages);

                // get the secondary maneuver
                Maneuver?secondaryManeuver = null;
                if (ols.ClosestGoodLane != null)
                {
                    secondaryManeuver = this.opposingReasoning.SecondaryManeuver(ols.OpposingLane, ols.ClosestGoodLane, vehicleState, blockages, ols.EntryParameters);
                }

                // check for reasonings secondary maneuver for desired behavior other than going straight
                if (secondaryManeuver != null)
                {
                    // return the secondary maneuver
                    return(secondaryManeuver.Value);
                }
                // otherwise our default behavior and posibly desired is going straight
                else
                {
                    // return default forward maneuver
                    return(forwardManeuver);
                }
            }

            #endregion

            #region not imp

            /*
             #region Uturn
             *
             * // we are making a uturn
             * else if (planningState is uTurnState)
             * {
             *      // get the uturn state
             *      uTurnState uts = (uTurnState)planningState;
             *
             *      // get the final lane we wish to be in
             *      ArbiterLane targetLane = uts.TargetLane;
             *
             *      // get operational state
             *      Type operationalBehaviorType = CoreCommon.Communications.GetCurrentOperationalBehavior();
             *
             *      // check if we have completed the uturn
             *      bool complete = operationalBehaviorType == typeof(StayInLaneBehavior);
             *
             *      // default next behavior
             *      Behavior nextBehavior = new StayInLaneBehavior(targetLane.LaneId, new ScalarSpeedCommand(CoreCommon.OperationalStopSpeed), new List<int>());
             *      nextBehavior.Decorators = TurnDecorators.NoDecorators;
             *
             *      // check if complete
             *      if (complete)
             *      {
             *              // stay in lane
             *              List<ArbiterLaneId> aprioriLanes = new List<ArbiterLaneId>();
             *              aprioriLanes.Add(targetLane.LaneId);
             *              return new Maneuver(nextBehavior, new StayInLaneState(targetLane), null, null, aprioriLanes, true);
             *      }
             *      // otherwise keep same
             *      else
             *      {
             *              // set abort behavior
             *              ((StayInLaneBehavior)nextBehavior).SpeedCommand = new ScalarSpeedCommand(0.0);
             *
             *              // maneuver
             *              return new Maneuver(uts.DefaultBehavior, uts, nextBehavior, new StayInLaneState(targetLane));
             *      }
             * }
             *
             #endregion*/

            #endregion

            #region Unknown

            // unknown state
            else
            {
                throw new Exception("Unknown Travel State type: planningState: " + planningState.ToString() + "\n with type: " + planningState.GetType().ToString());
            }

            #endregion
        }
Beispiel #3
0
        /// <summary>
        /// Determines the state of the given vehicle.
        /// The returned vehicle state is not necessarily valid.
        /// </summary>
        /// <param name="vehicleId"></param>
        /// <returns>the vehicle state</returns>
        internal VehicleState _GetVehicleState(ushort vehicleId)
        {
            VehicleState ret = VehicleStates[vehicleId];

            return(ret);
        }
Beispiel #4
0
 /// <summary>Is called every frame.</summary>
 /// <param name="data">The data.</param>
 internal void Elapse(ElapseData data)
 {
     this.PluginInitializing = false;
     if (data.ElapsedTime.Seconds > 0.0 & data.ElapsedTime.Seconds < 1.0)
     {
         // --- panel ---
         for (int i = 0; i < this.Panel.Length; i++)
         {
             this.Panel[i] = 0;
         }
         // --- devices ---
         this.State   = data.Vehicle;
         this.Handles = new ReadOnlyHandles(data.Handles);
         bool blocking = false;
         foreach (var device in this.Devices)
         {
             device.Elapse(data, ref blocking);
         }
         if (data.Handles.BrakeNotch != 0)
         {
             data.Handles.PowerNotch = 0;
         }
         // --- panel ---
         this.Panel[255] = 1;
         int seconds = (int)Math.Floor(data.TotalTime.Seconds);
         this.Panel[10]  = (seconds / 3600) % 24;
         this.Panel[11]  = (seconds / 60) % 60;
         this.Panel[12]  = seconds % 60;
         this.Panel[269] = data.Handles.ConstSpeed ? 1 : 0;
         if (data.Handles.Reverser != 0 & (this.Handles.PowerNotch > 0 & this.Handles.BrakeNotch == 0 | this.Handles.PowerNotch == 0 & this.Handles.BrakeNotch == 1 & this.Specs.HasHoldBrake))
         {
             this.Panel[100] = 1;
         }
         if (data.Handles.BrakeNotch >= this.Specs.AtsNotch & data.Handles.BrakeNotch <= this.Specs.BrakeNotches | data.Handles.Reverser != 0 & data.Handles.BrakeNotch == 1 & this.Specs.HasHoldBrake)
         {
             this.Panel[101] = 1;
         }
         for (int i = (int)VirtualKeys.S; i <= (int)VirtualKeys.C2; i++)
         {
             if (KeysPressed[i])
             {
                 this.Panel[93 + i] = 1;
             }
         }
         if (PanelIllumination)
         {
             this.Panel[161] = 1;
         }
         // --- accelerometer ---
         this.AccelerometerTimer += data.ElapsedTime.Seconds;
         if (this.AccelerometerTimer > AccelerometerMaximumTimer)
         {
             this.Acceleration       = (data.Vehicle.Speed.MetersPerSecond - AccelerometerSpeed) / this.AccelerometerTimer;
             this.AccelerometerSpeed = data.Vehicle.Speed.MetersPerSecond;
             this.AccelerometerTimer = 0.0;
         }
         if (this.Acceleration < 0.0)
         {
             double value = -3.6 * this.Acceleration;
             if (value >= 10.0)
             {
                 this.Panel[74] = 9;
                 this.Panel[75] = 9;
             }
             else
             {
                 this.Panel[74] = (int)Math.Floor(value) % 10;
                 this.Panel[75] = (int)Math.Floor(10.0 * value) % 10;
             }
         }
         // --- sound ---
         this.Sounds.Elapse(data);
         // --- AI ---
         this.Calling.Elapse(data);
     }
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="currentArbiterState"></param>
 /// <param name="internalCarMode"></param>
 /// <param name="fullRoute"></param>
 /// <param name="routeTime"></param>
 /// <param name="actionPoint"></param>
 /// <param name="currentGoal"></param>
 /// <param name="goals"></param>
 /// <param name="behavior"></param>
 public ArbiterInformation(string currentArbiterState, CarMode internalCarMode, FullRoute fullRoute, double routeTime,
                           RndfWaypointID actionPoint, RndfWaypointID currentGoal, Queue <RndfWaypointID> goals, Behavior behavior, VehicleState planningState)
 {
     this.CurrentArbiterState = currentArbiterState;
     this.InternalCarMode     = internalCarMode;
     this.FullRoute           = fullRoute;
     this.RouteTime           = routeTime;
     this.ActionPoint         = actionPoint;
     this.CurrentGoal         = currentGoal;
     this.Goals         = goals;
     this.Behavior      = behavior;
     this.PlanningState = planningState;
 }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
#if DEBUG
            //Log._Debug($"CustomTrainAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

            /// NON-STOCK CODE START ///
            ExtVehicleType vehicleType = VehicleStateManager.Instance._GetVehicleState(vehicleID).VehicleType;
            if (vehicleType == ExtVehicleType.None)
            {
#if DEBUG
                Log.Warning($"CustomTrainAI.CustomStartPathFind: Vehicle {vehicleID} does not have a valid vehicle type!");
#endif
                vehicleType = ExtVehicleType.RailVehicle;
            }
            else if (vehicleType == ExtVehicleType.CargoTrain)
            {
                vehicleType = ExtVehicleType.CargoVehicle;
            }
#if DEBUG
            /*if (vehicleType == ExtVehicleType.CargoVehicle) {
             *      bool reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
             *      ushort frontVehicleId;
             *      if (reversed) {
             *              frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
             *      } else {
             *              frontVehicleId = vehicleId;
             *      }
             *      Log._Debug($"CustomTrainAI.CustomStartPathFind. vehicleID={vehicleId}. reversed={reversed} frontVehicleId={frontVehicleId} type={this.GetType().ToString()} vehicleType={vehicleType} target={vehicleData.m_targetBuilding}");
             * }*/
#endif
            /// NON-STOCK CODE END ///

            VehicleInfo info = this.m_info;
            if ((vehicleData.m_flags & Vehicle.Flags.Spawned) == 0 && Vector3.Distance(startPos, endPos) < 100f)
            {
                startPos = endPos;
            }
            bool allowUnderground;
            bool allowUnderground2;
            if (info.m_vehicleType == VehicleInfo.VehicleType.Metro)
            {
                allowUnderground  = true;
                allowUnderground2 = true;
            }
            else
            {
                allowUnderground  = ((vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0);
                allowUnderground2 = false;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startSqrDistA;
            float             startSqrDistB;
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             endSqrDistA;
            float             endSqrDistB;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground2, false, 32f, out endPosA, out endPosB, out endSqrDistA, out endSqrDistB))
            {
                if (!startBothWays || startSqrDistB > startSqrDistA * 1.2f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || endSqrDistB > endSqrDistA * 1.2f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;
                if (CustomPathManager._instance.CreatePath((ExtVehicleType)vehicleType, vehicleID, ExtCitizenInstance.ExtPathType.None, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, false, false, true, false))
                {
#if USEPATHWAITCOUNTER
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleID);
                    state.PathWaitCounter = 0;
#endif

                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        /// <summary>
        /// Plans over the zone
        /// </summary>
        /// <param name="planningState"></param>
        /// <param name="navigationalPlan"></param>
        /// <param name="vehicleState"></param>
        /// <param name="vehicles"></param>
        /// <param name="obstacles"></param>
        /// <param name="blockages"></param>
        /// <returns></returns>
        public Maneuver Plan(IState planningState, INavigationalPlan navigationalPlan,
                             VehicleState vehicleState, SceneEstimatorTrackedClusterCollection vehicles,
                             SceneEstimatorUntrackedClusterCollection obstacles, List <ITacticalBlockage> blockages)
        {
            #region Zone Travelling State

            if (planningState is ZoneTravelingState)
            {
                // check blockages

                /*if (blockages != null && blockages.Count > 0 && blockages[0] is ZoneBlockage)
                 * {
                 *      // create the blockage state
                 *      EncounteredBlockageState ebs = new EncounteredBlockageState(blockages[0], CoreCommon.CorePlanningState);
                 *
                 *      // go to a blockage handling tactical
                 *      return new Maneuver(new NullBehavior(), ebs, TurnDecorators.NoDecorators, vehicleState.Timestamp);
                 * }*/

                // cast state
                ZoneState zs = (ZoneState)planningState;

                // plan over state and zone
                ZonePlan zp = (ZonePlan)navigationalPlan;

                // check zone path does not exist
                if (zp.RecommendedPath.Count < 2)
                {
                    // zone startup again
                    ZoneStartupState zss = new ZoneStartupState(zs.Zone, true);
                    return(new Maneuver(new HoldBrakeBehavior(), zss, TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }

                // final path seg
                LinePath.PointOnPath endBack = zp.RecommendedPath.AdvancePoint(zp.RecommendedPath.EndPoint, -TahoeParams.VL);
                LinePath             lp      = zp.RecommendedPath.SubPath(endBack, zp.RecommendedPath.EndPoint);
                LinePath             lB      = lp.ShiftLateral(TahoeParams.T);
                LinePath             rB      = lp.ShiftLateral(-TahoeParams.T);

                // add to info
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(lB, ArbiterInformationDisplayObjectType.leftBound));
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(rB, ArbiterInformationDisplayObjectType.rightBound));

                // get speed command
                ScalarSpeedCommand sc = new ScalarSpeedCommand(2.24);

                // Behavior
                Behavior b = new ZoneTravelingBehavior(zp.Zone.ZoneId, zp.Zone.Perimeter.PerimeterPolygon, zp.Zone.StayOutAreas.ToArray(),
                                                       sc, zp.RecommendedPath, lB, rB);

                // maneuver
                return(new Maneuver(b, CoreCommon.CorePlanningState, TurnDecorators.NoDecorators, vehicleState.Timestamp));
            }

            #endregion

            #region Parking State

            else if (planningState is ParkingState)
            {
                // get state
                ParkingState ps = (ParkingState)planningState;

                // determine stay out areas to use
                List <Polygon> stayOuts = new List <Polygon>();
                foreach (Polygon p in ps.Zone.StayOutAreas)
                {
                    if (!p.IsInside(ps.ParkingSpot.NormalWaypoint.Position) && !p.IsInside(ps.ParkingSpot.Checkpoint.Position))
                    {
                        stayOuts.Add(p);
                    }
                }

                LinePath rB = ps.ParkingSpot.GetRightBound();
                LinePath lB = ps.ParkingSpot.GetLeftBound();

                // add to info
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(lB, ArbiterInformationDisplayObjectType.leftBound));
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(rB, ArbiterInformationDisplayObjectType.rightBound));

                // create behavior
                ZoneParkingBehavior zpb = new ZoneParkingBehavior(ps.Zone.ZoneId, ps.Zone.Perimeter.PerimeterPolygon, stayOuts.ToArray(), new ScalarSpeedCommand(2.24),
                                                                  ps.ParkingSpot.GetSpotPath(), lB, rB, ps.ParkingSpot.SpotId, 1.0);

                // maneuver
                return(new Maneuver(zpb, ps, TurnDecorators.NoDecorators, vehicleState.Timestamp));
            }

            #endregion

            #region Pulling Out State

            else if (planningState is PullingOutState)
            {
                // get state
                PullingOutState pos = (PullingOutState)planningState;

                // plan over state and zone
                ZonePlan zp = (ZonePlan)navigationalPlan;

                // final path seg
                Coordinates endVec  = zp.RecommendedPath[0] - zp.RecommendedPath[1];
                Coordinates endBack = zp.RecommendedPath[0] + endVec.Normalize(TahoeParams.VL * 2.0);
                LinePath    rp      = new LinePath(new Coordinates[] { pos.ParkingSpot.Checkpoint.Position, pos.ParkingSpot.NormalWaypoint.Position,
                                                                       zp.RecommendedPath[0], endBack });
                LinePath lp = new LinePath(new Coordinates[] { zp.RecommendedPath[0], endBack });
                LinePath lB = lp.ShiftLateral(TahoeParams.T * 2.0);
                LinePath rB = lp.ShiftLateral(-TahoeParams.T * 2.0);

                // add to info
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(lB, ArbiterInformationDisplayObjectType.leftBound));
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(rB, ArbiterInformationDisplayObjectType.rightBound));
                CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(rp, ArbiterInformationDisplayObjectType.leftBound));

                // determine stay out areas to use
                List <Polygon> stayOuts = new List <Polygon>();
                foreach (Polygon p in pos.Zone.StayOutAreas)
                {
                    if (!p.IsInside(pos.ParkingSpot.NormalWaypoint.Position) && !p.IsInside(pos.ParkingSpot.Checkpoint.Position))
                    {
                        stayOuts.Add(p);
                    }
                }

                // get speed command
                ScalarSpeedCommand sc = new ScalarSpeedCommand(2.24);

                // Behavior
                Behavior b = new ZoneParkingPullOutBehavior(zp.Zone.ZoneId, zp.Zone.Perimeter.PerimeterPolygon, stayOuts.ToArray(),
                                                            sc, pos.ParkingSpot.GetSpotPath(), pos.ParkingSpot.GetLeftBound(), pos.ParkingSpot.GetRightBound(), pos.ParkingSpot.SpotId,
                                                            rp, lB, rB);

                // maneuver
                return(new Maneuver(b, pos, TurnDecorators.NoDecorators, vehicleState.Timestamp));
            }

            #endregion

            #region Zone Startup State

            else if (planningState is ZoneStartupState)
            {
                // state
                ZoneStartupState zss = (ZoneStartupState)planningState;

                // get the zone
                ArbiterZone az = zss.Zone;

                // navigational edge
                INavigableNode inn = CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId];

                // check over all the parking spaces
                foreach (ArbiterParkingSpot aps in az.ParkingSpots)
                {
                    // inside both parts of spot
                    if ((vehicleState.VehiclePolygon.IsInside(aps.NormalWaypoint.Position) && vehicleState.VehiclePolygon.IsInside(aps.Checkpoint.Position)) ||
                        (vehicleState.VehiclePolygon.IsInside(aps.NormalWaypoint.Position)))
                    {
                        // want to just park in it again
                        return(new Maneuver(new HoldBrakeBehavior(), new ParkingState(az, aps), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                    }
                }

                Polygon forwardPolygon = vehicleState.ForwardPolygon;
                Polygon rearPolygon    = vehicleState.RearPolygon;

                Navigator nav = CoreCommon.Navigation;
                List <ZoneNavigationEdgeSort> forwardForward             = new List <ZoneNavigationEdgeSort>();
                List <ZoneNavigationEdgeSort> reverseReverse             = new List <ZoneNavigationEdgeSort>();
                List <ZoneNavigationEdgeSort> perpendicularPerpendicular = new List <ZoneNavigationEdgeSort>();
                List <ZoneNavigationEdgeSort> allEdges         = new List <ZoneNavigationEdgeSort>();
                List <ZoneNavigationEdgeSort> allEdgesNoLimits = new List <ZoneNavigationEdgeSort>();
                foreach (NavigableEdge ne in az.NavigableEdges)
                {
                    if (!(ne.End is ArbiterParkingSpotWaypoint) && !(ne.Start is ArbiterParkingSpotWaypoint))
                    {
                        // get distance to edge
                        LinePath lp      = new LinePath(new Coordinates[] { ne.Start.Position, ne.End.Position });
                        double   distTmp = lp.GetClosestPoint(vehicleState.Front).Location.DistanceTo(vehicleState.Front);

                        // get direction along segment
                        DirectionAlong da = vehicleState.DirectionAlongSegment(lp);

                        // check dist reasonable
                        if (distTmp > TahoeParams.VL)
                        {
                            // zone navigation edge sort item
                            ZoneNavigationEdgeSort znes = new ZoneNavigationEdgeSort(distTmp, ne, lp);

                            // add to lists
                            if (da == DirectionAlong.Forwards &&
                                (forwardPolygon.IsInside(ne.Start.Position) || forwardPolygon.IsInside(ne.End.Position)))
                            {
                                forwardForward.Add(znes);
                            }

                            /*else if (da == DirectionAlong.Perpendicular &&
                             *      !(forwardPolygon.IsInside(ne.Start.Position) || forwardPolygon.IsInside(ne.End.Position)) &&
                             *      !(rearPolygon.IsInside(ne.Start.Position) || rearPolygon.IsInside(ne.End.Position)))
                             *      perpendicularPerpendicular.Add(znes);
                             * else if (rearPolygon.IsInside(ne.Start.Position) || rearPolygon.IsInside(ne.End.Position))
                             *      reverseReverse.Add(znes);*/

                            // add to all edges
                            allEdges.Add(znes);
                        }
                    }
                }

                // sort by distance
                forwardForward.Sort();
                reverseReverse.Sort();
                perpendicularPerpendicular.Sort();
                allEdges.Sort();

                ZoneNavigationEdgeSort bestZnes = null;

                for (int i = 0; i < allEdges.Count; i++)
                {
                    // get line to initial
                    Line          toInitial  = new Line(vehicleState.Front, allEdges[i].edge.Start.Position);
                    Line          toFinal    = new Line(vehicleState.Front, allEdges[i].edge.End.Position);
                    bool          intersects = false;
                    Coordinates[] interPts;
                    foreach (Polygon sop in az.StayOutAreas)
                    {
                        if (!intersects &&
                            (sop.Intersect(toInitial, out interPts) && sop.Intersect(toFinal, out interPts)))
                        {
                            intersects = true;
                        }
                    }

                    if (!intersects)
                    {
                        allEdges[i].zp       = nav.PlanZone(az, allEdges[i].edge.End, inn);
                        allEdges[i].zp.Time += vehicleState.Front.DistanceTo(allEdges[i].lp.GetClosestPoint(vehicleState.Front).Location) / 2.24;
                        ZoneNavigationEdgeSort tmpZnes = allEdges[i];
                        if ((bestZnes == null && tmpZnes.zp.RecommendedPath.Count > 1) ||
                            (bestZnes != null && tmpZnes.zp.RecommendedPath.Count > 1 && tmpZnes.zp.Time < bestZnes.zp.Time))
                        {
                            bestZnes = tmpZnes;
                        }
                    }

                    if (i > allEdges.Count / 2 && bestZnes != null)
                    {
                        break;
                    }
                }

                if (bestZnes != null)
                {
                    ArbiterOutput.Output("Found good edge to start in zone");
                    return(new Maneuver(new HoldBrakeBehavior(), new ZoneOrientationState(az, bestZnes.edge), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }
                else
                {
                    ArbiterOutput.Output("Could not find good edge to start, choosing random not blocked");

                    List <ZoneNavigationEdgeSort> okZnes = new List <ZoneNavigationEdgeSort>();
                    foreach (NavigableEdge tmpOk in az.NavigableEdges)
                    {
                        // get line to initial
                        LinePath edgePath = new LinePath(new Coordinates[] { tmpOk.Start.Position, tmpOk.End.Position });
                        double   dist     = edgePath.GetClosestPoint(vehicleState.Front).Location.DistanceTo(vehicleState.Front);
                        ZoneNavigationEdgeSort tmpZnes = new ZoneNavigationEdgeSort(dist, tmpOk, edgePath);
                        tmpZnes.zp       = nav.PlanZone(az, tmpZnes.edge.End, inn);
                        tmpZnes.zp.Time += vehicleState.Front.DistanceTo(tmpZnes.lp.GetClosestPoint(vehicleState.Front).Location) / 2.24;
                        if (tmpZnes.zp.RecommendedPath.Count >= 2)
                        {
                            okZnes.Add(tmpZnes);
                        }
                    }

                    if (okZnes.Count == 0)
                    {
                        okZnes = allEdges;
                    }
                    else
                    {
                        okZnes.Sort();
                    }

                    // get random close edge
                    Random rand   = new Random();
                    int    chosen = rand.Next(Math.Min(5, okZnes.Count));

                    // get closest edge not part of a parking spot, get on it
                    NavigableEdge closest = okZnes[chosen].edge;                    //null;
                    //double distance = Double.MaxValue;

                    /*foreach (NavigableEdge ne in az.NavigableEdges)
                     * {
                     *      if (!(ne.End is ArbiterParkingSpotWaypoint) && !(ne.Start is ArbiterParkingSpotWaypoint))
                     *      {
                     *              // get distance to edge
                     *              LinePath lp = new LinePath(new Coordinates[] { ne.Start.Position, ne.End.Position });
                     *              double distTmp = lp.GetClosestPoint(vehicleState.Front).Location.DistanceTo(vehicleState.Front);
                     *              if (closest == null || distTmp < distance)
                     *              {
                     *                      closest = ne;
                     *                      distance = distTmp;
                     *              }
                     *      }
                     * }*/
                    return(new Maneuver(new HoldBrakeBehavior(), new ZoneOrientationState(az, closest), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }
            }

            #endregion

            #region Unknown

            else
            {
                // non-handled state
                throw new ArgumentException("Unknown state", "CoreCommon.CorePlanningState");
            }

            #endregion
        }
Beispiel #8
0
        /// <summary>Called every frame to update the plugin.</summary>
        public void UpdatePlugin()
        {
            if (Train.Cars == null || Train.Cars.Length == 0)
            {
                return;
            }

            /*
             * Prepare the vehicle state.
             * */
            double location = this.Train.Cars[0].FrontAxle.Follower.TrackPosition - this.Train.Cars[0].FrontAxle.Position + 0.5 * this.Train.Cars[0].Length;

            //If the list of stations has not been loaded, do so
            if (!StationsLoaded)
            {
                currentRouteStations = new List <Station>();
                int s = 0;
                foreach (RouteStation selectedStation in TrainManagerBase.CurrentRoute.Stations)
                {
                    double stopPosition = -1;
                    int    stopIdx      = TrainManagerBase.CurrentRoute.Stations[s].GetStopIndex(Train.NumberOfCars);
                    if (selectedStation.Stops.Length != 0)
                    {
                        stopPosition = selectedStation.Stops[stopIdx].TrackPosition;
                    }

                    Station i = new Station(selectedStation, stopPosition);
                    currentRouteStations.Add(i);
                    s++;
                }

                StationsLoaded = true;
            }

            //End of additions
            double       speed       = this.Train.Cars[this.Train.DriverCar].Specs.PerceivedSpeed;
            double       bcPressure  = this.Train.Cars[this.Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure;
            double       mrPressure  = this.Train.Cars[this.Train.DriverCar].CarBrake.mainReservoir.CurrentPressure;
            double       erPressure  = this.Train.Cars[this.Train.DriverCar].CarBrake.equalizingReservoir.CurrentPressure;
            double       bpPressure  = this.Train.Cars[this.Train.DriverCar].CarBrake.brakePipe.CurrentPressure;
            double       sapPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.straightAirPipe.CurrentPressure;
            VehicleState vehicle     = new VehicleState(location, new Speed(speed), bcPressure, mrPressure, erPressure, bpPressure, sapPressure, this.Train.Cars[0].FrontAxle.Follower);

            /*
             * Prepare the preceding vehicle state.
             * */


            PrecedingVehicleState precedingVehicle;

            try
            {
                AbstractTrain closestTrain = TrainManagerBase.currentHost.ClosestTrain(this.Train);
                precedingVehicle = closestTrain != null ? new PrecedingVehicleState(closestTrain.RearCarTrackPosition(), closestTrain.RearCarTrackPosition() - location, new Speed(closestTrain.CurrentSpeed)) : new PrecedingVehicleState(Double.MaxValue, Double.MaxValue - location, new Speed(0.0));
            }
            catch
            {
                precedingVehicle = null;
            }

            /*
             * Get the driver handles.
             * */
            OpenBveApi.Runtime.Handles handles = GetHandles();

            /*
             * Update the plugin.
             * */
            double totalTime   = TrainManagerBase.currentHost.InGameTime;
            double elapsedTime = TrainManagerBase.currentHost.InGameTime - LastTime;

            ElapseData data = new ElapseData(vehicle, precedingVehicle, handles, this.Train.SafetySystems.DoorInterlockState, new Time(totalTime), new Time(elapsedTime), currentRouteStations, TrainManagerBase.Renderer.Camera.CurrentMode, Translations.CurrentLanguageCode, this.Train.Destination);
            ElapseData inputDevicePluginData = data;

            LastTime = TrainManagerBase.currentHost.InGameTime;
            Elapse(ref data);
            this.PluginMessage = data.DebugMessage;
            this.Train.SafetySystems.DoorInterlockState = data.DoorInterlockState;
            DisableTimeAcceleration = data.DisableTimeAcceleration;
            for (int i = 0; i < InputDevicePlugin.AvailablePluginInfos.Count; i++)
            {
                if (InputDevicePlugin.AvailablePluginInfos[i].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable)
                {
                    InputDevicePlugin.AvailablePlugins[i].SetElapseData(inputDevicePluginData);
                }
            }

            /*
             * Set the virtual handles.
             * */
            this.PluginValid = true;
            SetHandles(data.Handles, true);
            this.Train.Destination = data.Destination;
        }
        /// <summary>
        /// Checks if vehicle is far enough away to leave
        /// </summary>
        public bool Clear(VehicleState ourState)
        {
            // if no current vehicle, the stuff is fine
            if (currentVehicle == null)
            {
                return(true);
            }
            else
            {
                // check exit exists
                if (this.exit != null)
                {
                    // check not inside polygon
                    double distToExit;
                    if (this.exitPolygon.IsInside(this.currentVehicle.ClosestPointTo(this.exit.Position, ourState, out distToExit).Value))
                    {
                        if (!this.LargerExcessiveWaiting)
                        {
                            ArbiterOutput.Output("DLEM: " + this.lane.ToString() + " not clear, vehicle " + this.currentVehicle.ToString() + " in exit polygon" +
                                                 ", speed valid: " + this.currentVehicle.StateMonitor.Observed.speedValid.ToString() +
                                                 ", is stopped: " + this.currentVehicle.IsStopped);
                            return(false);
                        }
                        else
                        {
                            ArbiterOutput.Output("DLEM: " + this.lane.ToString() + " not clear, vehicle " + this.currentVehicle.ToString() + " in exit polygon" +
                                                 ", speed valid: " + this.currentVehicle.StateMonitor.Observed.speedValid.ToString() +
                                                 ", is stopped: " + this.currentVehicle.IsStopped + ", passed large excessive wait test so going");
                            return(true);
                        }
                    }
                }

                // get the point we are looking from
                LinePath.PointOnPath referencePoint;

                // reference from exit if exists
                if (exit != null)
                {
                    LinePath.PointOnPath pop = lane.LanePath().GetClosestPoint(exit.Position);
                    referencePoint = lane.LanePath().AdvancePoint(pop, 3.0);
                }
                // otherwise look from where we are closest
                else
                {
                    referencePoint = lane.LanePath().GetClosestPoint(ourState.Front);
                }

                // vehicle point
                LinePath.PointOnPath vehiclePoint = lane.LanePath().GetClosestPoint(currentVehicle.ClosestPosition);

                // distance
                double distance = lane.LanePath().DistanceBetween(vehiclePoint, referencePoint);

                if (distance < 30 && (!this.currentVehicle.StateMonitor.Observed.speedValid || !this.currentVehicle.IsStopped))
                {
                    ArbiterOutput.Output("DLEM: " + this.lane.ToString() + " not clear, moving vehicle " + this.currentVehicle.ToString() + " within 30m of intersection" +
                                         ", speed valid: " + this.currentVehicle.StateMonitor.Observed.speedValid.ToString() +
                                         ", is stopped: " + this.currentVehicle.IsStopped);
                    return(false);
                }
                else if (distance > 0)
                {
                    // vehicles speed
                    double vehicleSpeed = this.currentVehicle.StateMonitor.Observed.speedValid ? Math.Abs(currentVehicle.Speed) : lane.Way.Segment.SpeedLimits.MaximumSpeed;
                    if (!this.currentVehicle.StateMonitor.Observed.speedValid)
                    {
                        ArbiterOutput.Output("DLEM: " + this.lane.ToString() + ", vehicle: " + this.currentVehicle.ToString() + " speed not valid, set to: " + lane.Way.Segment.SpeedLimits.MaximumSpeed.ToString("F2"));
                    }

                    // check time
                    double time = vehicleSpeed != 0 ? distance / vehicleSpeed : 777;

                    // clear if time greater than 7.0 seconds
                    if (time > 8.0)
                    {
                        ArbiterOutput.Output("DLEM: " + this.lane.ToString() + " clear, vehicle " + this.currentVehicle.ToString() +
                                             ", speed valid: " + this.currentVehicle.StateMonitor.Observed.speedValid.ToString() +
                                             ", speed: " + this.currentVehicle.Speed.ToString("F2") +
                                             ", time to collision: " + time.ToString("F2") + " > 8");
                        return(true);
                    }
                    else
                    {
                        ArbiterOutput.Output("DLEM: " + this.lane.ToString() + " NOT clear, vehicle " + this.currentVehicle.ToString() +
                                             ", speed valid: " + this.currentVehicle.StateMonitor.Observed.speedValid.ToString() +
                                             ", speed: " + this.currentVehicle.Speed.ToString("F2") +
                                             ", time to collision: " + time.ToString("F2") + " < 8");
                        return(false);
                    }
                }
                else
                {
                    ArbiterOutput.Output("Exception: distance to vehicle negative in dlem is clear: " + distance.ToString("F3"));
                    return(false);
                }
            }
        }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

#if PATHRECALC
            VehicleState state           = VehicleStateManager._GetVehicleState(vehicleID);
            bool         recalcRequested = state.PathRecalculationRequested;
            state.PathRecalculationRequested = false;
#endif

            CitizenManager instance            = Singleton <CitizenManager> .instance;
            ushort         passengerInstanceId = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData);
            if (passengerInstanceId == 0 || (instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None)
            {
                return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget));
            }
            VehicleInfo             info        = this.m_info;
            CitizenInfo             info2       = instance.m_instances.m_buffer[(int)passengerInstanceId].Info;
            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startSqrDistA;
            float             startSqrDistB;
            PathUnit.Position endPosA;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) &&
                info2.m_citizenAI.FindPathPosition(passengerInstanceId, ref instance.m_instances.m_buffer[(int)passengerInstanceId], endPos, laneTypes, vehicleType, undergroundTarget, out endPosA))
            {
                if ((instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                {
                    laneTypes |= NetInfo.LaneType.PublicTransport;

                    uint citizenId = instance.m_instances.m_buffer[passengerInstanceId].m_citizen;
                    if (citizenId != 0u && (instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                    {
                        laneTypes |= NetInfo.LaneType.EvacuationTransport;
                    }
                }
                if (!startBothWays || startSqrDistA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                if (CustomPathManager._instance.CreatePath(
#if PATHRECALC
                        recalcRequested,
#endif
                        ExtVehicleType.Taxi, vehicleID, 0, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f))
                {
#if USEPATHWAITCOUNTER
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleID);
                    state.PathWaitCounter = 0;
#endif

                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
 public IAction ReactTo(VehicleState state, int wayPoint)
 => actions.AllPossibleActions[random.Next(0, actions.AllPossibleActions.Count - 1)];
        /// <summary>
        /// Plans what maneuer we should take next
        /// </summary>
        /// <param name="planningState"></param>
        /// <param name="navigationalPlan"></param>
        /// <param name="vehicleState"></param>
        /// <param name="vehicles"></param>
        /// <param name="obstacles"></param>
        /// <param name="blockage"></param>
        /// <returns></returns>
        public Maneuver Plan(IState planningState, INavigationalPlan navigationalPlan, VehicleState vehicleState,
                             SceneEstimatorTrackedClusterCollection vehicles, SceneEstimatorUntrackedClusterCollection obstacles, List <ITacticalBlockage> blockages)
        {
            #region Waiting At Intersection Exit

            if (planningState is WaitingAtIntersectionExitState)
            {
                // state
                WaitingAtIntersectionExitState waies = (WaitingAtIntersectionExitState)planningState;

                // get intersection plan
                IntersectionPlan ip = (IntersectionPlan)navigationalPlan;

                // nullify turn reasoning
                this.TurnReasoning = null;

                #region Intersection Monitor Updates

                // check correct intersection monitor
                if (CoreCommon.RoadNetwork.IntersectionLookup.ContainsKey(waies.exitWaypoint.AreaSubtypeWaypointId) &&
                    (IntersectionTactical.IntersectionMonitor == null ||
                     !IntersectionTactical.IntersectionMonitor.OurMonitor.Waypoint.Equals(waies.exitWaypoint)))
                {
                    // create new intersection monitor
                    IntersectionTactical.IntersectionMonitor = new IntersectionMonitor(
                        waies.exitWaypoint,
                        CoreCommon.RoadNetwork.IntersectionLookup[waies.exitWaypoint.AreaSubtypeWaypointId],
                        vehicleState,
                        ip.BestOption);
                }

                // update if exists
                if (IntersectionTactical.IntersectionMonitor != null)
                {
                    // update monitor
                    IntersectionTactical.IntersectionMonitor.Update(vehicleState);

                    // print current
                    ArbiterOutput.Output(IntersectionTactical.IntersectionMonitor.IntersectionStateString());
                }

                #endregion

                #region Desired Behavior

                // get best option from previously saved
                IConnectAreaWaypoints icaw = null;

                if (waies.desired != null)
                {
                    ArbiterInterconnect tmpInterconnect = waies.desired;
                    if (waies.desired.InitialGeneric is ArbiterWaypoint)
                    {
                        ArbiterWaypoint init = (ArbiterWaypoint)waies.desired.InitialGeneric;
                        if (init.NextPartition != null && init.NextPartition.Final.Equals(tmpInterconnect.FinalGeneric))
                        {
                            icaw = init.NextPartition;
                        }
                        else
                        {
                            icaw = waies.desired;
                        }
                    }
                    else
                    {
                        icaw = waies.desired;
                    }
                }
                else
                {
                    icaw          = ip.BestOption;
                    waies.desired = icaw.ToInterconnect;
                }

                #endregion

                #region Turn Feasibility Reasoning

                // check uturn
                if (waies.desired.TurnDirection == ArbiterTurnDirection.UTurn)
                {
                    waies.turnTestState = TurnTestState.Completed;
                }

                // check already determined feasible
                if (waies.turnTestState == TurnTestState.Unknown ||
                    waies.turnTestState == TurnTestState.Failed)
                {
                    #region Determine Behavior to Accomplish Turn

                    // get default turn behavior
                    TurnBehavior testTurnBehavior = this.DefaultTurnBehavior(icaw);

                    // set saudi decorator
                    if (waies.saudi != SAUDILevel.None)
                    {
                        testTurnBehavior.Decorators.Add(new ShutUpAndDoItDecorator(waies.saudi));
                    }

                    // set to ignore all vehicles
                    testTurnBehavior.VehiclesToIgnore = new List <int>(new int[] { -1 });

                    #endregion

                    #region Check Turn Feasible

                    // check if we have completed
                    CompletionReport turnCompletionReport;
                    bool             completedTest = CoreCommon.Communications.TestExecute(testTurnBehavior, out turnCompletionReport);        //CoreCommon.Communications.AsynchronousTestHasCompleted(testTurnBehavior, out turnCompletionReport, true);

                    // if we have completed the test
                    if (completedTest || ((TrajectoryBlockedReport)turnCompletionReport).BlockageType != BlockageType.Dynamic)
                    {
                        #region Can Complete

                        // check success
                        if (turnCompletionReport.Result == CompletionResult.Success)
                        {
                            // set completion state of the turn
                            waies.turnTestState = TurnTestState.Completed;
                        }

                        #endregion

                        #region No Saudi Level, Found Initial Blockage

                        // otherwise we cannot do the turn, check if saudi is still none
                        else if (waies.saudi == SAUDILevel.None)
                        {
                            // notify
                            ArbiterOutput.Output("Increased Saudi Level of Turn to L1");

                            // up the saudi level, set as turn failed and no other option
                            waies.saudi         = SAUDILevel.L1;
                            waies.turnTestState = TurnTestState.Failed;
                        }

                        #endregion

                        #region Already at L1 Saudi

                        else if (waies.saudi == SAUDILevel.L1)
                        {
                            // notify
                            ArbiterOutput.Output("Turn with Saudi L1 Level failed");

                            // get an intersection plan without this interconnect
                            IntersectionPlan testPlan = CoreCommon.Navigation.PlanIntersectionWithoutInterconnect(
                                waies.exitWaypoint,
                                CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId],
                                waies.desired);

                            // check that the plan exists
                            if (!testPlan.BestOption.ToInterconnect.Equals(waies.desired) &&
                                testPlan.BestRouteTime < double.MaxValue - 1.0)
                            {
                                // get the desired interconnect
                                ArbiterInterconnect reset = testPlan.BestOption.ToInterconnect;

                                #region Check that the reset interconnect is feasible

                                // test the reset interconnect
                                TurnBehavior testResetTurnBehavior = this.DefaultTurnBehavior(reset);

                                // set to ignore all vehicles
                                testResetTurnBehavior.VehiclesToIgnore = new List <int>(new int[] { -1 });

                                // check if we have completed
                                CompletionReport turnResetCompletionReport;
                                bool             completedResetTest = CoreCommon.Communications.TestExecute(testResetTurnBehavior, out turnResetCompletionReport);

                                // check to see if this is feasible
                                if (completedResetTest && turnResetCompletionReport is SuccessCompletionReport && reset.Blockage.ProbabilityExists < 0.95)
                                {
                                    // notify
                                    ArbiterOutput.Output("Found clear interconnect: " + reset.ToString() + " adding blockage to current interconnect: " + waies.desired.ToString());

                                    // set the interconnect as being blocked
                                    CoreCommon.Navigation.AddInterconnectBlockage(waies.desired);

                                    // reset all
                                    waies.desired       = reset;
                                    waies.turnTestState = TurnTestState.Completed;
                                    waies.saudi         = SAUDILevel.None;
                                    waies.useTurnBounds = true;
                                    IntersectionMonitor.ResetDesired(reset);
                                }

                                #endregion

                                #region No Lane Bounds

                                // otherwise try without lane bounds
                                else
                                {
                                    // notify
                                    ArbiterOutput.Output("Had to fallout to using no turn bounds");

                                    // up the saudi level, set as turn failed and no other option
                                    waies.saudi         = SAUDILevel.L1;
                                    waies.turnTestState = TurnTestState.Completed;
                                    waies.useTurnBounds = false;
                                }

                                #endregion
                            }

                            #region No Lane Bounds

                            // otherwise try without lane bounds
                            else
                            {
                                // up the saudi level, set as turn failed and no other option
                                waies.saudi         = SAUDILevel.L1;
                                waies.turnTestState = TurnTestState.Unknown;
                                waies.useTurnBounds = false;
                            }

                            #endregion
                        }

                        #endregion

                        // want to reset ourselves
                        return(new Maneuver(new HoldBrakeBehavior(), CoreCommon.CorePlanningState, TurnDecorators.NoDecorators, vehicleState.Timestamp));
                    }

                    #endregion
                }

                #endregion

                #region Entry Monitor Blocked

                // checks the entry monitor vehicle for failure
                if (IntersectionMonitor != null && IntersectionMonitor.EntryAreaMonitor != null &&
                    IntersectionMonitor.EntryAreaMonitor.Vehicle != null && IntersectionMonitor.EntryAreaMonitor.Failed)
                {
                    ArbiterOutput.Output("Entry area blocked");

                    // get an intersection plan without this interconnect
                    IntersectionPlan testPlan = CoreCommon.Navigation.PlanIntersectionWithoutInterconnect(
                        waies.exitWaypoint,
                        CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId],
                        waies.desired,
                        true);

                    // check that the plan exists
                    if (!testPlan.BestOption.ToInterconnect.Equals(waies.desired) &&
                        testPlan.BestRouteTime < double.MaxValue - 1.0)
                    {
                        // get the desired interconnect
                        ArbiterInterconnect reset = testPlan.BestOption.ToInterconnect;

                        #region Check that the reset interconnect is feasible

                        // test the reset interconnect
                        TurnBehavior testResetTurnBehavior = this.DefaultTurnBehavior(reset);

                        // set to ignore all vehicles
                        testResetTurnBehavior.VehiclesToIgnore = new List <int>(new int[] { -1 });

                        // check if we have completed
                        CompletionReport turnResetCompletionReport;
                        bool             completedResetTest = CoreCommon.Communications.TestExecute(testResetTurnBehavior, out turnResetCompletionReport);

                        // check to see if this is feasible
                        if (reset.TurnDirection == ArbiterTurnDirection.UTurn || (completedResetTest && turnResetCompletionReport is SuccessCompletionReport && reset.Blockage.ProbabilityExists < 0.95))
                        {
                            // notify
                            ArbiterOutput.Output("Found clear interconnect: " + reset.ToString() + " adding blockage to all possible turns into final");

                            // set all the interconnects to the final as being blocked
                            if (((ITraversableWaypoint)waies.desired.FinalGeneric).IsEntry)
                            {
                                foreach (ArbiterInterconnect toBlock in ((ITraversableWaypoint)waies.desired.FinalGeneric).Entries)
                                {
                                    CoreCommon.Navigation.AddInterconnectBlockage(toBlock);
                                }
                            }

                            // check if exists previous partition to block
                            if (waies.desired.FinalGeneric is ArbiterWaypoint)
                            {
                                ArbiterWaypoint finWaypoint = (ArbiterWaypoint)waies.desired.FinalGeneric;
                                if (finWaypoint.PreviousPartition != null)
                                {
                                    CoreCommon.Navigation.AddBlockage(finWaypoint.PreviousPartition, finWaypoint.Position, false);
                                }
                            }

                            // reset all
                            waies.desired       = reset;
                            waies.turnTestState = TurnTestState.Completed;
                            waies.saudi         = SAUDILevel.None;
                            waies.useTurnBounds = true;
                            IntersectionMonitor.ResetDesired(reset);

                            // want to reset ourselves
                            return(new Maneuver(new HoldBrakeBehavior(), CoreCommon.CorePlanningState, TurnDecorators.NoDecorators, vehicleState.Timestamp));
                        }

                        #endregion
                    }
                    else
                    {
                        ArbiterOutput.Output("Entry area blocked, but no otehr valid route found");
                    }
                }

                #endregion

                // check if can traverse
                if (IntersectionTactical.IntersectionMonitor == null || IntersectionTactical.IntersectionMonitor.CanTraverse(icaw, vehicleState))
                {
                    #region If can traverse the intersection

                    // quick check not interconnect
                    if (!(icaw is ArbiterInterconnect))
                    {
                        icaw = icaw.ToInterconnect;
                    }

                    // get interconnect
                    ArbiterInterconnect ai = (ArbiterInterconnect)icaw;

                    // clear all old completion reports
                    CoreCommon.Communications.ClearCompletionReports();

                    // check if uturn
                    if (ai.InitialGeneric is ArbiterWaypoint && ai.FinalGeneric is ArbiterWaypoint && ai.TurnDirection == ArbiterTurnDirection.UTurn)
                    {
                        // go into turn
                        List <ArbiterLane> involvedLanes = new List <ArbiterLane>();
                        involvedLanes.Add(((ArbiterWaypoint)ai.InitialGeneric).Lane);
                        involvedLanes.Add(((ArbiterWaypoint)ai.FinalGeneric).Lane);
                        uTurnState nextState = new uTurnState(((ArbiterWaypoint)ai.FinalGeneric).Lane,
                                                              IntersectionToolkit.uTurnBounds(vehicleState, involvedLanes));
                        nextState.Interconnect = ai;

                        // hold brake
                        Behavior b = new HoldBrakeBehavior();

                        // return maneuver
                        return(new Maneuver(b, nextState, nextState.DefaultStateDecorators, vehicleState.Timestamp));
                    }
                    else
                    {
                        if (ai.FinalGeneric is ArbiterWaypoint)
                        {
                            ArbiterWaypoint finalWaypoint = (ArbiterWaypoint)ai.FinalGeneric;

                            // get turn params
                            LinePath finalPath;
                            LineList leftLL;
                            LineList rightLL;
                            IntersectionToolkit.TurnInfo(finalWaypoint, out finalPath, out leftLL, out rightLL);

                            // go into turn
                            IState nextState = new TurnState(ai, ai.TurnDirection, finalWaypoint.Lane, finalPath, leftLL, rightLL, new ScalarSpeedCommand(2.5), waies.saudi, waies.useTurnBounds);

                            // hold brake
                            Behavior b = new HoldBrakeBehavior();

                            // return maneuver
                            return(new Maneuver(b, nextState, nextState.DefaultStateDecorators, vehicleState.Timestamp));
                        }
                        else
                        {
                            // final perimeter waypoint
                            ArbiterPerimeterWaypoint apw = (ArbiterPerimeterWaypoint)ai.FinalGeneric;

                            // get turn params
                            LinePath finalPath;
                            LineList leftLL;
                            LineList rightLL;
                            IntersectionToolkit.ZoneTurnInfo(ai, apw, out finalPath, out leftLL, out rightLL);

                            // go into turn
                            IState nextState = new TurnState(ai, ai.TurnDirection, null, finalPath, leftLL, rightLL, new ScalarSpeedCommand(2.5), waies.saudi, waies.useTurnBounds);

                            // hold brake
                            Behavior b = new HoldBrakeBehavior();

                            // return maneuver
                            return(new Maneuver(b, nextState, nextState.DefaultStateDecorators, vehicleState.Timestamp));
                        }
                    }

                    #endregion
                }
                // otherwise need to wait
                else
                {
                    IState next = waies;
                    return(new Maneuver(new HoldBrakeBehavior(), next, next.DefaultStateDecorators, vehicleState.Timestamp));
                }
            }

            #endregion

            #region Stopping At Exit

            else if (planningState is StoppingAtExitState)
            {
                // cast to exit stopping
                StoppingAtExitState saes = (StoppingAtExitState)planningState;
                saes.currentPosition = vehicleState.Front;

                // get intersection plan
                IntersectionPlan ip = (IntersectionPlan)navigationalPlan;

                // if has an intersection
                if (CoreCommon.RoadNetwork.IntersectionLookup.ContainsKey(saes.waypoint.AreaSubtypeWaypointId))
                {
                    // create new intersection monitor
                    IntersectionTactical.IntersectionMonitor = new IntersectionMonitor(
                        saes.waypoint,
                        CoreCommon.RoadNetwork.IntersectionLookup[saes.waypoint.AreaSubtypeWaypointId],
                        vehicleState,
                        ip.BestOption);

                    // update it
                    IntersectionTactical.IntersectionMonitor.Update(vehicleState);
                }
                else
                {
                    IntersectionTactical.IntersectionMonitor = null;
                }

                // otherwise update the stop parameters
                saes.currentPosition = vehicleState.Front;
                Behavior b = saes.Resume(vehicleState, CoreCommon.Communications.GetVehicleSpeed().Value);
                return(new Maneuver(b, saes, saes.DefaultStateDecorators, vehicleState.Timestamp));
            }

            #endregion

            #region In uTurn

            else if (planningState is uTurnState)
            {
                // get state
                uTurnState uts = (uTurnState)planningState;

                // check if in other lane
                if (CoreCommon.Communications.HasCompleted((new UTurnBehavior(null, null, null, null)).GetType()))
                {
                    // quick check
                    if (uts.Interconnect != null && uts.Interconnect.FinalGeneric is ArbiterWaypoint)
                    {
                        // get the closest partition to the new lane
                        ArbiterLanePartition alpClose = uts.TargetLane.GetClosestPartition(vehicleState.Front);

                        // waypoints
                        ArbiterWaypoint partitionInitial = alpClose.Initial;
                        ArbiterWaypoint uturnEnd         = (ArbiterWaypoint)uts.Interconnect.FinalGeneric;

                        // check initial past end
                        if (partitionInitial.WaypointId.Number > uturnEnd.WaypointId.Number)
                        {
                            // get waypoints inclusive
                            List <ArbiterWaypoint> inclusive = uts.TargetLane.WaypointsInclusive(uturnEnd, partitionInitial);
                            bool found = false;

                            // loop through
                            foreach (ArbiterWaypoint aw in inclusive)
                            {
                                if (!found && aw.WaypointId.Equals(CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId))
                                {
                                    // notiofy
                                    ArbiterOutput.Output("removed checkpoint: " + CoreCommon.Mission.MissionCheckpoints.Peek().CheckpointNumber.ToString() + " as passed over in uturn");

                                    // remove
                                    CoreCommon.Mission.MissionCheckpoints.Dequeue();

                                    // set found
                                    found = true;
                                }
                            }
                        }
                        // default check
                        else if (uts.Interconnect.FinalGeneric.Equals(CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId]))
                        {
                            // notiofy
                            ArbiterOutput.Output("removed checkpoint: " + CoreCommon.Mission.MissionCheckpoints.Peek().CheckpointNumber.ToString() + " as end of uturn");

                            // remove
                            CoreCommon.Mission.MissionCheckpoints.Dequeue();
                        }
                    }
                    // check if the uturn is for a blockage
                    else if (uts.Interconnect == null)
                    {
                        // get final lane
                        ArbiterLane targetLane = uts.TargetLane;

                        // check has opposing
                        if (targetLane.Way.Segment.Lanes.Count > 1)
                        {
                            // check the final checkpoint is in our lane
                            if (CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.AreaSubtypeId.Equals(targetLane.LaneId))
                            {
                                // check that the final checkpoint is within the uturn polygon
                                if (uts.Polygon != null &&
                                    uts.Polygon.IsInside(CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId].Position))
                                {
                                    // remove the checkpoint
                                    ArbiterOutput.Output("Found checkpoint: " + CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.ToString() + " inside blockage uturn area, dequeuing");
                                    CoreCommon.Mission.MissionCheckpoints.Dequeue();
                                }
                            }
                        }
                    }

                    // stay in target lane
                    IState   nextState = new StayInLaneState(uts.TargetLane, new Probability(0.8, 0.2), true, CoreCommon.CorePlanningState);
                    Behavior b         = new StayInLaneBehavior(uts.TargetLane.LaneId, new ScalarSpeedCommand(2.0), new List <int>(), uts.TargetLane.LanePath(), uts.TargetLane.Width, uts.TargetLane.NumberOfLanesLeft(vehicleState.Front, true), uts.TargetLane.NumberOfLanesRight(vehicleState.Front, true));
                    return(new Maneuver(b, nextState, TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }
                // otherwise continue uturn
                else
                {
                    // get polygon
                    Polygon p = uts.Polygon;

                    // add polygon to observable
                    CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(p, ArbiterInformationDisplayObjectType.uTurnPolygon));

                    // check the type of uturn
                    if (!uts.singleLaneUturn)
                    {
                        // get ending path
                        LinePath endingPath = uts.TargetLane.LanePath();

                        // next state is current
                        IState nextState = uts;

                        // behavior
                        Behavior b = new UTurnBehavior(p, endingPath, uts.TargetLane.LaneId, new ScalarSpeedCommand(2.0));

                        // maneuver
                        return(new Maneuver(b, nextState, null, vehicleState.Timestamp));
                    }
                    else
                    {
                        // get ending path
                        LinePath endingPath = uts.TargetLane.LanePath().Clone();
                        endingPath = endingPath.ShiftLateral(-2.0);                        //uts.TargetLane.Width);

                        // add polygon to observable
                        CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(endingPath, ArbiterInformationDisplayObjectType.leftBound));

                        // next state is current
                        IState nextState = uts;

                        // behavior
                        Behavior b = new UTurnBehavior(p, endingPath, uts.TargetLane.LaneId, new ScalarSpeedCommand(2.0));

                        // maneuver
                        return(new Maneuver(b, nextState, null, vehicleState.Timestamp));
                    }
                }
            }

            #endregion

            #region In Turn

            else if (planningState is TurnState)
            {
                // get state
                TurnState ts = (TurnState)planningState;

                // add bounds to observable
                if (ts.LeftBound != null && ts.RightBound != null)
                {
                    CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(ts.LeftBound, ArbiterInformationDisplayObjectType.leftBound));
                    CoreCommon.CurrentInformation.DisplayObjects.Add(new ArbiterInformationDisplayObject(ts.RightBound, ArbiterInformationDisplayObjectType.rightBound));
                }

                // create current turn reasoning
                if (this.TurnReasoning == null)
                {
                    this.TurnReasoning = new TurnReasoning(ts.Interconnect,
                                                           IntersectionTactical.IntersectionMonitor != null ? IntersectionTactical.IntersectionMonitor.EntryAreaMonitor : null);
                }

                // get primary maneuver
                Maneuver primary = this.TurnReasoning.PrimaryManeuver(vehicleState, blockages, ts);

                // get secondary maneuver
                Maneuver?secondary = this.TurnReasoning.SecondaryManeuver(vehicleState, (IntersectionPlan)navigationalPlan);

                // return the manevuer
                return(secondary.HasValue ? secondary.Value : primary);
            }

            #endregion

            #region Itnersection Startup

            else if (planningState is IntersectionStartupState)
            {
                // state and plan
                IntersectionStartupState iss = (IntersectionStartupState)planningState;
                IntersectionStartupPlan  isp = (IntersectionStartupPlan)navigationalPlan;

                // initial path
                LinePath vehiclePath = new LinePath(new Coordinates[] { vehicleState.Rear, vehicleState.Front });
                List <ITraversableWaypoint> feasibleEntries = new List <ITraversableWaypoint>();

                // vehicle polygon forward of us
                Polygon vehicleForward = vehicleState.ForwardPolygon;

                // best waypoint
                ITraversableWaypoint best = null;
                double bestCost           = Double.MaxValue;

                // given feasible choose best, no feasible choose random
                if (feasibleEntries.Count == 0)
                {
                    foreach (ITraversableWaypoint itw in iss.Intersection.AllEntries.Values)
                    {
                        if (vehicleForward.IsInside(itw.Position))
                        {
                            feasibleEntries.Add(itw);
                        }
                    }

                    if (feasibleEntries.Count == 0)
                    {
                        foreach (ITraversableWaypoint itw in iss.Intersection.AllEntries.Values)
                        {
                            feasibleEntries.Add(itw);
                        }
                    }
                }

                // get best
                foreach (ITraversableWaypoint itw in feasibleEntries)
                {
                    if (isp.NodeTimeCosts.ContainsKey(itw))
                    {
                        KeyValuePair <ITraversableWaypoint, double> lookup = new KeyValuePair <ITraversableWaypoint, double>(itw, isp.NodeTimeCosts[itw]);

                        if (best == null || lookup.Value < bestCost)
                        {
                            best     = lookup.Key;
                            bestCost = lookup.Value;
                        }
                    }
                }

                // get something going to this waypoint
                ArbiterInterconnect interconnect = null;
                if (best.IsEntry)
                {
                    ArbiterInterconnect closest = null;
                    double closestDistance      = double.MaxValue;

                    foreach (ArbiterInterconnect ai in best.Entries)
                    {
                        double dist = ai.InterconnectPath.GetClosestPoint(vehicleState.Front).Location.DistanceTo(vehicleState.Front);
                        if (closest == null || dist < closestDistance)
                        {
                            closest         = ai;
                            closestDistance = dist;
                        }
                    }

                    interconnect = closest;
                }
                else if (best is ArbiterWaypoint && ((ArbiterWaypoint)best).PreviousPartition != null)
                {
                    interconnect = ((ArbiterWaypoint)best).PreviousPartition.ToInterconnect;
                }

                // get state
                if (best is ArbiterWaypoint)
                {
                    // go to this turn state
                    LinePath finalPath;
                    LineList leftBound;
                    LineList rightBound;
                    IntersectionToolkit.TurnInfo((ArbiterWaypoint)best, out finalPath, out leftBound, out rightBound);
                    return(new Maneuver(new HoldBrakeBehavior(), new TurnState(interconnect, interconnect.TurnDirection, ((ArbiterWaypoint)best).Lane,
                                                                               finalPath, leftBound, rightBound, new ScalarSpeedCommand(2.0)), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }
                else
                {
                    // go to this turn state
                    LinePath finalPath;
                    LineList leftBound;
                    LineList rightBound;
                    IntersectionToolkit.ZoneTurnInfo(interconnect, (ArbiterPerimeterWaypoint)best, out finalPath, out leftBound, out rightBound);
                    return(new Maneuver(new HoldBrakeBehavior(), new TurnState(interconnect, interconnect.TurnDirection, null,
                                                                               finalPath, leftBound, rightBound, new ScalarSpeedCommand(2.0)), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                }
            }

            #endregion

            #region Unknown

            else
            {
                throw new Exception("Unknown planning state in intersection tactical plan: " + planningState.ToString());
            }

            #endregion
        }
Beispiel #13
0
 public virtual void OnStateEnter(VehicleState previousState)
 {
 }
Beispiel #14
0
 public virtual void OnStateExit(VehicleState nextState)
 {
 }
Beispiel #15
0
        internal static float CalcMaxSpeed(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, Vector3 pos, float maxSpeed, bool isRecklessDriver)
        {
            var          netManager   = Singleton <NetManager> .instance;
            NetInfo      segmentInfo  = netManager.m_segments.m_buffer[(int)position.m_segment].Info;
            bool         highwayRules = (segmentInfo.m_netAI is RoadBaseAI && ((RoadBaseAI)segmentInfo.m_netAI).m_highwayRules);
            VehicleState state        = VehicleStateManager.Instance.GetVehicleState(vehicleId);

            if (!highwayRules)
            {
                if (netManager.m_treatWetAsSnow)
                {
                    DistrictManager districtManager = Singleton <DistrictManager> .instance;
                    byte            district        = districtManager.GetDistrict(pos);
                    DistrictPolicies.CityPlanning cityPlanningPolicies = districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
                    if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None)
                    {
                        if (Options.strongerRoadConditionEffects)
                        {
                            if (maxSpeed > ICY_ROADS_STUDDED_MIN_SPEED)
                            {
                                maxSpeed = ICY_ROADS_STUDDED_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_STUDDED_MIN_SPEED);
                            }
                        }
                        else
                        {
                            maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;                             // vanilla: -15% .. ±0%
                        }
                        districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= DistrictPolicies.CityPlanning.StuddedTires;
                    }
                    else
                    {
                        if (Options.strongerRoadConditionEffects)
                        {
                            if (maxSpeed > ICY_ROADS_MIN_SPEED)
                            {
                                maxSpeed = ICY_ROADS_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_MIN_SPEED);
                            }
                        }
                        else
                        {
                            maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.00117647066f;                             // vanilla: -30% .. ±0%
                        }
                    }
                }
                else
                {
                    if (Options.strongerRoadConditionEffects)
                    {
                        float minSpeed = Math.Min(maxSpeed * WET_ROADS_FACTOR, WET_ROADS_MAX_SPEED);
                        if (maxSpeed > minSpeed)
                        {
                            maxSpeed = minSpeed + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - minSpeed);
                        }
                    }
                    else
                    {
                        maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;                         // vanilla: -15% .. ±0%
                    }
                }

                if (Options.strongerRoadConditionEffects)
                {
                    float minSpeed = Math.Min(maxSpeed * BROKEN_ROADS_FACTOR, BROKEN_ROADS_MAX_SPEED);
                    if (maxSpeed > minSpeed)
                    {
                        maxSpeed = minSpeed + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0039215686f * (maxSpeed - minSpeed);
                    }
                }
                else
                {
                    maxSpeed *= 1f + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0005882353f;                     // vanilla: ±0% .. +15 %
                }
            }

            if (Options.realisticSpeeds)
            {
                float vehicleRand = Math.Min(1f, (float)(vehicleId % 101) * 0.01f);                 // we choose 101 because it's a prime number
                if (state != null && state.HeavyVehicle)
                {
                    maxSpeed *= 0.9f + vehicleRand * 0.1f;                     // a little variance, 0.85 .. 1
                }
                else if (isRecklessDriver)
                {
                    maxSpeed *= 1.2f + vehicleRand * 0.8f;                     // woohooo, 1.2 .. 2
                }
                else
                {
                    maxSpeed *= 0.8f + vehicleRand * 0.5f;                     // a little variance, 0.8 .. 1.3
                }
            }
            else
            {
                if (isRecklessDriver)
                {
                    maxSpeed *= 1.4f;
                }
            }

            maxSpeed = Math.Max(MIN_SPEED, maxSpeed);             // at least 10 km/h

            return(maxSpeed);
        }
        /// <summary>
        /// Gets closest vehicle on lane before either the exit or where we are clsoest
        /// </summary>
        /// <param name="ourState"></param>
        public void Update(VehicleState ourState)
        {
            #region Exit Polygon

            // check the exit polygon
            if (exit != null)
            {
                // create the polygon
                Polygon p = this.exitPolygon;

                // closest vehicle
                VehicleAgent closest     = null;
                double       closestDist = Double.MinValue;

                // check all inside the polygon
                foreach (VehicleAgent va in TacticalDirector.ValidVehicles.Values)
                {
                    // check if stopped
                    if (va.IsStopped)                    // && va.StateMonitor.Observed.speedValid)
                    {
                        // get distance to exit
                        double      distToExit;
                        Coordinates c = va.ClosestPointTo(this.exit.Position, ourState, out distToExit).Value;

                        // check inside polygon
                        if (p.IsInside(c))
                        {
                            // check dist
                            if (closest == null || distToExit < closestDist)
                            {
                                closest     = va;
                                closestDist = distToExit;
                            }
                        }
                    }
                }

                // check closest not null
                if (closest != null)
                {
                    // check vehicle switch
                    if (currentVehicle != closest)
                    {
                        this.ResetTiming();
                    }

                    // check if waiting timer not running
                    if (!this.waitingTimer.IsRunning)
                    {
                        this.ResetTiming();
                        this.waitingTimer.Start();
                    }

                    // set the new vehicle
                    this.currentVehicle = closest;

                    // return to stop update
                    return;
                }
                else
                {
                    // check if we were waiting for something in this area
                    if (this.globalMonitor.PreviouslyWaiting.Contains(this))
                    {
                        // remove the previous waiting
                        this.globalMonitor.PreviouslyWaiting.Remove(this);
                    }
                }
            }

            #endregion

            #region Lane Vehicles

            // get the possible vehicles that could be in this stop
            if (TacticalDirector.VehicleAreas.ContainsKey(this.lane))
            {
                // get vehicles in the the lane of the exit
                List <VehicleAgent> possibleVehicles = TacticalDirector.VehicleAreas[this.lane];

                // get the point we are looking from
                LinePath.PointOnPath referencePoint;

                // reference from exit if exists
                if (exit != null)
                {
                    LinePath.PointOnPath pop = lane.LanePath().GetClosestPoint(exit.Position);
                    referencePoint = lane.LanePath().AdvancePoint(pop, 3.0);
                }
                // otherwise look from where we are closest
                else
                {
                    referencePoint = lane.LanePath().GetClosestPoint(ourState.Front);
                }

                // tmp
                VehicleAgent tmp     = null;
                double       tmpDist = Double.MaxValue;

                // check over all possible vehicles in the lane
                foreach (VehicleAgent possible in possibleVehicles)
                {
                    // get vehicle point on lane
                    LinePath.PointOnPath vehiclePoint = lane.LanePath().GetClosestPoint(possible.ClosestPosition);

                    // check if the vehicle is behind the reference point
                    double vehicleDist = lane.LanePath().DistanceBetween(vehiclePoint, referencePoint);

                    // check for closest
                    if (vehicleDist > 0 && (tmp == null || vehicleDist < tmpDist))
                    {
                        tmp     = possible;
                        tmpDist = vehicleDist;
                    }
                }

                // set the closest
                this.currentVehicle = tmp;
            }
            else
            {
                // set the closest
                this.currentVehicle = null;
            }

            #endregion

            // reset the timing if got this far
            this.ResetTiming();
        }
 public LocalVehicleController()
 {
     state = new VehicleState();
     state.Position = Vector3.zero;
     state.Rotation = Quaternion.identity;
 }
Beispiel #18
0
        /// <summary>
        /// Check if we can go
        /// </summary>
        /// <param name="vs"></param>
        private bool CanGo(VehicleState vs)
        {
            #region Moving Vehicles Inside Turn

            // check if we can still go through this turn
            if (TacticalDirector.VehicleAreas.ContainsKey(this.turn))
            {
                // get the subpath of the interconnect we care about
                LinePath.PointOnPath frontPos  = this.turn.InterconnectPath.GetClosestPoint(vs.Front);
                LinePath             aiSubpath = this.turn.InterconnectPath.SubPath(frontPos, this.turn.InterconnectPath.EndPoint);

                if (aiSubpath.PathLength > 4.0)
                {
                    aiSubpath = aiSubpath.SubPath(aiSubpath.StartPoint, aiSubpath.PathLength - 2.0);

                    // get vehicles
                    List <VehicleAgent> turnVehicles = TacticalDirector.VehicleAreas[this.turn];

                    // loop vehicles
                    foreach (VehicleAgent va in turnVehicles)
                    {
                        // check if inside turn
                        LinePath.PointOnPath vaPop = aiSubpath.GetClosestPoint(va.ClosestPosition);
                        if (!va.IsStopped && this.turn.TurnPolygon.IsInside(va.ClosestPosition) && !vaPop.Equals(aiSubpath.StartPoint) && !vaPop.Equals(aiSubpath.EndPoint))
                        {
                            ArbiterOutput.Output("Vehicle seen inside our turn: " + va.ToString() + ", stopping");
                            return(false);
                        }
                    }
                }
            }

            #endregion

            // test if this turn is part of an intersection
            if (CoreCommon.RoadNetwork.IntersectionLookup.ContainsKey(this.turn.InitialGeneric.AreaSubtypeWaypointId))
            {
                // intersection
                ArbiterIntersection inter = CoreCommon.RoadNetwork.IntersectionLookup[this.turn.InitialGeneric.AreaSubtypeWaypointId];

                // check if priority lanes exist for this interconnect
                if (inter.PriorityLanes.ContainsKey(this.turn))
                {
                    // get all the default priority lanes
                    List <IntersectionInvolved> priorities = inter.PriorityLanes[this.turn];

                    // get the subpath of the interconnect we care about
                    //LinePath.PointOnPath frontPos = this.turn.InterconnectPath.GetClosestPoint(vs.Front);
                    LinePath aiSubpath = new LinePath(new List <Coordinates>(new Coordinates[] { vs.Front, this.turn.FinalGeneric.Position }));                   //this.turn.InterconnectPath.SubPath(frontPos, this.turn.InterconnectPath.EndPoint);

                    // check if path ended
                    if (aiSubpath.Count < 2)
                    {
                        return(true);
                    }

                    // determine all of the new priority lanes
                    List <IntersectionInvolved> updatedPriorities = new List <IntersectionInvolved>();

                    #region Determine new priority areas given position

                    // loop through old priorities
                    foreach (IntersectionInvolved ii in priorities)
                    {
                        // check ii lane
                        if (ii.Area is ArbiterLane)
                        {
                            #region Lane Intersects Turn Path w/ Point of No Return

                            // check if the waypoint is not the last waypoint in the lane
                            if (ii.Exit == null || ((ArbiterWaypoint)ii.Exit).NextPartition != null)
                            {
                                // check where line intersects path
                                Coordinates?intersect = this.LaneIntersectsPath(ii, aiSubpath, this.turn.FinalGeneric);

                                // check for an intersection
                                if (intersect.HasValue)
                                {
                                    // distance to intersection
                                    double distanceToIntersection = (intersect.Value.DistanceTo(vs.Front) + ((ArbiterLane)ii.Area).LanePath().GetClosestPoint(vs.Front).Location.DistanceTo(vs.Front)) / 2.0;

                                    // determine if we can stop before or after the intersection
                                    double distanceToStoppage = RoadToolkit.DistanceToStop(CoreCommon.Communications.GetVehicleSpeed().Value);

                                    // check dist to intersection > distance to stoppage
                                    if (distanceToIntersection > distanceToStoppage)
                                    {
                                        // add updated priority
                                        updatedPriorities.Add(new IntersectionInvolved(new ArbiterWaypoint(intersect.Value, new ArbiterWaypointId(0, ((ArbiterLane)ii.Area).LaneId)),
                                                                                       ii.Area, ArbiterTurnDirection.Straight));
                                    }
                                    else
                                    {
                                        ArbiterOutput.Output("Passed point of No Return for Lane: " + ii.Area.ToString());
                                    }
                                }
                            }

                            #endregion

                            // we know there is an exit and it is the last waypoint of the segment, fuxk!
                            else
                            {
                                #region Turns Intersect

                                // get point to look at if exists
                                ArbiterInterconnect interconnect;
                                Coordinates?        intersect = this.TurnIntersects(aiSubpath, ii.Exit, out interconnect);

                                // check for the intersect
                                if (intersect.HasValue)
                                {
                                    ArbiterLane al = (ArbiterLane)ii.Area;
                                    LinePath    lp = al.LanePath().SubPath(al.LanePath().StartPoint, al.LanePath().GetClosestPoint(ii.Exit.Position));
                                    lp.Add(interconnect.InterconnectPath.EndPoint.Location);

                                    // get our time to the intersection point
                                    //double ourTime = Math.Min(4.0, Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value) < 0.001 ? aiSubpath.PathLength / 1.0 : aiSubpath.PathLength / Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value));

                                    // get our time to the intersection point
                                    double ourSpeed         = Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value);
                                    double stoppedTime      = ourSpeed < 1.0 ? 1.5 : 0.0;
                                    double extraTime        = 1.5;
                                    double interconnectTime = aiSubpath.PathLength / this.turn.MaximumDefaultSpeed;
                                    double ourTime          = Math.Min(6.5, stoppedTime + extraTime + interconnectTime);

                                    // get closest vehicle in that lane to the intersection
                                    List <VehicleAgent> toLook = new List <VehicleAgent>();
                                    if (TacticalDirector.VehicleAreas.ContainsKey(ii.Area))
                                    {
                                        foreach (VehicleAgent tmpVa in TacticalDirector.VehicleAreas[ii.Area])
                                        {
                                            double upstreamDist = al.DistanceBetween(tmpVa.ClosestPosition, ii.Exit.Position);
                                            if (upstreamDist > 0 && tmpVa.PassedDelayedBirth)
                                            {
                                                toLook.Add(tmpVa);
                                            }
                                        }
                                    }
                                    if (TacticalDirector.VehicleAreas.ContainsKey(interconnect))
                                    {
                                        toLook.AddRange(TacticalDirector.VehicleAreas[interconnect]);
                                    }

                                    // check length of stuff to look at
                                    if (toLook.Count > 0)
                                    {
                                        foreach (VehicleAgent va in toLook)
                                        {
                                            // distance along path to location of intersect
                                            double distToIntersect = lp.DistanceBetween(lp.GetClosestPoint(va.ClosestPosition), lp.GetClosestPoint(aiSubpath.GetClosestPoint(va.ClosestPosition).Location));

                                            double speed  = va.Speed == 0.0 ? 0.01 : va.Speed;
                                            double vaTime = distToIntersect / Math.Abs(speed);
                                            if (vaTime > 0 && vaTime < ourTime)
                                            {
                                                ArbiterOutput.Output("va: " + va.ToString() + " CollisionTimer: " + vaTime.ToString("f2") + " < TimeUs: " + ourTime.ToString("F2") + ", NOGO");
                                                return(false);
                                            }
                                        }
                                    }
                                }

                                #endregion
                            }
                        }
                    }

                    #endregion

                    #region Updated Priority Intersection Code

                    // loop through updated priorities
                    bool updatedPrioritiesClear = true;
                    foreach (IntersectionInvolved ii in updatedPriorities)
                    {
                        // lane
                        ArbiterLane al = (ArbiterLane)ii.Area;

                        // get our time to the intersection point
                        double ourSpeed         = Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value);
                        double stoppedTime      = ourSpeed < 1.0 ? 1.5 : 0.0;
                        double extraTime        = 1.5;
                        double interconnectTime = aiSubpath.PathLength / this.turn.MaximumDefaultSpeed;
                        double ourTime          = Math.Min(6.5, stoppedTime + extraTime + interconnectTime);

                        // double outTime = Math.Min(4.0, Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value) < 0.001 ? aiSubpath.PathLength / 1.0 : aiSubpath.PathLength / Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value));

                        // get closest vehicle in that lane to the intersection
                        if (TacticalDirector.VehicleAreas.ContainsKey(ii.Area))
                        {
                            // get lane vehicles
                            List <VehicleAgent> vas = TacticalDirector.VehicleAreas[ii.Area];

                            // determine for all
                            VehicleAgent closestLaneVa     = null;
                            double       closestDistanceVa = Double.MaxValue;
                            double       closestTime       = Double.MaxValue;
                            foreach (VehicleAgent testVa in vas)
                            {
                                // check upstream
                                double distance = al.DistanceBetween(testVa.ClosestPosition, ii.Exit.Position);

                                // get speed
                                double speed = testVa.Speed;
                                double time  = testVa.StateMonitor.Observed.speedValid ? distance / Math.Abs(speed) : distance / al.Way.Segment.SpeedLimits.MaximumSpeed;

                                // check distance > 0
                                if (distance > 0)
                                {
                                    // check if closer or none other exists
                                    if (closestLaneVa == null || time < closestTime)
                                    {
                                        closestLaneVa     = testVa;
                                        closestDistanceVa = distance;
                                        closestTime       = time;
                                    }
                                }
                            }

                            // check if closest exists
                            if (closestLaneVa != null)
                            {
                                // set va
                                VehicleAgent va       = closestLaneVa;
                                double       distance = closestDistanceVa;

                                // check dist and birth time
                                if (distance > 0 && va.PassedDelayedBirth)
                                {
                                    // check time
                                    double speed = va.Speed == 0.0 ? 0.01 : va.Speed;
                                    double time  = va.StateMonitor.Observed.speedValid ? distance / Math.Abs(speed) : distance / al.Way.Segment.SpeedLimits.MaximumSpeed;

                                    // too close
                                    if (!al.LanePolygon.IsInside(CoreCommon.Communications.GetVehicleState().Front) &&
                                        distance < 25 && (!va.StateMonitor.Observed.speedValid || !va.StateMonitor.Observed.isStopped) &&
                                        CoreCommon.Communications.GetVehicleState().Front.DistanceTo(va.ClosestPosition) < 20)
                                    {
                                        ArbiterOutput.Output("Turn, NOGO, Lane: " + al.ToString() + " vehicle: " + va.ToString() + " possibly moving to close, stopping");
                                        //return false;
                                        updatedPrioritiesClear = false;
                                        return(false);
                                    }
                                    else if (time > 0 && time < ourTime)
                                    {
                                        ArbiterOutput.Output("Turn, NOGO, Lane: " + al.ToString() + ", va: " + va.ToString() + ", stopped: " + va.IsStopped.ToString() + ", timeUs: " + ourTime.ToString("f2") + ", timeThem: " + time.ToString("f2"));
                                        //return false;
                                        updatedPrioritiesClear = false;
                                        return(false);
                                    }
                                    else
                                    {
                                        ArbiterOutput.Output("Turn, CANGO, Lane: " + al.ToString() + ", va: " + va.ToString() + ", stopped: " + va.IsStopped.ToString() + ", timeUs: " + ourTime.ToString("f2") + ", timeThem: " + time.ToString("f2"));
                                        //return true;
                                    }
                                }
                            }
                            else
                            {
                                ArbiterOutput.Output("Turn, CANGO, Lane: " + al.ToString() + " has no traffic vehicles");
                            }
                        }
                    }
                    return(updatedPrioritiesClear);

                    #endregion
                }
            }

            // fall through fine to go
            ArbiterOutput.Output("In Turn, CAN GO, Clear of vehicles upstream");
            return(true);
        }
Beispiel #19
0
            /// <summary>Called every frame to update the plugin.</summary>
            internal void UpdatePlugin()
            {
                /*
                 * Prepare the vehicle state.
                 * */
                double       location    = this.Train.Cars[0].FrontAxle.Follower.TrackPosition - this.Train.Cars[0].FrontAxlePosition + 0.5 * this.Train.Cars[0].Length;
                double       speed       = this.Train.Cars[this.Train.DriverCar].Specs.CurrentPerceivedSpeed;
                double       bcPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakeCylinderCurrentPressure;
                double       mrPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.MainReservoirCurrentPressure;
                double       erPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.EqualizingReservoirCurrentPressure;
                double       bpPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakePipeCurrentPressure;
                double       sapPressure = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.StraightAirPipeCurrentPressure;
                VehicleState vehicle     = new VehicleState(location, new Speed(speed), bcPressure, mrPressure, erPressure, bpPressure, sapPressure);

                /*
                 * Prepare the preceding vehicle state.
                 * */
                double bestLocation = double.MaxValue;
                double bestSpeed    = 0.0;

                for (int i = 0; i < TrainManager.Trains.Length; i++)
                {
                    if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainManager.TrainState.Available)
                    {
                        int    c = TrainManager.Trains[i].Cars.Length - 1;
                        double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxlePosition - 0.5 * TrainManager.Trains[i].Cars[c].Length;
                        if (z >= location & z < bestLocation)
                        {
                            bestLocation = z;
                            bestSpeed    = TrainManager.Trains[i].Specs.CurrentAverageSpeed;
                        }
                    }
                }
                PrecedingVehicleState precedingVehicle;

                if (bestLocation != double.MaxValue)
                {
                    precedingVehicle = new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed));
                }
                else
                {
                    precedingVehicle = null;
                }

                /*
                 * Get the driver handles.
                 * */
                Handles handles = GetHandles();

                /*
                 * Update the plugin.
                 * */
                double     totalTime   = Game.SecondsSinceMidnight;
                double     elapsedTime = Game.SecondsSinceMidnight - LastTime;
                ElapseData data        = new ElapseData(vehicle, precedingVehicle, handles, new Time(totalTime), new Time(elapsedTime));

                LastTime = Game.SecondsSinceMidnight;
                Elapse(data);
                this.PluginMessage = data.DebugMessage;

                /*
                 * Set the virtual handles.
                 * */
                this.PluginValid = true;
                SetHandles(data.Handles, true);
            }
Beispiel #20
0
        /// <summary>
        /// Gets primary maneuver given our position and the turn we are traveling upon
        /// </summary>
        /// <param name="vehicleState"></param>
        /// <returns></returns>
        public Maneuver PrimaryManeuver(VehicleState vehicleState, List <ITacticalBlockage> blockages, TurnState turnState)
        {
            #region Check are planning over the correct turn

            if (CoreCommon.CorePlanningState is TurnState)
            {
                TurnState ts = (TurnState)CoreCommon.CorePlanningState;
                if (this.turn == null || !this.turn.Equals(ts.Interconnect))
                {
                    this.turn           = ts.Interconnect;
                    this.forwardMonitor = new TurnForwardMonitor(ts.Interconnect, null);
                }
                else if (this.forwardMonitor.turn == null || !this.forwardMonitor.turn.Equals(ts.Interconnect))
                {
                    this.forwardMonitor = new TurnForwardMonitor(ts.Interconnect, null);
                }
            }

            #endregion

            #region Blockages

            // check blockages
            if (blockages != null && blockages.Count > 0 && blockages[0] is TurnBlockage)
            {
                // create the blockage state
                EncounteredBlockageState ebs = new EncounteredBlockageState(blockages[0], CoreCommon.CorePlanningState);

                // check not at highest level already
                if (turnState.Saudi != SAUDILevel.L1 || turnState.UseTurnBounds)
                {
                    // check not from a dynamicly moving vehicle
                    if (blockages[0].BlockageReport.BlockageType != BlockageType.Dynamic ||
                        (TacticalDirector.ValidVehicles.ContainsKey(blockages[0].BlockageReport.TrackID) &&
                         TacticalDirector.ValidVehicles[blockages[0].BlockageReport.TrackID].IsStopped))
                    {
                        // go to a blockage handling tactical
                        return(new Maneuver(new NullBehavior(), ebs, TurnDecorators.NoDecorators, vehicleState.Timestamp));
                    }
                    else
                    {
                        ArbiterOutput.Output("Turn blockage reported for moving vehicle, ignoring");
                    }
                }
                else
                {
                    ArbiterOutput.Output("Turn blockage, but recovery escalation already at highest state, ignoring report");
                }
            }

            #endregion

            #region Intersection Check

            if (!this.CanGo(vehicleState))
            {
                if (turn.FinalGeneric is ArbiterWaypoint)
                {
                    TravelingParameters tp = this.GetParameters(0.0, 0.0, (ArbiterWaypoint)turn.FinalGeneric, vehicleState, false);
                    return(new Maneuver(tp.Behavior, CoreCommon.CorePlanningState, tp.NextState.DefaultStateDecorators, vehicleState.Timestamp));
                }
                else
                {
                    // get turn params
                    LinePath finalPath;
                    LineList leftLL;
                    LineList rightLL;
                    IntersectionToolkit.ZoneTurnInfo(this.turn, (ArbiterPerimeterWaypoint)this.turn.FinalGeneric, out finalPath, out leftLL, out rightLL);

                    // hold brake
                    IState       nextState = new TurnState(this.turn, this.turn.TurnDirection, null, finalPath, leftLL, rightLL, new ScalarSpeedCommand(0.0));
                    TurnBehavior b         = new TurnBehavior(null, finalPath, leftLL, rightLL, new ScalarSpeedCommand(0.0), this.turn.InterconnectId);
                    return(new Maneuver(b, CoreCommon.CorePlanningState, nextState.DefaultStateDecorators, vehicleState.Timestamp));
                }
            }

            #endregion

            #region Final is Lane Waypoint

            if (turn.FinalGeneric is ArbiterWaypoint)
            {
                // final point
                ArbiterWaypoint final = (ArbiterWaypoint)turn.FinalGeneric;

                // plan down entry lane
                RoadPlan rp = navigation.PlanNavigableArea(final.Lane, final.Position,
                                                           CoreCommon.RoadNetwork.ArbiterWaypoints[CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId], new List <ArbiterWaypoint>());

                // point of interest downstream
                DownstreamPointOfInterest dpoi = rp.BestPlan.laneWaypointOfInterest;

                // get path this represents
                List <Coordinates> pathCoordinates = new List <Coordinates>();
                pathCoordinates.Add(vehicleState.Position);
                foreach (ArbiterWaypoint aw in final.Lane.WaypointsInclusive(final, final.Lane.WaypointList[final.Lane.WaypointList.Count - 1]))
                {
                    pathCoordinates.Add(aw.Position);
                }
                LinePath lp = new LinePath(pathCoordinates);

                // list of all parameterizations
                List <TravelingParameters> parameterizations = new List <TravelingParameters>();

                // get lane navigation parameterization
                TravelingParameters navigationParameters = this.NavigationParameterization(vehicleState, dpoi, final, lp);
                parameterizations.Add(navigationParameters);

                // update forward tracker and get vehicle parameterizations if forward vehicle exists
                this.forwardMonitor.Update(vehicleState, final, lp);
                if (this.forwardMonitor.ShouldUseForwardTracker())
                {
                    // get vehicle parameterization
                    TravelingParameters vehicleParameters = this.VehicleParameterization(vehicleState, lp, final);
                    parameterizations.Add(vehicleParameters);
                }

                // sort and return funal
                parameterizations.Sort();

                // get the final behavior
                TurnBehavior tb = (TurnBehavior)parameterizations[0].Behavior;

                // get vehicles to ignore
                tb.VehiclesToIgnore = this.forwardMonitor.VehiclesToIgnore;

                // add persistent information about saudi level
                if (turnState.Saudi == SAUDILevel.L1)
                {
                    tb.Decorators = new List <BehaviorDecorator>(tb.Decorators.ToArray());
                    tb.Decorators.Add(new ShutUpAndDoItDecorator(SAUDILevel.L1));
                }

                // add persistent information about turn bounds
                if (!turnState.UseTurnBounds)
                {
                    tb.LeftBound  = null;
                    tb.RightBound = null;
                }

                //  return the behavior
                return(new Maneuver(tb, CoreCommon.CorePlanningState, tb.Decorators, vehicleState.Timestamp));
            }

            #endregion

            #region Final is Zone Waypoint

            else if (turn.FinalGeneric is ArbiterPerimeterWaypoint)
            {
                // get inteconnect path
                Coordinates entryVec = ((ArbiterPerimeterWaypoint)turn.FinalGeneric).Perimeter.PerimeterPolygon.BoundingCircle.center -
                                       turn.FinalGeneric.Position;
                entryVec = entryVec.Normalize(TahoeParams.VL / 2.0);
                LinePath ip = new LinePath(new Coordinates[] { turn.InitialGeneric.Position, turn.FinalGeneric.Position, entryVec + this.turn.FinalGeneric.Position });

                // get distance from end
                double d = ip.DistanceBetween(
                    ip.GetClosestPoint(vehicleState.Front),
                    ip.EndPoint);

                // get speed command
                SpeedCommand sc = null;
                if (d < TahoeParams.VL)
                {
                    sc = new StopAtDistSpeedCommand(d);
                }
                else
                {
                    sc = new ScalarSpeedCommand(SpeedTools.GenerateSpeed(d - TahoeParams.VL, 1.7, turn.MaximumDefaultSpeed));
                }

                // final perimeter waypoint
                ArbiterPerimeterWaypoint apw = (ArbiterPerimeterWaypoint)this.turn.FinalGeneric;

                // get turn params
                LinePath finalPath;
                LineList leftLL;
                LineList rightLL;
                IntersectionToolkit.ZoneTurnInfo(this.turn, (ArbiterPerimeterWaypoint)this.turn.FinalGeneric, out finalPath, out leftLL, out rightLL);

                // hold brake
                IState       nextState = new TurnState(this.turn, this.turn.TurnDirection, null, finalPath, leftLL, rightLL, sc);
                TurnBehavior tb        = new TurnBehavior(null, finalPath, leftLL, rightLL, sc, null, new List <int>(), this.turn.InterconnectId);

                // add persistent information about saudi level
                if (turnState.Saudi == SAUDILevel.L1)
                {
                    tb.Decorators = new List <BehaviorDecorator>(tb.Decorators.ToArray());
                    tb.Decorators.Add(new ShutUpAndDoItDecorator(SAUDILevel.L1));
                }

                // add persistent information about turn bounds
                if (!turnState.UseTurnBounds)
                {
                    tb.LeftBound  = null;
                    tb.RightBound = null;
                }

                // return maneuver
                return(new Maneuver(tb, CoreCommon.CorePlanningState, tb.Decorators, vehicleState.Timestamp));
            }

            #endregion

            #region Unknown

            else
            {
                throw new Exception("unrecognized type: " + turn.FinalGeneric.ToString());
            }

            #endregion
        }
Beispiel #21
0
 public void SetState(VehicleState state)
 {
     transform.position = state.Position;
     transform.rotation = state.Rotation;
 }
Beispiel #22
0
 /// <summary>
 /// Plans if we need secondary maneuver if intersection breaks down and need to abort
 /// </summary>
 /// <param name="vehicleState"></param>
 /// <param name="intersectionPlan"></param>
 /// <returns></returns>
 public Maneuver?SecondaryManeuver(VehicleState vehicleState, IntersectionPlan intersectionPlan)
 {
     // don't say anything
     return(null);
 }
 public Coordinates TransformCoordAbs(Coordinates c, VehicleState state)
 {
     c = c.Rotate(state.Heading.ArcTan);
     c = c + state.Position;
     return(c);
 }
Beispiel #24
0
        /// <summary>
        /// Gets parameterization
        /// </summary>
        /// <param name="lane"></param>
        /// <param name="speed"></param>
        /// <param name="distance"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public TravelingParameters GetParameters(double speed, double distance, ArbiterWaypoint final, VehicleState state, bool canUseDistance)
        {
            double       distanceCutOff = CoreCommon.OperationalStopDistance;
            SpeedCommand sc;
            bool         usingSpeed = true;
            Maneuver     m;

            #region Generate Next State

            // get turn params
            LinePath finalPath;
            LineList leftLL;
            LineList rightLL;
            IntersectionToolkit.TurnInfo(final, out finalPath, out leftLL, out rightLL);
            TurnState ts = new TurnState(this.turn, this.turn.TurnDirection, final.Lane, finalPath, leftLL, rightLL, new ScalarSpeedCommand(speed));

            #endregion

            #region Distance Cutoff

            // check if distance is less than cutoff
            if (distance < distanceCutOff && canUseDistance)
            {
                // default behavior
                sc = new StopAtDistSpeedCommand(distance);

                // stopping so not using speed param
                usingSpeed = false;
            }

            #endregion

            #region Outisde Distance Envelope

            // not inside distance envalope
            else
            {
                // default behavior
                sc = new ScalarSpeedCommand(speed);
            }

            #endregion

            #region Generate Maneuver

            if (ts.Interconnect.InitialGeneric is ArbiterWaypoint &&
                CoreCommon.RoadNetwork.IntersectionLookup.ContainsKey(((ArbiterWaypoint)ts.Interconnect.InitialGeneric).AreaSubtypeWaypointId))
            {
                Polygon p = CoreCommon.RoadNetwork.IntersectionLookup[((ArbiterWaypoint)ts.Interconnect.InitialGeneric).AreaSubtypeWaypointId].IntersectionPolygon;

                // behavior
                Behavior b = new TurnBehavior(ts.TargetLane.LaneId, ts.EndingPath, ts.LeftBound, ts.RightBound, sc, p, this.forwardMonitor.VehiclesToIgnore, ts.Interconnect.InterconnectId);
                m = new Maneuver(b, ts, ts.DefaultStateDecorators, state.Timestamp);
            }
            else
            {
                // behavior
                Behavior b = new TurnBehavior(ts.TargetLane.LaneId, ts.EndingPath, ts.LeftBound, ts.RightBound, sc, null, this.forwardMonitor.VehiclesToIgnore, ts.Interconnect.InterconnectId);
                m = new Maneuver(b, ts, ts.DefaultStateDecorators, state.Timestamp);
            }

            #endregion

            #region Parameterize

            // create new params
            TravelingParameters tp = new TravelingParameters();
            tp.Behavior         = m.PrimaryBehavior;
            tp.Decorators       = m.PrimaryBehavior.Decorators;
            tp.DistanceToGo     = distance;
            tp.NextState        = m.PrimaryState;
            tp.RecommendedSpeed = speed;
            tp.Type             = TravellingType.Navigation;
            tp.UsingSpeed       = usingSpeed;
            tp.SpeedCommand     = sc;
            tp.VehiclesToIgnore = this.forwardMonitor.VehiclesToIgnore;

            #endregion

            // return navigation params
            return(tp);
        }
Beispiel #25
0
        /// <summary>
        /// Updates this monitor
        /// </summary>
        public void Update(VehicleState ourState)
        {
            // make sure not our vehicle
            if (!isOurs)
            {
                // get a list of vehicles possibly in the exit
                List <VehicleAgent> stopVehicles = new List <VehicleAgent>();

                // check all valid vehicles
                foreach (VehicleAgent va in TacticalDirector.ValidVehicles.Values)
                {
                    // check if any of the point inside the polygon
                    for (int i = 0; i < va.StateMonitor.Observed.relativePoints.Length; i++)
                    {
                        // get abs coord
                        Coordinates c = va.TransformCoordAbs(va.StateMonitor.Observed.relativePoints[i], ourState);

                        // check if inside poly
                        if (this.stoppedExit.ExitPolygon.IsInside(c) && !stopVehicles.Contains(va))
                        {
                            // add vehicle
                            stopVehicles.Add(va);
                        }
                    }
                }

                // check occluded
                foreach (VehicleAgent va in TacticalDirector.OccludedVehicles.Values)
                {
                    // check if any of the point inside the polygon
                    for (int i = 0; i < va.StateMonitor.Observed.relativePoints.Length; i++)
                    {
                        // get abs coord
                        Coordinates c = va.TransformCoordAbs(va.StateMonitor.Observed.relativePoints[i], ourState);

                        // check if inside poly
                        if (this.stoppedExit.ExitPolygon.IsInside(c) && !stopVehicles.Contains(va))
                        {
                            // add vehicle
                            ArbiterOutput.Output("Added occluded vehicle: " + va.ToString() + " to SEM: " + this.stoppedExit.ToString());
                            stopVehicles.Add(va);
                        }
                    }
                }

                // check if we already have a vehicle we are referencing
                if (this.currentVehicle != null && !stopVehicles.Contains(this.currentVehicle))
                {
                    // get the polygon of the current vehicle	and inflate a tiny bit?
                    Polygon p = this.currentVehicle.GetAbsolutePolygon(ourState);
                    p = p.Inflate(1.0);

                    // Vehicle agent to switch to if exists
                    VehicleAgent newer    = null;
                    double       distance = Double.MaxValue;

                    // check for closest vehicle to exist in that polygon
                    foreach (VehicleAgent va in TacticalDirector.ValidVehicles.Values)
                    {
                        // check if vehicle is stopped
                        if (stopVehicles.Contains(va))
                        {
                            // get distance to stop
                            double stopLineDist;
                            va.ClosestPointTo(this.stoppedExit.Waypoint.Position, ourState, out stopLineDist);

                            // check all vehicle points
                            foreach (Coordinates rel in va.StateMonitor.Observed.relativePoints)
                            {
                                Coordinates abs     = va.TransformCoordAbs(rel, ourState);
                                double      tmpDist = stopLineDist;

                                // check for the clsoest with points inside vehicle
                                if (p.IsInside(abs) && (newer == null || tmpDist < distance))
                                {
                                    newer    = va;
                                    distance = tmpDist;
                                }
                            }
                        }
                    }

                    // check if we can switch vehicles
                    if (newer != null)
                    {
                        ArbiterOutput.Output("For StopLine: " + this.stoppedExit.ToString() + " switched vehicleId: " + this.currentVehicle.VehicleId.ToString() + " for vehicleId: " + newer.VehicleId.ToString());
                        this.currentVehicle   = newer;
                        this.NotFoundPrevious = notFoundDefault;
                    }
                    else if (NotFoundPrevious == 0)
                    {
                        // set this as not having a vehicle
                        this.currentVehicle = null;

                        // set not found before
                        this.NotFoundPrevious = this.notFoundDefault;

                        // stop timers
                        this.timer.Stop();
                        this.timer.Reset();
                    }
                    else
                    {
                        // set not found before
                        this.NotFoundPrevious--;
                        ArbiterOutput.Output("current not found, not found previous: " + this.NotFoundPrevious.ToString() + ", at stopped exit: " + this.stoppedExit.Waypoint.ToString());
                    }
                }
                // update the current vehicle
                else if (this.currentVehicle != null && stopVehicles.Contains(this.currentVehicle))
                {
                    // udpate current
                    this.currentVehicle = stopVehicles[stopVehicles.IndexOf(this.currentVehicle)];

                    // set as found previous
                    this.NotFoundPrevious = this.notFoundDefault;

                    // check if need to update timer
                    if (this.currentVehicle.IsStopped && !this.timer.IsRunning)
                    {
                        this.timer.Stop();
                        this.timer.Reset();
                        this.timer.Start();
                    }
                    // otherwise check if moving
                    else if (!this.currentVehicle.IsStopped && this.timer.IsRunning)
                    {
                        this.timer.Stop();
                        this.timer.Reset();
                    }
                }
                // otherwise if we have no vehicle and exist vehicles in stop area
                else if (this.currentVehicle == null && stopVehicles.Count > 0)
                {
                    // get closest vehicle to the stop
                    VehicleAgent toTrack  = null;
                    double       distance = Double.MaxValue;

                    // set as found previous
                    this.NotFoundPrevious = this.notFoundDefault;

                    // loop through
                    foreach (VehicleAgent va in stopVehicles)
                    {
                        // check if vehicle is stopped
                        if (va.IsStopped)
                        {
                            // distance of vehicle to stop line
                            double      distanceToStop;
                            Coordinates closestToStop = va.ClosestPointTo(this.stoppedExit.Waypoint.Position, ourState, out distanceToStop).Value;

                            // check if we don't have one or tmp closer than tracked
                            if (toTrack == null || distanceToStop < distance)
                            {
                                toTrack  = va;
                                distance = distanceToStop;
                            }
                        }
                    }

                    // check if we have one to track
                    if (toTrack != null)
                    {
                        this.currentVehicle = toTrack;
                    }
                }
            }
        }
Beispiel #26
0
            /// <summary>Called every frame to update the plugin.</summary>
            internal void UpdatePlugin()
            {
                /*
                 * Prepare the vehicle state.
                 * */
                double location = this.Train.Cars[0].FrontAxle.Follower.TrackPosition - this.Train.Cars[0].FrontAxle.Position + 0.5 * this.Train.Cars[0].Length;
                //Curve Radius, Cant and Pitch Added
                double CurrentRadius = this.Train.Cars[0].FrontAxle.Follower.CurveRadius;
                double CurrentCant   = this.Train.Cars[0].FrontAxle.Follower.CurveCant;
                double CurrentPitch  = this.Train.Cars[0].FrontAxle.Follower.Pitch;

                //If the list of stations has not been loaded, do so
                if (!StationsLoaded)
                {
                    currentRouteStations = new List <Station>();
                    foreach (Game.Station selectedStation in Game.Stations)
                    {
                        Station i = new Station
                        {
                            Name                 = selectedStation.Name,
                            ArrivalTime          = selectedStation.ArrivalTime,
                            DepartureTime        = selectedStation.DepartureTime,
                            StopTime             = selectedStation.StopTime,
                            OpenLeftDoors        = selectedStation.OpenLeftDoors,
                            OpenRightDoors       = selectedStation.OpenRightDoors,
                            ForceStopSignal      = selectedStation.ForceStopSignal,
                            DefaultTrackPosition = selectedStation.DefaultTrackPosition
                        };
                        currentRouteStations.Add(i);
                    }
                    StationsLoaded = true;
                }
                //End of additions
                double       speed       = this.Train.Cars[this.Train.DriverCar].Specs.CurrentPerceivedSpeed;
                double       bcPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakeCylinderCurrentPressure;
                double       mrPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.MainReservoirCurrentPressure;
                double       erPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.EqualizingReservoirCurrentPressure;
                double       bpPressure  = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.BrakePipeCurrentPressure;
                double       sapPressure = this.Train.Cars[this.Train.DriverCar].Specs.AirBrake.StraightAirPipeCurrentPressure;
                VehicleState vehicle     = new VehicleState(location, new Speed(speed), bcPressure, mrPressure, erPressure, bpPressure, sapPressure, CurrentRadius, CurrentCant, CurrentPitch);

                /*
                 * Prepare the preceding vehicle state.
                 * */
                double bestLocation = double.MaxValue;
                double bestSpeed    = 0.0;

                for (int i = 0; i < TrainManager.Trains.Length; i++)
                {
                    if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainManager.TrainState.Available)
                    {
                        int    c = TrainManager.Trains[i].Cars.Length - 1;
                        double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[c].Length;
                        if (z >= location & z < bestLocation)
                        {
                            bestLocation = z;
                            bestSpeed    = TrainManager.Trains[i].Specs.CurrentAverageSpeed;
                        }
                    }
                }
                var precedingVehicle = bestLocation != double.MaxValue ? new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed)) : null;

                /*
                 * Get the driver handles.
                 * */
                Handles handles = GetHandles();

                /*
                 * Update the plugin.
                 * */
                double totalTime   = Game.SecondsSinceMidnight;
                double elapsedTime = Game.SecondsSinceMidnight - LastTime;

                /*
                 * Set the current camera view mode
                 * Could probably do away with the CurrentCameraViewMode and use a direct cast??
                 *
                 */
                CurrentCameraViewMode = (OpenBveApi.Runtime.CameraViewMode)World.CameraMode;
                ElapseData data = new ElapseData(vehicle, precedingVehicle, handles, (DoorInterlockStates)this.Train.Specs.DoorInterlockState, new Time(totalTime), new Time(elapsedTime), currentRouteStations, CurrentCameraViewMode, Interface.CurrentLanguageCode);

                LastTime = Game.SecondsSinceMidnight;
                Elapse(data);
                this.PluginMessage = data.DebugMessage;
                this.Train.Specs.DoorInterlockState = (TrainManager.DoorInterlockStates)data.DoorInterlockState;
                DisableTimeAcceleration             = data.DisableTimeAcceleration;

                /*
                 * Set the virtual handles.
                 * */
                this.PluginValid = true;
                SetHandles(data.Handles, true);
            }
    public void AsyncLoadingScript(GameObject myReturnValue)
    {
        #region 读取模型
        transform.position += StartPointOffSet;
        InstanceMesh        = Instantiate(myReturnValue) as GameObject;
        InstanceMesh.transform.SetParent(this.transform);
        InstanceMesh.transform.localPosition    = Vector3.zero;
        InstanceMesh.transform.localEulerAngles = Vector3.zero;
        #endregion

                #if UNITY_EDITOR && UNITY_ANDROID
        foreach (MeshRenderer meshRenderer in InstanceMesh.GetComponentsInChildren <MeshRenderer>())
        {
            meshRenderer.sharedMaterial.shader = Shader.Find("Standard");
        }
                #endif

        #region 设置网络状态
        if (_InstanceNetType != InstanceNetType.GarageTank && !isBot(_InstanceNetType) && _InstanceNetType != InstanceNetType.GameNetWorkOffline)
        {
        }
        #endregion


        //模块加载
        dontDestroyManager = new VehicleDontDestroyManagerModule();

        referenceManager = InstanceMesh.GetComponent <VehicleComponentsReferenceManager>();


        #region 加载完毕游戏资源加载脚本
        TankPrefabs     = gameObject;
        TurretTransform = InstanceMesh.transform.Find("TurretTransform").gameObject;
        MainHitBox      = InstanceMesh.transform.Find("MainHitBox").gameObject;
        TankTransform   = InstanceMesh.transform.Find("TankTransform").gameObject;
        GunTransform    = TurretTransform.transform.Find("GunTransform").gameObject;
        FFPoint         = GunTransform.transform.Find("FFPoint").gameObject;
        EffectStart     = GunTransform.transform.Find("EffectStart").gameObject;
        TurretHitBox    = TurretTransform.transform.Find("TurretHitBox").gameObject;



        GameObject       TankScript = null, TankCrossHair = null, MainCamera = null;
        Rigidbody        TankPhysic = null;
        TurretController mt         = null;
//		SyncGroundVehicle _syncGroundVehicle = null;
        PlayerTracksController PTC = null;
        PlayerState            PS  = null;
        PTC = InstanceMesh.AddComponent <PlayerTracksController> ();

        #region 物理效果
        TankPhysic             = GetComponentInChildren <Rigidbody> ();
        TankPhysic.mass        = PTCParameter.Mass;
        TankPhysic.drag        = 0.1f; //PTCParameter.Drag;
        TankPhysic.angularDrag = 2.5f; //PTCParameter.AirDrag;
        TankPhysic.useGravity  = false;
        BoxCollider[] collisions = PTC.GetComponentsInChildren <BoxCollider> ();
        foreach (Collider collision in collisions)
        {
            if (collision.isTrigger != true)
            {
                collision.material = StaticResourcesReferences.Instance.VehiclePhysicMaterial;
            }
        }

        #endregion
        if (_InstanceNetType != InstanceNetType.GarageTank)
        {
            if (isLocalPlayer(_InstanceNetType))
            {
                TankCrossHair = Instantiate((GameObject)Resources.Load("TankCrossHair"), Vector3.zero, Quaternion.identity) as GameObject;
                MainCamera    = Instantiate((GameObject)Resources.Load("MainCamera"), Vector3.zero, Quaternion.identity) as GameObject;
                TankCrossHair.transform.parent = TankPrefabs.transform;
                MainCamera.transform.parent    = InstanceMesh.transform;
                MainCamera.transform.name      = "MainCamera";
            }
            TankScript = Instantiate((GameObject)Resources.Load("TankScript"), Vector3.zero, Quaternion.identity) as GameObject;

            TankScript.transform.name   = "TankScript";
            TankScript.transform.parent = TankPrefabs.transform;
            TankPhysic.useGravity       = true;

            #region PlayerState 脚本设置
            if (!isBot(_InstanceNetType))
            {
                PS = InstanceMesh.AddComponent <PlayerState>();
                PS.tankInitSystem = this;

                foreach (HitBox HB in GetComponentsInChildren <HitBox>())
                {
                    HB.SetTarget(PS);
                }
                PS.playerStateParameter = PSParameter;

                PS.netType            = _InstanceNetType;
                PS.Turret             = TurretTransform;
                PS.TankScript         = TankScript;
                PS.DiedDestoryObjects = new Object[] { MainHitBox, TurretHitBox };
                PS.TankName           = VehicleName;
                PS.Health             = PSParameter.Health;
                PS.engineType         = PSParameter.engineType;

                PS.IsMobile = isMobile;
            }
            #endregion
            if (isBot(_InstanceNetType))
            {
                EnemyAiState enemyState = InstanceMesh.AddComponent <EnemyAiState>();
                foreach (HitBox HB in GetComponentsInChildren <HitBox>())
                {
                    HB.SetTarget(enemyState);
                }
                enemyState.TankScript = TankScript;
                enemyState.Health     = PSParameter.Health;
                enemyState.TankName   = VehicleName;
                enemyState.MyTeam     = ownerTeam;
            }

            #region TankScript 脚本设置
            mt = TankScript.GetComponent <TurretController>();
            if (isLocalPlayer(_InstanceNetType))
            {
                mt.target = MainCamera.transform.Find("CameraTarget");
            }
            mt.gun                    = GunTransform.transform;
            mt.Turret                 = TurretTransform.transform;
            mt.DownMaxDegree          = MTParameter.DownMaxDegree;
            mt.UpMaxDegree            = MTParameter.UpMaxDegree;
            mt.maxTurretAngle         = MTParameter.maxTurretAngle;
            mt.gunDegreesPerSecond    = MTParameter.gunDegreesPerSecond;
            mt.turretDegreesPerSecond = MTParameter.turretDegreesPerSecond;
            mt.isMobile               = isMobile;
            #endregion
            #region 主摄像机设置
            if (isLocalPlayer(_InstanceNetType))
            {
                MainCamera.GetComponent <VehicleCamera>().target = referenceManager.MainCameraFollowTarget.transform;
                MainCamera.GetComponent <VehicleCamera>().mainCameraFollowTarget = referenceManager.MainCameraFollowTarget.transform;
                MainCamera.GetComponent <VehicleCamera>().mainCameraGunner       = referenceManager.MachineGunFFPoint.transform;
                referenceManager.MachineGunFFPoint.transform.position            = referenceManager.FFPoint.transform.position;
                MainCamera.GetComponent <VehicleCamera>().IsMobile = isMobile;
                if (PSParameter.vehicleType == VehicleType.SPG)
                {
                    MainCamera.GetComponent <VehicleCamera>().isVehicleSPG = true;
                }
            }

            #endregion
            #region 瞄准射线
            if (isLocalPlayer(_InstanceNetType))
            {
                RayManager rayManager = TankScript.AddComponent <RayManager>();
                rayManager.Init(FFPoint.transform);
            }
            #endregion
            #region 瞄准镜设置
            if (isLocalPlayer(_InstanceNetType))
            {
                TankCrossHair.GetComponent <CrossHair>().MainCamera = MainCamera.GetComponent <Camera>();
                TankCrossHair.GetComponent <CrossHair>().tankCamera = MainCamera.GetComponent <VehicleCamera>();
                TankCrossHair.GetComponent <CrossHair>().FFPoint    = EffectStart.transform;
            }
            #endregion
            #region 坦克发射器脚本设置
            TFParameter.recoilTransform = referenceManager.FireForceFeedbackPoint.transform;

            TankFire tf = TankScript.GetComponent <TankFire>();
            tf.tankFireParameter = TFParameter;
            tf.tankInitSystem    = this;
            tf.MachineGunFFPoint = referenceManager.MachineGunFFPoint.transform;
            tf.FFPoint           = referenceManager.FFPoint.transform;
            tf.FireEffectPoint   = referenceManager.EffectStart.transform;
            tf.BulletCountList   = BulletCountList;
            tf.GunDym            = GunTransform.transform.Find("GunDym").GetComponent <Animator>();
            tf.MainBody          = InstanceMesh.transform;
            tf.netType           = _InstanceNetType;


            if (PSParameter.vehicleType == VehicleType.SPG)
            {
                tf.isAutoCaclulateGravity = true;
            }
            #endregion

            #region 引擎音效控制
            EngineSoundModule engineSoundModule = InstanceMesh.AddComponent <EngineSoundModule>();
            engineSoundModule.tankInitSystem = this;
            engineSoundModule.engineData     = PTCParameter.vehicleEngineSoundData;
            engineSoundModule.Init(referenceManager.EngineSound.transform);
            #endregion
            GameObject EngineSmoke = Instantiate <GameObject>(Resources.Load <GameObject>("EngineSmoke"));
            EngineSmoke.transform.SetParent(referenceManager.EngineSmoke.transform);
            EngineSmoke.transform.localPosition    = Vector3.zero;
            EngineSmoke.transform.localEulerAngles = Vector3.zero;

            //GameObject grounddust = Instantiate(Resources.Load<GameObject>("TrackEffect"));
            //grounddust.transform.SetParent(InstanceMesh..transform);
            //grounddust.transform.localPosition = Vector3.zero;
            //grounddust.transform.localEulerAngles = Vector3.zero;

            VehicleState vehicleState = InstanceMesh.AddComponent <VehicleState>();
            vehicleState.engineSoundModule    = engineSoundModule;
            vehicleState.tankTracksController = PTC;
        }

        #region 坦克控制器设置
        PTC.tankInitSystem = this;

        PTC.rightTrackUpperWheels = GetAllChilds(TankTransform.transform.Find("RightUpperWheel"));
        PTC.leftTrackUpperWheels  = GetAllChilds(TankTransform.transform.Find("LeftUpperWheel"));
        PTC.rightTrackWheels      = GetAllChilds(TankTransform.transform.Find("RightWheel"));
        PTC.leftTrackWheels       = GetAllChilds(TankTransform.transform.Find("LeftWheel"));
        PTC.leftTrack             = referenceManager.LeftTrack;
        PTC.rightTrack            = referenceManager.RightTrack;

        //PTC.leftTrackBones = CreateTrack (true, TankTransform.transform, ref PTC);
        //PTC.rightTrackBones = CreateTrack (false, TankTransform.transform, ref PTC);
        PTC.tankTransform = TankTransform.transform;



        PTC.maxAngularVelocity = PTCParameter.MaxAngularVelocity;
        PTC.MaxSpeed           = PTCParameter.MaxSpeed;
        PTC.MinSpeed           = PTCParameter.MinSpeed;
        PTC.gravityCenter      = PTCParameter.CenterOfGravity;
        PTC.PushSpeed          = PTCParameter.PushSpeed;
        PTC.BackSpeed          = PTCParameter.BackSpeed;

        PTC.sidewaysFrictionAsymptoteFactor = PTCParameter.SideWaysFrictionAsymptoteFactor;
        PTC.sidewaysFrictionExtremumFactor  = PTCParameter.SideWaysFrictionExtremumFactor;
        PTC.wheelCollider = PTCParameter.TankWheelCollider;

        PTC.wheelsAndBonesAxisSettings = new PlayerTracksController.WheelsAxisSettings();
        PTC.wheelsAndBonesAxisSettings.bonesPositionAxis  = TankTracksController.Axis.Z;
        PTC.wheelsAndBonesAxisSettings.wheelsPositionAxis = TankTracksController.Axis.Z;
        PTC.wheelsAndBonesAxisSettings.wheelsRotationAxis = TankTracksController.Axis.X;

        PTC.accelerationConfiguration           = PTCParameter.VAconfigSetting;
        PTC.rotationOnAccelerationConfiguration = PTCParameter.HAconfigSetting;
        PTC.rotationOnStayConfiguration         = PTCParameter.HAconfigSetting;


        #endregion

        #region 车库状态
        if (_InstanceNetType == InstanceNetType.GarageTank)
        {
            PTC.enabled            = false;
            TankPhysic.isKinematic = true;

            if (ShowHitBoxInspecter)
            {
                foreach (HitBox HB in GetComponentsInChildren <HitBox>())
                {
                    HB.StartCoroutine(HB.ShowArmorInfo());
                }
            }

            foreach (MeshCollider MC in transform.root.GetComponentsInChildren <MeshCollider>())
            {
                if (MC.GetComponent <HitBox> () == null)
                {
                    MC.enabled = false;
                }
            }
            //EventManager.StartListening ("TankInitSystem.InitTankShader", GarageInitTankShaderPreView);
            return;
        }
        #endregion

        if (ExtraTF && !isBot(_InstanceNetType))
        {
            for (int i = 0; i < multiTurrets.Length; i++)
            {
                GameObject TankScriptExtra = Instantiate((GameObject)Resources.Load("TankScript"), Vector3.zero, Quaternion.identity) as GameObject;
                TankScriptExtra.transform.name   = "TankScriptExtra";
                TankScriptExtra.transform.parent = TankPrefabs.transform;
                TurretController mouseTurretExtra = TankScriptExtra.GetComponent <TurretController> ();
                if (isLocalPlayer(_InstanceNetType))
                {
                    mouseTurretExtra.target = MainCamera.transform.Find("CameraTarget");
                }
                Transform ExtraTurret = InstanceMesh.transform.Find(multiTurrets [i].ObjectPath);

                Transform ExtraGun = ExtraTurret.transform.Find("GunTransform");

                mouseTurretExtra.gun                    = ExtraGun;
                mouseTurretExtra.Turret                 = ExtraTurret;
                mouseTurretExtra.DownMaxDegree          = multiTurrets [i].MTParameter.DownMaxDegree;
                mouseTurretExtra.UpMaxDegree            = multiTurrets [i].MTParameter.UpMaxDegree;
                mouseTurretExtra.maxTurretAngle         = multiTurrets [i].MTParameter.maxTurretAngle;
                mouseTurretExtra.gunDegreesPerSecond    = multiTurrets [i].MTParameter.gunDegreesPerSecond;
                mouseTurretExtra.turretDegreesPerSecond = multiTurrets [i].MTParameter.turretDegreesPerSecond;
                mouseTurretExtra.isMobile               = isMobile;

                TankFire  tfExtra         = TankScriptExtra.GetComponent <TankFire> ();
                Transform ExtraFFPoint    = ExtraGun.Find("FFPoint");
                Transform ExtraFireEffect = ExtraGun.Find("FireEffect");

                tfExtra.FFPoint         = ExtraFFPoint;
                tfExtra.FireRecoilPoint = FFPoint.transform;
                tfExtra.FireEffectPoint = ExtraFireEffect;
                tfExtra.MainBody        = InstanceMesh.transform;
                //tfExtra.FireRecoil = multiTurrets [i].tankFireParameter.FireRecoil;
                //tfExtra.ReloadTime = multiTurrets [i].tankFireParameter.ReloadTime;
                //tfExtra.AmmoCount = multiTurrets [i].tankFireParameter.AmmoCount;
                //tfExtra.HasMahineGun = multiTurrets [i].tankFireParameter.HasMachineGun;
                //tfExtra.muzzleFire = multiTurrets [i].tankFireParameter.MuzzleFire;
                //tfExtra.advanceFireClass = multiTurrets [i].tankFireParameter.advanceFireClass;
                //tfExtra.fireState = multiTurrets [i].tankFireParameter.FireState;
                //tfExtra.netType = InstanceNetType;
            }
        }
        #endregion

        InstanceMesh.AddComponent <Identity> ();
        if (isLocalPlayer(_InstanceNetType))
        {
            GameEvent.InitPlayer(InstanceMesh.GetComponent <Identity>());
        }
        #region 初始化玩家网络
        if (!GameDataManager.OfflineMode)
        {
            if (_InstanceNetType == InstanceNetType.GameNetworkOthers)
            {
                PTC.enableUserInput = false;
                //PTC.AdvanceTrackSystem = false;
                PTC.OnlyReceiveControlActions = true;
            }
            if (_InstanceNetType == InstanceNetType.GameNetworkMaster)
            {
                PTC.enableUserInput = false;
            }

            if (_InstanceNetType == InstanceNetType.GameNetworkClient)
            {
                PTC.enableUserInput           = true;
                PTC.OnlyReceiveControlActions = true;
            }
            if (isBot(_InstanceNetType))
            {
                PTC.enableUserInput = false;
                if (_InstanceNetType == InstanceNetType.GameNetWorkBotClient)
                {
                    PTC.OnlyReceiveControlActions = true;
                }
                else
                {
                    PTC.OnlyReceiveControlActions = false;
                }
            }

            //_syncGroundVehicle = InstanceMesh.AddComponent<SyncGroundVehicle> ();
            //_syncGroundVehicle.tankInitSystem = this;
            //_syncGroundVehicle.Init (PTC, mt, _InstanceNetType);
        }
        #region 设置离线标识
        if (GameDataManager.OfflineMode)
        {
            if (_InstanceNetType == InstanceNetType.GameNetWorkOffline)
            {
                Identity MyIdentity = InstanceMesh.GetComponent <Identity> ();
                MyIdentity.Init(ownerTeam, InstanceNetType.GameNetWorkOffline);
                MyIdentity.SetOwnerInfo("LocalPlayer", VehicleName, 0);
            }
        }
        #endregion
        #endregion
        if (!isBot(_InstanceNetType))
        {
            StartCoroutine(PS.Init());
        }

        if (GameEventManager.onNewVehicleSpawned != null)
        {
            GameEventManager.onNewVehicleSpawned(this);
        }

        if (onVehicleLoaded != null)
        {
            onVehicleLoaded();
        }
    }
Beispiel #28
0
        private uint SpawnVehicle(VehiclePrototype prototype, DynamicTransform2 placement)
        {
            VehicleState initialState = new VehicleState(placement, prototype.ControlConfig.DefaultControl);

            return(mMTSGame.AddVehicle(prototype, initialState));
        }
        public IPlan?FindOptimalPlanFor(VehicleState initialState)
        {
            var heuristic = createShortestPathHeuristic(initialState);

            var open   = new BinaryHeapOpenSet <DiscreteState, SearchNode>();
            var closed = new ClosedSet <DiscreteState>();

            open.Add(
                new SearchNode(
                    discreteState: discretizer.Discretize(initialState, wayPoints.Count),
                    state: initialState,
                    actionFromPreviousState: null,
                    previousState: null,
                    costToCome: 0,
                    estimatedTotalCost: 0, // we don't need estimate for the initial node
                    targetWayPoint: 0));

            while (!open.IsEmpty)
            {
                var node = open.DequeueMostPromissing();

                if (node.TargetWayPoint == wayPoints.Count)
                {
                    return(node.ReconstructPlan());
                }

                closed.Add(node.Key);
                exploredStates.OnNext(node.State);

                foreach (var action in actions.AllPossibleActions)
                {
                    var predictedStates  = motionModel.CalculateNextState(node.State, action, timeStep);
                    var elapsedTime      = predictedStates.Last().relativeTime;
                    var nextVehicleState = predictedStates.Last().state;
                    var reachedWayPoint  = false;
                    var collided         = false;

                    foreach (var(simulationTime, state) in predictedStates)
                    {
                        if (collisionDetector.IsCollision(state))
                        {
                            elapsedTime      = simulationTime;
                            nextVehicleState = state;
                            reachedWayPoint  = false;
                            collided         = true;
                            break;
                        }

                        if (wayPoints[node.TargetWayPoint].ReachedGoal(state.Position))
                        {
                            reachedWayPoint = true;
                        }
                    }

                    var nextTargetWayPoint = reachedWayPoint
                        ? node.TargetWayPoint + 1
                        : node.TargetWayPoint;

                    var nextDiscreteState = discretizer.Discretize(nextVehicleState, nextTargetWayPoint);
                    if (closed.Contains(nextDiscreteState))
                    {
                        continue;
                    }

                    if (collided)
                    {
                        closed.Add(nextDiscreteState);
                        continue;
                    }

                    var costToCome          = node.CostToCome + timeStep.TotalSeconds;
                    var reachedLastWayPoint = nextTargetWayPoint != wayPoints.Count;
                    var costToGo            = reachedLastWayPoint
                        ? heuristic.EstimateTimeToGoal(nextVehicleState, nextTargetWayPoint).TotalSeconds
                        : 0;

                    var discoveredNode = new SearchNode(
                        discreteState: nextDiscreteState,
                        state: nextVehicleState,
                        actionFromPreviousState: action,
                        previousState: node,
                        costToCome: costToCome,
                        estimatedTotalCost: costToCome + costToGo,
                        nextTargetWayPoint);

                    if (greedy && reachedLastWayPoint)
                    {
                        return(discoveredNode.ReconstructPlan());
                    }

                    if (!open.Contains(discoveredNode.Key))
                    {
                        open.Add(discoveredNode);
                    }
                    else if (discoveredNode.CostToCome < open.Get(discoveredNode.Key).CostToCome)
                    {
                        open.ReplaceExistingWithTheSameKey(discoveredNode);
                    }
                }
            }

            return(null);
        }
        /// <summary>
        /// Plan a lane change
        /// </summary>
        /// <param name="cls"></param>
        /// <param name="initialManeuver"></param>
        /// <param name="targetManeuver"></param>
        /// <returns></returns>
        public Maneuver PlanLaneChange(ChangeLanesState cls, VehicleState vehicleState, RoadPlan roadPlan,
                                       List <ITacticalBlockage> blockages, List <ArbiterWaypoint> ignorable)
        {
            // check blockages
            if (blockages != null && blockages.Count > 0 && blockages[0] is LaneChangeBlockage)
            {
                // create the blockage state
                EncounteredBlockageState ebs = new EncounteredBlockageState(blockages[0], CoreCommon.CorePlanningState);

                // go to a blockage handling tactical
                return(new Maneuver(new NullBehavior(), ebs, TurnDecorators.NoDecorators, vehicleState.Timestamp));
            }

            // lanes of the lane change
            ArbiterLane initial = cls.Parameters.Initial;
            ArbiterLane target  = cls.Parameters.Target;

            #region Initial Forwards

            if (!cls.Parameters.InitialOncoming)
            {
                ForwardReasoning initialReasoning = new ForwardReasoning(new LateralReasoning(null, SideObstacleSide.Driver), new LateralReasoning(null, SideObstacleSide.Driver), initial);

                #region Target Forwards

                if (!cls.Parameters.TargetOncoming)
                {
                    // target reasoning
                    ForwardReasoning targetReasoning = new ForwardReasoning(new LateralReasoning(null, SideObstacleSide.Driver), new LateralReasoning(null, SideObstacleSide.Driver), target);

                    #region Navigation

                    if (cls.Parameters.Reason == LaneChangeReason.Navigation)
                    {
                        // parameters to follow
                        List <TravelingParameters> tps = new List <TravelingParameters>();

                        // vehicles to ignore
                        List <int> ignorableVehicles = new List <int>();

                        // params for forward lane
                        initialReasoning.ForwardManeuver(initial, vehicleState, roadPlan, blockages, ignorable);
                        TravelingParameters initialParams = initialReasoning.ForwardMonitor.ParameterizationHelper(initial, initial,
                                                                                                                   CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.Equals(roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.WaypointId) ?
                                                                                                                   initial.WaypointList[initial.WaypointList.Count - 1].Position : roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.Position,
                                                                                                                   vehicleState.Front, CoreCommon.CorePlanningState, vehicleState, initialReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle);

                        ArbiterOutput.Output("initial dist to go: " + initialParams.DistanceToGo.ToString("f3"));

                        if (initialParams.Type == TravellingType.Vehicle && !initialReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle.IsStopped)
                        {
                            tps.Add(initialParams);
                        }
                        else
                        {
                            tps.Add(initialReasoning.ForwardMonitor.NavigationParameters);
                        }

                        ignorableVehicles.AddRange(initialParams.VehiclesToIgnore);

                        // get params for the final lane
                        targetReasoning.ForwardManeuver(target, vehicleState, roadPlan, blockages, new List <ArbiterWaypoint>());
                        TravelingParameters targetParams = targetReasoning.ForwardMonitor.CurrentParameters;
                        tps.Add(targetParams);
                        ignorableVehicles.AddRange(targetParams.VehiclesToIgnore);

                        try
                        {
                            if (CoreCommon.Communications.GetVehicleSpeed().Value < 0.1 &&
                                targetParams.Type == TravellingType.Vehicle &&
                                targetReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle != null &&
                                targetReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle.QueuingState.Queuing == QueuingState.Failed)
                            {
                                return(new Maneuver(new HoldBrakeBehavior(), new StayInLaneState(target, CoreCommon.CorePlanningState), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                            }
                        }
                        catch (Exception) { }

                        ArbiterOutput.Output("target dist to go: " + targetParams.DistanceToGo.ToString("f3"));

                        // decorators
                        List <BehaviorDecorator> decorators = initial.LaneOnLeft != null && initial.LaneOnLeft.Equals(target) ? TurnDecorators.LeftTurnDecorator : TurnDecorators.RightTurnDecorator;

                        // distance
                        double distanceToGo = initial.DistanceBetween(vehicleState.Front, cls.Parameters.DepartUpperBound);
                        cls.Parameters.DistanceToDepartUpperBound = distanceToGo;

                        // check if need to modify distance to go
                        if (initialParams.Type == TravellingType.Vehicle && initialReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle.IsStopped)
                        {
                            double curDistToUpper    = cls.Parameters.DistanceToDepartUpperBound;
                            double newVhcDistToUpper = initial.DistanceBetween(vehicleState.Front, initialReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle.ClosestPosition) - 2.0;

                            if (curDistToUpper > newVhcDistToUpper)
                            {
                                distanceToGo = newVhcDistToUpper;
                            }
                        }

                        // get final
                        tps.Sort();

                        // get the proper speed command
                        ScalarSpeedCommand sc = new ScalarSpeedCommand(tps[0].RecommendedSpeed);
                        if (sc.Speed < 8.84)
                        {
                            sc = new ScalarSpeedCommand(Math.Min(targetParams.RecommendedSpeed, 8.84));
                        }

                        // continue the lane change with the proper speed command
                        ChangeLaneBehavior clb = new ChangeLaneBehavior(initial.LaneId, target.LaneId, initial.LaneOnLeft != null && initial.LaneOnLeft.Equals(target), distanceToGo,
                                                                        sc, targetParams.VehiclesToIgnore, initial.LanePath(), target.LanePath(), initial.Width, target.Width, initial.NumberOfLanesLeft(vehicleState.Front, true),
                                                                        initial.NumberOfLanesRight(vehicleState.Front, true));

                        // standard maneuver
                        return(new Maneuver(clb, CoreCommon.CorePlanningState, decorators, vehicleState.Timestamp));
                    }

                    #endregion

                    #region Failed Forwards

                    else if (cls.Parameters.Reason == LaneChangeReason.FailedForwardVehicle)
                    {
                        // parameters to follow
                        List <TravelingParameters> tps = new List <TravelingParameters>();

                        // vehicles to ignore
                        List <int> ignorableVehicles = new List <int>();

                        // params for forward lane
                        initialReasoning.ForwardManeuver(initial, vehicleState, roadPlan, blockages, ignorable);
                        TravelingParameters initialParams = initialReasoning.ForwardMonitor.ParameterizationHelper(initial, initial,
                                                                                                                   CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.Equals(roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.WaypointId) ?
                                                                                                                   initial.WaypointList[initial.WaypointList.Count - 1].Position : roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.Position,
                                                                                                                   vehicleState.Front, CoreCommon.CorePlanningState, vehicleState, null);
                        tps.Add(initialParams);
                        ignorableVehicles.AddRange(initialParams.VehiclesToIgnore);

                        // get params for the final lane
                        targetReasoning.ForwardManeuver(target, vehicleState, roadPlan, blockages, new List <ArbiterWaypoint>());
                        TravelingParameters targetParams = targetReasoning.ForwardMonitor.CurrentParameters;
                        tps.Add(targetParams);
                        ignorableVehicles.AddRange(targetParams.VehiclesToIgnore);

                        // decorators
                        List <BehaviorDecorator> decorators = initial.LaneOnLeft != null && initial.LaneOnLeft.Equals(target) ? TurnDecorators.LeftTurnDecorator : TurnDecorators.RightTurnDecorator;

                        // distance
                        double distanceToGo = initial.DistanceBetween(vehicleState.Front, cls.Parameters.DepartUpperBound);
                        cls.Parameters.DistanceToDepartUpperBound = distanceToGo;

                        // get final
                        tps.Sort();

                        // get the proper speed command
                        SpeedCommand sc = new ScalarSpeedCommand(tps[0].RecommendedSpeed);

                        // continue the lane change with the proper speed command
                        ChangeLaneBehavior clb = new ChangeLaneBehavior(initial.LaneId, target.LaneId, initial.LaneOnLeft != null && initial.LaneOnLeft.Equals(target), distanceToGo,
                                                                        sc, targetParams.VehiclesToIgnore, initial.LanePath(), target.LanePath(), initial.Width, target.Width, initial.NumberOfLanesLeft(vehicleState.Front, true),
                                                                        initial.NumberOfLanesRight(vehicleState.Front, true));

                        // standard maneuver
                        return(new Maneuver(clb, CoreCommon.CorePlanningState, decorators, vehicleState.Timestamp));
                    }

                    #endregion

                    #region Slow

                    else if (cls.Parameters.Reason == LaneChangeReason.SlowForwardVehicle)
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }

                    #endregion

                    else
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }
                }

                #endregion

                #region Target Oncoming

                else
                {
                    OpposingReasoning targetReasoning = new OpposingReasoning(new OpposingLateralReasoning(null, SideObstacleSide.Driver), new OpposingLateralReasoning(null, SideObstacleSide.Driver), target);

                    #region Failed Forward

                    if (cls.Parameters.Reason == LaneChangeReason.FailedForwardVehicle)
                    {
                        // parameters to follow
                        List <TravelingParameters> tps = new List <TravelingParameters>();

                        // ignore the forward vehicle but keep params for forward lane
                        initialReasoning.ForwardManeuver(initial, vehicleState, roadPlan, blockages, ignorable);
                        TravelingParameters initialParams = initialReasoning.ForwardMonitor.ParameterizationHelper(initial, initial,
                                                                                                                   CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.Equals(roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.WaypointId) ?
                                                                                                                   initial.WaypointList[initial.WaypointList.Count - 1].Position : roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.Position, vehicleState.Front, CoreCommon.CorePlanningState, vehicleState, null);
                        tps.Add(initialParams);

                        // get params for the final lane
                        targetReasoning.ForwardManeuver(target, initial, vehicleState, roadPlan, blockages);
                        TravelingParameters targetParams = targetReasoning.OpposingForwardMonitor.CurrentParamters.Value;
                        tps.Add(targetParams);

                        // decorators
                        List <BehaviorDecorator> decorators = cls.Parameters.ToLeft ? TurnDecorators.LeftTurnDecorator : TurnDecorators.RightTurnDecorator;

                        // distance
                        double distanceToGo = initial.DistanceBetween(vehicleState.Front, cls.Parameters.DepartUpperBound);
                        cls.Parameters.DistanceToDepartUpperBound = distanceToGo;

                        // get final
                        tps.Sort();

                        // get the proper speed command
                        SpeedCommand sc = new ScalarSpeedCommand(Math.Min(tps[0].RecommendedSpeed, 2.24));

                        // check final for stopped failed opposing
                        VehicleAgent forwardVa = targetReasoning.OpposingForwardMonitor.ForwardVehicle.CurrentVehicle;
                        if (forwardVa != null)
                        {
                            // dist between
                            double distToFV = -targetReasoning.Lane.DistanceBetween(vehicleState.Front, forwardVa.ClosestPosition);

                            // check stopped
                            bool stopped = Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value) < 0.5;

                            // check distance
                            bool distOk = distToFV < 2.5 * TahoeParams.VL;

                            // check failed
                            bool failed = forwardVa.QueuingState.Queuing == QueuingState.Failed;

                            // notify
                            ArbiterOutput.Output("Forward Vehicle: Stopped: " + stopped.ToString() + ", DistOk: " + distOk.ToString() + ", Failed: " + failed.ToString());

                            // check all for failed
                            if (stopped && distOk && failed)
                            {
                                // check inside target
                                if (target.LanePolygon.IsInside(vehicleState.Front))
                                {
                                    // blockage recovery
                                    StayInLaneState       sils = new StayInLaneState(initial, CoreCommon.CorePlanningState);
                                    StayInLaneBehavior    silb = new StayInLaneBehavior(initial.LaneId, new StopAtDistSpeedCommand(TahoeParams.VL * 2.0, true), new List <int>(), initial.LanePath(), initial.Width, initial.NumberOfLanesLeft(vehicleState.Front, false), initial.NumberOfLanesRight(vehicleState.Front, false));
                                    BlockageRecoveryState brs  = new BlockageRecoveryState(silb, sils, sils, BlockageRecoveryDEFCON.REVERSE,
                                                                                           new EncounteredBlockageState(new LaneBlockage(new TrajectoryBlockedReport(CompletionResult.Stopped, 4.0, BlockageType.Static, -1, true, silb.GetType())), sils, BlockageRecoveryDEFCON.INITIAL, SAUDILevel.None),
                                                                                           BlockageRecoverySTATUS.EXECUTING);
                                    return(new Maneuver(silb, brs, TurnDecorators.HazardDecorator, vehicleState.Timestamp));
                                }
                                // check which lane we are in
                                else
                                {
                                    // return to forward lane
                                    return(new Maneuver(new HoldBrakeBehavior(), new StayInLaneState(initial, CoreCommon.CorePlanningState), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                                }
                            }
                        }

                        // continue the lane change with the proper speed command
                        ChangeLaneBehavior clb = new ChangeLaneBehavior(initial.LaneId, target.LaneId, cls.Parameters.ToLeft, distanceToGo,
                                                                        sc, targetParams.VehiclesToIgnore, initial.LanePath(), target.ReversePath, initial.Width, target.Width, initial.NumberOfLanesLeft(vehicleState.Front, true),
                                                                        initial.NumberOfLanesRight(vehicleState.Front, true));

                        // standard maneuver
                        return(new Maneuver(clb, CoreCommon.CorePlanningState, decorators, vehicleState.Timestamp));
                    }

                    #endregion

                    #region Other

                    else if (cls.Parameters.Reason == LaneChangeReason.Navigation)
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }
                    else if (cls.Parameters.Reason == LaneChangeReason.SlowForwardVehicle)
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }
                    else
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }

                    #endregion
                }

                #endregion
            }

            #endregion

            #region Initial Oncoming

            else
            {
                OpposingReasoning initialReasoning = new OpposingReasoning(new OpposingLateralReasoning(null, SideObstacleSide.Driver), new OpposingLateralReasoning(null, SideObstacleSide.Driver), initial);

                #region Target Forwards

                if (!cls.Parameters.TargetOncoming)
                {
                    ForwardReasoning targetReasoning = new ForwardReasoning(new LateralReasoning(null, SideObstacleSide.Driver), new LateralReasoning(null, SideObstacleSide.Driver), target);

                    if (cls.Parameters.Reason == LaneChangeReason.FailedForwardVehicle)
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }

                    #region Navigation

                    else if (cls.Parameters.Reason == LaneChangeReason.Navigation)
                    {
                        // parameters to follow
                        List <TravelingParameters> tps = new List <TravelingParameters>();

                        // distance to the upper bound of the change
                        double distanceToGo = target.DistanceBetween(vehicleState.Front, cls.Parameters.DepartUpperBound);
                        cls.Parameters.DistanceToDepartUpperBound = distanceToGo;

                        // get params for the initial lane
                        initialReasoning.ForwardManeuver(initial, target, vehicleState, roadPlan, blockages);

                        // current params of the fqm
                        TravelingParameters initialParams = initialReasoning.OpposingForwardMonitor.CurrentParamters.Value;

                        if (initialParams.Type == TravellingType.Vehicle)
                        {
                            if (!initialReasoning.OpposingForwardMonitor.ForwardVehicle.CurrentVehicle.IsStopped)
                            {
                                tps.Add(initialParams);
                            }
                            else
                            {
                                tps.Add(initialReasoning.OpposingForwardMonitor.NaviationParameters);
                                distanceToGo = initial.DistanceBetween(initialReasoning.OpposingForwardMonitor.ForwardVehicle.CurrentVehicle.ClosestPosition, vehicleState.Front) - TahoeParams.VL;
                            }
                        }
                        else
                        {
                            tps.Add(initialReasoning.OpposingForwardMonitor.NaviationParameters);
                        }

                        // get params for forward lane
                        targetReasoning.ForwardManeuver(target, vehicleState, roadPlan, blockages, ignorable);
                        TravelingParameters targetParams = targetReasoning.ForwardMonitor.ParameterizationHelper(target, target,
                                                                                                                 CoreCommon.Mission.MissionCheckpoints.Peek().WaypointId.Equals(roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.WaypointId) ?
                                                                                                                 target.WaypointList[target.WaypointList.Count - 1].Position : roadPlan.BestPlan.laneWaypointOfInterest.PointOfInterest.Position,
                                                                                                                 vehicleState.Front, CoreCommon.CorePlanningState, vehicleState, targetReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle);
                        tps.Add(targetParams);

                        // ignoring vehicles add
                        List <int> ignoreVehicles = initialParams.VehiclesToIgnore;
                        ignoreVehicles.AddRange(targetParams.VehiclesToIgnore);

                        // decorators
                        List <BehaviorDecorator> decorators = !cls.Parameters.ToLeft ? TurnDecorators.RightTurnDecorator : TurnDecorators.LeftTurnDecorator;

                        // get final
                        tps.Sort();

                        // get the proper speed command
                        SpeedCommand sc = tps[0].SpeedCommand;

                        if (sc is StopAtDistSpeedCommand)
                        {
                            sc = new ScalarSpeedCommand(0.0);
                        }

                        // check final for stopped failed opposing
                        VehicleAgent forwardVa = targetReasoning.ForwardMonitor.ForwardVehicle.CurrentVehicle;
                        if (forwardVa != null)
                        {
                            // dist between
                            double distToFV = targetReasoning.Lane.DistanceBetween(vehicleState.Front, forwardVa.ClosestPosition);

                            // check stopped
                            bool stopped = Math.Abs(CoreCommon.Communications.GetVehicleSpeed().Value) < 0.5;

                            // check distance
                            bool distOk = distToFV < 2.5 * TahoeParams.VL;

                            // check failed
                            bool failed = forwardVa.QueuingState.Queuing == QueuingState.Failed;

                            // notify
                            ArbiterOutput.Output("Forward Vehicle: Stopped: " + stopped.ToString() + ", DistOk: " + distOk.ToString() + ", Failed: " + failed.ToString());

                            // check all for failed
                            if (stopped && distOk && failed)
                            {
                                // check which lane we are in
                                if (initial.LanePolygon.IsInside(vehicleState.Front))
                                {
                                    // return to opposing lane
                                    return(new Maneuver(new HoldBrakeBehavior(), new OpposingLanesState(initial, true, CoreCommon.CorePlanningState, vehicleState), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                                }
                                else
                                {
                                    // lane state
                                    return(new Maneuver(new HoldBrakeBehavior(), new StayInLaneState(target, CoreCommon.CorePlanningState), TurnDecorators.NoDecorators, vehicleState.Timestamp));
                                }
                            }
                        }

                        // continue the lane change with the proper speed command
                        ChangeLaneBehavior clb = new ChangeLaneBehavior(initial.LaneId, target.LaneId, cls.Parameters.ToLeft, distanceToGo,
                                                                        sc, ignoreVehicles, initial.ReversePath, target.LanePath(), initial.Width, target.Width, initial.NumberOfLanesLeft(vehicleState.Front, false),
                                                                        initial.NumberOfLanesRight(vehicleState.Front, false));

                        // standard maneuver
                        return(new Maneuver(clb, CoreCommon.CorePlanningState, decorators, vehicleState.Timestamp));
                    }

                    #endregion

                    else if (cls.Parameters.Reason == LaneChangeReason.SlowForwardVehicle)
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }
                    else
                    {
                        // fallout exception
                        throw new Exception("currently unsupported lane change type");
                    }
                }

                #endregion

                else
                {
                    // fallout exception
                    throw new Exception("currently unsupported lane change type");
                }
            }

            #endregion
        }
Beispiel #31
0
        /// <summary>
        /// Lightweight simulation step method.
        /// This method is occasionally being called for different cars.
        /// </summary>
        /// <param name="vehicleId"></param>
        /// <param name="vehicleData"></param>
        /// <param name="physicsLodRefPos"></param>
        public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos)
        {
            PathManager pathMan = Singleton <PathManager> .instance;

#if DEBUG
            /*if (!GlobalConfig.Instance.DebugSwitches[0]) {
             *      Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}) called. flags: {vehicleData.m_flags} pfFlags: {pathMan.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags}");
             * }*/
#endif

            // NON-STOCK CODE START
            VehicleState       state             = null;
            ExtCitizenInstance driverExtInstance = null;
            bool prohibitPocketCars = Options.prohibitPocketCars;
            if (prohibitPocketCars)
            {
                // check for valid driver and update return path state
                state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleId));
                if (state.VehicleType == ExtVehicleType.PassengerCar)
                {
                    driverExtInstance = state.GetDriverExtInstance();
                    if (driverExtInstance == null)
                    {
                        prohibitPocketCars = false;
                    }
                    else
                    {
                        driverExtInstance.UpdateReturnPathState();
                    }
                }
                else
                {
                    prohibitPocketCars = false;
                }
            }
            // NON-STOCK CODE END

            if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0 &&
                (!prohibitPocketCars || driverExtInstance.ReturnPathState != ExtCitizenInstance.ExtPathState.Calculating))                    // NON-STOCK CODE: Parking AI: wait for the return path to be calculated
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags;

                bool pathFindFailed    = (pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0;              // path == 0: non-stock code!
                bool pathFindSucceeded = (pathFindFlags & PathUnit.FLAG_READY) != 0;

#if USEPATHWAITCOUNTER
                if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0)
                {
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId);
                    state.PathWaitCounter = 0;                     // NON-STOCK CODE
                }
#endif

                if (prohibitPocketCars)
                {
                    if (driverExtInstance.ReturnPathState == ExtPathState.Failed)
                    {
                        // no walking path from parking position to target found. flag main path as 'failed'.
#if DEBUG
                        if (GlobalConfig.Instance.DebugSwitches[2])
                        {
                            Log._Debug($"CustomCarAI.CustomSimulationStep: Return path {driverExtInstance.ReturnPathId} FAILED. Forcing path-finding to fail.");
                        }
#endif
                        pathFindSucceeded = false;
                        pathFindFailed    = true;
                    }

                    driverExtInstance.ReleaseReturnPath();

                    if (pathFindSucceeded)
                    {
                        CustomPassengerCarAI.OnPathFindSuccess(vehicleId, ref vehicleData, driverExtInstance);
                    }
                    else if (pathFindFailed)
                    {
                        CustomPassengerCarAI.OnPathFindFailure(driverExtInstance, vehicleId);
                    }
                }

                if (pathFindSucceeded)
                {
                    vehicleData.m_pathPositionIndex = 255;
                    vehicleData.m_flags            &= ~Vehicle.Flags.WaitingPath;
                    vehicleData.m_flags            &= ~Vehicle.Flags.Arriving;
                    this.PathfindSuccess(vehicleId, ref vehicleData);
                    this.TrySpawn(vehicleId, ref vehicleData);
                }
                else if (pathFindFailed)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                    Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                    vehicleData.m_path = 0u;
                    this.PathfindFailure(vehicleId, ref vehicleData);
                    return;
                }
#if USEPATHWAITCOUNTER
                else
                {
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId);
                    state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1);                   // NON-STOCK CODE
                }
#endif
            }
            else
            {
                if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0)
                {
                    this.TrySpawn(vehicleId, ref vehicleData);
                }
            }

            /// NON-STOCK CODE START ///
            VehicleStateManager vehStateManager = VehicleStateManager.Instance;
            if (Options.prioritySignsEnabled || Options.timedLightsEnabled)
            {
                // update vehicle position for timed traffic lights and priority signs
                try {
                    vehStateManager.UpdateVehiclePos(vehicleId, ref vehicleData);
                } catch (Exception e) {
                    Log.Error("CarAI CustomSimulationStep Error: " + e.ToString());
                }
            }

            if (!Options.isStockLaneChangerUsed())
            {
                // Advanced AI traffic measurement
                try {
                    vehStateManager.LogTraffic(vehicleId, ref vehicleData, true);
                } catch (Exception e) {
                    Log.Error("CarAI CustomSimulationStep Error: " + e.ToString());
                }
            }
            /// NON-STOCK CODE END ///

            Vector3 lastFramePosition = vehicleData.GetLastFramePosition();
            int     lodPhysics;
            if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f)
            {
                lodPhysics = 2;
            }
            else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f)
            {
                lodPhysics = 1;
            }
            else
            {
                lodPhysics = 0;
            }
            this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics);
            if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0)
            {
                VehicleManager vehManager = Singleton <VehicleManager> .instance;
                ushort         num        = vehicleData.m_trailingVehicle;
                int            num2       = 0;
                while (num != 0)
                {
                    ushort      trailingVehicle = vehManager.m_vehicles.m_buffer[(int)num].m_trailingVehicle;
                    VehicleInfo info            = vehManager.m_vehicles.m_buffer[(int)num].Info;
                    info.m_vehicleAI.SimulationStep(num, ref vehManager.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics);
                    num = trailingVehicle;
                    if (++num2 > 16384)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        break;
                    }
                }
            }
#if PATHRECALC
            ushort recalcSegmentId = 0;
#endif
            int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service);
            int maxBlockCounter     = (privateServiceIndex == -1) ? 150 : 100;
            if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0)
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
            else if ((int)vehicleData.m_blockCounter >= maxBlockCounter && Options.enableDespawning)
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
#if PATHRECALC
            else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId))
            {
                CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId);
                InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData);
            }
#endif
        }
 public abstract void HandleIncomingState(VehicleState state);
    public override void HandleIncomingState(VehicleState state)
    {
        this.state = state;

        Target.SetState(state);
    }
Beispiel #34
0
        private void HandleStateUpdate(NetIncomingMessage msg)
        {
            for (int i = 0; i < vehcileNetworkStates.Count; ++i)
            {
                vehcileNetworkStates[i].Read(msg);

                VehicleState state = new VehicleState();
                state.FromNetworkState(vehcileNetworkStates[i]);

                vehicles.SetVehicleState(i, state);
            }
        }
 public override void HandleIncomingState(VehicleState state)
 {
     // TODO: detect desync state changes etc
 }
    public class CustomTrainAI : TrainAI {     // TODO inherit from VehicleAI (in order to keep the correct references to `base`)
        public void TrafficManagerSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos)
        {
            if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0)
            {
                byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags;

#if USEPATHWAITCOUNTER
                if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0)
                {
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId);
                    state.PathWaitCounter = 0;                     // NON-STOCK CODE
                }
#endif

                if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    try {
                        this.PathFindReady(vehicleId, ref vehicleData);
                    } catch (Exception e) {
                        Log.Warning($"TrainAI.PathFindReady({vehicleId}) for vehicle {vehicleData.Info?.m_class?.name} threw an exception: {e.ToString()}");
                        vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                        vehicleData.m_path = 0u;
                        vehicleData.Unspawn(vehicleId);
                        return;
                    }
                }
                else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                    Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                    vehicleData.m_path = 0u;
                    vehicleData.Unspawn(vehicleId);
                    return;
                }
#if USEPATHWAITCOUNTER
                else
                {
                    VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId);
                    state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1);                   // NON-STOCK CODE
                }
#endif
            }
            else
            {
                if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0)
                {
                    this.TrySpawn(vehicleId, ref vehicleData);
                }
            }

            bool   reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
            ushort frontVehicleId;
            if (reversed)
            {
                frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
            }
            else
            {
                frontVehicleId = vehicleId;
            }

            /// NON-STOCK CODE START ///
            VehicleStateManager vehStateManager = VehicleStateManager.Instance;

            if (Options.prioritySignsEnabled || Options.timedLightsEnabled)
            {
                try {
                    vehStateManager.UpdateVehiclePos(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId]);
                } catch (Exception e) {
                    Log.Error("TrainAI TrafficManagerSimulationStep (2) Error: " + e.ToString());
                }
            }

            if (!Options.isStockLaneChangerUsed())
            {
                try {
                    //Log._Debug($"HandleVehicle for trams. vehicleId={vehicleId} frontVehicleId={frontVehicleId}");
                    vehStateManager.LogTraffic(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], true);
                } catch (Exception e) {
                    Log.Error("TrainAI TrafficManagerSimulationStep (1) Error: " + e.ToString());
                }
            }
            /// NON-STOCK CODE END ///

            VehicleManager instance = Singleton <VehicleManager> .instance;
            VehicleInfo    info     = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
            info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
            if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
            {
                return;
            }
            bool flag2 = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
            if (flag2 != reversed)
            {
                reversed = flag2;
                if (reversed)
                {
                    frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
                }
                else
                {
                    frontVehicleId = vehicleId;
                }
                info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                {
                    return;
                }
                flag2 = ((vehicleData.m_flags & Vehicle.Flags.Reversed) != 0);
                if (flag2 != reversed)
                {
                    Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);

                    return;
                }
            }
            if (reversed)
            {
                frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle;
                int num2 = 0;
                while (frontVehicleId != 0)
                {
                    info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                    info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                    if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                    {
                        return;
                    }
                    frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle;
                    if (++num2 > 16384)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        break;
                    }
                }
            }
            else
            {
                frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle;
                int num3 = 0;
                while (frontVehicleId != 0)
                {
                    info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                    info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                    if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                    {
                        return;
                    }
                    frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle;
                    if (++num3 > 16384)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        break;
                    }
                }
            }
            if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || (vehicleData.m_blockCounter == 255 /*&& Options.enableDespawning*/))
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
        }