Skip to content

Commit c173d4f

Browse files
committed
#263: DLS cost profile varies per vehicle
1 parent 9d281ae commit c173d4f

File tree

5 files changed

+139
-7
lines changed

5 files changed

+139
-7
lines changed

TLM/TLM/Manager/Impl/VehicleBehaviorManager.cs

+8-7
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
763763
vehicleState.lastAltLaneSelSegmentId = currentPathPos.m_segment;
764764

765765
bool recklessDriver = vehicleState.recklessDriver;
766+
float maxReservedSpace = vehicleState.maxReservedSpace;
766767

767768
// cur -> next1
768769
float vehicleLength = 1f + vehicleState.totalLength;
@@ -1168,7 +1169,7 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
11681169
#endif
11691170

11701171
Services.NetService.ProcessLane(next1BackTransitions[j].laneId, delegate (uint prevLaneId, ref NetLane prevLane) {
1171-
prevLanesClear = prevLane.GetReservedSpace() <= (recklessDriver ? conf.DynamicLaneSelection.MaxRecklessReservedSpace : conf.DynamicLaneSelection.MaxReservedSpace);
1172+
prevLanesClear = prevLane.GetReservedSpace() <= maxReservedSpace;
11721173
return true;
11731174
});
11741175

@@ -1213,8 +1214,8 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
12131214

12141215
float relMeanSpeedInPercent = meanSpeed / (TrafficMeasurementManager.REF_REL_SPEED / TrafficMeasurementManager.REF_REL_SPEED_PERCENT_DENOMINATOR);
12151216
float randSpeed = 0f;
1216-
if (conf.DynamicLaneSelection.LaneSpeedRandInterval > 0) {
1217-
randSpeed = Services.SimulationService.Randomizer.Int32((uint)conf.DynamicLaneSelection.LaneSpeedRandInterval + 1u) - conf.DynamicLaneSelection.LaneSpeedRandInterval / 2f;
1217+
if (vehicleState.laneSpeedRandInterval > 0) {
1218+
randSpeed = Services.SimulationService.Randomizer.Int32((uint)vehicleState.laneSpeedRandInterval + 1u) - vehicleState.laneSpeedRandInterval / 2f;
12181219
relMeanSpeedInPercent += randSpeed;
12191220
}
12201221

@@ -1360,7 +1361,7 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
13601361
return bestStayNext1LaneIndex;
13611362
}
13621363

1363-
if (bestStayTotalLaneDist != bestOptTotalLaneDist && Math.Max(bestStayTotalLaneDist, bestOptTotalLaneDist) > conf.DynamicLaneSelection.MaxOptLaneChanges) {
1364+
if (bestStayTotalLaneDist != bestOptTotalLaneDist && Math.Max(bestStayTotalLaneDist, bestOptTotalLaneDist) > vehicleState.maxOptLaneChanges) {
13641365
/*
13651366
* best route contains more lane changes than allowed: choose lane with the least number of future lane changes
13661367
*/
@@ -1397,8 +1398,8 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
13971398
Log._Debug($"VehicleBehaviorManager.FindBestLane({vehicleId}): a lane change for speed improvement is possible. optImprovementInKmH={optImprovementInKmH} km/h speedDiff={speedDiff} (bestOptMeanSpeed={bestOptMeanSpeed}, vehicleCurVelocity={vehicleCurSpeed}, foundSafeLaneChange={foundSafeLaneChange})");
13981399
}
13991400
#endif
1400-
if (optImprovementInKmH >= conf.DynamicLaneSelection.MinSafeSpeedImprovement &&
1401-
(foundSafeLaneChange || (speedDiff <= conf.DynamicLaneSelection.MaxUnsafeSpeedDiff))
1401+
if (optImprovementInKmH >= vehicleState.minSafeSpeedImprovement &&
1402+
(foundSafeLaneChange || (speedDiff <= vehicleState.maxUnsafeSpeedDiff))
14021403
) {
14031404
// speed improvement is significant
14041405
#if DEBUG
@@ -1424,7 +1425,7 @@ public int FindBestLane(ushort vehicleId, ref Vehicle vehicleData, ref VehicleSt
14241425
Log._Debug($"VehicleBehaviorManager.FindBestLane({vehicleId}): found a lane change that optimizes overall traffic. optimization={optimization}%");
14251426
}
14261427
#endif
1427-
if (optimization >= conf.DynamicLaneSelection.MinSafeTrafficImprovement) {
1428+
if (optimization >= vehicleState.minSafeTrafficImprovement) {
14281429
// traffic optimization is significant
14291430
#if DEBUG
14301431
if (debug) {

TLM/TLM/State/ConfigData/DynamicLaneSelection.cs

+72
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,77 @@ public class DynamicLaneSelection {
4444
/// Minimum relative speed (in %) where volume measurement starts
4545
/// </summary>
4646
public ushort VolumeMeasurementRelSpeedThreshold = 50;
47+
48+
// ---
49+
50+
/// <summary>
51+
/// Minimum maximum allowed reserved space on previous vehicle lane (for regular drivers)
52+
/// </summary>
53+
public float MinMaxReservedSpace = 0f;
54+
55+
/// <summary>
56+
/// Maximum value for Maximum allowed reserved space on previous vehicle lane (for regular drivers)
57+
/// </summary>
58+
public float MaxMaxReservedSpace = 5f;
59+
60+
/// <summary>
61+
/// Minimum maximum allowed reserved space on previous vehicle lane (for reckless drivers)
62+
/// </summary>
63+
public float MinMaxRecklessReservedSpace = 10f;
64+
65+
/// <summary>
66+
/// Maximum maximum allowed reserved space on previous vehicle lane (for reckless drivers)
67+
/// </summary>
68+
public float MaxMaxRecklessReservedSpace = 50f;
69+
70+
/// <summary>
71+
/// Minimum lane speed randomization interval
72+
/// </summary>
73+
public float MinLaneSpeedRandInterval = 0f;
74+
75+
/// <summary>
76+
/// Maximum lane speed randomization interval
77+
/// </summary>
78+
public float MaxLaneSpeedRandInterval = 25f;
79+
80+
/// <summary>
81+
/// Maximum number of considered lane changes
82+
/// </summary>
83+
public int MinMaxOptLaneChanges = 1;
84+
85+
/// <summary>
86+
/// Maximum number of considered lane changes
87+
/// </summary>
88+
public int MaxMaxOptLaneChanges = 3;
89+
90+
/// <summary>
91+
/// Minimum maximum allowed speed difference for safe lane changes (in game units)
92+
/// </summary>
93+
public float MinMaxUnsafeSpeedDiff = 0.1f;
94+
95+
/// <summary>
96+
/// Maximum maximum allowed speed difference for safe lane changes (in game units)
97+
/// </summary>
98+
public float MaxMaxUnsafeSpeedDiff = 1f;
99+
100+
/// <summary>
101+
/// Minimum minimum required speed improvement for safe lane changes (in km/h)
102+
/// </summary>
103+
public float MinMinSafeSpeedImprovement = 5f;
104+
105+
/// <summary>
106+
/// Maximum minimum required speed improvement for safe lane changes (in km/h)
107+
/// </summary>
108+
public float MaxMinSafeSpeedImprovement = 30f;
109+
110+
/// <summary>
111+
/// Minimum minimum required traffic flow improvement for safe lane changes (in %)
112+
/// </summary>
113+
public float MinMinSafeTrafficImprovement = 5f;
114+
115+
/// <summary>
116+
/// Maximum minimum required traffic flow improvement for safe lane changes (in %)
117+
/// </summary>
118+
public float MaxMinSafeTrafficImprovement = 30f;
47119
}
48120
}

TLM/TLM/TLM.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@
259259
<Compile Include="Util\IObserver.cs" />
260260
<Compile Include="Manager\IManagerFactory.cs" />
261261
<Compile Include="Util\IVisitor.cs" />
262+
<Compile Include="Util\MathUtil.cs" />
262263
<Compile Include="Util\LoopUtil.cs" />
263264
<Compile Include="Util\ModsCompatibilityChecker.cs" />
264265
<Compile Include="Util\SegmentLaneTraverser.cs" />

TLM/TLM/Traffic/Data/VehicleState.cs

+45
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
using CSUtil.Commons;
1414
using TrafficManager.Manager.Impl;
1515
using ColossalFramework.Math;
16+
using TrafficManager.State.ConfigData;
17+
using TrafficManager.Util;
1618

1719
namespace TrafficManager.Traffic.Data {
1820
public struct VehicleState {
@@ -94,6 +96,14 @@ public float Velocity {
9496
public byte timedRand;
9597
private VehicleJunctionTransitState junctionTransitState;
9698

99+
// Dynamic Lane Selection
100+
public float maxReservedSpace;
101+
public float laneSpeedRandInterval;
102+
public int maxOptLaneChanges;
103+
public float maxUnsafeSpeedDiff;
104+
public float minSafeSpeedImprovement;
105+
public float minSafeTrafficImprovement;
106+
97107
public override string ToString() {
98108
return $"[VehicleState\n" +
99109
"\t" + $"vehicleId = {vehicleId}\n" +
@@ -121,6 +131,12 @@ public override string ToString() {
121131
"\t" + $"lastAltLaneSelSegmentId = {lastAltLaneSelSegmentId}\n" +
122132
"\t" + $"junctionTransitState = {junctionTransitState}\n" +
123133
"\t" + $"timedRand = {timedRand}\n" +
134+
"\t" + $"maxReservedSpace = {maxReservedSpace}\n" +
135+
"\t" + $"laneSpeedRandInterval = {laneSpeedRandInterval}\n" +
136+
"\t" + $"maxOptLaneChanges = {maxOptLaneChanges}\n" +
137+
"\t" + $"maxUnsafeSpeedDiff = {maxUnsafeSpeedDiff}\n" +
138+
"\t" + $"minSafeSpeedImprovement = {minSafeSpeedImprovement}\n" +
139+
"\t" + $"minSafeTrafficImprovement = {minSafeTrafficImprovement}\n" +
124140
"VehicleState]";
125141
}
126142

@@ -149,6 +165,12 @@ internal VehicleState(ushort vehicleId) {
149165
lastAltLaneSelSegmentId = 0;
150166
junctionTransitState = VehicleJunctionTransitState.None;
151167
timedRand = 0;
168+
maxReservedSpace = 0;
169+
laneSpeedRandInterval = 0;
170+
maxOptLaneChanges = 0;
171+
maxUnsafeSpeedDiff = 0;
172+
minSafeSpeedImprovement = 0;
173+
minSafeTrafficImprovement = 0;
152174
}
153175

154176
/*private void Reset(bool unlink=true) { // TODO this is called in wrong places!
@@ -273,6 +295,7 @@ internal ExtVehicleType OnStartPathFind(ref Vehicle vehicleData, ExtVehicleType?
273295
}
274296

275297
recklessDriver = Constants.ManagerFactory.VehicleBehaviorManager.IsRecklessDriver(vehicleId, ref vehicleData);
298+
UpdateTimedRandValues();
276299

277300
#if DEBUG
278301
if (GlobalConfig.Instance.Debug.Switches[9])
@@ -303,7 +326,9 @@ internal void OnSpawn(ref Vehicle vehicleData) {
303326
lastPathId = 0;
304327
lastPathPositionIndex = 0;
305328
lastAltLaneSelSegmentId = 0;
329+
306330
recklessDriver = Constants.ManagerFactory.VehicleBehaviorManager.IsRecklessDriver(vehicleId, ref vehicleData);
331+
UpdateTimedRandValues();
307332

308333
try {
309334
totalLength = vehicleData.CalculateTotalLength(vehicleId);
@@ -460,6 +485,12 @@ internal void OnRelease(ref Vehicle vehicleData) {
460485
lastAltLaneSelSegmentId = 0;
461486
junctionTransitState = VehicleJunctionTransitState.None;
462487
recklessDriver = false;
488+
maxReservedSpace = 0;
489+
laneSpeedRandInterval = 0;
490+
maxOptLaneChanges = 0;
491+
maxUnsafeSpeedDiff = 0;
492+
minSafeSpeedImprovement = 0;
493+
minSafeTrafficImprovement = 0;
463494

464495
#if DEBUG
465496
if (GlobalConfig.Instance.Debug.Switches[9])
@@ -480,9 +511,23 @@ public void StepRand() {
480511
Randomizer rand = Constants.ServiceFactory.SimulationService.Randomizer;
481512
if (rand.UInt32(20) == 0) {
482513
timedRand = (byte)(((uint)timedRand + rand.UInt32(25)) % MAX_TIMED_RAND);
514+
UpdateTimedRandValues();
483515
}
484516
}
485517

518+
private void UpdateTimedRandValues() {
519+
Randomizer rand = Constants.ServiceFactory.SimulationService.Randomizer;
520+
DynamicLaneSelection dls = GlobalConfig.Instance.DynamicLaneSelection;
521+
maxReservedSpace = recklessDriver
522+
? MathUtil.RandomizeFloat(rand, dls.MinMaxRecklessReservedSpace, dls.MaxMaxRecklessReservedSpace)
523+
: MathUtil.RandomizeFloat(rand, dls.MinMaxReservedSpace, dls.MaxMaxReservedSpace);
524+
laneSpeedRandInterval = MathUtil.RandomizeFloat(rand, dls.MinLaneSpeedRandInterval, dls.MaxLaneSpeedRandInterval);
525+
maxOptLaneChanges = rand.Int32(dls.MinMaxOptLaneChanges, dls.MaxMaxOptLaneChanges + 1);
526+
maxUnsafeSpeedDiff = MathUtil.RandomizeFloat(rand, dls.MinMaxUnsafeSpeedDiff, dls.MaxMaxOptLaneChanges);
527+
minSafeSpeedImprovement = MathUtil.RandomizeFloat(rand, dls.MinMinSafeSpeedImprovement, dls.MaxMinSafeSpeedImprovement);
528+
minSafeTrafficImprovement = MathUtil.RandomizeFloat(rand, dls.MinMinSafeTrafficImprovement, dls.MaxMinSafeTrafficImprovement);
529+
}
530+
486531
private static ushort GetTransitNodeId(ref PathUnit.Position curPos, ref PathUnit.Position nextPos) {
487532
bool startNode = IsTransitNodeCurStartNode(ref curPos, ref nextPos);
488533
ushort transitNodeId1 = 0;

TLM/TLM/Util/MathUtil.cs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using ColossalFramework.Math;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace TrafficManager.Util {
8+
public static class MathUtil {
9+
public static float RandomizeFloat(Randomizer rng, float lower, float upper) {
10+
return ((float)rng.UInt32(0, 10001) / 10000f) * (upper - lower) + lower;
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)